diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..26caf4f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +sudo: required +services: + - docker + +before_install: + - docker pull ps2docker/sdcc_docker + +script: + - docker run -v `pwd`:/subg_rfspy ps2docker/sdcc_docker /bin/sh -c "cd /subg_rfspy; make -f Makefile.test test" + - docker run -v `pwd`:/subg_rfspy ps2docker/sdcc_docker /bin/sh -c "cd /subg_rfspy; make -f Makefile.spi1_alt2" diff --git a/Makefile.spi1_alt2 b/Makefile.spi1_alt2 index 9c5d037..7048483 100755 --- a/Makefile.spi1_alt2 +++ b/Makefile.spi1_alt2 @@ -4,4 +4,8 @@ SERIAL_PARAMS := -DUSES_USART1_TX_ISR -DUSES_USART1_RX_ISR BOARD_TYPE := RILEYLINK BOARD_PARAMS := +CC := sdcc + +main_module = main.rel + include common.mk diff --git a/Makefile.srfstick b/Makefile.srfstick deleted file mode 100755 index 43ff864..0000000 --- a/Makefile.srfstick +++ /dev/null @@ -1,36 +0,0 @@ -SERIAL_TYPE := usb_ep0 -SERIAL_PARAMS := -DSRF_STICK - -BOARD_TYPE := SRF_STICK -BOARD_PARAMS := -DSRF_STICK - -TARGET_DEVICE := CC1111 - - -SRC = \ - hal.c \ - usb.c \ - usb_descriptors.c - -ADB=$(SRC:.c=.adb) -ASM=$(SRC:.c=.asm) -LNK=$(SRC:.c=.lnk) -LST=$(SRC:.c=.lst) -REL=$(SRC:.c=.rel) -RST=$(SRC:.c=.rst) -SYM=$(SRC:.c=.sym) - -PCDB=$(PROGS:.hex=.cdb) -PLNK=$(PROGS:.hex=.lnk) -PMAP=$(PROGS:.hex=.map) -PMEM=$(PROGS:.hex=.mem) -PAOM=$(PROGS:.hex=) -include common.mk - -hal.rel: ${SERIAL_TYPE}/hal.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< - -usb_descriptors.rel: ${SERIAL_TYPE}/usb_descriptors.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< -usb.rel: ${SERIAL_TYPE}/usb.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< diff --git a/Makefile.test b/Makefile.test new file mode 100755 index 0000000..05b098d --- /dev/null +++ b/Makefile.test @@ -0,0 +1,26 @@ +SERIAL_TYPE := spi1_alt2 +SERIAL_PARAMS := -DUSES_USART1_TX_ISR -DUSES_USART1_RX_ISR + +BOARD_TYPE := MOCK_HARDWARE +BOARD_PARAMS := + +CC := gcc + +CFLAGS+=-DRUN_TESTS -g -pthread + +LDFLAGS+=-g -pthread + +main_module = tests.rel + +extra_modules = mock_hardware.rel + +include common.mk + +output/${TARGET_BUILD}: + mkdir -p output/${TARGET_BUILD} + +output/${TARGET_BUILD}/check_subg_rfspy: $(common_modules) $(extra_modules) $(REL) serial.rel + cd output/${TARGET_BUILD} && $(CC) $(LDFLAGS) $(CFLAGS) $(common_modules) $(extra_modules) $(REL) serial.rel -o check_subg_rfspy + +test: output/${TARGET_BUILD} output/${TARGET_BUILD}/check_subg_rfspy + output/${TARGET_BUILD}/check_subg_rfspy diff --git a/Makefile.uart0_alt1 b/Makefile.uart0_alt1 deleted file mode 100755 index 79a7795..0000000 --- a/Makefile.uart0_alt1 +++ /dev/null @@ -1,7 +0,0 @@ -SERIAL_TYPE := uart0_alt1 -SERIAL_PARAMS := - -BOARD_TYPE := RILEYLINK -BOARD_PARAMS := - -include common.mk diff --git a/Makefile.uart1_alt2 b/Makefile.uart1_alt2 deleted file mode 100755 index 35a89c3..0000000 --- a/Makefile.uart1_alt2 +++ /dev/null @@ -1,7 +0,0 @@ -SERIAL_TYPE := uart1_alt2 -SERIAL_PARAMS := -DUSES_USART1_RX_ISR - -BOARD_TYPE := RILEYLINK -BOARD_PARAMS := - -include common.mk diff --git a/Makefile.usb_ep0 b/Makefile.usb_ep0 deleted file mode 100755 index 83ebeac..0000000 --- a/Makefile.usb_ep0 +++ /dev/null @@ -1,37 +0,0 @@ -SERIAL_TYPE := usb_ep0 -SERIAL_PARAMS := -DTI_DONGLE - -BOARD_TYPE := TI_DONGLE -BOARD_PARAMS := -DTI_DONGLE - -TARGET_DEVICE := CC1111 - - -SRC = \ - hal.c \ - usb.c \ - usb_descriptors.c - -ADB=$(SRC:.c=.adb) -ASM=$(SRC:.c=.asm) -LNK=$(SRC:.c=.lnk) -LST=$(SRC:.c=.lst) -REL=$(SRC:.c=.rel) -RST=$(SRC:.c=.rst) -SYM=$(SRC:.c=.sym) - -PCDB=$(PROGS:.hex=.cdb) -PLNK=$(PROGS:.hex=.lnk) -PMAP=$(PROGS:.hex=.map) -PMEM=$(PROGS:.hex=.mem) -PAOM=$(PROGS:.hex=) -include common.mk - -hal.rel: ${SERIAL_TYPE}/hal.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< - -usb_descriptors.rel: ${SERIAL_TYPE}/usb_descriptors.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< -usb.rel: ${SERIAL_TYPE}/usb.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< - diff --git a/Readme.md b/Readme.md index ea72e6c..f00cb0f 100644 --- a/Readme.md +++ b/Readme.md @@ -1,359 +1,213 @@ -# Pre-Requisites for Building subg_rfspy +# subg_rfspy -[sdcc] (http://sdcc.sourceforge.net/) package is required for this build. +[![Build Status](https://travis-ci.org/ps2/subg_rfspy.svg?branch=master)](https://travis-ci.org/ps2/subg_rfspy) - sudo apt-get install sdcc +## Pre-Requisites for Building subg_rfspy + +[sdcc] (http://sdcc.sourceforge.net/) version >= 3.7.0 is required for this build. There is a [docker image](https://hub.docker.com/r/ps2docker/sdcc_docker/) available for this purpose. It's also possible to build it under Windows. The best way to do this is to: -1. install SDCC +1. install SDCC version 3.7.0 2. install Cygwin 3. use Cygwin to install make 4. Use cygwin bash to build the project -# Building +To install, you'll need [cc-tool](https://github.com/dashesy/cc-tool) -You'll need to select a build type, like `uart0_alt1`. The examples below use this value, but you'll want to use the correct one for your hardware and use case. See below for different hardware types and use cases. +# Building and Installing -Perform the build. The output file will be stored at output/uart0_alt1_RILEYLINK_US/uart0_alt1_RILEYLINK_US.hex +``` +make -f Makefile.spi1_alt2 install - make -f Makefile.uart0_alt1 +``` -Perform the install: +# Building and Installing using docker +``` +docker run -v `pwd`:/subg_rfspy ps2docker/sdcc_docker /bin/sh -c "cd /subg_rfspy; make -f Makefile.spi1_alt2 +cc-tool -n CC1110 --log install.log -ew output/spi1_alt2_RILEYLINK_US_STDLOC/spi1_alt2_RILEYLINK_US_STDLOC.hex +``` - make -f Makefile.uart0_alt1 install - # Radio Frequency Selection This code defaults to building firmware that is tuned to 916.5 Mhz. You can also build a 'WorldWide' firmware. This changes the default frequency to 868 and tweaks a few other settings. - make -f Makefile.uart1_alt2 RADIO_LOCALE=WW - -# RileyLink - -If you are using a RileyLink via the onboard bluetooth module (which should be loaded with ble_rfspy), then you'll want to use `spi1_alt2` as your build type. - -If you are going to manually wire up to the cc1110 on the RileyLink via the debug header, use `uart1_alt2` as your build type, and use the pinout below. - -UART/SPI pins exposed on cc1110 debug header: - - PIN - SPI_alt2 / UART1_alt2 - P1.4 - CT / SSN - P1.5 - RT / SCK - P1.6 - TX / MOSI - P1.7 - RX / MISO - -# cc111x UART1_alt2 connected to the Intel Edison UART_1 - - P1.4 - CT / SSN -> UART_1_RTS (GP129) (pin 63) - P1.5 - RT / SCK -> UART_1_CTS (GP128) (pin 65) - P1.6 - TX / MOSI -> UART_1_RX (GP130) (pin 61) - P1.7 - RX / MISO -> UART_1_TX (GP131) (pin 46) - - -# UART on the WirelessThings ERF stick - -Perform the build. The output file will be stored at output/uart0_alt1_SRF_ERF_US/uart0_alt1_SRF_ERF_US.hex - - make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF - -Installation is bit more complicated, as you will need to attach connectors to -the SRF pins manually (you can't use the wiring points on the board itself). - -This [XRF blog post](http://paulswasteland.blogspot.co.uk/2015/01/building-your-own-firmware-for-ciseco.html) -maps cc-debugger connector to the XRF pin names. - -However, the XRF pins are not the same as the SRF pin locations. For that, you -can use the [SRF OpenMicros Data](http://openmicros.org/index.php/articles/88-ciseco-product-documentation/259-srf-technical-data) -to map things to the correct ERF locations. + make -f Makefile.spi1_alt2 RADIO_LOCALE=WW -- SRF Pin 5 - DDATA (also known as DD) -- SRF Pin 6 - DCLOCK (also known as DC) -- SRF Pin 9 - 3.3v (also known as VDD) -- SRF Pin 10 - Ground (also known as GND) -- SRF Pin 15 - Reset +# Protocol -To install the firmware: +See [protocol.md](protocol.md) - make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF install - -# USB on support on TI cc1111 USB stick (CC1111EMK868-915) AKA "Don's Dongle" - - make -f Makefile.usb_ep0 install - -Shows up as a serial device on linux. - - -# CCTL Support - -If you have [CCTL](https://github.com/oskarpearson/cctl/tree/24mhz_clock_and_erf_stick_hack) -on your device stick, you can re-program the firmware without requiring the cc-debugger. -To compile firmware that's compatible with CCTL, set the CODE_LOC and CODE_LOC_NAME parameters: - - make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL - -Then, compile the cctl writer program: - - cd /where/you/want/the/cctl/code/to/live - git clone https://github.com/oskarpearson/cctl.git - cd cctl - git checkout 24mhz_clock_and_erf_stick_hack - cd cctl-prog - make clean all - -Then connect the ERF stick over the serial port (normally /dev/ttyUSB0), and write the firmware: - - ./cctl-prog -d /dev/ttyUSB0 -f /path/to/subg_rfspy/output/uart0_alt1_SRF_ERF_WW_CCTL/uart0_alt1_SRF_ERF_WW_CCTL.hex - Waiting 10s for bootloader, reset board now - -Reset the board by disconnecting the +ve lead, and you should then see: - - ....Bootloader detected - Erasing, programming and verifying page 1 - ... - Erasing page 31 - Programming complete # Addendum -## Command List - -Different commands can be selected by sending the following numbers through the serial interface. - -### Interrupt: 0 +## Serial/Uart Support -Interrupts the current command. +Serial support is no longer supported. See [serial.md](serial.md) for +historical information. -### Get State: 1 -Check to make sure serial communications are functioning. Should return "OK" message. +## Supported Registers -### Get Version: 2 - -Prints the current version of the software e.g. "subg_rfspy 0.8". - -### Get Packet: 3 - -Gets the latest packet of wireless data and displays it on the serial interface. - -Follow command with the desired channel to receive data from and how long to wait to -receive a packet (in milliseconds). - -### Send Packet: 4 - -Sends a packet of data from the serial interface over the wireless connection. - -Follow command with desired channel to send data over, numbers of times to resend data, the -delay between each resend (in milliseconds). - -### Send and Listen: 5 - -Sends a packet of data from the serial interface over the wireless connection and waits -to receive a packet to display over the serial interface. - -Follow command with desired channel to send data over, numbers of times to resend data, the -delay between each resend (in milliseconds), the desired channel to receive data from, the -delay between each receive retry (in milliseconds), and the number of times to retry -receiving. - -### Update Register: 6 - -Use this command to update one of the major registers with a desired value. See section Major -Registers for a list of available registers and their functions. - -Follow command with the register you want to update, and the value you want to update it to. - -### Reset: 7 - -Use this command to reset the device. - -### LED: 8 - -Use this command to manually control the LEDs on the device. - -Follow this command with the LED you want to configure (0 for green, 1 for blue) and the mode -(0 for off, 1 for on, 2 for auto). - -### Read Register: 9 - -Use this command to read the current value of one of the major registers. See Major Registers section -for a list of available registers and their functions. - -## Frequency Channel Selection - -Each channel number corresponds to a different specific frequency. Channels start with 916.5 MHz at -Channel 0 and end with 934.4 MHz at Channel 255, in steps of about 0.07 MHz. You can select different -channels by adjusting the CHANNR.CHAN register. Available channels are governed by the following equation: - - f_carrier = (24MHz/(2^16))*(FREQ + CHAN(256 + CHANSPC_M)*2^(CHANSPC_E - 2)) - -The base frequency, FREQ, is set by the FREQ2, FREQ1, and FREQ0 registers. The value default value is -2502768 (0x263070). -CHANSPC_M and CHANSPC_E are used to set the channel spacing, and are contained in the registers MDMCFG0 -and MDMCFG1 (bits 1:0), respectively. Their default values are 126 (0x7E) and 1. - -## Major Registers - -### SYNC1 (0xDF00) +### SYNC1 (0x00) Sync Word, High Byte. 8 MSB of 16-bit sync word. -### SYNC0 (0xDF01) +### SYNC0 (0x01) Sync Word, Low Byte. 8 LSB of 16-bit sync word. -### PKTLEN (0xDF02) +### PKTLEN (0x02) Packet Length. Indicates the packet length when fixed length packets are enabled. If variable length packets are used, this value indicates the maximum length packets allowed. -### PKTCTRL1 (0xDF03) +### PKTCTRL1 (0x03) Packet Automation Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### PKTCTRL0 (0xDF04) +### PKTCTRL0 (0x04) Packet Automation Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### ADDR (0xDF05) +### ADDR (0x05) Device Address. Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). -### CHANNR (0xDF06) +### CHANNR (0x06) Channel Number. The 8-bit unsigned channel number, which is multiplied by the channel spacing setting and added to the base frequency. -### FSCTRL1 (0xDF07) +### FSCTRL1 (0x07) Frequency Synthesizer Control. -### FSCTRL0 (0xDF08) +### FSCTRL0 (0x08) Frequency Synthesizer Control. Frequency offset added to the base frequency before being used by the FS. -### FREQ2 (0xDF09) +### FREQ2 (0x09) Frequency Control Word, High Byte. -### FREQ1 (0xDF0A) +### FREQ1 (0x0A) Frequency Control Word, Middle Byte. -### FREQ0 (0xDF0B) +### FREQ0 (0x0B) Frequency Control Word, Low Byte. -### MDMCFG4 (0xDF0C) +### MDMCFG4 (0x0C) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MDMCFG3 (0xDF0D) +### MDMCFG3 (0x0D) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MDMCFG2 (0xDF0E) +### MDMCFG2 (0x0E) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MDMCFG1 (0xDF0F) +### MDMCFG1 (0x0F) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MDMCFG0 (0xDF10) +### MDMCFG0 (0x10) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### DEVIATN (0xDF11) +### DEVIATN (0x11) Modem Deviation Setting. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MCSM2 (0xDF12) +### MCSM2 (0x12) -Main Radio Control State Machine Configuration. Different bit ranges have +Main Radio Control State Machine Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MCSM1 (0xDF13) +### MCSM1 (0x13) -Main Radio Control State Machine Configuration. Different bit ranges have +Main Radio Control State Machine Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MCSM0 (0xDF14) +### MCSM0 (0x14) -Main Radio Control State Machine Configuration. Different bit ranges have +Main Radio Control State Machine Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FOCCFG (0xDF15) +### FOCCFG (0x15) -Frequency Offset Compensation Configuration. Different bit ranges have +Frequency Offset Compensation Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### BSCFG (0xDF16) +### BSCFG (0x16) -Bit Synchronization Configuration. Different bit ranges have different +Bit Synchronization Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. - -### AGCCTRL2 (0xDF17) + +### AGCCTRL2 (0x17) AGC Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### AGCCTRL1 (0xDF18) +### AGCCTRL1 (0x18) AGC Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### AGCCTRL0 (0xDF19) +### AGCCTRL0 (0x19) AGC Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FREND1 (0xDF1A) +### FREND1 (0x1A) -Front End RX Configuration. Different bit ranges have different +Front End RX Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FREND0 (0xDF1B) +### FREND0 (0x1B) -Front End RX Configuration. Different bit ranges have different +Front End RX Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FSCAL3 (0xDF1C) +### FSCAL3 (0x1C) -Frequency Synthesizer Calibration. Different bit ranges have +Frequency Synthesizer Calibration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FSCAL2 (0xDF1D) +### FSCAL2 (0x1D) -Frequency Synthesizer Calibration. Different bit ranges have different +Frequency Synthesizer Calibration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FSCAL1 (0xDF1E) +### FSCAL1 (0x1E) -Frequency Synthesizer Calibration. Different bit ranges have different +Frequency Synthesizer Calibration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FSCAL0 (0xDF1F) +### FSCAL0 (0x1F) -Frequency Synthesizer Calibration. Different bit ranges have different +Frequency Synthesizer Calibration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. - -### PA_TABLE1 (0xDF2D) + +### PA_TABLE1 (0x2D) Power amplifier output power setting 1. -### PA_TABLE0 (0xDF2E) +### PA_TABLE0 (0x2E) Power amplifier output power setting 0. - diff --git a/build-all.sh b/build-all.sh deleted file mode 100755 index 791cc94..0000000 --- a/build-all.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -set -x -set -e - -############################################################################ -# Rileylink and similar -############################################################################ -# USA: -make -f Makefile.uart1_alt2 -make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL -make -f Makefile.spi1_alt2 -# Worldwide: -make -f Makefile.uart1_alt2 RADIO_LOCALE=WW -make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW -make -f Makefile.spi1_alt2 RADIO_LOCALE=WW - -############################################################################ -# ERF stick -############################################################################ -# USA: -make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF -make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL -# Worldwide: -make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF RADIO_LOCALE=WW -make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW - -############################################################################ -# TI stick -############################################################################ -# USA: -make -f Makefile.usb_ep0 -make -f Makefile.usb_ep0 CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER -# Worldwide: -make -f Makefile.usb_ep0 RADIO_LOCALE=WW -make -f Makefile.usb_ep0 RADIO_LOCALE=WW CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER - -exit 0 diff --git a/circle.yml b/circle.yml deleted file mode 100644 index cea9b9e..0000000 --- a/circle.yml +++ /dev/null @@ -1,16 +0,0 @@ -test: - override: - - ./build-all.sh - -dependencies: - pre: - - sudo apt-get install -y sdcc - - go get github.com/tcnksm/ghr - -deployment: - release: - branch: master - commands: - - mkdir -p output/`git describe --tags`/ - - mv output/*/*.hex output/`git describe --tags`/ - - cd output ; ghr -t $GITHUB_TOKEN -u $CIRCLE_PROJECT_USERNAME -r $CIRCLE_PROJECT_REPONAME --replace `git describe --tags` `git describe --tags`/ diff --git a/client/README.md b/client/README.md new file mode 100644 index 0000000..83fb166 --- /dev/null +++ b/client/README.md @@ -0,0 +1,14 @@ +# Python client for interacting with subg_rfspy + +http://eblot.github.io/pyftdi/ + +# Install on mac: + +`brew install libusb` +`brew install libftdi` +`pip3 install pyftdi` + +# Hardware + +* An FT232H based board, like the [Shikra](https://int3.cc/products/the-shikra). +* A cc1110 device, like the [RileyLink](https://github.com/ps2/rileylink). If you use a RileyLink, install the [noop firmware](https://github.com/ps2/rileylink/tree/master/firmware/ble113_disabled) on the ble113. diff --git a/client/commands.py b/client/commands.py new file mode 100644 index 0000000..faf6f83 --- /dev/null +++ b/client/commands.py @@ -0,0 +1,157 @@ +from array import array +from struct import * +from enum import Enum + +class ResponseCode(Enum): + PROTOCOL_SYNC = 0x00 + UNKNOWN_COMMAND = 0x22 + RX_TIMEOUT = 0xaa + COMMAND_INTERRUPTED = 0xbb + COMMAND_SUCCESS = 0xdd + +class CommandCode(Enum): + GET_STATE = 1 + GET_VERSION = 2 + GET_PACKET = 3 + SEND_PACKET = 4 + SEND_AND_LISTEN = 5 + UPDATE_REGISTER = 6 + RESET = 7 + LED = 8 + READ_REGISTER = 9 + SET_MODE_REGISTERS = 10 + SET_SW_ENCODING = 11 + SET_PREAMBLE = 12 + RADIO_RESET_CONFIG = 13 + +class ByteResponse: + def __init__(self, response_data): + self.response_code = ResponseCode(response_data[0]) + self.response_data = bytearray(response_data[1:]) + + def __repr__(self): + return "ByteResponse(%s, %s)" % (self.response_code, self.response_data.hex()) + + +class StringResponse: + def __init__(self, response_data): + self.response_code = ResponseCode(response_data[0]) + self.response_data = array('B', response_data[1:]) + + def __repr__(self): + return "StringResponse(\"%s\")" % self.response_data.tostring().decode("UTF-8") + +class PacketResponse: + def __init__(self, response_data): + self.response_code = ResponseCode(response_data[0]) + if self.response_code == ResponseCode.COMMAND_SUCCESS: + self.rssi_dec = response_data[1] + self.packet_num = response_data[2] + self.response_data = array('B', response_data[3:]) + + def __repr__(self): + if self.response_code != ResponseCode.COMMAND_SUCCESS: + return "ResponseCode(%s)" % self.response_code + else: + hex = "".join(["%02x" % x for x in self.response_data]) + return "PacketResponse(\"%s\")" % hex + +class GetStateCommand: + def data(self): + return array('B', [CommandCode.GET_STATE.value]) + + def response_type(self): + return StringResponse + +class GetVersionCommand: + def data(self): + return array('B', [2]) + + def response_type(self): + return StringResponse + +class GetPacketCommand: + def __init__(self, timeout_ms=100, channel=0): + self.channel = channel + self.timeout_ms = timeout_ms + + def data(self): + data = pack('>BBL', CommandCode.GET_PACKET.value, self.channel, self.timeout_ms) + return array('B', data) + + def response_type(self): + return PacketResponse + +class SendPacketCommand: + def __init__(self, packet_data, repeat_count=0, delay_ms=5, preamble_extend_ms=0, channel=0): + self.channel = channel + self.repeat_count = repeat_count + self.delay_ms = delay_ms + self.preamble_extend_ms = preamble_extend_ms + self.packet_data = packet_data + + def data(self): + conf = pack('>BBBHH', CommandCode.SEND_PACKET.value, self.channel, self.repeat_count, self.delay_ms, self.preamble_extend_ms) + print("Send packet cmd: %s" % conf.hex()) + return array('B', conf) + self.packet_data + + def response_type(self): + return ByteResponse + +class Register(Enum): + SYNC1 = 0x00 + SYNC0 = 0x01 + PKTLEN = 0x02 + PKTCTRL1 = 0x03 + PKTCTRL0 = 0x04 + FSCTRL1 = 0x07 + FREQ2 = 0x09 + FREQ1 = 0x0a + FREQ0 = 0x0b + MDMCFG4 = 0x0c + MDMCFG3 = 0x0d + MDMCFG2 = 0x0e + MDMCFG1 = 0x0f + MDMCFG0 = 0x10 + DEVIATN = 0x11 + MCSM0 = 0x14 + FOCCFG = 0x15 + AGCCTRL2 = 0x17 + AGCCTRL1 = 0x18 + AGCCTRL0 = 0x19 + FREND1 = 0x1a + FREND0 = 0x1b + FSCAL3 = 0x1c + FSCAL2 = 0x1d + FSCAL1 = 0x1e + FSCAL0 = 0x1f + TEST1 = 0x24 + TEST0 = 0x25 + PATABLE0 = 0x2e + +class UpdateRegisterCommand: + def __init__(self, register, value): + self.register = register + self.value = value + + def data(self): + return array('B', [CommandCode.UPDATE_REGISTER.value, self.register.value, self.value]) + + def response_type(self): + return ByteResponse + + +class Encoding(Enum): + NONE = 0 + MANCHESTER = 1 + FOURBSIXB = 2 + +class SetSoftwareEncoding: + def __init__(self, encoding): + self.encoding = encoding + + def data(self): + return array('B', [CommandCode.SET_SW_ENCODING.value, self.encoding.value]) + + def response_type(self): + return ByteResponse diff --git a/client/listen.py b/client/listen.py new file mode 100644 index 0000000..a91e40e --- /dev/null +++ b/client/listen.py @@ -0,0 +1,14 @@ +from pyftdi.spi import SpiController +from spilink import SPILink +from commands import * +from array import array +import time + +link = SPILink(debug=True) +link.flush() + +print(link.do_command(SetSoftwareEncoding(Encoding.FOURBSIXB))) + +while True: + print(link.do_command(GetPacketCommand(timeout_ms=50000), timeout=51)) + time.sleep(0.1) diff --git a/client/listen_omni.py b/client/listen_omni.py new file mode 100644 index 0000000..f6fc746 --- /dev/null +++ b/client/listen_omni.py @@ -0,0 +1,16 @@ +from spilink import SPILink +from commands import * +from array import array +import omni + +link = SPILink(debug=True) +link.flush() + +omni.configure(link) + +# packet_data = [1,2,3,4,5,6,7,8,9] +# send_cmd = SendPacketCommand(array('B', packet_data), repeat_count=2, preamble_extend_ms=0) +# print(link.do_command(send_cmd, timeout=5)) + +while True: + print(link.do_command(GetPacketCommand(timeout_ms=50000), timeout=51)) diff --git a/client/omni.py b/client/omni.py new file mode 100644 index 0000000..449284e --- /dev/null +++ b/client/omni.py @@ -0,0 +1,26 @@ +from commands import * + +def configure(link): + link.do_command(SetSoftwareEncoding(Encoding.MANCHESTER)) + link.set_base_frequency(433910000) + link.update_register(Register.PKTCTRL1, 0x20) + link.update_register(Register.PKTCTRL0, 0x00) + link.update_register(Register.FSCTRL1, 0x06) + link.update_register(Register.PKTCTRL1, 0x20) + link.update_register(Register.MDMCFG4, 0xCA) + link.update_register(Register.MDMCFG3, 0xBC) + link.update_register(Register.MDMCFG2, 0x06) + link.update_register(Register.MDMCFG1, 0x10) + link.update_register(Register.MDMCFG0, 0x11) + link.update_register(Register.DEVIATN, 0x47) + link.update_register(Register.MCSM0, 0x18) + link.update_register(Register.FOCCFG, 0x17) + link.update_register(Register.FSCAL3, 0xE9) + link.update_register(Register.FSCAL2, 0x2A) + link.update_register(Register.FSCAL1, 0x00) + link.update_register(Register.FSCAL0, 0x1F) + link.update_register(Register.TEST1, 0x31) + link.update_register(Register.TEST0, 0x09) + link.update_register(Register.PATABLE0, 0x84) + link.update_register(Register.SYNC1, 0xA5) + link.update_register(Register.SYNC0, 0x5A) diff --git a/client/send_omni.py b/client/send_omni.py new file mode 100644 index 0000000..63650a1 --- /dev/null +++ b/client/send_omni.py @@ -0,0 +1,12 @@ +from spilink import SPILink +from commands import * +import omni + +link = SPILink(debug=True) +link.flush() + +omni.configure(link) + +packet_data = bytearray.fromhex("000000005800000000fbf9f8fbe0ff1179fed102") +send_cmd = SendPacketCommand(array('B', packet_data), repeat_count=2, preamble_extend_ms=0) +print(link.do_command(send_cmd, timeout=5)) diff --git a/client/spilink.py b/client/spilink.py new file mode 100644 index 0000000..0c2db1e --- /dev/null +++ b/client/spilink.py @@ -0,0 +1,106 @@ +from pyftdi.spi import SpiController +import time +from commands import * + +RILEYLINK_XTAL_FREQUENCY = 24000000 + +class SPITimeout(Exception): + pass + +class SPILink: + BIT_REV = [int('{:08b}'.format(n)[::-1], 2) for n in range(0,256)] + + def __init__(self, device='ftdi://ftdi:232h/1', debug=False): + self.device_str = device + self.debug = debug + self.ctrl = SpiController(silent_clock=False) + self.ctrl.configure(device, cs_count=1) + self.spi = self.ctrl.get_port(cs=0, freq=100000) + self.gpio = self.ctrl.get_gpio() + direction = self.gpio.direction + self.gpio.set_direction(0x30, 0x10) # Add reset as output + self.gpio.write(0x10) + + def reset(self): + self.gpio.write(0x00) # Pull reset line low + time.sleep(0.1) + self.gpio.write(0x10) # Reset line high + time.sleep(0.8) # Wait for cc111x to boot + + def flush(self): + # Send interrupt command + _, available = self.exchange([0x99, 1], readlen=2) + data = self.exchange([], readlen=max(1,available)) + # Discard any remaining data + _, available = self.exchange([0x99, 0], readlen=2) + while (available > 0): + data = self.exchange([], readlen=available) + if self.debug: + print("discarding %s" % "".join(["%02x" % x for x in data])) + _, available = self.exchange([0x99, 0], readlen=2) + + def reverse_bits(self, data): + return [SPILink.BIT_REV[x] for x in data] + + def as_hex(self, data): + return "".join(["%02x" % x for x in data]) + + def exchange(self, data, readlen=0): + lsb_send = self.reverse_bits(data) + lsb_rcv = self.spi.exchange(lsb_send,readlen=readlen, duplex=True) + return self.reverse_bits(lsb_rcv) + + def send_command(self, command): + data = command.data() + if len(data) == 0: + print("Empty command!") + return + + if self.debug: + print("send: %s" % self.as_hex(data)) + response = None + _, available = self.exchange([0x99, len(data)], readlen=2) + if available > 0: + print("Unexpected data available from client while sending command.") + return + self.exchange(data, readlen=0) + + def wait_for_response(self, response_type, timeout=1): + end_time = time.time() + timeout + response = None + while(time.time() < end_time and response == None): + _, available = self.exchange([0x99, 0], readlen=2) + if (available > 0): + if self.debug: + print("response: available = %d" % available) + rdata = self.exchange([], readlen=available) + else: + time.sleep(0.01) + if available > 0: + response = rdata + data = [] + + if response == None: + raise SPITimeout() + if self.debug: + print("recv: %s" % self.as_hex(response)) + response_obj = response_type(response) + return response_obj + + def do_command(self, command, timeout=1): + self.send_command(command) + response = self.wait_for_response(command.response_type(), timeout) + if response.response_code != ResponseCode.COMMAND_INTERRUPTED: + return response + else: + print("Command interrupted...") + return self.wait_for_response(command.response_type(), timeout) + + def update_register(self, register, value): + return self.do_command(UpdateRegisterCommand(register, value)) + + def set_base_frequency(self, freq): + val = int(freq / (RILEYLINK_XTAL_FREQUENCY / pow(2,16))) + self.update_register(Register.FREQ0, val & 0xff) + self.update_register(Register.FREQ1, (val >> 8) & 0xff) + self.update_register(Register.FREQ2, (val >> 16) & 0xff) diff --git a/client/test.py b/client/test.py new file mode 100644 index 0000000..7798d0b --- /dev/null +++ b/client/test.py @@ -0,0 +1,26 @@ +from pyftdi.spi import SpiController +from spilink import SPILink +from commands import * +from array import array +import time + +link = SPILink(debug=True) +link.reset() # This doesn't work when cc-debugger is connected +#link.flush() + +print("GetState:", link.do_command(GetStateCommand())) +print("GetVersion:", link.do_command(GetVersionCommand())) + +print("SetSoftwareEncoding:", link.do_command(SetSoftwareEncoding(Encoding.FOURBSIXB))) + +#packet_data = bytes.fromhex("a965a5d1a8da65a5665715555555555555") +packet_data = [1,2,3,4,5,6,7,8,9] +send_cmd = SendPacketCommand(array('B', packet_data), repeat_count=2, preamble_extend_ms=1) +print("SendPacket:", link.do_command(send_cmd, timeout=5)) + + +# Issue a longer listening command, and interrupt it +link.send_command(GetPacketCommand(timeout_ms=50000)) +time.sleep(0.1) +print("SetSoftwareEncoding:", link.do_command(SetSoftwareEncoding(Encoding.FOURBSIXB))) +print("GetVersionCommand:", link.do_command(GetVersionCommand())) diff --git a/commands.c b/commands.c index 9f8abb6..388b490 100644 --- a/commands.c +++ b/commands.c @@ -1,26 +1,83 @@ #include +#include #include "hardware.h" #include "serial.h" #include "radio.h" #include "commands.h" +#include "encoding.h" +#include "version.h" +#include "statistics.h" +#include "timer.h" uint8_t interrupting_cmd = 0; +// If use_pktlen is 0, then a sentinal value of 0 determines end of packet. +// If use_pktlen is non-zero, then rx will stop at PKTLEN +uint8_t use_pktlen = 0; + typedef void (*CommandHandler)(); -CommandHandler handlers[] = { - /* 0 */ 0, - /* 1 */ cmd_get_state, - /* 2 */ cmd_get_version, - /* 3 */ cmd_get_packet, - /* 4 */ cmd_send_packet, - /* 5 */ cmd_send_and_listen, - /* 6 */ cmd_update_register, - /* 7 */ cmd_reset, - /* 8 */ cmd_led, - /* 9 */ cmd_read_register -}; +void do_cmd(uint8_t cmd); + +void get_command() { + uint8_t cmd; + cmd = serial_rx_byte(); + do_cmd(cmd); + if (interrupting_cmd) { + do_cmd(interrupting_cmd); + interrupting_cmd = 0; + } +} + +void cmd_set_sw_encoding() { + EncodingType encoding_type; + + encoding_type = serial_rx_byte(); + if (set_encoding_type(encoding_type)) { + serial_tx_byte(RESPONSE_CODE_SUCCESS); + } else { + serial_tx_byte(RESPONSE_CODE_PARAM_ERROR); // Error: encoding type not supported + } + serial_flush(); +} + +void cmd_set_mode_registers() { + uint8_t register_mode; + uint8_t count; + uint8_t addr; + uint8_t value; + int i; + mode_registers *registers; + + register_mode = serial_rx_byte(); + count = serial_rx_avail() / 2; + + switch(register_mode) { + case RegisterModeTx: + registers = &tx_registers; + break; + case RegisterModeRx: + registers = &rx_registers; + break; + default: + registers = 0x0; + break; + } + + if (registers != NULL) { + mode_registers_clear(registers); + } + for (i=0; i 0 && cmd < sizeof(handlers)/sizeof(handlers[0])) { - handlers[cmd](); - } -} - -void get_command() { - uint8_t cmd; - cmd = serial_rx_byte(); - do_cmd(cmd); - if (interrupting_cmd) { - do_cmd(interrupting_cmd); - interrupting_cmd = 0; - } + serial_tx_byte(RESPONSE_CODE_SUCCESS); + serial_tx_str(SUBG_RFSPY_VERSION); } void cmd_send_packet() { uint8_t channel; uint8_t repeat_count; - uint8_t delay_ms; + uint16_t delay_ms; + uint16_t preamble_extend_ms; + uint8_t len; channel = serial_rx_byte(); repeat_count = serial_rx_byte(); - delay_ms = serial_rx_byte(); - send_packet_from_serial(channel, repeat_count, delay_ms); - serial_tx_byte(0); + delay_ms = serial_rx_word(); + preamble_extend_ms = serial_rx_word(); + len = serial_rx_avail(); + send_packet_from_serial(channel, repeat_count, delay_ms, preamble_extend_ms, len); + serial_tx_byte(RESPONSE_CODE_SUCCESS); + serial_flush(); } /* Combined send and receive */ void cmd_send_and_listen() { uint8_t send_channel; uint8_t repeat_count; - uint8_t delay_ms; + uint16_t delay_ms; uint8_t listen_channel; uint32_t timeout_ms; uint8_t retry_count; + uint16_t preamble_extend_ms; uint8_t result; + uint8_t len; send_channel = serial_rx_byte(); repeat_count = serial_rx_byte(); - delay_ms = serial_rx_byte(); + delay_ms = serial_rx_word(); listen_channel = serial_rx_byte(); timeout_ms = serial_rx_long(); retry_count = serial_rx_byte(); + preamble_extend_ms = serial_rx_word(); + len = serial_rx_avail(); - send_packet_from_serial(send_channel, repeat_count, delay_ms); - result = get_packet_and_write_to_serial(listen_channel, timeout_ms); + send_packet_from_serial(send_channel, repeat_count, delay_ms, preamble_extend_ms, len); + result = get_packet_and_write_to_serial(listen_channel, timeout_ms, use_pktlen); - while (result == ERROR_RX_TIMEOUT && retry_count > 0) { - resend_from_tx_buf(send_channel); - result = get_packet_and_write_to_serial(listen_channel, timeout_ms); + while (result == RESPONSE_CODE_RX_TIMEOUT && retry_count > 0) { + send_from_tx_buf(send_channel, preamble_extend_ms); + result = get_packet_and_write_to_serial(listen_channel, timeout_ms, use_pktlen); retry_count--; } if (result != 0) { // Error, and no retries left serial_tx_byte(result); - serial_tx_byte(0); } + serial_flush(); } void cmd_read_register() { uint8_t addr; uint8_t value; addr = serial_rx_byte(); - switch(addr) { - case 0x00: - value = SYNC1; - break; - case 0x01: - value = SYNC0; - break; - case 0x02: - value = PKTLEN; - break; - case 0x03: - value = PKTCTRL1; - break; - case 0x04: - value = PKTCTRL0; - break; - case 0x05: - value = ADDR; - break; - case 0x06: - value = CHANNR; - break; - case 0x07: - value = FSCTRL1; - break; - case 0x08: - value = FSCTRL0; - break; - case 0x09: - value = FREQ2; - break; - case 0x0A: - value = FREQ1; - break; - case 0x0B: - value = FREQ0; - break; - case 0x0C: - value = MDMCFG4; - break; - case 0x0D: - value = MDMCFG3; - break; - case 0x0E: - value = MDMCFG2; - break; - case 0x0F: - value = MDMCFG1; - break; - case 0x10: - value = MDMCFG0; - break; - case 0x11: - value = DEVIATN; - break; - case 0x12: - value = MCSM2; - break; - case 0x13: - value = MCSM1; - break; - case 0x14: - value = MCSM0; - break; - case 0x15: - value = FOCCFG; - break; - case 0x16: - value = BSCFG; - break; - case 0x17: - value = AGCCTRL2; - break; - case 0x18: - value = AGCCTRL1; - break; - case 0x19: - value = AGCCTRL0; - break; - case 0x1A: - value = FREND1; - break; - case 0x1B: - value = FREND0; - break; - case 0x1C: - value = FSCAL3; - break; - case 0x1D: - value = FSCAL2; - break; - case 0x1E: - value = FSCAL1; - break; - case 0x1F: - value = FSCAL0; - break; - case 0x20: - value = PA_TABLE1; - break; - case 0x21: - value = PA_TABLE0; - break; - default: - value = 0x5A; - } + value = get_register(addr); + serial_tx_byte(RESPONSE_CODE_SUCCESS); serial_tx_byte(value); - serial_tx_byte(0); + serial_flush(); } void cmd_update_register() { @@ -223,115 +171,15 @@ void cmd_update_register() { uint8_t rval; addr = serial_rx_byte(); value = serial_rx_byte(); - rval = 1; - switch(addr) { - case 0x00: - SYNC1 = value; - break; - case 0x01: - SYNC0 = value; - break; - case 0x02: - PKTLEN = value; - break; - case 0x03: - PKTCTRL1 = value; - break; - case 0x04: - PKTCTRL0 = value; - break; - case 0x05: - ADDR = value; - break; - case 0x06: - CHANNR = value; - break; - case 0x07: - FSCTRL1 = value; - break; - case 0x08: - FSCTRL0 = value; - break; - case 0x09: - FREQ2 = value; - break; - case 0x0A: - FREQ1 = value; - break; - case 0x0B: - FREQ0 = value; - break; - case 0x0C: - MDMCFG4 = value; - break; - case 0x0D: - MDMCFG3 = value; - break; - case 0x0E: - MDMCFG2 = value; - break; - case 0x0F: - MDMCFG1 = value; - break; - case 0x10: - MDMCFG0 = value; - break; - case 0x11: - DEVIATN = value; - break; - case 0x12: - MCSM2 = value; - break; - case 0x13: - MCSM1 = value; - break; - case 0x14: - MCSM0 = value; - break; - case 0x15: - FOCCFG = value; - break; - case 0x16: - BSCFG = value; - break; - case 0x17: - AGCCTRL2 = value; - break; - case 0x18: - AGCCTRL1= value; - break; - case 0x19: - AGCCTRL0 = value; - break; - case 0x1A: - FREND1 = value; - break; - case 0x1B: - FREND0 = value; - break; - case 0x1C: - FSCAL3 = value; - break; - case 0x1D: - FSCAL2 = value; - break; - case 0x1E: - FSCAL1 = value; - break; - case 0x1F: - FSCAL0 = value; - break; - case 0x20: - PA_TABLE1 = value; - break; - case 0x21: - PA_TABLE0 = value; - break; - default: - rval = 2; + rval = set_register(addr, value); + + // If pktlen is modified, then we set use_pktlen + if (addr == 0x02) { + use_pktlen = 1; } + serial_tx_byte(rval); - serial_tx_byte(0); + serial_flush(); } void cmd_reset() { @@ -343,6 +191,73 @@ void cmd_led() { uint8_t led; uint8_t mode; led = serial_rx_byte(); - mode = serial_rx_byte(); + mode = serial_rx_byte(); led_set_mode(led, mode);//0, 1, 2 = Off, On, Auto + serial_tx_byte(RESPONSE_CODE_SUCCESS); + serial_flush(); +} + +void cmd_set_preamble() { + uint16_t preamble_word; + preamble_word = serial_rx_word(); + radio_set_preamble(preamble_word); + serial_tx_byte(RESPONSE_CODE_SUCCESS); + serial_flush(); +} + +void cmd_reset_radio_config() { + configure_radio(); + set_encoding_type(EncodingTypeNone); + radio_set_preamble(0); + serial_tx_byte(RESPONSE_CODE_SUCCESS); + serial_flush(); +} + +void cmd_get_statistics() +{ + uint32_t uptime_ms; + + serial_tx_byte(RESPONSE_CODE_SUCCESS); + read_timer(&uptime_ms); + serial_tx_long(uptime_ms); + serial_tx_word(radio_rx_overflow_count); + serial_tx_word(radio_rx_fifo_overflow_count); + serial_tx_word(packet_rx_count); + serial_tx_word(packet_tx_count); + serial_tx_word(crc_failure_count); + serial_tx_word(spi_sync_failure_count); + serial_tx_word(0); // Placeholder + serial_tx_word(0); // Placeholder + serial_flush(); +} + + +CommandHandler __xdata handlers[] = { + /* 0 */ 0, + /* 1 */ cmd_get_state, + /* 2 */ cmd_get_version, + /* 3 */ cmd_get_packet, + /* 4 */ cmd_send_packet, + /* 5 */ cmd_send_and_listen, + /* 6 */ cmd_update_register, + /* 7 */ cmd_reset, + /* 8 */ cmd_led, + /* 9 */ cmd_read_register, + /* 10 */ cmd_set_mode_registers, + /* 11 */ cmd_set_sw_encoding, + /* 12 */ cmd_set_preamble, + /* 13 */ cmd_reset_radio_config, + /* 14 */ cmd_get_statistics +}; + +void do_cmd(uint8_t cmd) { + if (cmd > 0 && cmd < sizeof(handlers)/sizeof(handlers[0])) { + handlers[cmd](); + } else { + while(serial_rx_avail() > 0) { + serial_rx_byte(); + } + serial_tx_byte(RESPONSE_CODE_UNKNOWN_COMMAND); + serial_flush(); + } } diff --git a/commands.h b/commands.h index 27bf649..26bd27a 100644 --- a/commands.h +++ b/commands.h @@ -1,14 +1,39 @@ #ifndef COMMANDS_H #define COMMANDS_H -#define ERROR_RX_TIMEOUT 0xaa -#define ERROR_CMD_INTERRUPTED 0xbb -#define ERROR_ZERO_DATA 0xcc +#define RESPONSE_CODE_RX_TIMEOUT 0xaa +#define RESPONSE_CODE_CMD_INTERRUPTED 0xbb +#define RESPONSE_CODE_SUCCESS 0xdd +#define RESPONSE_CODE_PARAM_ERROR 0x11 +#define RESPONSE_CODE_UNKNOWN_COMMAND 0x22 + +enum CommandCode { + CmdGetState = 0x01, + CmdGetVersion = 0x02, + CmdGetPacket = 0x03, + CmdSendPacket = 0x04, + CmdSendAndListen = 0x05, + CmdUpdateRegister = 0x06, + CmdReset = 0x07, + CmdLED = 0x08, + CmdReadRegister = 0x09, + CmdSetModeRegisters = 0x0a, + CmdSetSWEncoding = 0x0b, + CmdSetPreamble = 0x0c, + CmdResetRadioConfig = 0x0d, + CmdGetStatistics = 0x0e +}; + +enum RegisterMode { + RegisterModeTx = 0x01, + RegisterModeRx = 0x02 + /* maybe idle in future? */ +}; void get_command(); // This is set when a command is received while processing a long running // command, like get_packet -extern uint8_t interrupting_cmd; +extern uint8_t interrupting_cmd; #endif diff --git a/common.mk b/common.mk index 4f6ec33..73624ea 100755 --- a/common.mk +++ b/common.mk @@ -10,15 +10,19 @@ CODE_LOC_NAME := STDLOC TARGET_BUILD := ${SERIAL_TYPE}_${BOARD_TYPE}_${RADIO_LOCALE}_${CODE_LOC_NAME} -CC=sdcc +CC ?= sdcc -LDFLAGS=--xram-loc 0xf000 --xram-size 0x1000 --code-loc ${CODE_LOC} -CFLAGS=-I. -I${SERIAL_TYPE} --verbose ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} ${SERIAL_PARAMS} +ifeq ($(CC),sdcc) + LDFLAGS+=--xram-loc 0xf000 --model-medium --xram-size 0x1000 --code-loc ${CODE_LOC} --code-size 0x8000 + CFLAGS+=--model-medium --verbose +endif + +CFLAGS+=-I. -I${SERIAL_TYPE} ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} ${SERIAL_PARAMS} default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex -common_modules = radio.rel main.rel timer.rel \ - commands.rel delay.rel hardware.rel +common_modules = $(main_module) subg_rfspy.rel radio.rel timer.rel encoding.rel manchester.rel \ + fourbsixb.rel commands.rel hardware.rel packet_buffer.rel statistics.rel clean: rm -rf output/${TARGET_BUILD} @@ -32,15 +36,12 @@ serial.rel: ${SERIAL_TYPE}/serial.c # ${REL} $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< $(REL) -output/${TARGET_BUILD}/${TARGET_BUILD}.hex: $(common_modules) $(REL) serial.rel - cd output/${TARGET_BUILD} && $(CC) $(LDFLAGS) $(CFLAGS) $(common_modules) $(REL) serial.rel -o ${TARGET_BUILD}.hex +output/${TARGET_BUILD}/${TARGET_BUILD}.hex: $(common_modules) $(extra_modules) $(REL) serial.rel + cd output/${TARGET_BUILD} && $(CC) $(LDFLAGS) $(CFLAGS) $(common_modules) $(extra_modules) $(REL) serial.rel -o ${TARGET_BUILD}.hex install: output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex sudo cc-tool -n ${TARGET_DEVICE} --log install.log -ew output/${TARGET_BUILD}/${TARGET_BUILD}.hex -test: main.c output - gcc -g -o output/${TARGET_BUILD}/test -DNON_NATIVE_TEST main.c - output: mkdir output diff --git a/delay.c b/delay.c deleted file mode 100644 index 2dcb956..0000000 --- a/delay.c +++ /dev/null @@ -1,21 +0,0 @@ - -#include -#include "hardware.h" - -// This factor is based on the particular instructions that -// sdcc generates for the loops -#define CYCLES_PER_LOOP 18 - -void delay(uint8_t msec) -{ - volatile uint8_t mhz_ctr; - volatile uint8_t adj_ctr; - while(msec--){ - adj_ctr = 1000 /* usec to msec */ / CYCLES_PER_LOOP; - while(adj_ctr--){ - mhz_ctr = SYSTEM_CLOCK_MHZ; - while(mhz_ctr--); - } - } -} - diff --git a/delay.h b/delay.h deleted file mode 100644 index 358b636..0000000 --- a/delay.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DELAY_H -#define DELAY_H - -void delay(uint8_t msec); - -#endif diff --git a/encoding.c b/encoding.c new file mode 100644 index 0000000..ab84c68 --- /dev/null +++ b/encoding.c @@ -0,0 +1,89 @@ + +#include "encoding.h" +#include "manchester.h" +#include "fourbsixb.h" + +// Passthrough encoder +static void passthrough_init_encoder(EncoderState *state) { + state->passthrough.count = 0; +} + +static void passthrough_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { + state->passthrough.count = 1; + state->passthrough.data = raw; +} + +static uint8_t passthrough_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant { + if (state->passthrough.count < 1) { + return 0; + } + *encoded = state->passthrough.data; + state->passthrough.count--; + return 1; +} + +// passthrough decoder funcs +static void passthrough_init_decoder(DecoderState *state) { + state->passthrough.count = 0; +} + +static uint8_t passthrough_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant { + state->passthrough.data = encoded; + state->passthrough.count = 1; + if (encoded == 0) { + return 1; + } + return 0; +} + +static uint8_t passthrough_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant { + if (state->passthrough.count < 1) { + return 0; + } + *decoded = state->passthrough.data; + state->passthrough.count = 0; + return 1; +} + + +// Init Encoder +void init_encoder(EncodingType encoding_type, Encoder *encoder, EncoderState *state) { + switch (encoding_type) { + case EncodingTypeNone: + encoder->add_raw_byte = passthrough_add_raw_byte; + encoder->next_encoded_byte = passthrough_next_encoded_byte; + passthrough_init_encoder(state); + break; + case EncodingTypeManchester: + encoder->add_raw_byte = manchester_add_raw_byte; + encoder->next_encoded_byte = manchester_next_encoded_byte; + manchester_init_encoder(state); + break; + case EncodingTypeFourbSixb: + encoder->add_raw_byte = fourbsixb_add_raw_byte; + encoder->next_encoded_byte = fourbsixb_next_encoded_byte; + fourbsixb_init_encoder(state); + break; + } +} + +// Init Decoder +void init_decoder(EncodingType encoding_type, Decoder *decoder, DecoderState *state) { + switch (encoding_type) { + case EncodingTypeNone: + decoder->add_encoded_byte = passthrough_add_encoded_byte; + decoder->next_decoded_byte = passthrough_next_decoded_byte; + passthrough_init_decoder(state); + break; + case EncodingTypeManchester: + decoder->add_encoded_byte = manchester_add_encoded_byte; + decoder->next_decoded_byte = manchester_next_decoded_byte; + manchester_init_decoder(state); + break; + case EncodingTypeFourbSixb: + decoder->add_encoded_byte = fourbsixb_add_encoded_byte; + decoder->next_decoded_byte = fourbsixb_next_decoded_byte; + fourbsixb_init_decoder(state); + break; + } +} diff --git a/encoding.h b/encoding.h new file mode 100644 index 0000000..490b1e3 --- /dev/null +++ b/encoding.h @@ -0,0 +1,60 @@ +#ifndef ENCODING_H +#define ENCODING_H + +#include +#include +#include "hardware.h" +#include "manchester_state.h" +#include "fourbsixb_state.h" + +typedef enum { + EncodingTypeNone = 0x0, + EncodingTypeManchester = 0x1, + EncodingTypeFourbSixb = 0x02, + MaxEncodingTypeValue = EncodingTypeFourbSixb +} EncodingType; + +typedef struct { + union { + struct { + uint8_t data; + uint8_t count; + } passthrough; + struct ManchesterEncoderState manchester; + struct FourbSixbEncoderState fourbsixb; + }; +} EncoderState; + +typedef struct { + union { + struct { + uint8_t data; + uint8_t count; + } passthrough; + struct ManchesterDecoderState manchester; + struct FourbSixbDecoderState fourbsixb; + }; +} DecoderState; + +typedef struct { + // Adds a byte to be encoded + void (*add_raw_byte)(EncoderState *state, uint8_t raw) __reentrant; + // encoded will be set to next available encoded byte. + // If flush is true, then encoder should return any partial bytes + // Return value is 0 if no more bytes are available. + uint8_t (*next_encoded_byte)(EncoderState *state, uint8_t *encoded, bool flush) __reentrant; +} Encoder; + +typedef struct { + // Adds a byte for decoding. The return value will be 1 if the byte + // contains encoding errors, otherwise it will be 0. + uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t encoded) __reentrant; + // decoded will be set to the next available decoded byte. + // Return value is 0 if no more bytes are available. + uint8_t (*next_decoded_byte)(DecoderState *state, uint8_t *decoded) __reentrant; +} Decoder; + +void init_encoder(EncodingType encoding_type, Encoder *encoder, EncoderState *state); +void init_decoder(EncodingType encoding_type, Decoder *decoder, DecoderState *state); + +#endif // ENCODING_H diff --git a/fifo.h b/fifo.h new file mode 100644 index 0000000..f7e4762 --- /dev/null +++ b/fifo.h @@ -0,0 +1,75 @@ + +/* fifo queue for use with interrupt routines. Size must be power of 2 */ + +#ifndef FIFO_H +#define FIFO_H + +#include +#include +#include "hardware.h" + +#ifdef __GNUC__ +#define inline static inline +#endif + +struct fifo_buffer_t { + volatile uint8_t head; /* first byte of data */ + volatile uint8_t tail; /* last byte of data */ + volatile uint8_t *buffer; /* block of memory or array of data */ + uint8_t buffer_len; /* length of the data */ +}; +typedef struct fifo_buffer_t fifo_buffer; + +inline uint8_t fifo_count(fifo_buffer const *b) { + return (b ? (b->head - b->tail) : 0); +} + +inline bool fifo_empty(fifo_buffer const *b) { + return (b ? (fifo_count(b) == 0) : true); +} + +inline uint8_t fifo_get(fifo_buffer * b) { + uint8_t data_byte = 0; + + if (!fifo_empty(b)) { + data_byte = b->buffer[b->tail % b->buffer_len]; + b->tail++; + } + return data_byte; +} + +inline bool fifo_full(fifo_buffer const *b) { + return (b ? (fifo_count(b) == b->buffer_len) : true); +} + +inline uint8_t fifo_peek(fifo_buffer const *b) { + if (b) { + return (b->buffer[b->tail % b->buffer_len]); + } + return 0; +} + +inline bool fifo_put(fifo_buffer * b, uint8_t data_byte) { + bool status = false; /* return value */ + + if (b) { + /* limit the ring to prevent overwriting */ + if (!fifo_full(b)) { + b->buffer[b->head % b->buffer_len] = data_byte; + b->head++; + status = true; + } + } + return status; +} + +inline void fifo_init(fifo_buffer * b, volatile uint8_t *buffer, uint8_t size) { + if (b) { + b->head = 0; + b->tail = 0; + b->buffer = buffer; + b->buffer_len = size; + } +} + +#endif // FIFO_H diff --git a/fourbsixb.c b/fourbsixb.c new file mode 100644 index 0000000..30eb5e8 --- /dev/null +++ b/fourbsixb.c @@ -0,0 +1,71 @@ + +#include "fourbsixb.h" + +//fileprivate let codesRev:Dictionary = [21: 0, 49: 1, 50: 2, 35: 3, 52: 4, 37: 5, 38: 6, 22: 7, 26: 8, 25: 9, 42: 10, 11: 11, 44: 12, 13: 13, 14: 14, 28: 15] + +static uint8_t __xdata codes[] = {21,49,50,35,52,37,38,22,26,25,42,11,44,13,14,28}; + +void fourbsixb_init_encoder(EncoderState *state) { + state->fourbsixb.acc = 0; + state->fourbsixb.bits_avail = 0; +} + +void fourbsixb_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { + uint16_t new_bits = (codes[raw >> 4] << 6) | codes[raw & 0xf]; + state->fourbsixb.acc = (state->fourbsixb.acc << 12) | new_bits; + state->fourbsixb.bits_avail += 12; +} + +uint8_t fourbsixb_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant { + if (state->fourbsixb.bits_avail < 8 && !flush) { + return 0; + } + if (state->fourbsixb.bits_avail == 0) { + return 0; + } + if (flush && state->fourbsixb.bits_avail < 8) { + *encoded = state->fourbsixb.acc << (8-state->fourbsixb.bits_avail); + state->fourbsixb.bits_avail = 0; + } else { + *encoded = state->fourbsixb.acc >> (state->fourbsixb.bits_avail-8); + state->fourbsixb.bits_avail -= 8; + } + return 1; +} + +void fourbsixb_init_decoder(DecoderState *state) { + state->fourbsixb.input_acc = 0; + state->fourbsixb.input_bits_avail = 0; + state->fourbsixb.output_acc = 0; + state->fourbsixb.output_bits_avail = 0; +} + +uint8_t fourbsixb_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant { + uint8_t code, i; + state->fourbsixb.input_acc = (state->fourbsixb.input_acc << 8) | encoded; + state->fourbsixb.input_bits_avail += 8; + while (state->fourbsixb.input_bits_avail >= 6) { + code = (state->fourbsixb.input_acc >> (state->fourbsixb.input_bits_avail - 6)) & 0b111111; + state->fourbsixb.input_bits_avail -= 6; + for (i=0; i<16; i++) { + if (codes[i] == code) { + break; + } + } + if (i == 16) { + return 1; // Encoding error + } + state->fourbsixb.output_acc = (state->fourbsixb.output_acc << 4) | i; + state->fourbsixb.output_bits_avail += 4; + } + return 0; +} + +uint8_t fourbsixb_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant { + if (state->fourbsixb.output_bits_avail < 8) { + return 0; + } + *decoded = state->fourbsixb.output_acc >> (state->fourbsixb.output_bits_avail - 8); + state->fourbsixb.output_bits_avail -= 8; + return 1; +} diff --git a/fourbsixb.h b/fourbsixb.h new file mode 100644 index 0000000..87d1227 --- /dev/null +++ b/fourbsixb.h @@ -0,0 +1,13 @@ +#ifndef FOURBSIXB_H +#define FOURBSIXB_H + +#include "encoding.h" + +void fourbsixb_init_encoder(EncoderState *state); +void fourbsixb_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant; +uint8_t fourbsixb_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant; +void fourbsixb_init_decoder(DecoderState *state); +uint8_t fourbsixb_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant; +uint8_t fourbsixb_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant; + +#endif //FOURBSIXB_H diff --git a/fourbsixb_state.h b/fourbsixb_state.h new file mode 100644 index 0000000..1efe401 --- /dev/null +++ b/fourbsixb_state.h @@ -0,0 +1,16 @@ +#ifndef FOURBSIXB_STATE_H +#define FOURBSIXB_STATE_H + +struct FourbSixbEncoderState { + uint16_t acc; + uint8_t bits_avail; +}; + +struct FourbSixbDecoderState { + uint16_t input_acc; + uint8_t input_bits_avail; + uint16_t output_acc; + uint8_t output_bits_avail; +}; + +#endif // FOURBSIXB_STATE_H diff --git a/hardware.c b/hardware.c index 65abd50..03c8d48 100644 --- a/hardware.c +++ b/hardware.c @@ -6,41 +6,309 @@ #include "radio.h" #include "timer.h" #include "commands.h" -#include "delay.h" -uint8_t green_mode = 2; -uint8_t blue_mode = 2; +static LEDMode green_mode = 0; +static LEDMode blue_mode = 0; -void led_set_mode(uint8_t led, uint8_t new_mode) +mode_registers __xdata tx_registers; +mode_registers __xdata rx_registers; + +void init_leds() { + // init LEDS + HARDWARE_LED_INIT; // see hardware.h + GREEN_LED_PIN = 0; + BLUE_LED_PIN = 0; + + led_set_mode(GreenLED, LEDModeOff); + led_set_mode(BlueLED, LEDModeOff); +} + + +void led_set_mode(LEDNumber led, LEDMode new_mode) { - if(led == 0){ + if(led == GreenLED){ green_mode = new_mode; - if(new_mode != 2){ - GREEN_LED = new_mode; + if(new_mode == LEDModeOn) { + GREEN_LED_PIN = LEDStateOn; + } else if (new_mode == LEDModeOff) { + GREEN_LED_PIN = LEDStateOff; } } - else if(led == 1){ + else if(led == BlueLED){ blue_mode = new_mode; - if(new_mode != 2){ - BLUE_LED = new_mode; + if(new_mode == LEDModeOn) { + BLUE_LED_PIN = LEDStateOn; + } else if (new_mode == LEDModeOff) { + BLUE_LED_PIN = LEDStateOff; } } } -void led_set_state(uint8_t led, uint8_t command) +void led_set_diagnostic(LEDNumber led, LEDState state) { - if(led == 0){ - if(green_mode == 2){ - if(command < 2){ - GREEN_LED = command; - } + if(led == GreenLED){ + if(green_mode == LEDModeDiagnostic){ + GREEN_LED_PIN = state; } } - else if(led == 1){ - if(blue_mode == 2){ - if(command < 2){ - BLUE_LED = command; - } + else if(led == BlueLED){ + if(blue_mode == LEDModeDiagnostic){ + BLUE_LED_PIN = state; } - } -} \ No newline at end of file + } +} + +uint8_t get_register(uint8_t addr) { + uint8_t value; + addr = serial_rx_byte(); + switch(addr) { + case 0x00: + value = SYNC1; + break; + case 0x01: + value = SYNC0; + break; + case 0x02: + value = PKTLEN; + break; + case 0x03: + value = PKTCTRL1; + break; + case 0x04: + value = PKTCTRL0; + break; + case 0x05: + value = ADDR; + break; + case 0x06: + value = CHANNR; + break; + case 0x07: + value = FSCTRL1; + break; + case 0x08: + value = FSCTRL0; + break; + case 0x09: + value = FREQ2; + break; + case 0x0A: + value = FREQ1; + break; + case 0x0B: + value = FREQ0; + break; + case 0x0C: + value = MDMCFG4; + break; + case 0x0D: + value = MDMCFG3; + break; + case 0x0E: + value = MDMCFG2; + break; + case 0x0F: + value = MDMCFG1; + break; + case 0x10: + value = MDMCFG0; + break; + case 0x11: + value = DEVIATN; + break; + case 0x12: + value = MCSM2; + break; + case 0x13: + value = MCSM1; + break; + case 0x14: + value = MCSM0; + break; + case 0x15: + value = FOCCFG; + break; + case 0x16: + value = BSCFG; + break; + case 0x17: + value = AGCCTRL2; + break; + case 0x18: + value = AGCCTRL1; + break; + case 0x19: + value = AGCCTRL0; + break; + case 0x1A: + value = FREND1; + break; + case 0x1B: + value = FREND0; + break; + case 0x1C: + value = FSCAL3; + break; + case 0x1D: + value = FSCAL2; + break; + case 0x1E: + value = FSCAL1; + break; + case 0x1F: + value = FSCAL0; + break; + case 0x24: + value = TEST1; + break; + case 0x25: + value = TEST0; + break; + case 0x2D: + value = PA_TABLE1; + break; + case 0x2E: + value = PA_TABLE0; + break; + default: + value = 0x5A; + } + return value; +} + +uint8_t set_register(uint8_t addr, uint8_t value) { + uint8_t rval; + rval = RESPONSE_CODE_SUCCESS; + switch(addr) { + case 0x00: + SYNC1 = value; + break; + case 0x01: + SYNC0 = value; + break; + case 0x02: + PKTLEN = value; + break; + case 0x03: + PKTCTRL1 = value; + break; + case 0x04: + PKTCTRL0 = value; + break; + case 0x05: + ADDR = value; + break; + case 0x06: + CHANNR = value; + break; + case 0x07: + FSCTRL1 = value; + break; + case 0x08: + FSCTRL0 = value; + break; + case 0x09: + FREQ2 = value; + break; + case 0x0A: + FREQ1 = value; + break; + case 0x0B: + FREQ0 = value; + break; + case 0x0C: + MDMCFG4 = value; + break; + case 0x0D: + MDMCFG3 = value; + break; + case 0x0E: + MDMCFG2 = value; + break; + case 0x0F: + MDMCFG1 = value; + break; + case 0x10: + MDMCFG0 = value; + break; + case 0x11: + DEVIATN = value; + break; + case 0x12: + MCSM2 = value; + break; + case 0x13: + MCSM1 = value; + break; + case 0x14: + MCSM0 = value; + break; + case 0x15: + FOCCFG = value; + break; + case 0x16: + BSCFG = value; + break; + case 0x17: + AGCCTRL2 = value; + break; + case 0x18: + AGCCTRL1= value; + break; + case 0x19: + AGCCTRL0 = value; + break; + case 0x1A: + FREND1 = value; + break; + case 0x1B: + FREND0 = value; + break; + case 0x1C: + FSCAL3 = value; + break; + case 0x1D: + FSCAL2 = value; + break; + case 0x1E: + FSCAL1 = value; + break; + case 0x1F: + FSCAL0 = value; + break; + case 0x24: + TEST1 = value; + break; + case 0x25: + TEST0 = value; + break; + case 0x2D: + PA_TABLE1 = value; + break; + case 0x2E: + PA_TABLE0 = value; + break; + default: + rval = RESPONSE_CODE_PARAM_ERROR; + } + return rval; +} + +void mode_registers_clear(mode_registers *mode) { + mode->count = 0; +} + +void mode_registers_add(mode_registers *mode, uint8_t addr, uint8_t value) { + if (mode->count < MAX_MODE_REGISTERS - 1) { + mode->registers[mode->count].addr = addr; + mode->registers[mode->count].value = value; + mode->count++; + } +} + +void mode_registers_enact(mode_registers const *mode) { + int i; + for (i=0; icount; i++) { + set_register(mode->registers[i].addr, mode->registers[i].value); + } +} diff --git a/hardware.h b/hardware.h index a33521e..9fa78d1 100644 --- a/hardware.h +++ b/hardware.h @@ -1,11 +1,16 @@ #ifndef HARDWARE_H #define HARDWARE_H -#ifndef NON_NATIVE_TEST +#ifdef MOCK_HARDWARE +#include "mock_hardware.h" +#else #include // /usr/share/sdcc/include/mcs51/cc1110.h -#include "ioCCxx10_bitdef.h" +#define U1DBUF_write U1DBUF +#define U1DBUF_read U1DBUF #endif +#include "ioCCxx10_bitdef.h" + #define BIT0 0x1 #define BIT1 0x2 #define BIT2 0x4 @@ -19,49 +24,95 @@ #define HARDWARE_FLOW_CONTROL_CONFIG 0xc0; /* 8N1, hw flow control, high stop bit */ #define HARDWARE_LED_INIT P0DIR |= BIT0|BIT1; -#define GREEN_LED P0_0 -#define BLUE_LED P0_1 +#define GREEN_LED_PIN P0_0 +#define BLUE_LED_PIN P0_1 #define SYSTEM_CLOCK_MHZ 24 #elif EDISON_EXPLORER #define HARDWARE_FLOW_CONTROL_CONFIG 0xc0; /* 8N1, hw flow control, high stop bit */ #define HARDWARE_LED_INIT P2DIR |= BIT3|BIT4; -#define GREEN_LED P2_3 -#define BLUE_LED P2_4 +#define GREEN_LED_PIN P2_3 +#define BLUE_LED_PIN P2_4 #define SYSTEM_CLOCK_MHZ 24 #elif TI_DONGLE #define HARDWARE_LED_INIT P1DIR |= 2; -#define GREEN_LED P1_1 -#define BLUE_LED P1_1 +#define GREEN_LED_PIN P1_1 +#define BLUE_LED_PIN P1_1 #define SYSTEM_CLOCK_MHZ 24 #elif SRF_ERF #define HARDWARE_FLOW_CONTROL_CONFIG 0x02; /* 8N1, NO flow control, high stop bit */ #define HARDWARE_LED_INIT P1DIR |= BIT7; -#define GREEN_LED P1_7 -#define BLUE_LED P1_7 +#define GREEN_LED_PIN P1_7 +#define BLUE_LED_PIN P1_7 #define SYSTEM_CLOCK_MHZ 24 #elif SRF_STICK #define HARDWARE_FLOW_CONTROL_CONFIG 0x02; /* 8N1, NO flow control, high stop bit */ #define HARDWARE_LED_INIT P1DIR |= BIT7; -#define GREEN_LED P1_7 -#define BLUE_LED P1_6 +#define GREEN_LED_PIN P1_7 +#define BLUE_LED_PIN P1_6 #define SYSTEM_CLOCK_MHZ 24 #elif TI_MINIDEV #define HARDWARE_FLOW_CONTROL_CONFIG 0xc0; /* 8N1, hw flow control, high stop bit */ #define HARDWARE_LED_INIT P1DIR |= BIT0|BIT1; -#define GREEN_LED P1_0 -#define BLUE_LED P1_1 +#define GREEN_LED_PIN P1_0 +#define BLUE_LED_PIN P1_1 #define SYSTEM_CLOCK_MHZ 26 #endif -void led_set_mode(uint8_t led, uint8_t new_mode); +#define MAX_MODE_REGISTERS 8 + +typedef struct register_setting { + uint8_t addr; + uint8_t value; +} register_setting; + +typedef struct mode_registers { + uint8_t count; + register_setting registers[MAX_MODE_REGISTERS]; +} mode_registers; + +typedef enum { + GreenLED = 0x00, + BlueLED = 0x01 +} LEDNumber; + +typedef enum { + LEDModeOff = 0x00, + LEDModeOn = 0x01, + LEDModeDiagnostic = 0x02 +} LEDMode; + +typedef enum LEDState { + LEDStateOff = 0x00, + LEDStateOn = 0x01 +} LEDState; + +void init_leds(); +void led_set_mode(LEDNumber led, LEDMode new_mode); +void led_set_diagnostic(LEDNumber led, LEDState state); + +uint8_t get_register(uint8_t addr); +uint8_t set_register(uint8_t addr, uint8_t value); + +void mode_registers_clear(mode_registers *mode); +void mode_registers_add(mode_registers *mode, uint8_t addr, uint8_t value); +void mode_registers_enact(mode_registers const *mode); + +extern mode_registers __xdata tx_registers; +extern mode_registers __xdata rx_registers; + +#define WDCLP1 0xA0 // Clear pattern 1 +#define WDCLP2 0x50 // Clear pattern 2 -void led_set_state(uint8_t led, uint8_t command); +inline void feed_watchdog() { + WDCTL = WDCLP1 | WDCTL_EN; + WDCTL = WDCLP2 | WDCTL_EN; +} #endif diff --git a/main.c b/main.c index ef3cd6d..eb5b353 100644 --- a/main.c +++ b/main.c @@ -1,64 +1,26 @@ -/* Control a cc1110 for sub-ghz RF comms over uart. */ -#include -#include "hardware.h" -#include "serial.h" -#include "radio.h" -#include "timer.h" -#include "commands.h" -#include "delay.h" +#include +#include "subg_rfspy.h" -// SDCC needs prototypes of all ISR functions in main. not sure why, but described in section 3.8.1 +// All ISR functions must be present or included in the file that contains the +// function main, as described in SDCC manual section 3.8.1 void t1_isr(void) __interrupt T1_VECTOR; void rftxrx_isr(void) __interrupt RFTXRX_VECTOR; void rf_isr(void) __interrupt RF_VECTOR; #ifdef USES_USART1_RX_ISR void rx1_isr(void) __interrupt URX1_VECTOR; -#endif +#endif #ifdef USES_USART1_TX_ISR void tx1_isr(void) __interrupt UTX1_VECTOR; #endif -#if TI_DONGLE || SRF_STICK +#if USES_USB void usb_isr() __interrupt 6; #endif int main(void) { - - // Set the system clock source to HS XOSC and max CPU speed, - // ref. [clk]=>[clk_xosc.c] - SLEEP &= ~SLEEP_OSC_PD; - while( !(SLEEP & SLEEP_XOSC_S) ); - CLKCON = (CLKCON & ~(CLKCON_CLKSPD | CLKCON_OSC)) | CLKSPD_DIV_1; - while (CLKCON & CLKCON_OSC); - SLEEP |= SLEEP_OSC_PD; - - - // init LEDS - HARDWARE_LED_INIT; // see hardware.h - led_set_state(0, 0); //GREEN_LED = 0; - led_set_state(1, 0); //BLUE_LED = 0; - - // Global interrupt enable - init_timer(); - EA = 1; - - //LED test - led_set_state(0, 1); //GREEN_LED = 1; - delay(1000); - led_set_state(0, 0); //GREEN_LED = 0; - led_set_state(1, 1); //BLUE_LED = 1; - delay(1000); - led_set_state(1, 0); //BLUE_LED = 0; - - configure_radio(); - configure_serial(); - - while(1) { - //led_set_state(0,2); - get_command(); - } + subg_rfspy_main(); } diff --git a/manchester.c b/manchester.c new file mode 100644 index 0000000..58bc9e0 --- /dev/null +++ b/manchester.c @@ -0,0 +1,61 @@ + +#include "manchester.h" + +void manchester_init_encoder(EncoderState *state) { + state->manchester.offset = 2; +} + +void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { + uint16_t acc = 0; + int i; + for (i=0; i<8; i++) { + acc = (acc << 2) + 2 - (raw >> 7); + raw = raw << 1; + } + state->manchester.output[0] = acc >> 8; + state->manchester.output[1] = acc & 0xff; + state->manchester.offset = 0; +} + +uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant { + if (state->manchester.offset > 1) { + return 0; + } + *encoded = state->manchester.output[state->manchester.offset]; + state->manchester.offset++; + return 1; +} + +// Manchester decoder funcs + +void manchester_init_decoder(DecoderState *state) { + state->manchester.output = 0; + state->manchester.bits_avail = 0; +} + +uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant { + uint8_t acc = 0; + int i; + for (i=6; i>=0; i-=2) { + acc = (acc << 1); + switch((encoded >> i) & 0b11) { + case 0b00: + case 0b11: + return 1; // Encoding error + case 0b01: + acc++; + } + } + state->manchester.output = (state->manchester.output << 4) + acc; + state->manchester.bits_avail += 4; + return 0; +} + +uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant { + if (state->manchester.bits_avail < 8) { + return 0; + } + *decoded = state->manchester.output; + state->manchester.bits_avail = 0; + return 1; +} diff --git a/manchester.h b/manchester.h new file mode 100644 index 0000000..a4eee63 --- /dev/null +++ b/manchester.h @@ -0,0 +1,13 @@ +#ifndef MANCHESTER_H +#define MANCHESTER_H + +#include "encoding.h" + +void manchester_init_encoder(EncoderState *state); +void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant; +uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant; +void manchester_init_decoder(DecoderState *state); +uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant; +uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant; + +#endif //MANCHESTER_H diff --git a/manchester_state.h b/manchester_state.h new file mode 100644 index 0000000..2856924 --- /dev/null +++ b/manchester_state.h @@ -0,0 +1,14 @@ +#ifndef MANCHESTER_STATE_H +#define MANCHESTER_STATE_H + +struct ManchesterEncoderState { + uint8_t output[2]; + uint8_t offset; +}; + +struct ManchesterDecoderState { + uint8_t output; + uint8_t bits_avail; +}; + +#endif // MANCHESTER_STATE_H diff --git a/mock_hardware.c b/mock_hardware.c new file mode 100644 index 0000000..46b0572 --- /dev/null +++ b/mock_hardware.c @@ -0,0 +1,128 @@ + +#include +#include +#include +#include +#include "hardware.h" + + +volatile uint8_t P0_0; +volatile uint8_t P0_1; +volatile uint8_t P0DIR; +volatile uint8_t P1DIR; +volatile uint8_t P1SEL; +volatile uint8_t SYNC1; +volatile uint8_t SYNC0; +volatile uint8_t PKTLEN; +volatile uint8_t PKTCTRL1; +volatile uint8_t PKTCTRL0; +volatile uint8_t FSCTRL1; +volatile uint8_t FSCTRL0; +volatile uint8_t FSCTRL1; +volatile uint8_t MDMCFG4; +volatile uint8_t MDMCFG3; +volatile uint8_t MDMCFG2; +volatile uint8_t MDMCFG1; +volatile uint8_t MDMCFG0; +volatile uint8_t TEST1; +volatile uint8_t TEST0; +volatile uint8_t PA_TABLE1; +volatile uint8_t PA_TABLE0; +volatile uint8_t AGCCTRL2; +volatile uint8_t AGCCTRL1; +volatile uint8_t AGCCTRL0; +volatile uint8_t FREQ2; +volatile uint8_t FREQ1; +volatile uint8_t FREQ0; +volatile uint8_t CHANNR; +volatile uint8_t IEN2; +volatile uint8_t RFTXRXIE; +volatile uint8_t FSCAL3; +volatile uint8_t FSCAL2; +volatile uint8_t FSCAL1; +volatile uint8_t FREND1; +volatile uint8_t FREND0; +volatile uint8_t BSCFG; +volatile uint8_t DEVIATN; +volatile uint8_t MCSM2; +volatile uint8_t MCSM1; +volatile uint8_t MCSM0; +volatile uint8_t ADDR; +volatile uint8_t FOCCFG; +volatile uint8_t FSCAL0; +volatile uint8_t MARCSTATE; +volatile uint8_t RFD; +volatile uint8_t RSSI; +volatile uint8_t RFIF; +volatile uint8_t RFST; +volatile uint8_t S1CON; +volatile uint8_t TCON; +volatile uint8_t SLEEP = 0b00000100; +volatile uint8_t CLKCON; +volatile uint8_t EA; +volatile uint8_t T1CTL; +volatile uint8_t T1CNTH; +volatile uint8_t T1CNTL; +volatile uint8_t T1CCTL0; +volatile uint8_t T1CC0H; +volatile uint8_t T1CC0L; +volatile uint8_t TIMIF; +volatile uint8_t OVFIM; +volatile uint8_t T1IE; +volatile uint8_t WDCTL; +volatile uint8_t PERCFG; +volatile uint8_t U1CSR; +volatile uint8_t U1BAUD; +volatile uint8_t U1GCR; +volatile uint8_t URX1IE; +volatile uint8_t IRCON2; +volatile uint8_t U1DBUF_write; +volatile uint8_t U1DBUF_read; + +bool mock_hardware_should_exit; + +// This is 10x normal clock speed +#define MOCK_CLOCK_TICK_RATE 0.0001 + +void *run_mock_hardware(void *vargp) { + clock_t start_time; + + // Mark oscillator as powered up and stable + SLEEP |= SLEEP_XOSC_S; + + printf("starting mock hardware thread\n"); + + start_time = clock(); + + while(!mock_hardware_should_exit) { + + double elapsed = ((double)(clock() - start_time))/CLOCKS_PER_SEC; + + if (elapsed > MOCK_CLOCK_TICK_RATE) { + // Run counter + if (T1CNTL == 255) { + T1CNTH += 1; + } + T1CNTL += 1; + t1_isr(); + start_time = clock(); + } + + // Watch radio strobe registers + if(RFST == RFST_SIDLE) { + MARCSTATE = MARC_STATE_IDLE; + RFST = RFST_SNOP; + } + + if(RFST == RFST_SRX) { + MARCSTATE = MARC_STATE_RX; + RFST = RFST_SNOP; + } + + if(RFST == RFST_STX) { + MARCSTATE = MARC_STATE_TX; + RFST = RFST_SNOP; + } + } + return NULL; +} diff --git a/mock_hardware.h b/mock_hardware.h new file mode 100644 index 0000000..7d80e9a --- /dev/null +++ b/mock_hardware.h @@ -0,0 +1,108 @@ +#ifndef MOCK_HARDWARE_H +#define MOCK_HARDWARE_H + +#include +#include + +#ifdef __GNUC__ +#define inline static inline +#endif + +#define __reentrant +#define __xdata +#define __interrupt +#define RFTXRX_VECTOR +#define RF_VECTOR +#define T1_VECTOR +#define URX1_VECTOR +#define UTX1_VECTOR + +extern volatile uint8_t P0_0; +extern volatile uint8_t P0_1; +extern volatile uint8_t P0DIR; +extern volatile uint8_t P1DIR; +extern volatile uint8_t P1SEL; +extern volatile uint8_t SYNC1; +extern volatile uint8_t SYNC0; +extern volatile uint8_t PKTLEN; +extern volatile uint8_t PKTCTRL1; +extern volatile uint8_t PKTCTRL0; +extern volatile uint8_t FSCTRL1; +extern volatile uint8_t FSCTRL0; +extern volatile uint8_t FSCTRL1; +extern volatile uint8_t MDMCFG4; +extern volatile uint8_t MDMCFG3; +extern volatile uint8_t MDMCFG2; +extern volatile uint8_t MDMCFG1; +extern volatile uint8_t MDMCFG0; +extern volatile uint8_t TEST1; +extern volatile uint8_t TEST0; +extern volatile uint8_t PA_TABLE1; +extern volatile uint8_t PA_TABLE0; +extern volatile uint8_t AGCCTRL2; +extern volatile uint8_t AGCCTRL1; +extern volatile uint8_t AGCCTRL0; +extern volatile uint8_t FREQ2; +extern volatile uint8_t FREQ1; +extern volatile uint8_t FREQ0; +extern volatile uint8_t CHANNR; +extern volatile uint8_t IEN2; +extern volatile uint8_t IEN2_RFIE; +extern volatile uint8_t RFTXRXIE; +extern volatile uint8_t FSCAL3; +extern volatile uint8_t FSCAL2; +extern volatile uint8_t FSCAL1; +extern volatile uint8_t FREND1; +extern volatile uint8_t FREND0; +extern volatile uint8_t BSCFG; +extern volatile uint8_t DEVIATN; +extern volatile uint8_t MCSM2; +extern volatile uint8_t MCSM1; +extern volatile uint8_t MCSM0; +extern volatile uint8_t ADDR; +extern volatile uint8_t FOCCFG; +extern volatile uint8_t FSCAL0; +extern volatile uint8_t MARCSTATE; +extern volatile uint8_t RFD; +extern volatile uint8_t RSSI; +extern volatile uint8_t RFIF; +extern volatile uint8_t RFST; +extern volatile uint8_t S1CON; +extern volatile uint8_t TCON; +extern volatile uint8_t SLEEP; +extern volatile uint8_t CLKCON; +extern volatile uint8_t EA; +extern volatile uint8_t T1CTL; +extern volatile uint8_t T1CNTH; +extern volatile uint8_t T1CNTL; +extern volatile uint8_t T1CCTL0; +extern volatile uint8_t T1CC0H; +extern volatile uint8_t T1CC0L; +extern volatile uint8_t TIMIF; +extern volatile uint8_t OVFIM; +extern volatile uint8_t T1IE; +extern volatile uint8_t WDCTL; +extern volatile uint8_t PERCFG; +extern volatile uint8_t U1CSR; +extern volatile uint8_t U1BAUD; +extern volatile uint8_t U1GCR; +extern volatile uint8_t URX1IE; +extern volatile uint8_t IRCON2; +extern volatile uint8_t U1DBUF_write; +extern volatile uint8_t U1DBUF_read; + +#define GREEN_LED_PIN P0_0 +#define BLUE_LED_PIN P0_1 +#define SYSTEM_CLOCK_MHZ 24 +#define HARDWARE_LED_INIT P0DIR |= BIT0|BIT1; + +void *run_tests(void *vargp); +void *run_mock_hardware(void *vargp); + +void t1_isr(void); // Timer Interrupt +void tx1_isr(void); // UTX1_VECTOR +void rx1_isr(void); // URX1_VECTOR + +extern bool mock_hardware_should_exit; + +#endif diff --git a/packet_buffer.c b/packet_buffer.c new file mode 100644 index 0000000..2830d91 --- /dev/null +++ b/packet_buffer.c @@ -0,0 +1,63 @@ +#include +#include "hardware.h" + +// FIFO queue for packets + +// Adjust this based on available space as indicated in linker .mem file +#define PACKET_DATA_BUF_LEN 2000 + +// This should be PACKET_DATA_LEN / average packet size +#define PACKET_COUNT_MAX 30 + +// Circular buffers +static uint8_t __xdata packet_data_buf[PACKET_DATA_BUF_LEN]; +static uint8_t __xdata packet_lengths[PACKET_COUNT_MAX]; + +static uint16_t __xdata packet_data_buf_head; +static uint16_t __xdata packet_data_buf_tail; +static uint16_t __xdata packet_data_buf_len; +static uint8_t __xdata packet_lengths_head; +static uint8_t __xdata packet_lengths_tail; +static volatile uint8_t __xdata packet_count; + +uint8_t enqueue_packet(const uint8_t *packet_data, uint16_t packet_len) { + uint16_t i; + + if (packet_data_buf_len + packet_len >= PACKET_DATA_BUF_LEN) { + return 0; + } + + if (packet_count + 1 >= PACKET_COUNT_MAX) { + return 0; + } + + packet_lengths[packet_lengths_head] = packet_len; + packet_lengths_head = (packet_lengths_head + 1) % PACKET_COUNT_MAX; + packet_count++; + + for (i=0; i +#include #include "hardware.h" #include "serial.h" #include "commands.h" -#include "delay.h" #include "timer.h" +#include "encoding.h" +#include "fifo.h" +#include "statistics.h" +#include "radio.h" -#define MAX_PACKET_LEN 192 -volatile uint8_t __xdata radio_tx_buf[MAX_PACKET_LEN]; -volatile uint8_t radio_tx_buf_len = 0; -volatile uint8_t radio_tx_buf_idx = 0; -volatile uint8_t __xdata radio_rx_buf[MAX_PACKET_LEN]; -volatile uint8_t radio_rx_buf_len = 0; -volatile uint8_t packet_count = 1; -volatile uint8_t underflow_count = 0; +#define RX_FIFO_SIZE 32 +#define TX_BUF_SIZE 255 + +static volatile uint8_t __xdata radio_rx_buf[RX_FIFO_SIZE]; +static fifo_buffer __xdata rx_fifo; +static volatile uint8_t rx_len; + +static volatile uint8_t __xdata radio_tx_buf[TX_BUF_SIZE]; +static volatile uint8_t __xdata radio_tx_buf_read_idx; +static volatile uint8_t __xdata radio_tx_buf_len; + +static volatile uint16_t __xdata preamble_word; +static volatile uint8_t stop_custom_preamble_semaphore; + +// TX States +enum TxState { + TxStatePreambleByte0 = 0x00, + TxStatePreambleByte1 = 0x01, + TxStatePreambleDefault = 0x02, + TxStateSync0 = 0x03, + TxStateSync1 = 0x04, + TxStateData = 0x05, + TxStateDone = 0x06, +}; +volatile enum TxState tx_state; + + +EncodingType encoding_type = EncodingTypeNone; void configure_radio() { @@ -39,7 +63,8 @@ void configure_radio() MCSM2 = 0x07; MCSM1 = 0x30; MCSM0 = 0x18; // main radio control state machine configuration - FOCCFG = 0x17; // frequency offset compensation configuration BSCFG = 0x6C; + FOCCFG = 0x17; // frequency offset compensation configuration + BSCFG = 0x6C; // bit synchronization configuration FREND1 = 0xB6; // front end tx configuration FREND0 = 0x11; // front end tx configuration FSCAL3 = 0xE9; // frequency synthesizer calibration @@ -71,48 +96,74 @@ void configure_radio() IEN2 |= IEN2_RFIE; RFTXRXIE = 1; + + fifo_init(&rx_fifo, radio_rx_buf, RX_FIFO_SIZE); +} + +// Set software based encoding +bool set_encoding_type(EncodingType new_type) { + if (new_type <= MaxEncodingTypeValue) { + encoding_type = new_type; + return true; + } else { + return false; + } +} + +inline void put_rx(uint8_t data) { + if (!fifo_put(&rx_fifo, data)) { + radio_rx_fifo_overflow_count++; + } } void rftxrx_isr(void) __interrupt RFTXRX_VECTOR { uint8_t d_byte; if (MARCSTATE==MARC_STATE_RX) { d_byte = RFD; - if (radio_rx_buf_len == 0) { - radio_rx_buf[0] = RSSI; - if (radio_rx_buf[0] == 0) { - radio_rx_buf[0] = 1; // Prevent RSSI of 0 from triggering end-of-packet - } - radio_rx_buf[1] = packet_count; - packet_count++; - radio_rx_buf_len = 2; - } - if (packet_count == 0) { - packet_count = 1; - } - if (radio_rx_buf_len < MAX_PACKET_LEN) { - radio_rx_buf[radio_rx_buf_len] = d_byte; - radio_rx_buf_len++; - } else { - // Overflow - } - if (d_byte == 0) { - RFST = RFST_SIDLE; - while(MARCSTATE!=MARC_STATE_IDLE); + if (rx_len == 0) { + put_rx(RSSI); + put_rx(packet_rx_count & 0xff); + rx_len = 2; } + put_rx(d_byte); + rx_len++; } else if (MARCSTATE==MARC_STATE_TX) { - if (radio_tx_buf_len > radio_tx_buf_idx) { - d_byte = radio_tx_buf[radio_tx_buf_idx++]; - RFD = d_byte; - } else { - RFD = 0; - underflow_count++; - // We wait a few counts to make sure the radio has sent the last bytes - // before turning it off. - if (underflow_count == 2) { - RFST = RFST_SIDLE; + switch (tx_state) { + case TxStatePreambleByte0: + RFD = preamble_word >> 8; + tx_state = TxStatePreambleByte1; + break; + case TxStatePreambleByte1: + RFD = preamble_word & 0xff; + if (stop_custom_preamble_semaphore) { + tx_state = TxStateSync1; + } else { + tx_state = TxStatePreambleByte0; } + break; + case TxStateSync1: + RFD = SYNC1; + tx_state = TxStateSync0; + break; + case TxStateSync0: + RFD = SYNC0; + tx_state = TxStateData; + break; + case TxStateData: + RFD = radio_tx_buf[radio_tx_buf_read_idx++]; + if (radio_tx_buf_read_idx >= radio_tx_buf_len) { + tx_state = TxStateDone; + } + break; + case TxStateDone: + // Letting RFD go empty will make the radio stop TX mode. + //RFD = 0; + break; + case TxStatePreambleDefault: + break; } + } } @@ -126,6 +177,7 @@ void rf_isr(void) __interrupt RF_VECTOR { } else if(RFIF & 0x40) // RX overflow { + radio_rx_overflow_count++; RFIF &= ~0x40; // Clear module interrupt flag } else if(RFIF & 0x20) // RX timeout @@ -136,133 +188,206 @@ void rf_isr(void) __interrupt RF_VECTOR { } -void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms) { +void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t delay_ms, uint16_t preamble_extend_ms, uint8_t len) { uint8_t s_byte; - - radio_tx_buf_len = 0; - radio_tx_buf_idx = 0; - underflow_count = 0; + uint16_t send_count = 0; + uint16_t total_send_count = repeat_count + 1; - RFST = RFST_SIDLE; - while(MARCSTATE!=MARC_STATE_IDLE); + Encoder encoder; + EncoderState encoder_state; + + init_encoder(encoding_type, &encoder, &encoder_state); + + mode_registers_enact(&tx_registers); CHANNR = channel; - //led_set_state(1,1); - while (1) { + radio_tx_buf_len = 0; + while (len > 0) { s_byte = serial_rx_byte(); - if (radio_tx_buf_len == (MAX_PACKET_LEN - 1)) { - s_byte = 0; - } - radio_tx_buf[radio_tx_buf_len++] = s_byte; - if (s_byte == 0) { - break; - } - - if (radio_tx_buf_len == 2) { - // Turn on radio - RFST = RFST_STX; + len--; + encoder.add_raw_byte(&encoder_state, s_byte); + while (encoder.next_encoded_byte(&encoder_state, &s_byte, len == 0)) { + if (radio_tx_buf_len+1 < TX_BUF_SIZE) { + radio_tx_buf[radio_tx_buf_len++] = s_byte; + } } } - // wait for sending to finish - while(MARCSTATE!=MARC_STATE_IDLE); - - while(repeat_count > 0) { - // Reset idx to beginning of buffer - radio_tx_buf_idx = 0; - underflow_count = 0; + while(send_count < total_send_count) { - // delay - if (delay_ms > 0) { + // delay + if (send_count > 0 && delay_ms > 0) { delay(delay_ms); } - - // Turn on radio (interrupts should start again) - RFST = RFST_STX; - while(MARCSTATE!=MARC_STATE_TX); - - // wait for sending to finish - while(MARCSTATE!=MARC_STATE_IDLE); - repeat_count--; + feed_watchdog(); + + send_from_tx_buf(channel, preamble_extend_ms); + + send_count++; } - //led_set_state(1,0); } -void resend_from_tx_buf(uint8_t channel) { +void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms) { + uint8_t pktlen_save; + uint8_t mdmcfg2_save; + uint8_t pktctrl0_save; + + mdmcfg2_save = MDMCFG2; + pktlen_save = PKTLEN; + pktctrl0_save = PKTCTRL0; + + packet_tx_count++; + + if (preamble_word != 0) { + // save and turn off preamble/sync registers + MDMCFG2 &= 0b11111100; // Disable PREAMBLE/SYNC + PKTCTRL0 = (PKTCTRL0 & ~0b11) | 0b10; // Enter "infinite" tx mode + PKTLEN = 0; + stop_custom_preamble_semaphore = 0; + tx_state = TxStatePreambleByte0; + } else { + if (preamble_extend_ms) { + tx_state = TxStatePreambleDefault; + } else { + tx_state = TxStateData; + } + PKTLEN = radio_tx_buf_len; + } RFST = RFST_SIDLE; while(MARCSTATE!=MARC_STATE_IDLE); CHANNR = channel; - // Reset idx to beginning of buffer - radio_tx_buf_idx = 0; - underflow_count = 0; + radio_tx_buf_read_idx = 0; - // Turn on radio (interrupts should start again) + // Turn on radio (interrupts will start again) RFST = RFST_STX; while(MARCSTATE!=MARC_STATE_TX); + if (preamble_extend_ms > 0) { + delay(preamble_extend_ms); + if(preamble_word==0) { + tx_state = TxStateData; + TCON |= 0b10; // Manually trigger RFTXRX vector. + } + } + + if (preamble_word != 0) { + stop_custom_preamble_semaphore = 1; + } + // wait for sending to finish - while(MARCSTATE!=MARC_STATE_IDLE); + while(MARCSTATE==MARC_STATE_TX); + + if (MARCSTATE==MARC_STATE_TX_UNDERFLOW) { + RFST = RFST_SIDLE; + } + + PKTLEN = pktlen_save; + MDMCFG2 = mdmcfg2_save; + PKTCTRL0 = pktctrl0_save; + } -uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms) { +uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uint8_t use_pktlen) { uint8_t read_idx = 0; uint8_t d_byte = 0; uint8_t rval = 0; + uint8_t encoding_error = 0; + uint32_t timer_start; + + Decoder __xdata decoder; + DecoderState __xdata decoder_state; + + if (timeout_ms > 0) { + read_timer(&timer_start); + } + + mode_registers_enact(&rx_registers); - reset_timer(); + init_decoder(encoding_type, &decoder, &decoder_state); RFST = RFST_SIDLE; while(MARCSTATE!=MARC_STATE_IDLE); CHANNR = channel; - radio_rx_buf_len = 0; + rx_len = 0; + memset((void*)radio_rx_buf, 0x11, RX_FIFO_SIZE); RFST = RFST_SRX; while(MARCSTATE!=MARC_STATE_RX); while(1) { - // Waiting for isr to put radio bytes into radio_rx_buf - if (radio_rx_buf_len > read_idx) { - //led_set_state(0,1); - if (read_idx == 0 && radio_rx_buf_len > 2 && radio_rx_buf[2] == 0) { - rval = ERROR_ZERO_DATA; + feed_watchdog(); + + // Waiting for isr to put radio bytes into rx_fifo + if (!fifo_empty(&rx_fifo)) { + + d_byte = fifo_get(&rx_fifo); + read_idx++; + + // Send status code + if (read_idx == 1) { + led_set_diagnostic(BlueLED, LEDStateOn); + serial_tx_byte(RESPONSE_CODE_SUCCESS); + } + // First two bytes are rssi and packet # + if (read_idx < 3) { + serial_tx_byte(d_byte); + } else { + encoding_error = decoder.add_encoded_byte(&decoder_state, d_byte); + + while (decoder.next_decoded_byte(&decoder_state, &d_byte)) { + serial_tx_byte(d_byte); + } + } + + if (encoding_error) { break; } - d_byte = radio_rx_buf[read_idx]; - serial_tx_byte(d_byte); - read_idx++; - if (read_idx > 1 && read_idx == radio_rx_buf_len && d_byte == 0) { - // End of packet. + + // Check for end of packet + if (use_pktlen && read_idx == PKTLEN) { break; } } - if (timeout_ms > 0 && timerCounter > timeout_ms && radio_rx_buf_len == 0) { - rval = ERROR_RX_TIMEOUT; + if (timeout_ms > 0 && check_elapsed(timer_start, timeout_ms)) { + rval = RESPONSE_CODE_RX_TIMEOUT; break; } - - #ifndef TI_DONGLE - #else - #endif + // Also going to watch serial in case the client wants to interrupt rx if (SERIAL_DATA_AVAILABLE) { // Received a byte from uart while waiting for radio packet // We will interrupt the RX and go handle the command. interrupting_cmd = serial_rx_byte(); - rval = ERROR_CMD_INTERRUPTED; + rval = RESPONSE_CODE_CMD_INTERRUPTED; break; } } + RFST = RFST_SIDLE; - //led_set_state(0,0); + while(MARCSTATE!=MARC_STATE_IDLE); + + while(!fifo_empty(&rx_fifo)) { + fifo_get(&rx_fifo); + } + + if (rval == 0) { + packet_rx_count++; + } + + led_set_diagnostic(BlueLED, LEDStateOff); return rval; } +// Set software based preamble, 0 = disable +void radio_set_preamble(uint16_t p) { + preamble_word = p; +} diff --git a/radio.h b/radio.h index a1a6fbd..71c1327 100644 --- a/radio.h +++ b/radio.h @@ -1,17 +1,25 @@ #ifndef RADIO_H #define RADIO_H +#include "encoding.h" +#include "stdbool.h" + void configure_radio(); // Return values: // 0 = timed out // 1 = got packet // 2 = rx interrupted by serial -uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms); +uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uint8_t use_pktlen); + +void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t delay_ms, uint16_t preamble_extend_ms, uint8_t len); + +void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms); -void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms); +// Set software based encoding. Returns false if encoding type is not supported +bool set_encoding_type(EncodingType encoding_type); -// Used for retry -void resend_from_tx_buf(uint8_t channel); +// Set software based preamble, 0 = disable +void radio_set_preamble(uint16_t preamble_word); #endif diff --git a/serial.md b/serial.md new file mode 100644 index 0000000..9b7130c --- /dev/null +++ b/serial.md @@ -0,0 +1,85 @@ +# Serial support +*Since the change to SPI framing carrying semantic information about the Length +of packets, the serial protocol no longer can be expected to work. It needs to +be updated to support some kind of framing.* + +This information is provide for users of legacy versions of the software. + +UART/SPI pins exposed on cc1110 debug header: + + PIN - SPI_alt2 / UART1_alt2 + P1.4 - CT / SSN + P1.5 - RT / SCK + P1.6 - TX / MOSI + P1.7 - RX / MISO + +# cc111x UART1_alt2 connected to the Intel Edison UART_1 + + P1.4 - CT / SSN -> UART_1_RTS (GP129) (pin 63) + P1.5 - RT / SCK -> UART_1_CTS (GP128) (pin 65) + P1.6 - TX / MOSI -> UART_1_RX (GP130) (pin 61) + P1.7 - RX / MISO -> UART_1_TX (GP131) (pin 46) + + +# UART on the WirelessThings ERF stick + +Perform the build. The output file will be stored at output/uart0_alt1_SRF_ERF_US/uart0_alt1_SRF_ERF_US.hex + + make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF + +Installation is bit more complicated, as you will need to attach connectors to +the SRF pins manually (you can't use the wiring points on the board itself). + +This [XRF blog post](http://paulswasteland.blogspot.co.uk/2015/01/building-your-own-firmware-for-ciseco.html) +maps cc-debugger connector to the XRF pin names. + +However, the XRF pins are not the same as the SRF pin locations. For that, you +can use the [SRF OpenMicros Data](http://openmicros.org/index.php/articles/88-ciseco-product-documentation/259-srf-technical-data) +to map things to the correct ERF locations. + +- SRF Pin 5 - DDATA (also known as DD) +- SRF Pin 6 - DCLOCK (also known as DC) +- SRF Pin 9 - 3.3v (also known as VDD) +- SRF Pin 10 - Ground (also known as GND) +- SRF Pin 15 - Reset + +To install the firmware: + + make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF install + +# USB on support on TI cc1111 USB stick (CC1111EMK868-915) AKA "Don's Dongle" + + make -f Makefile.usb_ep0 install + +Shows up as a serial device on linux. + + +# CCTL Support + +If you have [CCTL](https://github.com/oskarpearson/cctl/tree/24mhz_clock_and_erf_stick_hack) +on your device stick, you can re-program the firmware without requiring the cc-debugger. +To compile firmware that's compatible with CCTL, set the CODE_LOC and CODE_LOC_NAME parameters: + + make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL + +Then, compile the cctl writer program: + + cd /where/you/want/the/cctl/code/to/live + git clone https://github.com/oskarpearson/cctl.git + cd cctl + git checkout 24mhz_clock_and_erf_stick_hack + cd cctl-prog + make clean all + +Then connect the ERF stick over the serial port (normally /dev/ttyUSB0), and write the firmware: + + ./cctl-prog -d /dev/ttyUSB0 -f /path/to/subg_rfspy/output/uart0_alt1_SRF_ERF_WW_CCTL/uart0_alt1_SRF_ERF_WW_CCTL.hex + Waiting 10s for bootloader, reset board now + +Reset the board by disconnecting the +ve lead, and you should then see: + + ....Bootloader detected + Erasing, programming and verifying page 1 + ... + Erasing page 31 + Programming complete diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 77fc1a2..f723c73 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -1,42 +1,45 @@ #include +#include #include "hardware.h" +#include "subg_rfspy.h" #include "serial.h" #include "radio.h" +#include "statistics.h" +#include "fifo.h" +#include "timer.h" -#define SPI_BUF_LEN 220 +#define SPI_BUF_LEN 128 +#define FLUSH_TIMEOUT_MS 5000 -volatile uint8_t __xdata spi_input_buf[SPI_BUF_LEN]; -volatile uint8_t input_size = 0; -volatile uint8_t input_head_idx = 0; -volatile uint8_t input_tail_idx = 0; +static fifo_buffer __xdata input_buffer; +static volatile uint8_t __xdata input_buffer_mem[SPI_BUF_LEN]; -volatile uint8_t __xdata spi_output_buf[SPI_BUF_LEN]; -volatile uint8_t output_size = 0; -volatile uint8_t output_head_idx = 0; -volatile uint8_t output_tail_idx = 0; +static fifo_buffer __xdata output_buffer; +static volatile uint8_t __xdata output_buffer_mem[SPI_BUF_LEN]; volatile uint8_t ready_to_send = 0; volatile uint8_t serial_data_available; -#define SPI_MODE_WAIT 0 +#define SPI_MODE_IDLE 0 #define SPI_MODE_SIZE 1 #define SPI_MODE_XFER 2 +#define SPI_MODE_OUT_OF_SYNC 3 volatile uint8_t spi_mode; volatile uint8_t master_send_size = 0; volatile uint8_t slave_send_size = 0; +volatile uint8_t xfer_size = 0; /*************************************************************************** - * - * SPI encoding: + * + * SPI encoding: * * Master sends a 0x99 byte, followed by number of bytes that will be sent. - * Before second byte xfer, slave loads up buffer with number of bytes - * available. - * + * Slave sends back number of bytes available during second xfer. + * */ @@ -88,116 +91,164 @@ void configure_serial() IRCON2 &= ~BIT2; // Clear UTX1IF IEN2 |= BIT3; // Enable UTX1IE interrupt -} -void rx1_isr(void) __interrupt URX1_VECTOR { - uint8_t value; - value = U1DBUF; + U1DBUF_write = 0x44; - if (spi_mode == SPI_MODE_WAIT && value == 0x99) { - if (ready_to_send) { - slave_send_size = output_size; - ready_to_send = 0; - } else { - slave_send_size = 0; - } - spi_mode = SPI_MODE_SIZE; - U1DBUF = slave_send_size; - return; - } + // Initialize fifos + fifo_init(&input_buffer, input_buffer_mem, SPI_BUF_LEN); + fifo_init(&output_buffer, output_buffer_mem, SPI_BUF_LEN); +} - if (spi_mode == SPI_MODE_SIZE) { - master_send_size = value; - if (master_send_size > 0 || slave_send_size > 0) { - spi_mode = SPI_MODE_XFER; - } else { - spi_mode = SPI_MODE_WAIT; - } - return; - } +void rx1_isr(void) __interrupt URX1_VECTOR +{ + uint8_t value; + value = U1DBUF_read; - if (spi_mode == SPI_MODE_XFER && input_size < master_send_size) { - if (input_size < SPI_BUF_LEN) { - spi_input_buf[input_head_idx] = value; - input_head_idx++; - if (input_head_idx >= SPI_BUF_LEN) { - input_head_idx = 0; + switch(spi_mode) + { + case SPI_MODE_OUT_OF_SYNC: + if (value == 0x99) { + spi_mode = SPI_MODE_SIZE; } - input_size++; - if (input_size == master_send_size) { - master_send_size = 0; - serial_data_available = 1; + break; + case SPI_MODE_IDLE: + if (value != 0x99) { + spi_sync_failure_count++; + spi_mode = SPI_MODE_OUT_OF_SYNC; + } else { + spi_mode = SPI_MODE_SIZE; } - } - if (slave_send_size == 0 && master_send_size == 0) { - spi_mode = SPI_MODE_WAIT; - } + break; + case SPI_MODE_SIZE: + if (value > SPI_BUF_LEN) { + spi_sync_failure_count++; + spi_mode = SPI_MODE_OUT_OF_SYNC; + return; + } + master_send_size = value; + xfer_size = master_send_size; + if (slave_send_size > xfer_size) { + xfer_size = slave_send_size; + } + if (xfer_size > 0) { + spi_mode = SPI_MODE_XFER; + } else { + spi_mode = SPI_MODE_IDLE; + } + break; + case SPI_MODE_XFER: + if(xfer_size > 0) { + if (fifo_count(&input_buffer) < master_send_size) { + fifo_put(&input_buffer, value); + if (fifo_count(&input_buffer) == master_send_size) { + master_send_size = 0; + serial_data_available = 1; + } + } + xfer_size--; + } + if (xfer_size == 0) { + slave_send_size = 0; + spi_mode = SPI_MODE_IDLE; + } + break; } } -void tx1_isr(void) __interrupt UTX1_VECTOR { +void tx1_isr(void) __interrupt UTX1_VECTOR +{ IRCON2 &= ~BIT2; // Clear UTX1IF - if (spi_mode == SPI_MODE_SIZE || spi_mode == SPI_MODE_XFER) { - if (slave_send_size > 0 && output_size > 0) { - slave_send_size--; - if (slave_send_size == 0 && master_send_size == 0) { - spi_mode = SPI_MODE_WAIT; - } - U1DBUF = spi_output_buf[output_tail_idx]; - output_size--; - output_tail_idx++; - if (output_tail_idx >= SPI_BUF_LEN) { - output_tail_idx = 0; - } + if (spi_mode == SPI_MODE_IDLE) { + if (ready_to_send) { + slave_send_size = fifo_count(&output_buffer); + U1DBUF_write = slave_send_size; } else { - U1DBUF = 0x99; + U1DBUF_write = 0; } + } + else if (slave_send_size > 0) { + U1DBUF_write = fifo_get(&output_buffer); } else { - U1DBUF = 0x99; + // Filler for when we are receiving data, but not sending anything + U1DBUF_write = 0x00; } } -uint8_t serial_rx_byte() { +uint8_t serial_rx_avail() +{ + return fifo_count(&input_buffer); +} + +uint8_t serial_rx_byte() +{ uint8_t s_data; - while(!SERIAL_DATA_AVAILABLE); - s_data = spi_input_buf[input_tail_idx]; - input_tail_idx++; - if (input_tail_idx >= SPI_BUF_LEN) { - input_tail_idx = 0; + if (!serial_data_available) { + while(!serial_data_available && !subg_rfspy_should_exit) { + feed_watchdog(); + } } - input_size--; - if (input_size == 0) { + s_data = fifo_get(&input_buffer); + if (fifo_empty(&input_buffer)) { serial_data_available = 0; } return s_data; -} +} -uint16_t serial_rx_word() { +uint16_t serial_rx_word() +{ return (serial_rx_byte() << 8) + serial_rx_byte(); } -uint32_t serial_rx_long() { +uint32_t serial_rx_long() +{ return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); } -void serial_tx_byte(uint8_t tx_byte) { - if (output_size >= SPI_BUF_LEN) { - // drop oldest byte - output_size--; - output_tail_idx++; - if (output_tail_idx >= SPI_BUF_LEN) { - output_tail_idx = 0; - } +void serial_tx_byte(uint8_t tx_byte) +{ + fifo_put(&output_buffer, tx_byte); +} + +void serial_tx_word(uint16_t tx_word) +{ + fifo_put(&output_buffer, tx_word >> 8); + fifo_put(&output_buffer, tx_word & 0xff); +} + +void serial_tx_long(uint32_t tx_long) +{ + fifo_put(&output_buffer, tx_long >> 24); + fifo_put(&output_buffer, (tx_long >> 16) & 0xff); + fifo_put(&output_buffer, (tx_long >> 8) & 0xff); + fifo_put(&output_buffer, tx_long & 0xff); +} + +void serial_flush() +{ + uint32_t start_time; + + if (fifo_empty(&output_buffer)) { + return; } - spi_output_buf[output_head_idx] = tx_byte; - if (tx_byte == 0) { - ready_to_send = 1; + + // Waiting for tx isr to ask for data + read_timer(&start_time); + ready_to_send = 1; + while(!fifo_empty(&output_buffer) && !subg_rfspy_should_exit) { + feed_watchdog(); + if (check_elapsed(start_time, FLUSH_TIMEOUT_MS)) { + break; + } } - output_head_idx++; - if (output_head_idx >= SPI_BUF_LEN) { - output_head_idx = 0; + + // Waiting to finish spi transfer + while(slave_send_size != 0 && !subg_rfspy_should_exit) { + feed_watchdog(); + if (check_elapsed(start_time, FLUSH_TIMEOUT_MS)) { + break; + } } - output_size++; + ready_to_send = 0; } void serial_tx_str(const char *str) { @@ -205,7 +256,5 @@ void serial_tx_str(const char *str) { serial_tx_byte(*str); str++; } - serial_tx_byte(0); + serial_flush(); } - - diff --git a/spi1_alt2/serial.h b/spi1_alt2/serial.h index 2b20f2b..52c1425 100644 --- a/spi1_alt2/serial.h +++ b/spi1_alt2/serial.h @@ -1,14 +1,21 @@ #ifndef SERIAL_H #define SERIAL_H +#include + #define SERIAL_DATA_AVAILABLE serial_data_available extern volatile uint8_t serial_data_available; void configure_serial(); void serial_tx_byte(uint8_t); +void serial_tx_word(uint16_t tx_word); +void serial_tx_long(uint32_t tx_long); void serial_tx_str(const char *str); +void serial_flush(); uint8_t serial_rx_byte(); +uint16_t serial_rx_word(); uint32_t serial_rx_long(); +uint8_t serial_rx_avail(); #endif diff --git a/statistics.c b/statistics.c new file mode 100644 index 0000000..b8ca8c4 --- /dev/null +++ b/statistics.c @@ -0,0 +1,9 @@ + +#include "statistics.h" + +volatile uint16_t radio_rx_overflow_count; +volatile uint16_t radio_rx_fifo_overflow_count; +uint16_t packet_rx_count; +uint16_t packet_tx_count; +uint16_t crc_failure_count; +volatile uint16_t spi_sync_failure_count; diff --git a/statistics.h b/statistics.h new file mode 100644 index 0000000..445043f --- /dev/null +++ b/statistics.h @@ -0,0 +1,14 @@ +#ifndef STATISTICS_H +#define STATISTICS_H + +#include + +volatile extern uint16_t radio_rx_overflow_count; +volatile extern uint16_t radio_rx_fifo_overflow_count; +volatile extern uint16_t serial_rx_overflow_count; +extern uint16_t packet_tx_count; +extern uint16_t packet_rx_count; +extern uint16_t crc_failure_count; +volatile extern uint16_t spi_sync_failure_count; + +#endif //STATISTICS_H diff --git a/subg_rfspy.c b/subg_rfspy.c new file mode 100644 index 0000000..d781ee6 --- /dev/null +++ b/subg_rfspy.c @@ -0,0 +1,49 @@ +/* Control a cc1110 for sub-ghz RF comms over uart. */ + +#include +#include +#include "hardware.h" +#include "serial.h" +#include "radio.h" +#include "timer.h" +#include "commands.h" +#include "subg_rfspy.h" + +bool __xdata subg_rfspy_init_finished; +bool __xdata subg_rfspy_should_exit; + +void subg_rfspy_main() { + // Set the system clock source to HS XOSC and max CPU speed, + // ref. [clk]=>[clk_xosc.c] + SLEEP &= ~SLEEP_OSC_PD; + while( !(SLEEP & SLEEP_XOSC_S) ); + CLKCON = (CLKCON & ~(CLKCON_CLKSPD | CLKCON_OSC)) | CLKSPD_DIV_1; + while (CLKCON & CLKCON_OSC); + SLEEP |= SLEEP_OSC_PD; + + init_leds(); + + // Global interrupt enable + init_timer(); + EA = 1; + + configure_serial(); + configure_radio(); + + //LED test + GREEN_LED_PIN = 1; + delay(100); + GREEN_LED_PIN = 0; + BLUE_LED_PIN = 1; + delay(100); + BLUE_LED_PIN = 0; + + subg_rfspy_init_finished = true; + + // Start watchdog at 1s interval + WDCTL = WDCTL_EN; + + while(!subg_rfspy_should_exit) { + get_command(); + } +} diff --git a/subg_rfspy.h b/subg_rfspy.h new file mode 100644 index 0000000..1298901 --- /dev/null +++ b/subg_rfspy.h @@ -0,0 +1,11 @@ +#ifndef SUBG_RFSPY_H +#define SUBG_RFSPY_H + +#include + +void subg_rfspy_main(); + +extern bool __xdata subg_rfspy_init_finished; +extern bool __xdata subg_rfspy_should_exit; + +#endif // SUBG_RFSPY_H diff --git a/tests.c b/tests.c new file mode 100644 index 0000000..e19e61c --- /dev/null +++ b/tests.c @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include +#include +#include "hardware.h" +#include "subg_rfspy.h" +#include "serial.h" +#include "commands.h" +#include "version.h" + +#define RESPONSE_BUFFER_SIZE 128 + +typedef struct { + uint8_t response_code; + uint8_t data[RESPONSE_BUFFER_SIZE]; + uint8_t response_length; + bool timed_out; +} CommandResponse; + +void hexprint(const char *prefix, const uint8_t *data, int len) +{ + printf("%s", prefix); + for (int i=0; i RESPONSE_BUFFER_SIZE) { + printf("Bad response size: %d\n", len); + len = RESPONSE_BUFFER_SIZE; + } + + uint8_t throwaway_rx_buf[RESPONSE_BUFFER_SIZE]; + + if (input) { + hexprint("tx: ", input, len); + } else { + printf("tx: NULL\n"); + } + + if (output == NULL) { + output = throwaway_rx_buf; + } + + uint8_t slave_byte; + for (int i=0; i 0) { + printf("Unexpected response data while sending command\n"); + if (slave_bytes_avail > len) { + len = slave_bytes_avail; + } + } + do_spi(data, NULL, len); +} + +CommandResponse wait_for_response(int max_xfer_cycles) { + CommandResponse response; + uint8_t tmp[2]; + memset(&response, 0, sizeof(CommandResponse)); + while(max_xfer_cycles--) { + tmp[0] = 0x99; + tmp[1] = 0; + do_spi(tmp, tmp, 2); + if (tmp[1] > 0) { + response.response_length = tmp[1]; + do_spi(NULL, (uint8_t*)&response, response.response_length); + break; + } + // TODO: check timeout + } + if (max_xfer_cycles <= 0) { + response.timed_out = true; + } + return response; +} + + +CommandResponse run_command(uint8_t len, const uint8_t *data, int max_xfer_cycles) +{ + send_command(len, data); + return wait_for_response(max_xfer_cycles); +} + +bool equal(int expected, int actual, const char *desc) +{ + if (expected != actual) { + fprintf(stderr, "Expected %s to equal %d, but was %d instead.\n", desc, expected, actual); + } + return expected == actual; +} + +void check_version() +{ + uint8_t cmd = CmdGetVersion; + CommandResponse response; + response = run_command(1, &cmd, 20); + assert(!response.timed_out); + assert(strcmp((const char*)response.data, SUBG_RFSPY_VERSION) == 0); +} + +void check_sync_error_extra_byte() +{ + CommandResponse response; + uint8_t tmp[1]; + + // Send extra byte (not conforming to protocol) + tmp[0] = 0x99; + do_spi(tmp, tmp, 1); + + tmp[0] = CmdGetVersion; + response = run_command(1, tmp, 20); + // Expected behavior: timeout + assert(response.timed_out); + + // Should recover + tmp[0] = CmdGetVersion; + response = run_command(1, tmp, 20); + assert(!response.timed_out); + assert(strcmp((const char*)response.data, SUBG_RFSPY_VERSION) == 0); +} + +void check_sync_error_dropped_byte() +{ + CommandResponse response; + uint8_t tmp[3]; + + // Drop byte (not conforming to protocol) + // CmdUpdateRegister should be 3 bytes, but only send 2 + tmp[0] = CmdUpdateRegister; + tmp[1] = 1; // SYNC0 + tmp[2] = 0xff; + response = run_command(2, tmp, 20); + // Expected behavior: timeout + assert(response.timed_out); + + // one failure (this data finishes the previous update register command) + // subg_rfspy responds with success, since it received enough data for + // the update register command. But we're out of sync now. + tmp[0] = CmdGetVersion; + response = run_command(1, tmp, 20); + assert(!response.timed_out); + assert(equal(1, response.response_length, "response.response_length")); + + // Recovery + tmp[0] = CmdGetVersion; + response = run_command(1, tmp, 20); + assert(!response.timed_out); + assert(strcmp((const char*)response.data, SUBG_RFSPY_VERSION) == 0); +} + +void check_interrupting_command() +{ + CommandResponse response; + uint8_t tmp[6]; + + // Send a listening command (4s timeout) + tmp[0] = CmdGetPacket; + tmp[1] = 1; // channel + tmp[2] = 1; // timeout(4) + tmp[3] = 0; // timeout(3) + tmp[4] = 0; // timeout(2) + tmp[5] = 0; // timeout(1) + send_command(6, tmp); + + // Interrupt it with a set register command + tmp[0] = CmdUpdateRegister; + tmp[1] = 1; // SYNC0 + tmp[2] = 0xff; + send_command(3, tmp); + + response = wait_for_response(20); + + // Expected response: command interrupted + assert(!response.timed_out); + assert(equal(RESPONSE_CODE_CMD_INTERRUPTED, response.response_code, "response.response_code")); + + response = wait_for_response(20); + + // Expected response: command successful + assert(!response.timed_out); + assert(equal(RESPONSE_CODE_SUCCESS, response.response_code, "response.response_code")); +} + + +void *run_main(void *vargp) { + printf("starting main thread\n"); + subg_rfspy_main(); + return NULL; +} + +int main(void) +{ + #ifdef MOCK_HARDWARE + pthread_t mock_hardware_thread; + pthread_create(&mock_hardware_thread, NULL, run_mock_hardware, NULL); + #endif + + #ifdef RUN_TESTS + pthread_t run_main_thread; + pthread_create(&run_main_thread, NULL, run_main, NULL); + #endif + + while(!subg_rfspy_init_finished); + + // Run tests! + check_version(); + check_sync_error_extra_byte(); + check_sync_error_dropped_byte(); + check_interrupting_command(); + + subg_rfspy_should_exit = true; + pthread_join(run_main_thread, NULL); + + mock_hardware_should_exit = true; + pthread_join(mock_hardware_thread, NULL); + + // If we are here, all tests passed. + printf("Tests succeeded!\n"); +} diff --git a/timer.c b/timer.c index d56b9b0..9485ef2 100644 --- a/timer.c +++ b/timer.c @@ -1,8 +1,9 @@ #include #include "hardware.h" +#include "timer.h" -volatile uint32_t timerCounter = 0; +volatile uint32_t __timerCounter = 0; void init_timer() { union { @@ -14,6 +15,8 @@ void init_timer() { // 1000 is scaling mhz to cycles/msec, 128 is T1CTL.DIV, 2 is TICKSPD uint16_t timer_ticks_per_ms = (SYSTEM_CLOCK_MHZ * 1000) / 128 / 2; + __timerCounter = 0; + T1CTL = 0x00; // disable timer T1CNTL = 0x00; // Clear counter low @@ -22,7 +25,7 @@ void init_timer() { do { t1cnt.byte[0] = T1CNTL; - t1cnt.byte[1] = T1CNTH; + t1cnt.byte[1] = T1CNTH; } while (t1cnt.val <= 0xA000); // Stop timer @@ -40,15 +43,15 @@ void init_timer() { T1CTL = 0x0e; // TickFreq/128, modulo } -void reset_timer() { - timerCounter = 0; -} - void t1_isr(void) __interrupt T1_VECTOR { - if (timerCounter % 1000 == 0) { - //BLUE_LED = !BLUE_LED; - } - timerCounter++; + __timerCounter++; } +void delay(uint32_t msec) { + uint32_t start_time; + read_timer(&start_time); + while(!check_elapsed(start_time, msec)) { + feed_watchdog(); + } +} diff --git a/timer.h b/timer.h index 82157a3..e26c112 100644 --- a/timer.h +++ b/timer.h @@ -1,10 +1,28 @@ #ifndef TIMER_H #define TIMER_H -volatile extern uint32_t timerCounter; +#include +#include + +volatile extern uint32_t __timerCounter; void init_timer(); -void reset_timer(); -#endif +void delay(uint32_t msec); + +inline void read_timer(uint32_t *result) { + EA = 0; + *result = __timerCounter; + EA = 1; +} +// Returns true if time has elapsed +inline bool check_elapsed(uint32_t start_time, uint32_t duration) { + bool rval; + EA = 0; + rval = (__timerCounter - start_time) > duration; + EA = 1; + return rval; +} + +#endif diff --git a/tools/serial_rf_spy.py b/tools/serial_rf_spy.py index 4e4b975..0d23722 100755 --- a/tools/serial_rf_spy.py +++ b/tools/serial_rf_spy.py @@ -9,10 +9,11 @@ class SerialRfSpy: CMD_GET_STATE = 1 CMD_GET_VERSION = 2 CMD_GET_PACKET = 3 - CMD_SEND_PACKET = 4 + CMD_OLD_SEND_PACKET = 4 CMD_SEND_AND_LISTEN = 5 CMD_UPDATE_REGISTER = 6 CMD_RESET = 7 + CMD_SEND_PACKET = 8 def __init__(self, serial_port, rtscts=None): if not rtscts: @@ -24,15 +25,15 @@ def __init__(self, serial_port, rtscts=None): self.ser = serial.Serial(serial_port, 19200, rtscts=rtscts, timeout=1) self.buf = bytearray() - def do_command(self, command, param=""): + def do_command(self, command, param=""): self.send_command(command, param) return self.get_response() - def send_command(self, command, param=""): + def send_command(self, command, param=""): cmd_str = chr(command) + param self.ser.write(cmd_str) - def get_response(self, timeout=0): + def get_response(self, timeout=0): start = time.time() while 1: bytesToRead = self.ser.inWaiting() @@ -46,10 +47,10 @@ def get_response(self, timeout=0): if (timeout > 0) and (start + timeout < time.time()): return bytearray() time.sleep(0.005) - + def sync(self): while 1: - self.send_command(self.CMD_GET_STATE) + self.send_command(self.CMD_GET_STATE) data = self.get_response(1) if data == "OK": print "RileyLink " + data @@ -57,7 +58,7 @@ def sync(self): print "retry", len(data), str(data).encode('hex'), "(Do you need to run 'export RFSPY_RTSCTS=0' first?)" while 1: - self.send_command(self.CMD_GET_VERSION) + self.send_command(self.CMD_GET_VERSION) data = self.get_response(1) if len(data) >= 3: print "Version: " + data diff --git a/uart0_alt1/serial.c b/uart0_alt1/serial.c deleted file mode 100644 index 77b2dca..0000000 --- a/uart0_alt1/serial.c +++ /dev/null @@ -1,64 +0,0 @@ - -#include -#include "hardware.h" -#include "serial.h" -#include "radio.h" - -void configure_serial() -{ - - // UART0 Alt. 1 - // P0.2 - RX - // P0.3 - TX - // P0.4 - CT - // P0.5 - RT - - U0CSR |= 0x80; // UART Mode - PERCFG &= ~0x01; // Alternative 1 - P0SEL |= 0x3C; // P0.5 -> P0.2 - P1SEL &= ~0x3C; - - /////////////////////////////////////////////////////////////// - // Initialize bitrate (U0BAUD.BAUD_M, U0GCR.BAUD_E) - // Bitrate 19200 - U0BAUD = 163; - U0GCR = (U0GCR&~0x1F) | 9; - U0UCR |= HARDWARE_FLOW_CONTROL_CONFIG; // Flush, and configure hw flow control - - // Enable receive - U0CSR |= 0x40; - URX0IF = 0; - -} - -uint8_t serial_rx_byte() { - uint8_t s_data; - while(!SERIAL_DATA_AVAILABLE); // URX0IF - s_data = U0DBUF; - URX0IF = 0; - return s_data; -} - -uint16_t serial_rx_word() { - return (serial_rx_byte() << 8) + serial_rx_byte(); -} - -uint32_t serial_rx_long() { - return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); -} - - -void serial_tx_byte(uint8_t tx_byte) { - UTX0IF = 0; - U0DBUF = tx_byte; - while ( !UTX0IF ); - UTX0IF = 0; -} - -void serial_tx_str(const char *str) { - while(*str != 0) { - serial_tx_byte(*str); - str++; - } - serial_tx_byte(0); -} diff --git a/uart0_alt1/serial.h b/uart0_alt1/serial.h deleted file mode 100644 index 388485a..0000000 --- a/uart0_alt1/serial.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef SERIAL_H -#define SERIAL_H - -#define SERIAL_DATA_AVAILABLE URX0IF - -void configure_serial(); -void serial_tx_byte(uint8_t); -void serial_tx_str(const char *str); -uint8_t serial_rx_byte(); -uint32_t serial_rx_long(); - -#endif diff --git a/uart1_alt2/serial.c b/uart1_alt2/serial.c deleted file mode 100644 index 70956ce..0000000 --- a/uart1_alt2/serial.c +++ /dev/null @@ -1,108 +0,0 @@ - -#include -#include "hardware.h" -#include "serial.h" -#include "radio.h" - -#define SERIAL_BUF_LEN 220 - -volatile uint8_t __xdata serial_input_buf[SERIAL_BUF_LEN]; -volatile uint8_t input_size = 0; -volatile uint8_t input_head_idx = 0; -volatile uint8_t input_tail_idx = 0; - -volatile uint8_t __xdata serial_output_buf[SERIAL_BUF_LEN]; -volatile uint8_t output_size = 0; -volatile uint8_t output_head_idx = 0; -volatile uint8_t output_tail_idx = 0; - -volatile uint8_t ready_to_send = 0; - -volatile uint8_t serial_data_available; - -void configure_serial() -{ - // UART1 Alt. 2 - // P1.4 - CT - // P1.5 - RT - // P1.6 - TX - // P1.7 - RX - - U1CSR |= 0x80; // UART Mode - PERCFG |= 0x02; // Alternative 2 - P1SEL |= 0xf0; // P1.7 -> P1.4 - P0SEL &= ~0x3c; - - /////////////////////////////////////////////////////////////// - // Initialize bitrate (U1BAUD.BAUD_M, U1GCR.BAUD_E) - // Bitrate 19200 -#if SYSTEM_CLOCK_MHZ == 26 - U1BAUD = 131; -#else - U1BAUD = 163; -#endif - U1GCR = (U0GCR&~0x1F) | 9; - U1UCR |= HARDWARE_FLOW_CONTROL_CONFIG; // Flush, and configure hw flow control - - // Enable receive - U1CSR |= 0x40; - URX1IF = 0; - IEN0 |= 0x88; -} - -void rx1_isr(void) __interrupt URX1_VECTOR { - URX1IF = 0; - if (input_size < SERIAL_BUF_LEN) { - serial_input_buf[input_head_idx] = U1DBUF; - input_head_idx++; - if (input_head_idx >= SERIAL_BUF_LEN) { - input_head_idx = 0; - } - input_size++; - serial_data_available = 1; - } else { - // overflow - } -} - -uint8_t serial_rx_byte() { - uint8_t s_data; - while(!SERIAL_DATA_AVAILABLE); // URX1IF - s_data = serial_input_buf[input_tail_idx]; - input_tail_idx++; - if (input_tail_idx >= SERIAL_BUF_LEN) { - input_tail_idx = 0; - } - input_size--; - if (input_size == 0) { - serial_data_available = 0; - } - return s_data; -} - -uint16_t serial_rx_word() { - return (serial_rx_byte() << 8) + serial_rx_byte(); -} - -uint32_t serial_rx_long() { - return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); -} - - -void serial_tx_byte(uint8_t tx_byte) { - UTX1IF = 0; - U1DBUF = tx_byte; - while ( !UTX1IF ); - UTX1IF = 0; -} - -void serial_tx_str(const char *str) { - while(*str != 0) { - serial_tx_byte(*str); - str++; - } - serial_tx_byte(0); -} - - - diff --git a/uart1_alt2/serial.h b/uart1_alt2/serial.h deleted file mode 100644 index 2b20f2b..0000000 --- a/uart1_alt2/serial.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef SERIAL_H -#define SERIAL_H - -#define SERIAL_DATA_AVAILABLE serial_data_available - -extern volatile uint8_t serial_data_available; - -void configure_serial(); -void serial_tx_byte(uint8_t); -void serial_tx_str(const char *str); -uint8_t serial_rx_byte(); -uint32_t serial_rx_long(); - -#endif diff --git a/usb_ep0/cc1111.h b/usb_ep0/cc1111.h deleted file mode 100644 index ac1e71c..0000000 --- a/usb_ep0/cc1111.h +++ /dev/null @@ -1,1389 +0,0 @@ -/*------------------------------------------------------------------------- - Register Declarations for the ChipCon CC1111 Processor Range - - Copyright © 2008 Keith Packard - - 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; version 2 of the License. - - 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; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - Adapted from the Cygnal C8051F12x config file which is: - - Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --------------------------------------------------------------------------*/ - -#ifndef _CC1111_H_ -#define _CC1111_H_ -#include -#include - -__sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ - -__sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ -__sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ -__sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ -__sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ -__sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ -__sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ -__sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ -__sbit __at 0xAF EA; /* Enable All */ - -#define IEN0_EA (1 << 7) -#define IEN0_STIE (1 << 5) -#define IEN0_ENCIE (1 << 4) -#define IEN0_URX1IE (1 << 3) -#define IEN0_I2SRXIE (1 << 3) -#define IEN0_URX0IE (1 << 2) -#define IEN0_ADCIE (1 << 1) -#define IEN0_RFTXRXIE (1 << 0) - -__sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ - -#define IEN1_P0IE (1 << 5) /* Port 0 interrupt enable */ -#define IEN1_T4IE (1 << 4) /* Timer 4 interrupt enable */ -#define IEN1_T3IE (1 << 3) /* Timer 3 interrupt enable */ -#define IEN1_T2IE (1 << 2) /* Timer 2 interrupt enable */ -#define IEN1_T1IE (1 << 1) /* Timer 1 interrupt enable */ -#define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ - -/* IEN2 */ -__sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ - -#define IEN2_WDTIE (1 << 5) /* Watchdog timer interrupt enable */ -#define IEN2_P1IE (1 << 4) /* Port 1 interrupt enable */ -#define IEN2_UTX1IE (1 << 3) /* USART1 TX interrupt enable */ -#define IEN2_I2STXIE (1 << 3) /* I2S TX interrupt enable */ -#define IEN2_UTX0IE (1 << 2) /* USART0 TX interrupt enable */ -#define IEN2_P2IE (1 << 1) /* Port 2 interrupt enable */ -#define IEN2_USBIE (1 << 1) /* USB interrupt enable */ -#define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ - -/* CLKCON 0xC6 */ -__sfr __at 0xC6 CLKCON; /* Clock Control */ - -#define CLKCON_OSC32K_RC (1 << 7) -#define CLKCON_OSC32K_XTAL (0 << 7) -#define CLKCON_OSC32K_MASK (1 << 7) -#define CLKCON_OSC_RC (1 << 6) -#define CLKCON_OSC_XTAL (0 << 6) -#define CLKCON_OSC_MASK (1 << 6) -#define CLKCON_TICKSPD_MASK (7 << 3) -# define CLKCON_TICKSPD_1 (0 << 3) -# define CLKCON_TICKSPD_1_2 (1 << 3) -# define CLKCON_TICKSPD_1_4 (2 << 3) -# define CLKCON_TICKSPD_1_8 (3 << 3) -# define CLKCON_TICKSPD_1_16 (4 << 3) -# define CLKCON_TICKSPD_1_32 (5 << 3) -# define CLKCON_TICKSPD_1_64 (6 << 3) -# define CLKCON_TICKSPD_1_128 (7 << 3) - -#define CLKCON_CLKSPD_MASK (7 << 0) -# define CLKCON_CLKSPD_1 (0 << 0) -# define CLKCON_CLKSPD_1_2 (1 << 0) -# define CLKCON_CLKSPD_1_4 (2 << 0) -# define CLKCON_CLKSPD_1_8 (3 << 0) -# define CLKCON_CLKSPD_1_16 (4 << 0) -# define CLKCON_CLKSPD_1_32 (5 << 0) -# define CLKCON_CLKSPD_1_64 (6 << 0) -# define CLKCON_CLKSPD_1_128 (7 << 0) - -/* SLEEP 0xBE */ -#define SLEEP_USB_EN (1 << 7) -#define SLEEP_XOSC_STB (1 << 6) -#define SLEEP_HFRC_STB (1 << 5) -#define SLEEP_RST_POWER (0 << 3) -#define SLEEP_RST_EXTERNAL (1 << 3) -#define SLEEP_RST_WATCHDOG (2 << 3) -#define SLEEP_RST_MASK (3 << 3) -#define SLEEP_OSC_PD (1 << 2) -#define SLEEP_MODE_PM0 (0 << 0) -#define SLEEP_MODE_PM1 (1 << 0) -#define SLEEP_MODE_PM2 (2 << 0) -#define SLEEP_MODE_PM3 (3 << 0) -#define SLEEP_MODE_MASK (3 << 0) - -/* PCON 0x87 */ -__sfr __at 0x87 PCON; /* Power Mode Control Register */ - -#define PCON_IDLE (1 << 0) - -/* - * TCON - */ -__sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ - -__sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ -__sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ -__sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ -__sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ -__sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ - -#define TCON_URX1IF (1 << 7) -#define TCON_I2SRXIF (1 << 7) -#define TCON_ADCIF (1 << 5) -#define TCON_URX0IF (1 << 3) -#define TCON_RFTXRXIF (1 << 1) - -/* - * S0CON - */ -__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ - -__sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ -__sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ - -#define S0CON_ENCIF_1 (1 << 1) -#define S0CON_ENCIF_0 (1 << 0) - -/* - * S1CON - */ -__sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ - -#define S1CON_RFIF_1 (1 << 1) -#define S1CON_RFIF_0 (1 << 0) - -/* - * IRCON - */ -__sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ - -__sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ -__sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ -__sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ -__sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ -__sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ -__sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ -__sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ - -#define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ -#define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ -#define IRCON_T2IF (1 << 2) /* Timer 2 interrupt flag. Automatically cleared */ -#define IRCON_T3IF (1 << 3) /* Timer 3 interrupt flag. Automatically cleared */ -#define IRCON_T4IF (1 << 4) /* Timer 4 interrupt flag. Automatically cleared */ -#define IRCON_P0IF (1 << 5) /* Port0 interrupt flag */ -#define IRCON_STIF (1 << 7) /* Sleep Timer interrupt flag */ - -/* - * IRCON2 - */ -__sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ - -__sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ -__sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ -__sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ -__sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ -__sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ -__sbit __at 0xEB P1IF; /* Port1 interrupt flag */ -__sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ - -#define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ -#define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ -#define IRCON2_UTX0IF (1 << 1) /* USART0 TX interrupt flag */ -#define IRCON2_UTX1IF (1 << 2) /* USART1 TX interrupt flag (shared with I2S TX) */ -#define IRCON2_I2STXIF (1 << 2) /* I2S TX interrupt flag (shared with USART1 TX) */ -#define IRCON2_P1IF (1 << 3) /* Port1 interrupt flag */ -#define IRCON2_WDTIF (1 << 4) /* Watchdog timer interrupt flag */ - -/* - * IP1 - Interrupt Priority 1 - */ - -/* - * Interrupt priority groups: - * - * IPG0 RFTXRX RF DMA - * IPG1 ADC T1 P2INT/USB - * IPG2 URX0 T2 UTX0 - * IPG3 URX1/I2SRX T3 UTX1 / I2STX - * IPG4 ENC T4 P1INT - * IPG5 ST P0INT WDT - * - * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first - */ - -__sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ -__sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ - -#define IP1_IPG5 (1 << 5) -#define IP1_IPG4 (1 << 4) -#define IP1_IPG3 (1 << 3) -#define IP1_IPG2 (1 << 2) -#define IP1_IPG1 (1 << 1) -#define IP1_IPG0 (1 << 0) - -#define IP0_IPG5 (1 << 5) -#define IP0_IPG4 (1 << 4) -#define IP0_IPG3 (1 << 3) -#define IP0_IPG2 (1 << 2) -#define IP0_IPG1 (1 << 1) -#define IP0_IPG0 (1 << 0) - -/* - * Timer 1 - */ -#define T1CTL_MODE_SUSPENDED (0 << 0) -#define T1CTL_MODE_FREE (1 << 0) -#define T1CTL_MODE_MODULO (2 << 0) -#define T1CTL_MODE_UP_DOWN (3 << 0) -#define T1CTL_MODE_MASK (3 << 0) -#define T1CTL_DIV_1 (0 << 2) -#define T1CTL_DIV_8 (1 << 2) -#define T1CTL_DIV_32 (2 << 2) -#define T1CTL_DIV_128 (3 << 2) -#define T1CTL_DIV_MASK (3 << 2) -#define T1CTL_OVFIF (1 << 4) -#define T1CTL_CH0IF (1 << 5) -#define T1CTL_CH1IF (1 << 6) -#define T1CTL_CH2IF (1 << 7) - -#define T1CCTL_NO_CAPTURE (0 << 0) -#define T1CCTL_CAPTURE_RISING (1 << 0) -#define T1CCTL_CAPTURE_FALLING (2 << 0) -#define T1CCTL_CAPTURE_BOTH (3 << 0) -#define T1CCTL_CAPTURE_MASK (3 << 0) - -#define T1CCTL_MODE_CAPTURE (0 << 2) -#define T1CCTL_MODE_COMPARE (1 << 2) - -#define T1CTL_CMP_SET (0 << 3) -#define T1CTL_CMP_CLEAR (1 << 3) -#define T1CTL_CMP_TOGGLE (2 << 3) -#define T1CTL_CMP_SET_CLEAR (3 << 3) -#define T1CTL_CMP_CLEAR_SET (4 << 3) - -#define T1CTL_IM_DISABLED (0 << 6) -#define T1CTL_IM_ENABLED (1 << 6) - -#define T1CTL_CPSEL_NORMAL (0 << 7) -#define T1CTL_CPSEL_RF (1 << 7) - -/* - * Timer 3 and Timer 4 - */ - -/* Timer count */ -__sfr __at 0xCA T3CNT; -__sfr __at 0xEA T4CNT; - -/* Timer control */ - -__sfr __at 0xCB T3CTL; -__sfr __at 0xEB T4CTL; - -#define TxCTL_DIV_1 (0 << 5) -#define TxCTL_DIV_2 (1 << 5) -#define TxCTL_DIV_4 (2 << 5) -#define TxCTL_DIV_8 (3 << 5) -#define TxCTL_DIV_16 (4 << 5) -#define TxCTL_DIV_32 (5 << 5) -#define TxCTL_DIV_64 (6 << 5) -#define TxCTL_DIV_128 (7 << 5) -#define TxCTL_START (1 << 4) -#define TxCTL_OVFIM (1 << 3) -#define TxCTL_CLR (1 << 2) -#define TxCTL_MODE_FREE (0 << 0) -#define TxCTL_MODE_DOWN (1 << 0) -#define TxCTL_MODE_MODULO (2 << 0) -#define TxCTL_MODE_UP_DOWN (3 << 0) - -/* Timer 4 channel 0 compare control */ - -__sfr __at 0xCC T3CCTL0; -__sfr __at 0xCE T3CCTL1; -__sfr __at 0xEC T4CCTL0; -__sfr __at 0xEE T4CCTL1; - -#define TxCCTLy_IM (1 << 6) -#define TxCCTLy_CMP_SET (0 << 3) -#define TxCCTLy_CMP_CLEAR (1 << 3) -#define TxCCTLy_CMP_TOGGLE (2 << 3) -#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN (3 << 3) -#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN (4 << 3) -#define TxCCTLy_CMP_SET_CLEAR_FF (5 << 3) -#define TxCCTLy_CMP_CLEAR_SET_00 (6 << 3) -#define TxCCTLy_CMP_MODE_ENABLE (1 << 2) - -/* Timer compare value */ -__sfr __at 0xCD T3CC0; -__sfr __at 0xCF T3CC1; -__sfr __at 0xED T4CC0; -__sfr __at 0xEF T4CC1; - -/* - * Peripheral control - */ - -__sfr __at 0xf1 PERCFG; -#define PERCFG_T1CFG_ALT_1 (0 << 6) -#define PERCFG_T1CFG_ALT_2 (1 << 6) -#define PERCFG_T1CFG_ALT_MASK (1 << 6) - -#define PERCFG_T3CFG_ALT_1 (0 << 5) -#define PERCFG_T3CFG_ALT_2 (1 << 5) -#define PERCFG_T3CFG_ALT_MASK (1 << 5) - -#define PERCFG_T4CFG_ALT_1 (0 << 4) -#define PERCFG_T4CFG_ALT_2 (1 << 4) -#define PERCFG_T4CFG_ALT_MASK (1 << 4) - -#define PERCFG_U1CFG_ALT_1 (0 << 1) -#define PERCFG_U1CFG_ALT_2 (1 << 1) -#define PERCFG_U1CFG_ALT_MASK (1 << 1) - -#define PERCFG_U0CFG_ALT_1 (0 << 0) -#define PERCFG_U0CFG_ALT_2 (1 << 0) -#define PERCFG_U0CFG_ALT_MASK (1 << 0) - -/* directly addressed USB registers */ -__xdata __at (0xde00) volatile uint8_t USBADDR; -__xdata __at (0xde01) volatile uint8_t USBPOW; -__xdata __at (0xde02) volatile uint8_t USBIIF; - -__xdata __at (0xde04) volatile uint8_t USBOIF; - -__xdata __at (0xde06) volatile uint8_t USBCIF; - -# define USBCIF_SOFIF (1 << 3) -# define USBCIF_RSTIF (1 << 2) -# define USBCIF_RESUMEIF (1 << 1) -# define USBCIF_SUSPENDIF (1 << 0) - -__xdata __at (0xde07) volatile uint8_t USBIIE; - -__xdata __at (0xde09) volatile uint8_t USBOIE; - -__xdata __at (0xde0b) volatile uint8_t USBCIE; - -# define USBCIE_SOFIE (1 << 3) -# define USBCIE_RSTIE (1 << 2) -# define USBCIE_RESUMEIE (1 << 1) -# define USBCIE_SUSPENDIE (1 << 0) - -__xdata __at (0xde0c) volatile uint8_t USBFRML; -__xdata __at (0xde0d) volatile uint8_t USBFRMH; -__xdata __at (0xde0e) volatile uint8_t USBINDEX; - -/* indexed USB registers, must set USBINDEX to 0-5 */ -__xdata __at (0xde10) volatile uint8_t USBMAXI; -__xdata __at (0xde11) volatile uint8_t USBCS0; - -# define USBCS0_CLR_SETUP_END (1 << 7) -# define USBCS0_CLR_OUTPKT_RDY (1 << 6) -# define USBCS0_SEND_STALL (1 << 5) -# define USBCS0_SETUP_END (1 << 4) -# define USBCS0_DATA_END (1 << 3) -# define USBCS0_SENT_STALL (1 << 2) -# define USBCS0_INPKT_RDY (1 << 1) -# define USBCS0_OUTPKT_RDY (1 << 0) - -__xdata __at (0xde11) volatile uint8_t USBCSIL; - -# define USBCSIL_CLR_DATA_TOG (1 << 6) -# define USBCSIL_SENT_STALL (1 << 5) -# define USBCSIL_SEND_STALL (1 << 4) -# define USBCSIL_FLUSH_PACKET (1 << 3) -# define USBCSIL_UNDERRUN (1 << 2) -# define USBCSIL_PKT_PRESENT (1 << 1) -# define USBCSIL_INPKT_RDY (1 << 0) - -__xdata __at (0xde12) volatile uint8_t USBCSIH; - -# define USBCSIH_AUTOSET (1 << 7) -# define USBCSIH_ISO (1 << 6) -# define USBCSIH_FORCE_DATA_TOG (1 << 3) -# define USBCSIH_IN_DBL_BUF (1 << 0) - -__xdata __at (0xde13) volatile uint8_t USBMAXO; -__xdata __at (0xde14) volatile uint8_t USBCSOL; - -# define USBCSOL_CLR_DATA_TOG (1 << 7) -# define USBCSOL_SENT_STALL (1 << 6) -# define USBCSOL_SEND_STALL (1 << 5) -# define USBCSOL_FLUSH_PACKET (1 << 4) -# define USBCSOL_DATA_ERROR (1 << 3) -# define USBCSOL_OVERRUN (1 << 2) -# define USBCSOL_FIFO_FULL (1 << 1) -# define USBCSOL_OUTPKT_RDY (1 << 0) - -__xdata __at (0xde15) volatile uint8_t USBCSOH; - -# define USBCSOH_AUTOCLEAR (1 << 7) -# define USBCSOH_ISO (1 << 6) -# define USBCSOH_OUT_DBL_BUF (1 << 0) - -__xdata __at (0xde16) volatile uint8_t USBCNT0; -__xdata __at (0xde16) volatile uint8_t USBCNTL; -__xdata __at (0xde17) volatile uint8_t USBCNTH; - -__xdata __at (0xde20) volatile uint8_t USBFIFO[12]; - -/* ADC Data register, low and high */ -__sfr __at 0xBA ADCL; -__sfr __at 0xBB ADCH; -__xdata __at (0xDFBA) volatile uint16_t ADCXDATA; - -/* ADC Control Register 1 */ -__sfr __at 0xB4 ADCCON1; - -# define ADCCON1_EOC (1 << 7) /* conversion complete */ -# define ADCCON1_ST (1 << 6) /* start conversion */ - -# define ADCCON1_STSEL_MASK (3 << 4) /* start select */ -# define ADCCON1_STSEL_EXTERNAL (0 << 4) /* P2_0 pin triggers */ -# define ADCCON1_STSEL_FULLSPEED (1 << 4) /* full speed, no waiting */ -# define ADCCON1_STSEL_TIMER1 (2 << 4) /* timer 1 channel 0 */ -# define ADCCON1_STSEL_START (3 << 4) /* set start bit */ - -# define ADCCON1_RCTRL_MASK (3 << 2) /* random number control */ -# define ADCCON1_RCTRL_COMPLETE (0 << 2) /* operation completed */ -# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ - -/* ADC Control Register 2 */ -__sfr __at 0xB5 ADCCON2; - -# define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ -# define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ -# define ADCCON2_SREF_EXTERNAL (1 << 6) /* external on AIN7 cc1110 */ -# define ADCCON2_SREF_VDD (2 << 6) /* VDD on the AVDD pin */ -# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6) /* external on AIN6-7 cc1110 */ - -# define ADCCON2_SDIV_MASK (3 << 4) /* decimation rate */ -# define ADCCON2_SDIV_64 (0 << 4) /* 7 bits */ -# define ADCCON2_SDIV_128 (1 << 4) /* 9 bits */ -# define ADCCON2_SDIV_256 (2 << 4) /* 10 bits */ -# define ADCCON2_SDIV_512 (3 << 4) /* 12 bits */ - -# define ADCCON2_SCH_MASK (0xf << 0) /* Sequence channel select */ -# define ADCCON2_SCH_SHIFT 0 -# define ADCCON2_SCH_AIN0 (0 << 0) -# define ADCCON2_SCH_AIN1 (1 << 0) -# define ADCCON2_SCH_AIN2 (2 << 0) -# define ADCCON2_SCH_AIN3 (3 << 0) -# define ADCCON2_SCH_AIN4 (4 << 0) -# define ADCCON2_SCH_AIN5 (5 << 0) -# define ADCCON2_SCH_AIN6 (6 << 0) -# define ADCCON2_SCH_AIN7 (7 << 0) -# define ADCCON2_SCH_AIN0_AIN1 (8 << 0) -# define ADCCON2_SCH_AIN2_AIN3 (9 << 0) -# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0) -# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0) -# define ADCCON2_SCH_GND (0xc << 0) -# define ADCCON2_SCH_VREF (0xd << 0) -# define ADCCON2_SCH_TEMP (0xe << 0) -# define ADCCON2_SCH_VDD_3 (0xf << 0) - - -/* ADC Control Register 3 */ -__sfr __at 0xB6 ADCCON3; - -# define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ -# define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ -# define ADCCON3_EREF_EXTERNAL (1 << 6) /* external AIN7 cc1110 */ -# define ADCCON3_EREF_VDD (2 << 6) /* VDD on the AVDD pin */ -# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6) /* external AIN6-7 cc1110 */ -# define ADCCON3_EDIV_MASK (3 << 4) /* extral decimation */ -# define ADCCON3_EDIV_64 (0 << 4) /* 7 bits */ -# define ADCCON3_EDIV_128 (1 << 4) /* 9 bits */ -# define ADCCON3_EDIV_256 (2 << 4) /* 10 bits */ -# define ADCCON3_EDIV_512 (3 << 4) /* 12 bits */ -# define ADCCON3_ECH_MASK (0xf << 0) /* Sequence channel select */ -# define ADCCON3_ECH_SHIFT 0 -# define ADCCON3_ECH_AIN0 (0 << 0) -# define ADCCON3_ECH_AIN1 (1 << 0) -# define ADCCON3_ECH_AIN2 (2 << 0) -# define ADCCON3_ECH_AIN3 (3 << 0) -# define ADCCON3_ECH_AIN4 (4 << 0) -# define ADCCON3_ECH_AIN5 (5 << 0) -# define ADCCON3_ECH_AIN6 (6 << 0) -# define ADCCON3_ECH_AIN7 (7 << 0) -# define ADCCON3_ECH_AIN0_AIN1 (8 << 0) -# define ADCCON3_ECH_AIN2_AIN3 (9 << 0) -# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0) -# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0) -# define ADCCON3_ECH_GND (0xc << 0) -# define ADCCON3_ECH_VREF (0xd << 0) -# define ADCCON3_ECH_TEMP (0xe << 0) -# define ADCCON3_ECH_VDD_3 (0xf << 0) - -/* - * ADC configuration register, this selects which - * GPIO pins are to be used as ADC inputs - */ -__sfr __at 0xF2 ADCCFG; - -/* - * Watchdog timer - */ - -__sfr __at 0xc9 WDCTL; - -#define WDCTL_CLEAR_FIRST (0xa << 4) -#define WDCTL_CLEAR_SECOND (0x5 << 4) -#define WDCTL_EN (1 << 3) -#define WDCTL_MODE_WATCHDOG (0 << 2) -#define WDCTL_MODE_TIMER (1 << 2) -#define WDCTL_MODE_MASK (1 << 2) -#define WDCTL_INT_32768 (0 << 0) -#define WDCTL_INT_8192 (1 << 0) -#define WDCTL_INT_512 (2 << 0) -#define WDCTL_INT_64 (3 << 0) - -/* - * Pin selectors, these set which pins are - * using their peripheral function - */ -__sfr __at 0xF3 P0SEL; -__sfr __at 0xF4 P1SEL; -__sfr __at 0xF5 P2SEL; - -#define P2SEL_PRI3P1_USART0 (0 << 6) -#define P2SEL_PRI3P1_USART1 (1 << 6) -#define P2SEL_PRI3P1_MASK (1 << 6) -#define P2SEL_PRI2P1_USART1 (0 << 5) -#define P2SEL_PRI2P1_TIMER3 (1 << 5) -#define P2SEL_PRI2P1_MASK (1 << 5) -#define P2SEL_PRI1P1_TIMER1 (0 << 4) -#define P2SEL_PRI1P1_TIMER4 (1 << 4) -#define P2SEL_PRI1P1_MASK (1 << 4) -#define P2SEL_PRI0P1_USART0 (0 << 3) -#define P2SEL_PRI0P1_TIMER1 (1 << 3) -#define P2SEL_PRI0P1_MASK (1 << 3) -#define P2SEL_SELP2_4_GPIO (0 << 2) -#define P2SEL_SELP2_4_PERIPHERAL (1 << 2) -#define P2SEL_SELP2_4_MASK (1 << 2) -#define P2SEL_SELP2_3_GPIO (0 << 1) -#define P2SEL_SELP2_3_PERIPHERAL (1 << 1) -#define P2SEL_SELP2_3_MASK (1 << 1) -#define P2SEL_SELP2_0_GPIO (0 << 0) -#define P2SEL_SELP2_0_PERIPHERAL (1 << 0) -#define P2SEL_SELP2_0_MASK (1 << 0) - -/* - * For pins used as GPIOs, these set which are used as outputs - */ -__sfr __at 0xFD P0DIR; -__sfr __at 0xFE P1DIR; -__sfr __at 0xFF P2DIR; - -#define P2DIR_PRIP0_USART0_USART1 (0 << 6) -#define P2DIR_PRIP0_USART1_USART0 (1 << 6) -#define P2DIR_PRIP0_TIMER1_01_USART1 (2 << 6) -#define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) -#define P2DIR_PRIP0_MASK (3 << 6) - -__sfr __at 0x8F P0INP; - -/* Select between tri-state and pull up/down - * for pins P0_0 - P0_7. - */ -#define P0INP_MDP0_7_PULL (0 << 7) -#define P0INP_MDP0_7_TRISTATE (1 << 7) -#define P0INP_MDP0_6_PULL (0 << 6) -#define P0INP_MDP0_6_TRISTATE (1 << 6) -#define P0INP_MDP0_5_PULL (0 << 5) -#define P0INP_MDP0_5_TRISTATE (1 << 5) -#define P0INP_MDP0_4_PULL (0 << 4) -#define P0INP_MDP0_4_TRISTATE (1 << 4) -#define P0INP_MDP0_3_PULL (0 << 3) -#define P0INP_MDP0_3_TRISTATE (1 << 3) -#define P0INP_MDP0_2_PULL (0 << 2) -#define P0INP_MDP0_2_TRISTATE (1 << 2) -#define P0INP_MDP0_1_PULL (0 << 1) -#define P0INP_MDP0_1_TRISTATE (1 << 1) -#define P0INP_MDP0_0_PULL (0 << 0) -#define P0INP_MDP0_0_TRISTATE (1 << 0) - -__sfr __at 0xF6 P1INP; - -/* Select between tri-state and pull up/down - * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are - * always tri-stated - */ -#define P1INP_MDP1_7_PULL (0 << 7) -#define P1INP_MDP1_7_TRISTATE (1 << 7) -#define P1INP_MDP1_6_PULL (0 << 6) -#define P1INP_MDP1_6_TRISTATE (1 << 6) -#define P1INP_MDP1_5_PULL (0 << 5) -#define P1INP_MDP1_5_TRISTATE (1 << 5) -#define P1INP_MDP1_4_PULL (0 << 4) -#define P1INP_MDP1_4_TRISTATE (1 << 4) -#define P1INP_MDP1_3_PULL (0 << 3) -#define P1INP_MDP1_3_TRISTATE (1 << 3) -#define P1INP_MDP1_2_PULL (0 << 2) -#define P1INP_MDP1_2_TRISTATE (1 << 2) - -__sfr __at 0xF7 P2INP; -/* P2INP has three extra bits which are used to choose - * between pull-up and pull-down when they are not tri-stated - */ -#define P2INP_PDUP2_PULL_UP (0 << 7) -#define P2INP_PDUP2_PULL_DOWN (1 << 7) -#define P2INP_PDUP1_PULL_UP (0 << 6) -#define P2INP_PDUP1_PULL_DOWN (1 << 6) -#define P2INP_PDUP0_PULL_UP (0 << 5) -#define P2INP_PDUP0_PULL_DOWN (1 << 5) - -/* For the P2 pins, choose between tri-state and pull up/down - * mode - */ -#define P2INP_MDP2_4_PULL (0 << 4) -#define P2INP_MDP2_4_TRISTATE (1 << 4) -#define P2INP_MDP2_3_PULL (0 << 3) -#define P2INP_MDP2_3_TRISTATE (1 << 3) -#define P2INP_MDP2_2_PULL (0 << 2) -#define P2INP_MDP2_2_TRISTATE (1 << 2) -#define P2INP_MDP2_1_PULL (0 << 1) -#define P2INP_MDP2_1_TRISTATE (1 << 1) -#define P2INP_MDP2_0_PULL (0 << 0) -#define P2INP_MDP2_0_TRISTATE (1 << 0) - -/* GPIO interrupt status flags */ -__sfr __at 0x89 P0IFG; -__sfr __at 0x8A P1IFG; -__sfr __at 0x8B P2IFG; - -#define P0IFG_USB_RESUME (1 << 7) - -__sfr __at 0x8C PICTL; -#define PICTL_P2IEN (1 << 5) -#define PICTL_P0IENH (1 << 4) -#define PICTL_P0IENL (1 << 3) -#define PICTL_P2ICON (1 << 2) -#define PICTL_P1ICON (1 << 1) -#define PICTL_P0ICON (1 << 0) - -/* GPIO pins */ -__sfr __at 0x80 P0; - -__sbit __at 0x80 P0_0; -__sbit __at 0x81 P0_1; -__sbit __at 0x82 P0_2; -__sbit __at 0x83 P0_3; -__sbit __at 0x84 P0_4; -__sbit __at 0x85 P0_5; -__sbit __at 0x86 P0_6; -__sbit __at 0x87 P0_7; - -__sfr __at 0x90 P1; - -__sbit __at 0x90 P1_0; -__sbit __at 0x91 P1_1; -__sbit __at 0x92 P1_2; -__sbit __at 0x93 P1_3; -__sbit __at 0x94 P1_4; -__sbit __at 0x95 P1_5; -__sbit __at 0x96 P1_6; -__sbit __at 0x97 P1_7; - -__sfr __at 0xa0 P2; - -__sbit __at 0xa0 P2_0; -__sbit __at 0xa1 P2_1; -__sbit __at 0xa2 P2_2; -__sbit __at 0xa3 P2_3; -__sbit __at 0xa4 P2_4; - -/* DMA controller */ -struct cc_dma_channel { - uint8_t src_high; - uint8_t src_low; - uint8_t dst_high; - uint8_t dst_low; - uint8_t len_high; - uint8_t len_low; - uint8_t cfg0; - uint8_t cfg1; -}; - -# define DMA_LEN_HIGH_VLEN_MASK (7 << 5) -# define DMA_LEN_HIGH_VLEN_LEN (0 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) -# define DMA_LEN_HIGH_VLEN (2 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) -# define DMA_LEN_HIGH_MASK (0x1f) - -# define DMA_CFG0_WORDSIZE_8 (0 << 7) -# define DMA_CFG0_WORDSIZE_16 (1 << 7) -# define DMA_CFG0_TMODE_MASK (3 << 5) -# define DMA_CFG0_TMODE_SINGLE (0 << 5) -# define DMA_CFG0_TMODE_BLOCK (1 << 5) -# define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) -# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) - -/* - * DMA triggers - */ -# define DMA_CFG0_TRIGGER_NONE 0 -# define DMA_CFG0_TRIGGER_PREV 1 -# define DMA_CFG0_TRIGGER_T1_CH0 2 -# define DMA_CFG0_TRIGGER_T1_CH1 3 -# define DMA_CFG0_TRIGGER_T1_CH2 4 -# define DMA_CFG0_TRIGGER_T2_OVFL 6 -# define DMA_CFG0_TRIGGER_T3_CH0 7 -# define DMA_CFG0_TRIGGER_T3_CH1 8 -# define DMA_CFG0_TRIGGER_T4_CH0 9 -# define DMA_CFG0_TRIGGER_T4_CH1 10 -# define DMA_CFG0_TRIGGER_IOC_0 12 -# define DMA_CFG0_TRIGGER_IOC_1 13 -# define DMA_CFG0_TRIGGER_URX0 14 -# define DMA_CFG0_TRIGGER_UTX0 15 -# define DMA_CFG0_TRIGGER_URX1 16 -# define DMA_CFG0_TRIGGER_UTX1 17 -# define DMA_CFG0_TRIGGER_FLASH 18 -# define DMA_CFG0_TRIGGER_RADIO 19 -# define DMA_CFG0_TRIGGER_ADC_CHALL 20 -# define DMA_CFG0_TRIGGER_ADC_CH0 21 -# define DMA_CFG0_TRIGGER_ADC_CH1 22 -# define DMA_CFG0_TRIGGER_ADC_CH2 23 -# define DMA_CFG0_TRIGGER_ADC_CH3 24 -# define DMA_CFG0_TRIGGER_ADC_CH4 25 -# define DMA_CFG0_TRIGGER_ADC_CH5 26 -# define DMA_CFG0_TRIGGER_ADC_CH6 27 -# define DMA_CFG0_TRIGGER_I2SRX 27 -# define DMA_CFG0_TRIGGER_ADC_CH7 28 -# define DMA_CFG0_TRIGGER_I2STX 28 -# define DMA_CFG0_TRIGGER_ENC_DW 29 -# define DMA_CFG0_TRIGGER_ENC_UP 30 - -# define DMA_CFG1_SRCINC_MASK (3 << 6) -# define DMA_CFG1_SRCINC_0 (0 << 6) -# define DMA_CFG1_SRCINC_1 (1 << 6) -# define DMA_CFG1_SRCINC_2 (2 << 6) -# define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) - -# define DMA_CFG1_DESTINC_MASK (3 << 4) -# define DMA_CFG1_DESTINC_0 (0 << 4) -# define DMA_CFG1_DESTINC_1 (1 << 4) -# define DMA_CFG1_DESTINC_2 (2 << 4) -# define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) - -# define DMA_CFG1_IRQMASK (1 << 3) -# define DMA_CFG1_M8 (1 << 2) - -# define DMA_CFG1_PRIORITY_MASK (3 << 0) -# define DMA_CFG1_PRIORITY_LOW (0 << 0) -# define DMA_CFG1_PRIORITY_NORMAL (1 << 0) -# define DMA_CFG1_PRIORITY_HIGH (2 << 0) - -/* - * DMAARM - DMA Channel Arm - */ - -__sfr __at 0xD6 DMAARM; - -# define DMAARM_ABORT (1 << 7) -# define DMAARM_DMAARM4 (1 << 4) -# define DMAARM_DMAARM3 (1 << 3) -# define DMAARM_DMAARM2 (1 << 2) -# define DMAARM_DMAARM1 (1 << 1) -# define DMAARM_DMAARM0 (1 << 0) - -/* - * DMAREQ - DMA Channel Start Request and Status - */ - -__sfr __at 0xD7 DMAREQ; - -# define DMAREQ_DMAREQ4 (1 << 4) -# define DMAREQ_DMAREQ3 (1 << 3) -# define DMAREQ_DMAREQ2 (1 << 2) -# define DMAREQ_DMAREQ1 (1 << 1) -# define DMAREQ_DMAREQ0 (1 << 0) - -/* - * DMA configuration 0 address - */ - -__sfr __at 0xD5 DMA0CFGH; -__sfr __at 0xD4 DMA0CFGL; - -/* - * DMA configuration 1-4 address - */ - -__sfr __at 0xD3 DMA1CFGH; -__sfr __at 0xD2 DMA1CFGL; - -/* - * DMAIRQ - DMA Interrupt Flag - */ - -__sfr __at 0xD1 DMAIRQ; - -# define DMAIRQ_DMAIF4 (1 << 4) -# define DMAIRQ_DMAIF3 (1 << 3) -# define DMAIRQ_DMAIF2 (1 << 2) -# define DMAIRQ_DMAIF1 (1 << 1) -# define DMAIRQ_DMAIF0 (1 << 0) - -/* - * UART registers - */ - -/* USART config/status registers */ -__sfr __at 0x86 U0CSR; -__sfr __at 0xF8 U1CSR; - -# define UxCSR_MODE_UART (1 << 7) -# define UxCSR_MODE_SPI (0 << 7) -# define UxCSR_RE (1 << 6) -# define UxCSR_SLAVE (1 << 5) -# define UxCSR_MASTER (0 << 5) -# define UxCSR_FE (1 << 4) -# define UxCSR_ERR (1 << 3) -# define UxCSR_RX_BYTE (1 << 2) -# define UxCSR_TX_BYTE (1 << 1) -# define UxCSR_ACTIVE (1 << 0) - -/* UART configuration registers */ -__sfr __at 0xc4 U0UCR; -__sfr __at 0xfb U1UCR; - -# define UxUCR_FLUSH (1 << 7) -# define UxUCR_FLOW_DISABLE (0 << 6) -# define UxUCR_FLOW_ENABLE (1 << 6) -# define UxUCR_D9_EVEN_PARITY (0 << 5) -# define UxUCR_D9_ODD_PARITY (1 << 5) -# define UxUCR_BIT9_8_BITS (0 << 4) -# define UxUCR_BIT9_9_BITS (1 << 4) -# define UxUCR_PARITY_DISABLE (0 << 3) -# define UxUCR_PARITY_ENABLE (1 << 3) -# define UxUCR_SPB_1_STOP_BIT (0 << 2) -# define UxUCR_SPB_2_STOP_BITS (1 << 2) -# define UxUCR_STOP_LOW (0 << 1) -# define UxUCR_STOP_HIGH (1 << 1) -# define UxUCR_START_LOW (0 << 0) -# define UxUCR_START_HIGH (1 << 0) - -/* USART General configuration registers (mostly SPI) */ -__sfr __at 0xc5 U0GCR; -__sfr __at 0xfc U1GCR; - -# define UxGCR_CPOL_NEGATIVE (0 << 7) -# define UxGCR_CPOL_POSITIVE (1 << 7) -# define UxGCR_CPHA_FIRST_EDGE (0 << 6) -# define UxGCR_CPHA_SECOND_EDGE (1 << 6) -# define UxGCR_ORDER_LSB (0 << 5) -# define UxGCR_ORDER_MSB (1 << 5) -# define UxGCR_BAUD_E_MASK (0x1f) -# define UxGCR_BAUD_E_SHIFT 0 - -/* USART data registers */ -__sfr __at 0xc1 U0DBUF; -__xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; -__sfr __at 0xf9 U1DBUF; -__xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; - -/* USART baud rate registers, M value */ -__sfr __at 0xc2 U0BAUD; -__sfr __at 0xfa U1BAUD; - -/* Flash controller */ - -__sfr __at 0xAE FCTL; -#define FCTL_BUSY (1 << 7) -#define FCTL_SWBSY (1 << 6) -#define FCTL_CONTRD_ENABLE (1 << 4) -#define FCTL_WRITE (1 << 1) -#define FCTL_ERASE (1 << 0) - -/* Flash write data. Write two bytes here */ -__sfr __at 0xAF FWDATA; -__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; - -/* Flash write/erase address */ -__sfr __at 0xAD FADDRH; -__sfr __at 0xAC FADDRL; - -/* Flash timing */ -__sfr __at 0xAB FWT; - -/* Radio */ - -__sfr __at 0xD9 RFD; -__xdata __at (0xDFD9) volatile uint8_t RFDXADDR; - -__sfr __at 0xE9 RFIF; -#define RFIF_IM_TXUNF (1 << 7) -#define RFIF_IM_RXOVF (1 << 6) -#define RFIF_IM_TIMEOUT (1 << 5) -#define RFIF_IM_DONE (1 << 4) -#define RFIF_IM_CS (1 << 3) -#define RFIF_IM_PQT (1 << 2) -#define RFIF_IM_CCA (1 << 1) -#define RFIF_IM_SFD (1 << 0) - -__sfr __at 0x91 RFIM; -#define RFIM_IM_TXUNF (1 << 7) -#define RFIM_IM_RXOVF (1 << 6) -#define RFIM_IM_TIMEOUT (1 << 5) -#define RFIM_IM_DONE (1 << 4) -#define RFIM_IM_CS (1 << 3) -#define RFIM_IM_PQT (1 << 2) -#define RFIM_IM_CCA (1 << 1) -#define RFIM_IM_SFD (1 << 0) - -__sfr __at 0xE1 RFST; - -#define RFST_SFSTXON 0x00 -#define RFST_SCAL 0x01 -#define RFST_SRX 0x02 -#define RFST_STX 0x03 -#define RFST_SIDLE 0x04 - -__xdata __at (0xdf00) uint8_t RF[0x3c]; - -__xdata __at (0xdf2f) uint8_t RF_IOCFG2; -#define RF_IOCFG2_OFF 0x2f - -__xdata __at (0xdf30) uint8_t RF_IOCFG1; -#define RF_IOCFG1_OFF 0x30 - -__xdata __at (0xdf31) uint8_t RF_IOCFG0; -#define RF_IOCFG0_OFF 0x31 - -__xdata __at (0xdf00) uint8_t RF_SYNC1; -#define RF_SYNC1_OFF 0x00 - -__xdata __at (0xdf01) uint8_t RF_SYNC0; -#define RF_SYNC0_OFF 0x01 - -__xdata __at (0xdf02) uint8_t RF_PKTLEN; -#define RF_PKTLEN_OFF 0x02 - -__xdata __at (0xdf03) uint8_t RF_PKTCTRL1; -#define RF_PKTCTRL1_OFF 0x03 -#define PKTCTRL1_PQT_MASK (0x7 << 5) -#define PKTCTRL1_PQT_SHIFT 5 -#define PKTCTRL1_APPEND_STATUS (1 << 2) -#define PKTCTRL1_ADR_CHK_NONE (0 << 0) -#define PKTCTRL1_ADR_CHK_NO_BROADCAST (1 << 0) -#define PKTCTRL1_ADR_CHK_00_BROADCAST (2 << 0) -#define PKTCTRL1_ADR_CHK_00_FF_BROADCAST (3 << 0) - -/* If APPEND_STATUS is used, two bytes will be added to the packet data */ -#define PKT_APPEND_STATUS_0_RSSI_MASK (0xff) -#define PKT_APPEND_STATUS_0_RSSI_SHIFT 0 -#define PKT_APPEND_STATUS_1_CRC_OK (1 << 7) -#define PKT_APPEND_STATUS_1_LQI_MASK (0x7f) -#define PKT_APPEND_STATUS_1_LQI_SHIFT 0 - -__xdata __at (0xdf04) uint8_t RF_PKTCTRL0; -#define RF_PKTCTRL0_OFF 0x04 -#define RF_PKTCTRL0_WHITE_DATA (1 << 6) -#define RF_PKTCTRL0_PKT_FORMAT_NORMAL (0 << 4) -#define RF_PKTCTRL0_PKT_FORMAT_RANDOM (2 << 4) -#define RF_PKTCTRL0_CRC_EN (1 << 2) -#define RF_PKTCTRL0_LENGTH_CONFIG_FIXED (0 << 0) -#define RF_PKTCTRL0_LENGTH_CONFIG_VARIABLE (1 << 0) - -__xdata __at (0xdf05) uint8_t RF_ADDR; -#define RF_ADDR_OFF 0x05 - -__xdata __at (0xdf06) uint8_t RF_CHANNR; -#define RF_CHANNR_OFF 0x06 - -__xdata __at (0xdf07) uint8_t RF_FSCTRL1; -#define RF_FSCTRL1_OFF 0x07 - -#define RF_FSCTRL1_FREQ_IF_SHIFT (0) - -__xdata __at (0xdf08) uint8_t RF_FSCTRL0; -#define RF_FSCTRL0_OFF 0x08 - -#define RF_FSCTRL0_FREQOFF_SHIFT (0) - -__xdata __at (0xdf09) uint8_t RF_FREQ2; -#define RF_FREQ2_OFF 0x09 - -__xdata __at (0xdf0a) uint8_t RF_FREQ1; -#define RF_FREQ1_OFF 0x0a - -__xdata __at (0xdf0b) uint8_t RF_FREQ0; -#define RF_FREQ0_OFF 0x0b - -__xdata __at (0xdf0c) uint8_t RF_MDMCFG4; -#define RF_MDMCFG4_OFF 0x0c - -#define RF_MDMCFG4_CHANBW_E_SHIFT 6 -#define RF_MDMCFG4_CHANBW_M_SHIFT 4 -#define RF_MDMCFG4_DRATE_E_SHIFT 0 - -__xdata __at (0xdf0d) uint8_t RF_MDMCFG3; -#define RF_MDMCFG3_OFF 0x0d - -#define RF_MDMCFG3_DRATE_M_SHIFT 0 - -__xdata __at (0xdf0e) uint8_t RF_MDMCFG2; -#define RF_MDMCFG2_OFF 0x0e - -#define RF_MDMCFG2_DEM_DCFILT_OFF (1 << 7) -#define RF_MDMCFG2_DEM_DCFILT_ON (0 << 7) - -#define RF_MDMCFG2_MOD_FORMAT_MASK (7 << 4) -#define RF_MDMCFG2_MOD_FORMAT_2_FSK (0 << 4) -#define RF_MDMCFG2_MOD_FORMAT_GFSK (1 << 4) -#define RF_MDMCFG2_MOD_FORMAT_ASK_OOK (3 << 4) -#define RF_MDMCFG2_MOD_FORMAT_MSK (7 << 4) - -#define RF_MDMCFG2_MANCHESTER_EN (1 << 3) - -#define RF_MDMCFG2_SYNC_MODE_MASK (0x7 << 0) -#define RF_MDMCFG2_SYNC_MODE_NONE (0x0 << 0) -#define RF_MDMCFG2_SYNC_MODE_15_16 (0x1 << 0) -#define RF_MDMCFG2_SYNC_MODE_16_16 (0x2 << 0) -#define RF_MDMCFG2_SYNC_MODE_30_32 (0x3 << 0) -#define RF_MDMCFG2_SYNC_MODE_NONE_THRES (0x4 << 0) -#define RF_MDMCFG2_SYNC_MODE_15_16_THRES (0x5 << 0) -#define RF_MDMCFG2_SYNC_MODE_16_16_THRES (0x6 << 0) -#define RF_MDMCFG2_SYNC_MODE_30_32_THRES (0x7 << 0) - -__xdata __at (0xdf0f) uint8_t RF_MDMCFG1; -#define RF_MDMCFG1_OFF 0x0f - -#define RF_MDMCFG1_FEC_EN (1 << 7) -#define RF_MDMCFG1_FEC_DIS (0 << 7) - -#define RF_MDMCFG1_NUM_PREAMBLE_MASK (7 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_2 (0 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_3 (1 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_4 (2 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_6 (3 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_8 (4 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_12 (5 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_16 (6 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_24 (7 << 4) - -#define RF_MDMCFG1_CHANSPC_E_MASK (3 << 0) -#define RF_MDMCFG1_CHANSPC_E_SHIFT (0) - -__xdata __at (0xdf10) uint8_t RF_MDMCFG0; -#define RF_MDMCFG0_OFF 0x10 - -#define RF_MDMCFG0_CHANSPC_M_SHIFT (0) - -__xdata __at (0xdf11) uint8_t RF_DEVIATN; -#define RF_DEVIATN_OFF 0x11 - -#define RF_DEVIATN_DEVIATION_E_SHIFT 4 -#define RF_DEVIATN_DEVIATION_M_SHIFT 0 - -__xdata __at (0xdf12) uint8_t RF_MCSM2; -#define RF_MCSM2_OFF 0x12 -#define RF_MCSM2_RX_TIME_RSSI (1 << 4) -#define RF_MCSM2_RX_TIME_QUAL (1 << 3) -#define RF_MCSM2_RX_TIME_MASK (0x7) -#define RF_MCSM2_RX_TIME_SHIFT 0 -#define RF_MCSM2_RX_TIME_END_OF_PACKET (7) - -__xdata __at (0xdf13) uint8_t RF_MCSM1; -#define RF_MCSM1_OFF 0x13 -#define RF_MCSM1_CCA_MODE_ALWAYS (0 << 4) -#define RF_MCSM1_CCA_MODE_RSSI_BELOW (1 << 4) -#define RF_MCSM1_CCA_MODE_UNLESS_RECEIVING (2 << 4) -#define RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING (3 << 4) -#define RF_MCSM1_RXOFF_MODE_IDLE (0 << 2) -#define RF_MCSM1_RXOFF_MODE_FSTXON (1 << 2) -#define RF_MCSM1_RXOFF_MODE_TX (2 << 2) -#define RF_MCSM1_RXOFF_MODE_RX (3 << 2) -#define RF_MCSM1_TXOFF_MODE_IDLE (0 << 0) -#define RF_MCSM1_TXOFF_MODE_FSTXON (1 << 0) -#define RF_MCSM1_TXOFF_MODE_TX (2 << 0) -#define RF_MCSM1_TXOFF_MODE_RX (3 << 0) - -__xdata __at (0xdf14) uint8_t RF_MCSM0; -#define RF_MCSM0_OFF 0x14 -#define RF_MCSM0_FS_AUTOCAL_NEVER (0 << 4) -#define RF_MCSM0_FS_AUTOCAL_FROM_IDLE (1 << 4) -#define RF_MCSM0_FS_AUTOCAL_TO_IDLE (2 << 4) -#define RF_MCSM0_FS_AUTOCAL_TO_IDLE_EVERY_4 (3 << 4) -#define RF_MCSM0_MAGIC_3 (1 << 3) -#define RF_MCSM0_MAGIC_2 (1 << 2) -#define RF_MCSM0_CLOSE_IN_RX_0DB (0 << 0) -#define RF_MCSM0_CLOSE_IN_RX_6DB (1 << 0) -#define RF_MCSM0_CLOSE_IN_RX_12DB (2 << 0) -#define RF_MCSM0_CLOSE_IN_RX_18DB (3 << 0) - -__xdata __at (0xdf15) uint8_t RF_FOCCFG; -#define RF_FOCCFG_OFF 0x15 -#define RF_FOCCFG_FOC_BS_CS_GATE (1 << 5) -#define RF_FOCCFG_FOC_PRE_K_1K (0 << 3) -#define RF_FOCCFG_FOC_PRE_K_2K (1 << 3) -#define RF_FOCCFG_FOC_PRE_K_3K (2 << 3) -#define RF_FOCCFG_FOC_PRE_K_4K (3 << 3) -#define RF_FOCCFG_FOC_POST_K_PRE_K (0 << 2) -#define RF_FOCCFG_FOC_POST_K_PRE_K_OVER_2 (1 << 2) -#define RF_FOCCFG_FOC_LIMIT_0 (0 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_8 (1 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_4 (2 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_2 (3 << 0) - -__xdata __at (0xdf16) uint8_t RF_BSCFG; -#define RF_BSCFG_OFF 0x16 -#define RF_BSCFG_BS_PRE_K_1K (0 << 6) -#define RF_BSCFG_BS_PRE_K_2K (1 << 6) -#define RF_BSCFG_BS_PRE_K_3K (2 << 6) -#define RF_BSCFG_BS_PRE_K_4K (3 << 6) -#define RF_BSCFG_BS_PRE_KP_1KP (0 << 4) -#define RF_BSCFG_BS_PRE_KP_2KP (1 << 4) -#define RF_BSCFG_BS_PRE_KP_3KP (2 << 4) -#define RF_BSCFG_BS_PRE_KP_4KP (3 << 4) -#define RF_BSCFG_BS_POST_KI_PRE_KI (0 << 3) -#define RF_BSCFG_BS_POST_KI_PRE_KI_OVER_2 (1 << 3) -#define RF_BSCFG_BS_POST_KP_PRE_KP (0 << 2) -#define RF_BSCFG_BS_POST_KP_PRE_KP_OVER_2 (1 << 2) -#define RF_BSCFG_BS_LIMIT_0 (0 << 0) -#define RF_BSCFG_BS_LIMIT_3_125 (1 << 0) -#define RF_BSCFG_BS_LIMIT_6_25 (2 << 0) -#define RF_BSCFG_BS_LIMIT_12_5 (3 << 0) - -__xdata __at (0xdf17) uint8_t RF_AGCCTRL2; -#define RF_AGCCTRL2_OFF 0x17 - -#define RF_AGCCTRL2_MAX_DVGA_GAIN_ALL (0 << 6) -#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_1 (1 << 6) -#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_2 (2 << 6) -#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_3 (3 << 6) -#define RF_AGCCTRL2_MAX_LNA_GAIN_0 (0 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_2_6 (1 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_6_1 (2 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_7_4 (3 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_9_2 (4 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_11_5 (5 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_14_6 (6 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_17_1 (7 << 3) -#define RF_AGCCTRL2_MAGN_TARGET_24dB (0 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_27dB (1 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_30dB (2 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_33dB (3 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_36dB (4 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_38dB (5 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_40dB (6 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_42dB (7 << 0) - -__xdata __at (0xdf18) uint8_t RF_AGCCTRL1; -#define RF_AGCCTRL1_OFF 0x18 - -#define RF_AGCCTRL1_AGC_LNA_PRIORITY_0 (0 << 6) -#define RF_AGCCTRL1_AGC_LNA_PRIORITY_1 (1 << 6) -#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE (0 << 4) -#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_6DB (1 << 4) -#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_10DB (2 << 4) -#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_14DB (3 << 4) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_DISABLE (0x8 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_BELOW (0x9 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_BELOW (0xa << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_BELOW (0xb << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_BELOW (0xc << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_BELOW (0xd << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_BELOW (0xe << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_BELOW (0xf << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB (0x0 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_ABOVE (0x1 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_ABOVE (0x2 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_ABOVE (0x3 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_ABOVE (0x4 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_ABOVE (0x5 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_ABOVE (0x6 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_ABOVE (0x7 << 0) - -__xdata __at (0xdf19) uint8_t RF_AGCCTRL0; -#define RF_AGCCTRL0_OFF 0x19 - -#define RF_AGCCTRL0_HYST_LEVEL_NONE (0 << 6) -#define RF_AGCCTRL0_HYST_LEVEL_LOW (1 << 6) -#define RF_AGCCTRL0_HYST_LEVEL_MEDIUM (2 << 6) -#define RF_AGCCTRL0_HYST_LEVEL_HIGH (3 << 6) -#define RF_AGCCTRL0_WAIT_TIME_8 (0 << 4) -#define RF_AGCCTRL0_WAIT_TIME_16 (1 << 4) -#define RF_AGCCTRL0_WAIT_TIME_24 (2 << 4) -#define RF_AGCCTRL0_WAIT_TIME_32 (3 << 4) -#define RF_AGCCTRL0_AGC_FREEZE_NORMAL (0 << 2) -#define RF_AGCCTRL0_AGC_FREEZE_SYNC (1 << 2) -#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_ANALOG (2 << 2) -#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_BOTH (3 << 2) -#define RF_AGCCTRL0_FILTER_LENGTH_8 (0 << 0) -#define RF_AGCCTRL0_FILTER_LENGTH_16 (1 << 0) -#define RF_AGCCTRL0_FILTER_LENGTH_32 (2 << 0) -#define RF_AGCCTRL0_FILTER_LENGTH_64 (3 << 0) - -__xdata __at (0xdf1a) uint8_t RF_FREND1; -#define RF_FREND1_OFF 0x1a - -#define RF_FREND1_LNA_CURRENT_SHIFT 6 -#define RF_FREND1_LNA2MIX_CURRENT_SHIFT 4 -#define RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT 2 -#define RF_FREND1_MIX_CURRENT_SHIFT 0 - -__xdata __at (0xdf1b) uint8_t RF_FREND0; -#define RF_FREND0_OFF 0x1b - -#define RF_FREND0_LODIV_BUF_CURRENT_TX_MASK (0x3 << 4) -#define RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT 4 -#define RF_FREND0_PA_POWER_MASK (0x7) -#define RF_FREND0_PA_POWER_SHIFT 0 - -__xdata __at (0xdf1c) uint8_t RF_FSCAL3; -#define RF_FSCAL3_OFF 0x1c - -__xdata __at (0xdf1d) uint8_t RF_FSCAL2; -#define RF_FSCAL2_OFF 0x1d - -__xdata __at (0xdf1e) uint8_t RF_FSCAL1; -#define RF_FSCAL1_OFF 0x1e - -__xdata __at (0xdf1f) uint8_t RF_FSCAL0; -#define RF_FSCAL0_OFF 0x1f - -__xdata __at (0xdf23) uint8_t RF_TEST2; -#define RF_TEST2_OFF 0x23 - -#define RF_TEST2_NORMAL_MAGIC 0x88 -#define RF_TEST2_RX_LOW_DATA_RATE_MAGIC 0x81 - -__xdata __at (0xdf24) uint8_t RF_TEST1; -#define RF_TEST1_OFF 0x24 - -#define RF_TEST1_TX_MAGIC 0x31 -#define RF_TEST1_RX_LOW_DATA_RATE_MAGIC 0x35 - -__xdata __at (0xdf25) uint8_t RF_TEST0; -#define RF_TEST0_OFF 0x25 - -#define RF_TEST0_7_2_MASK (0xfc) -#define RF_TEST0_VCO_SEL_CAL_EN (1 << 1) -#define RF_TEST0_0_MASK (1) - -/* These are undocumented, and must be computed - * using the provided tool. - */ -__xdata __at (0xdf27) uint8_t RF_PA_TABLE7; -#define RF_PA_TABLE7_OFF 0x27 - -__xdata __at (0xdf28) uint8_t RF_PA_TABLE6; -#define RF_PA_TABLE6_OFF 0x28 - -__xdata __at (0xdf29) uint8_t RF_PA_TABLE5; -#define RF_PA_TABLE5_OFF 0x29 - -__xdata __at (0xdf2a) uint8_t RF_PA_TABLE4; -#define RF_PA_TABLE4_OFF 0x2a - -__xdata __at (0xdf2b) uint8_t RF_PA_TABLE3; -#define RF_PA_TABLE3_OFF 0x2b - -__xdata __at (0xdf2c) uint8_t RF_PA_TABLE2; -#define RF_PA_TABLE2_OFF 0x2c - -__xdata __at (0xdf2d) uint8_t RF_PA_TABLE1; -#define RF_PA_TABLE1_OFF 0x2d - -__xdata __at (0xdf2e) uint8_t RF_PA_TABLE0; -#define RF_PA_TABLE0_OFF 0x2e - -__xdata __at (0xdf36) uint8_t RF_PARTNUM; -#define RF_PARTNUM_OFF 0x36 - -__xdata __at (0xdf37) uint8_t RF_VERSION; -#define RF_VERSION_OFF 0x37 - -__xdata __at (0xdf38) uint8_t RF_FREQEST; -#define RF_FREQEST_OFF 0x38 - -__xdata __at (0xdf39) uint8_t RF_LQI; -#define RF_LQI_OFF 0x39 - -#define RF_LQI_CRC_OK (1 << 7) -#define RF_LQI_LQI_EST_MASK (0x7f) - -__xdata __at (0xdf3a) uint8_t RF_RSSI; -#define RF_RSSI_OFF 0x3a - -__xdata __at (0xdf3b) uint8_t RF_MARCSTATE; -#define RF_MARCSTATE_OFF 0x3b - -#define RF_MARCSTATE_MASK 0x1f -#define RF_MARCSTATE_SLEEP 0x00 -#define RF_MARCSTATE_IDLE 0x01 -#define RF_MARCSTATE_VCOON_MC 0x03 -#define RF_MARCSTATE_REGON_MC 0x04 -#define RF_MARCSTATE_MANCAL 0x05 -#define RF_MARCSTATE_VCOON 0x06 -#define RF_MARCSTATE_REGON 0x07 -#define RF_MARCSTATE_STARTCAL 0x08 -#define RF_MARCSTATE_BWBOOST 0x09 -#define RF_MARCSTATE_FS_LOCK 0x0a -#define RF_MARCSTATE_IFADCON 0x0b -#define RF_MARCSTATE_ENDCAL 0x0c -#define RF_MARCSTATE_RX 0x0d -#define RF_MARCSTATE_RX_END 0x0e -#define RF_MARCSTATE_RX_RST 0x0f -#define RF_MARCSTATE_TXRX_SWITCH 0x10 -#define RF_MARCSTATE_RX_OVERFLOW 0x11 -#define RF_MARCSTATE_FSTXON 0x12 -#define RF_MARCSTATE_TX 0x13 -#define RF_MARCSTATE_TX_END 0x14 -#define RF_MARCSTATE_RXTX_SWITCH 0x15 -#define RF_MARCSTATE_TX_UNDERFLOW 0x16 - - -__xdata __at (0xdf3c) uint8_t RF_PKTSTATUS; -#define RF_PKTSTATUS_OFF 0x3c - -#define RF_PKTSTATUS_CRC_OK (1 << 7) -#define RF_PKTSTATUS_CS (1 << 6) -#define RF_PKTSTATUS_PQT_REACHED (1 << 5) -#define RF_PKTSTATUS_CCA (1 << 4) -#define RF_PKTSTATUS_SFD (1 << 3) - -__xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; -#define RF_VCO_VC_DAC_OFF 0x3d - -/* AES engine */ - -__sfr __at 0xB1 ENCDI; -__sfr __at 0xB2 ENCDO; -__xdata __at (0xDFB1) volatile uint8_t ENCDIXADDR; -__xdata __at (0xDFB2) volatile uint8_t ENCDOXADDR; - -__sfr __at 0xB3 ENCCCS; - -#define ENCCCS_MODE_CBC (0 << 4) -#define ENCCCS_MODE_CFB (1 << 4) -#define ENCCCS_MODE_OFB (2 << 4) -#define ENCCCS_MODE_CTR (3 << 4) -#define ENCCCS_MODE_ECB (4 << 4) -#define ENCCCS_MODE_CBC_MAC (5 << 4) -#define ENCCCS_RDY (1 << 3) -#define ENCCCS_CMD_ENCRYPT (0 << 1) -#define ENCCCS_CMD_DECRYPT (1 << 1) -#define ENCCCS_CMD_LOAD_KEY (2 << 1) -#define ENCCCS_CMD_LOAD_IV (3 << 1) -#define ENCCCS_START (1 << 0) - -#endif diff --git a/usb_ep0/hal.c b/usb_ep0/hal.c deleted file mode 100644 index f74304b..0000000 --- a/usb_ep0/hal.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * CC Bootloader - Hardware Abstraction Layer - * - * Fergus Noble (c) 2011 - * - * 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; version 2 of the License. - * - * 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; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "cc1111.h" - -void setup_led() { - // Setup LED and turn it off - P1DIR |= 2; - P1_1 = 0; -} - -void led_on() { - P1_1 = 1; -} - -void led_off() { - P1_1 = 0; -} - -void usb_up() { - // Bring up the USB link -#ifdef TI_DONGLE - P1DIR |= 1; - P1_0 = 1; -#elif SRF_STICK - P2DIR |= 1; - P2_0 = 1; -#endif -} - -void usb_down() { - // Bring down the USB link -#ifdef TI_DONGLE - P1_0 = 0; - P1DIR &= ~1; -#elif SRF_STICK - P2_0 = 0; - P2DIR &= ~1; -#endif -} diff --git a/usb_ep0/hal.h b/usb_ep0/hal.h deleted file mode 100644 index 1e1075c..0000000 --- a/usb_ep0/hal.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * CC Bootloader - Hardware Abstraction Layer - * - * Fergus Noble (c) 2011 - * - * 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; version 2 of the License. - * - * 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; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _HAL_H_ -#define _HAL_H_ - -void setup_led(); -void led_on(); -void led_off(); - -void usb_up(); -void usb_down(); - -#endif // _HAL_H_ diff --git a/usb_ep0/serial.c b/usb_ep0/serial.c deleted file mode 100644 index 0c07fa8..0000000 --- a/usb_ep0/serial.c +++ /dev/null @@ -1,73 +0,0 @@ - -#include -#include "hardware.h" -#include "serial.h" -#include "radio.h" -#include "hal.h" -#include "usb.h" - -// extern int SERIAL_DATA_AVAILABLE = 0; - -void configure_serial() -{ - - setup_led( ); -// led_set_state(0,1); -// led_set_state(0,0); - usb_init( ); - usb_enable( ); - usb_up( ); - usb_flush( ); - /// GREEN_LED = 1; - -} - -uint8_t serial_has_bytes() -{ - - usb_flush( ); - if (usb_pollchar() == USB_READ_AGAIN) { -// led_set_state(0,0); - return 0; - } -// led_set_state(0,1); - return 1; -} - - -uint8_t serial_rx_byte() { - // return (uint8_t) usb_getc( ); - char c = usb_getchar( ); - return (uint8_t) c; -} - -uint16_t serial_rx_word() { - return (serial_rx_byte() << 8) + serial_rx_byte(); -} - -uint32_t serial_rx_long() { - return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); -} - - -void flush_serial( ) { -// led_set_state(0,2); - usb_flush( ); -// led_set_state(0,2); -} - -void serial_tx_byte(uint8_t tx_byte) { - // return usb_putc(tx_byte); - usb_putchar( tx_byte); - usb_flush( ); -} - -void serial_tx_str(const char *str) { - while(*str != 0) { - serial_tx_byte(*str); - str++; - } - serial_tx_byte(0); - usb_flush( ); -} - diff --git a/usb_ep0/serial.h b/usb_ep0/serial.h deleted file mode 100644 index 8cbc08e..0000000 --- a/usb_ep0/serial.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef SERIAL_H -#define SERIAL_H - -#define SERIAL_DATA_AVAILABLE serial_has_bytes( ) - -void configure_serial(); -void serial_tx_byte(uint8_t); -void serial_tx_str(const char *str); -void run_command_from_serial(); -uint8_t serial_rx_byte(); -uint8_t serial_has_bytes(); -uint32_t serial_rx_long(); -void flush_serial( ); - -#endif diff --git a/usb_ep0/usb.c b/usb_ep0/usb.c deleted file mode 100644 index 3923bf9..0000000 --- a/usb_ep0/usb.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * CC Bootloader - USB CDC class (serial) driver - * - * Adapted from AltOS code by Fergus Noble (c) 2011 - * AltOS code Copyright © 2009 Keith Packard - * - * 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; version 2 of the License. - * - * 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; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "cc1111.h" -#include "usb.h" - -static __xdata uint16_t usb_in_bytes; -static __xdata uint16_t usb_in_bytes_last; -static __xdata uint16_t usb_out_bytes; -volatile static __xdata uint8_t usb_iif; -static __xdata uint8_t usb_running; - -static void usb_set_interrupts() -{ - // IN interrupts on the control an IN endpoints - USBIIE = (1 << USB_CONTROL_EP) | (1 << USB_IN_EP); - // OUT interrupts on the OUT endpoint - USBOIE = (1 << USB_OUT_EP); - // Only care about reset - USBCIE = USBCIE_RSTIE; -} - -struct usb_setup { - uint8_t dir_type_recip; - uint8_t request; - uint16_t value; - uint16_t index; - uint16_t length; -}; // } __xdata usb_setup; -__xdata static struct usb_setup usb_setup; - -__xdata uint8_t usb_ep0_state; -const uint8_t * __xdata usb_ep0_in_data; -__xdata uint8_t usb_ep0_in_len; -__xdata uint8_t usb_ep0_in_buf[2]; -__xdata uint8_t usb_ep0_out_len; -__xdata uint8_t *__xdata usb_ep0_out_data; -__xdata uint8_t usb_configuration; - -// Send an IN data packet -static void usb_ep0_flush() -{ - __xdata uint8_t this_len; - __xdata uint8_t cs0; - - // If the IN packet hasn't been picked up, just return - USBINDEX = 0; - cs0 = USBCS0; - if (cs0 & USBCS0_INPKT_RDY) - return; - - this_len = usb_ep0_in_len; - if (this_len > USB_CONTROL_SIZE) - this_len = USB_CONTROL_SIZE; - cs0 = USBCS0_INPKT_RDY; - if (this_len != USB_CONTROL_SIZE) { - cs0 = USBCS0_INPKT_RDY | USBCS0_DATA_END; - usb_ep0_state = USB_EP0_IDLE; - } - usb_ep0_in_len -= this_len; - while (this_len--) - USBFIFO[0] = *usb_ep0_in_data++; - USBINDEX = 0; - USBCS0 = cs0; -} - -__xdata static struct usb_line_coding usb_line_coding = {115200, 0, 0, 8}; - -// Walk through the list of descriptors and find a match -static void usb_get_descriptor(uint16_t value) -{ - __xdata uint8_t * descriptor; - // uint8_t *__xdata descriptor; - __xdata uint8_t type = value >> 8; - __xdata uint8_t index = value; - - descriptor = usb_descriptors; - while (descriptor[0] != 0) { - if (descriptor[1] == type && index-- == 0) { - if (type == USB_DESC_CONFIGURATION) - usb_ep0_in_len = descriptor[2]; - else - usb_ep0_in_len = descriptor[0]; - usb_ep0_in_data = descriptor; - break; - } - descriptor += descriptor[0]; - } -} - -// Read data from the ep0 OUT fifo -static void usb_ep0_fill() -{ - __xdata uint8_t len; - - USBINDEX = 0; - len = USBCNT0; - if (len > usb_ep0_out_len) - len = usb_ep0_out_len; - usb_ep0_out_len -= len; - while (len--) - *usb_ep0_out_data++ = USBFIFO[0]; -} - -void usb_ep0_queue_byte (uint8_t a) -{ - usb_ep0_in_buf[usb_ep0_in_len++] = a; -} - -void usb_set_address (uint8_t address) -{ - usb_running = 1; - USBADDR = address | 0x80; - while (USBADDR & 0x80) {} -} - -static void usb_set_configuration() -{ - // Set the IN max packet size, double buffered - USBINDEX = USB_IN_EP; - USBMAXI = USB_IN_SIZE >> 3; - USBCSIH |= USBCSIH_IN_DBL_BUF; - - // Set the OUT max packet size, double buffered - USBINDEX = USB_OUT_EP; - USBMAXO = USB_OUT_SIZE >> 3; - USBCSOH = USBCSOH_OUT_DBL_BUF; -} - -static void usb_ep0_setup() -{ - // Pull the setup packet out of the fifo - usb_ep0_out_data = (__xdata uint8_t *) &usb_setup; - usb_ep0_out_len = 8; - usb_ep0_fill(); - if (usb_ep0_out_len != 0) - return; - - // Figure out how to ACK the setup packet - if (usb_setup.dir_type_recip & USB_DIR_IN) { - if (usb_setup.length) - usb_ep0_state = USB_EP0_DATA_IN; - else - usb_ep0_state = USB_EP0_IDLE; - } else { - if (usb_setup.length) - usb_ep0_state = USB_EP0_DATA_OUT; - else - usb_ep0_state = USB_EP0_IDLE; - } - USBINDEX = 0; - if (usb_ep0_state == USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - - usb_ep0_in_data = usb_ep0_in_buf; - usb_ep0_in_len = 0; - switch(usb_setup.dir_type_recip & USB_SETUP_TYPE_MASK) { - case USB_TYPE_STANDARD: - switch(usb_setup.dir_type_recip & USB_SETUP_RECIP_MASK) { - case USB_RECIP_DEVICE: - switch(usb_setup.request) { - case USB_REQ_GET_STATUS: - usb_ep0_queue_byte(0); - usb_ep0_queue_byte(0); - break; - case USB_REQ_SET_ADDRESS: - usb_set_address(usb_setup.value); - break; - case USB_REQ_GET_DESCRIPTOR: - usb_get_descriptor(usb_setup.value); - break; - case USB_REQ_GET_CONFIGURATION: - usb_ep0_queue_byte(usb_configuration); - break; - case USB_REQ_SET_CONFIGURATION: - usb_configuration = usb_setup.value; - usb_set_configuration(); - break; - } - break; - case USB_RECIP_INTERFACE: - #pragma disable_warning 110 - switch(usb_setup.request) { - case USB_REQ_GET_STATUS: - usb_ep0_queue_byte(0); - usb_ep0_queue_byte(0); - break; - case USB_REQ_GET_INTERFACE: - usb_ep0_queue_byte(0); - break; - case USB_REQ_SET_INTERFACE: - break; - } - break; - case USB_RECIP_ENDPOINT: - switch(usb_setup.request) { - case USB_REQ_GET_STATUS: - usb_ep0_queue_byte(0); - usb_ep0_queue_byte(0); - break; - } - break; - } - break; - case USB_TYPE_CLASS: - switch (usb_setup.request) { - case SET_LINE_CODING: - usb_ep0_out_len = 7; - usb_ep0_out_data = (__xdata uint8_t *) &usb_line_coding; - break; - case GET_LINE_CODING: - usb_ep0_in_len = 7; - usb_ep0_in_data = (uint8_t *) &usb_line_coding; - break; - case SET_CONTROL_LINE_STATE: - break; - } - break; - } - if (usb_ep0_state != USB_EP0_DATA_OUT) { - if (usb_setup.length < usb_ep0_in_len) - usb_ep0_in_len = usb_setup.length; - usb_ep0_flush(); - } -} - -// End point 0 receives all of the control messages. -// This function must be called periodically to process ep0 messages. -static void usb_ep0() -{ - __xdata uint8_t cs0; - - // If the ep0 flag has been set by the USB interrupt then do some processing - if (usb_iif & 1) - { - usb_iif &= ~1; // clear flag - - USBINDEX = 0; - cs0 = USBCS0; - if (cs0 & USBCS0_SETUP_END) { - usb_ep0_state = USB_EP0_IDLE; - USBCS0 = USBCS0_CLR_SETUP_END; - } - if (cs0 & USBCS0_SENT_STALL) { - usb_ep0_state = USB_EP0_IDLE; - USBCS0 &= ~USBCS0_SENT_STALL; - } - if (usb_ep0_state == USB_EP0_DATA_IN && - (cs0 & USBCS0_INPKT_RDY) == 0) - { - usb_ep0_flush(); - } - if (cs0 & USBCS0_OUTPKT_RDY) { - switch (usb_ep0_state) { - case USB_EP0_IDLE: - usb_ep0_setup(); - break; - case USB_EP0_DATA_OUT: - usb_ep0_fill(); - if (usb_ep0_out_len == 0) - usb_ep0_state = USB_EP0_IDLE; - USBINDEX = 0; - if (usb_ep0_state == USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - break; - } - } - } -} - -// This interrupt is shared with port 2, -// so when we hook that up, fix this -void usb_isr() __interrupt 6 -{ - USBIF = 0; - usb_iif |= USBIIF; - usb_ep0(); - - if (USBCIF & USBCIF_RSTIF) - usb_set_interrupts(); -} - -// Wait for a free IN buffer -static void usb_in_wait() -{ - while (1) { - USBINDEX = USB_IN_EP; - if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) - break; - while (!(usb_iif & (1 << USB_IN_EP))) {} - } -} - -// Send the current IN packet -static void usb_in_send() -{ - USBINDEX = USB_IN_EP; - USBCSIL |= USBCSIL_INPKT_RDY; - usb_in_bytes_last = usb_in_bytes; - usb_in_bytes = 0; -} - -void usb_flush() -{ - if (!usb_running) - return; - - // If there are pending bytes, or if the last packet was full, - // send another IN packet - if (usb_in_bytes || (usb_in_bytes_last == USB_IN_SIZE)) { - usb_in_wait(); - usb_in_send(); - } -} - -void usb_putchar(char c) __reentrant -{ - if (!usb_running) - return; - - usb_in_wait(); - - // Queue a byte, sending the packet when full - USBFIFO[USB_IN_EP << 1] = c; - if (++usb_in_bytes == USB_IN_SIZE) - usb_in_send(); -} - -char usb_pollchar() -{ - char c; - if (usb_out_bytes == 0) { - USBINDEX = USB_OUT_EP; - if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) - return USB_READ_AGAIN; - usb_out_bytes = (USBCNTH << 8) | USBCNTL; - if (usb_out_bytes == 0) { - USBINDEX = USB_OUT_EP; - USBCSOL &= ~USBCSOL_OUTPKT_RDY; - return USB_READ_AGAIN; - } - } - --usb_out_bytes; - c = USBFIFO[USB_OUT_EP << 1]; - if (usb_out_bytes == 0) { - USBINDEX = USB_OUT_EP; - USBCSOL &= ~USBCSOL_OUTPKT_RDY; - } - return c; -} - -char usb_getchar() -{ - char c; - while ((c = usb_pollchar()) == USB_READ_AGAIN) - { - while (!(USBOIF & (1 << USB_OUT_EP))) {} - } - return c; -} - -void usb_enable() -{ - // Turn on the USB controller - SLEEP |= SLEEP_USB_EN; - - usb_set_configuration(); - usb_set_interrupts(); - - // enable USB interrupts - IEN2 |= IEN2_USBIE; - - // Clear any pending interrupts - USBCIF = 0; - USBOIF = 0; - USBIIF = 0; - USBIF = 0; -} - -void usb_disable() -{ - // Disable USB interrupts - USBIIE = 0; - USBOIE = 0; - USBCIE = 0; - IEN2 &= ~IEN2_USBIE; - - // Clear any pending interrupts - USBCIF = 0; - USBOIF = 0; - USBIIF = 0; - - // Turn off the USB controller - SLEEP &= ~SLEEP_USB_EN; -} - -void usb_init() -{ - // Init ep0 - usb_ep0_state = USB_EP0_IDLE; - usb_iif = 0; - usb_enable(); -} - -void usb_readline(char* buff) { - char c; - while ((c = usb_getchar()) != '\n') { - *buff++ = c; - } - *buff = 0; -} - -void usb_putstr(char* buff) { - while (*buff) { - usb_putchar(*buff++); - } - usb_flush(); -} - diff --git a/usb_ep0/usb.h b/usb_ep0/usb.h deleted file mode 100644 index f421cc4..0000000 --- a/usb_ep0/usb.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * CC Bootloader - USB CDC class (serial) driver - * - * Adapted from AltOS code by Fergus Noble (c) 2011 - * AltOS code Copyright © 2009 Keith Packard - * - * 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; version 2 of the License. - * - * 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; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _USB_H_ -#define _USB_H_ - -// External interface - -void usb_init(); -void usb_disable(); -void usb_enable(); -char usb_getchar(); -void usb_putchar(char c); -void usb_flush(); - -void usb_putstr(char* buff); -void usb_readline(char* buff); - -char usb_pollchar(); - -// End external interface - -// USB interrupt handler -void usb_isr() __interrupt 6; - -#define USB_SETUP_DIR_MASK (0x01 << 7) -#define USB_SETUP_TYPE_MASK (0x03 << 5) -#define USB_SETUP_RECIP_MASK (0x1f) - -#define USB_DIR_OUT 0 -#define USB_DIR_IN (1 << 7) - -#define USB_TYPE_STANDARD 0 -#define USB_TYPE_CLASS (1 << 5) -#define USB_TYPE_VENDOR (2 << 5) -#define USB_TYPE_RESERVED (3 << 5) - -#define USB_RECIP_DEVICE 0 -#define USB_RECIP_INTERFACE 1 -#define USB_RECIP_ENDPOINT 2 -#define USB_RECIP_OTHER 3 - -// Standard requests -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - -#define USB_DESC_DEVICE 1 -#define USB_DESC_CONFIGURATION 2 -#define USB_DESC_STRING 3 -#define USB_DESC_INTERFACE 4 -#define USB_DESC_ENDPOINT 5 -#define USB_DESC_DEVICE_QUALIFIER 6 -#define USB_DESC_OTHER_SPEED 7 -#define USB_DESC_INTERFACE_POWER 8 - -#define USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define USB_CONTROL_EP 0 -#define USB_INT_EP 1 -#define USB_OUT_EP 4 -#define USB_IN_EP 5 -#define USB_CONTROL_SIZE 32 - -// Double buffer IN and OUT EPs, so each -// gets half of the available space -// -// Ah, but USB bulk packets can only come in 8, 16, 32 and 64 -// byte sizes, so we'll use 64 for everything -#define USB_IN_SIZE 64 -#define USB_OUT_SIZE 64 - -#define USB_EP0_IDLE 0 -#define USB_EP0_DATA_IN 1 -#define USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -// CDC definitions -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -// Data structure for GET_LINE_CODING / SET_LINE_CODING class requests -struct usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -}; - -#define USB_READ_AGAIN ((char) -1) - -#define USB_VID 0x1d50 -#define USB_PID 0x8001 - -// iManufacturer -#define USB_iManufacturer_LEN 0x16 -#define USB_iManufacturer_STRING "Nightscout" -#define USB_iManufacturer_UCS2 'N', 0, 'i', 0, 'g', 0, 'h', 0, 't', 0, 's', 0, 'c', 0, 'o', 0, 'u', 0, 't', 0 -// iProduct -#define USB_iProduct_LEN 0x16 -#define USB_iProduct_STRING "subg_rfspy" -#define USB_iProduct_UCS2 's', 0, 'u', 0, 'b', 0, 'g', 0, '_', 0, 'r', 0, 'f', 0, 's', 0, 'p', 0, 'y', 0 -// iSerial -#define USB_iSerial_LEN 0x0e -#define USB_iSerial_STRING "000002" -#define USB_iSerial_UCS2 '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '2', 0 - -// extern __code __at(0x00aa) uint8_t usb_descriptors[]; -extern __xdata uint8_t usb_descriptors[]; - -#endif // _USB_H_ diff --git a/usb_ep0/usb_descriptors.c b/usb_ep0/usb_descriptors.c deleted file mode 100644 index f63b500..0000000 --- a/usb_ep0/usb_descriptors.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * CC Bootloader - USB descriptors - * - * Adapted from AltOS code by Fergus Noble (c) 2011 - * AltOS code Copyright © 2009 Keith Packard - * - * 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; version 2 of the License. - * - * 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; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "cc1111.h" -#include "usb.h" - -// USB descriptors in one giant block of bytes -// __code __at(0x00aa) uint8_t usb_descriptors [] = -__xdata uint8_t usb_descriptors [] = -{ - // Device descriptor - 0x12, - USB_DESC_DEVICE, - LE_WORD(0x0110), // bcdUSB - 0x02, // bDeviceClass - 0x00, // bDeviceSubClass - 0x00, // bDeviceProtocol - USB_CONTROL_SIZE, // bMaxPacketSize - LE_WORD(USB_VID), // idVendor - LE_WORD(USB_PID), // idProduct - LE_WORD(0x010), // bcdDevice - 0x01, // iManufacturer - 0x02, // iProduct - 0x03, // iSerialNumber - 0x01, // bNumConfigurations - - // Configuration descriptor - 0x09, - USB_DESC_CONFIGURATION, - LE_WORD(67), // wTotalLength - 0x02, // bNumInterfaces - 0x01, // bConfigurationValue - 0x00, // iConfiguration - 0xC0, // bmAttributes - 0x32, // bMaxPower - - // Control class interface - 0x09, - USB_DESC_INTERFACE, - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x01, // bNumEndPoints - 0x02, // bInterfaceClass - 0x02, // bInterfaceSubClass - 0x01, // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module - 0x00, // iInterface - - // Header functional descriptor - 0x05, - CS_INTERFACE, - 0x00, // bDescriptor SubType Header - LE_WORD(0x0110), // CDC version 1.1 - - // Call management functional descriptor - 0x05, - CS_INTERFACE, - 0x01, // bDescriptor SubType Call Management - 0x01, // bmCapabilities = device handles call management - 0x01, // bDataInterface call management interface number - - // ACM functional descriptor - 0x04, - CS_INTERFACE, - 0x02, // bDescriptor SubType Abstract Control Management - 0x02, // bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) - - // Union functional descriptor - 0x05, - CS_INTERFACE, - 0x06, // bDescriptor SubType Union Functional descriptor - 0x00, // bMasterInterface - 0x01, // bSlaveInterface0 - - // Notification EP - 0x07, - USB_DESC_ENDPOINT, - USB_INT_EP|0x80, // bEndpointAddress - 0x03, // bmAttributes = intr - LE_WORD(8), // wMaxPacketSize - 0x0A, // bInterval - - // Data class interface descriptor - 0x09, - USB_DESC_INTERFACE, - 0x01, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndPoints - 0x0A, // bInterfaceClass = data - 0x00, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0x00, // iInterface - - // Data EP OUT - 0x07, - USB_DESC_ENDPOINT, - USB_OUT_EP, // bEndpointAddress - 0x02, // bmAttributes = bulk - LE_WORD(USB_OUT_SIZE), // wMaxPacketSize - 0x00, // bInterval - - // Data EP in - 0x07, - USB_DESC_ENDPOINT, - USB_IN_EP|0x80, // bEndpointAddress - 0x02, // bmAttributes = bulk - LE_WORD(USB_IN_SIZE), // wMaxPacketSize - 0x00, // bInterval - - // String descriptors - 0x04, - USB_DESC_STRING, - LE_WORD(0x0409), - - // iManufacturer - USB_iManufacturer_LEN, - USB_DESC_STRING, - USB_iManufacturer_UCS2, - - // iProduct - USB_iProduct_LEN, - USB_DESC_STRING, - USB_iProduct_UCS2, - - // iSerial - USB_iSerial_LEN, - USB_DESC_STRING, - USB_iSerial_UCS2, - - // Terminating zero - 0 -}; diff --git a/version.h b/version.h new file mode 100644 index 0000000..047028b --- /dev/null +++ b/version.h @@ -0,0 +1,6 @@ +#ifndef VERSION_H +#define VERSION_H + +#define SUBG_RFSPY_VERSION "subg_rfspy 2.2" + +#endif //VERSION_H