Handheld controller (RF) for Pi Swarm system
Fork of Pi_Swarm_Handheld_Controller by
Diff: alpha433.cpp
- Revision:
- 0:d63a63feb104
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/alpha433.cpp Tue Jun 10 11:05:23 2014 +0000 @@ -0,0 +1,379 @@ +/* University of York Robot Lab m3pi Library: 433MHz Alpha Transceiver + * + * (C) Dr James Hilder, Dept. Electronics & Computer Science, University of York + * + * October 2013 + * + * Designed for use with the enhanced MBED sensor board + * + * Based on code developed by Tobias Dipper, University of Stuttgart + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "mbed.h" +#include "alpha433.h" +#include "main.h" + +// Variables + +//Serial pc(USBTX, USBRX); +//DigitalOut tx_led(LED2); +//DigitalOut rx_led(LED3); +DigitalOut irqled(LED4); +Timeout reset_timeout; + + +char cRFStatus = 0; + +signed short ssTransmitCount = 0; +signed short ssTransmitPointer = 0; +char cTXBuffer[64]; + +signed short ssReceiveCount = 0; +signed short ssReceivePointer = 0; +char cRXBuffer[64]; + +char cDataAvailable = 0; + +Alpha433::Alpha433(PinName mosi, PinName miso, PinName sck, PinName fss, PinName nirq) : Stream("alpha433"), _spi(mosi,miso,sck), _fss(fss), _nirq_test(nirq), _nirq(nirq) { + +} + +Alpha433::Alpha433() : Stream("alpha433"), _spi(p5,p6,p7), _fss(p8), _nirq_test(p11), _nirq(p11) { + +} + + + + +// RF Send Data +// +// Eg: +// unsigned char message[32]; +// unsigned char count; +// count = snprintf(message, 32, "Hello: %i", 42); +// sendString(count, message); +unsigned long Alpha433::sendString(char cCount, char* cBuffer) +{ + //pc.printf("SendString called"); + char i = 0; + if(cRFStatus == ALPHA433_MODE_TRANSMITTING) {// RF already transmitting + pc.printf("Error: Already transmitting\n"); + + return 1; // Error + + } + + if(cCount > 62) {// Amount of data to high + pc.printf("Error: Too much tx data\n"); + + return 2; // Error + + } + if(cCount == 0) {// No Data + pc.printf("Error: No tx data\n"); + return 3; // Error + } + cTXBuffer[i] = cCount; + + unsigned char checksum_byte = 0; + for(i=0; i<cCount; i++) {// make a copy + cTXBuffer[i+1] = cBuffer[i]; + checksum_byte ^= cBuffer[i]; + } + cTXBuffer[cCount+1] = checksum_byte; + //pc.printf("Message: \"%s\" Checksum: %2X\n",cBuffer,checksum_byte); + ssTransmitCount = cCount+3; // add count and checksum + ssTransmitPointer = -6; + cRFStatus = ALPHA433_MODE_SWITCHING; + disableReceiver(); + enableTransmitter(); + cRFStatus = ALPHA433_MODE_TRANSMITTING; + + //pc.printf("Transmitting %d bytes\n",ssTransmitCount); + + while(ssTransmitPointer <= ssTransmitCount){ + while(_nirq_test); + + if(ssTransmitPointer < -2) + _write(0xB8AA); // send sync + else if(ssTransmitPointer == -2) + _write(0xB82D); // send first part of the fifo pattern; + else if(ssTransmitPointer == -1) + _write(0xB8D4); // send second part of the fifo pattern; + else if(ssTransmitPointer == ssTransmitCount) + _write(0xB800); // send dummy byte + else + _write(0xB800 | cTXBuffer[ssTransmitPointer]); // send data + ssTransmitPointer++; + } + + _write(0xB800); // send dummy byte, maybe redundant + disableTransmitter(); + enableReceiver(); + ssReceivePointer = 0; + cRFStatus = ALPHA433_MODE_RECEIVING; + return 0; +} + +// Enable RF Transmitter +void Alpha433::enableTransmitter(void) +{ + //pc.printf("Enable TX\n"); + //RFCommand(0x8229); + _write(0x8229); + //tx_led = 1; +} + +// Disable RF Transmitter +void Alpha433::disableTransmitter(void) +{ + //pc.printf("Disable TX\n"); + //RFCommand(0x8209); + _write(0x8209); + // tx_led = 0; + +} + + +// Enable RF Receiver +void Alpha433::enableReceiver(void) +{ + //pc.printf("Enable RX\n"); + //RFCommand(0x8288); + _write(0x8288); + // rx_led = 1; + enableFifoFill(); +} + +// Disable RF Receiver +void Alpha433::disableReceiver(void) +{ + //pc.printf("Disable RX\n"); + //RFCommand(0x8208); + _write(0x8208); + // rx_led = 0; + disableFifoFill(); +} + +// SSI FiFo Clear +void Alpha433::clearBuffer(void) +{ + while(_read(0xB000) != 0); +} + +// Reset RF +void Alpha433::rf_reset(void) +{ + // Chip must be deselected + _fss = 1; + + // Setup the spi for 16 bit data, high steady state clock, second edge capture, with a 1MHz clock rate + _spi.format(16,0); //Was 16,3 + _spi.frequency(2000000); + _nirq.mode(PullUp); + _nirq.fall(this,&Alpha433::interrupt); + // Select the device by seting chip select low + _fss = 0; + //pc.printf("End reset\n"); + +} + +void Alpha433::timeout(void) +{ + pc.printf("Error on read; resetting chip\n"); + rf_init(); +} + +// Initialise RF +void Alpha433::rf_init(void) +{ + + pc.printf("Init start\n"); + + rf_reset(); // RF Hardware Reset + _write(0x0000); // read status to cancel prior interrupt + pc.printf("Start setup\n"); + + _write(0x8000 | ALPHA433_FREQUENCY | ALPHA433_CRYSTAL_LOAD | ALPHA433_USE_FIFO); + _write(0x9000 | ALPHA433_PIN20 | ALPHA433_VDI_RESPONSE | ALPHA433_BANDWIDTH | ALPHA433_LNA_GAIN | ALPHA433_RSSI); + _write(0xC228 | ALPHA433_CLOCK_RECOVERY | ALPHA433_FILTER | ALPHA433_DQD); + _write(0xCA00 | ALPHA433_FIFO_LEVEL | ALPHA433_FIFO_FILL | ALPHA433_HI_SENS_RESET); + _write(0xC400 | ALPHA433_AFC_MODE | ALPHA433_AFC_RANGE | ALPHA433_AFC_FINE_MODE | ALPHA433_AFC); + _write(0x9800 | ALPHA433_MOD_POLARITY | ALPHA433_MOD_FREQUENCY | ALPHA433_TX_POWER); + _write(0xC000 | ALPHA433_CLK_OUT | ALPHA433_LOW_BAT); + + enableReceiver(); + //pc.printf("End setup\n"); + + ssReceivePointer = 0; + reset_timeout.attach(this,&Alpha433::timeout,TIMEOUT); + pc.printf("Init end\n"); + cRFStatus = ALPHA433_MODE_RECEIVING; + +} + + +// RF Interrupt +void Alpha433::interrupt(void) +{ + if(cRFStatus == ALPHA433_MODE_RECEIVING){ + irqled=1; + //Add reset timeout + reset_timeout.detach(); + reset_timeout.attach(this,&Alpha433::timeout,0.5); + pc.printf("Rec. ISR\n"); + int res = _read(0x0000); + if(res==0) res = _read(0x0000); + char read_failure = 0; + + if (res & (ALPHA433_STATUS_TX_NEXT_BYTE | ALPHA433_STATUS_FIFO_LIMIT_REACHED)) { // RF: waiting for next Byte OR FIFO full + pc.printf("Receiving"); + cRXBuffer[ssReceivePointer] = _read(0xB000) & 0xFF; // get data + if(ssReceivePointer == 0) { + ssReceiveCount = cRXBuffer[0]; + + if((ssReceiveCount == 0) || (ssReceiveCount > 62)) { // error amount of data + read_failure=1; + pc.printf("Error amount of RX data: %d\n",ssReceiveCount); + reset_timeout.detach(); + reset_timeout.attach(this,&Alpha433::timeout,TIMEOUT); + } else ssReceiveCount += 2; // add count + checksum + } + if(!read_failure){ + ssReceivePointer++; + if (ssReceivePointer > ssReceiveCount) { // End transmission + disableFifoFill(); + enableFifoFill(); + irqled=0; + reset_timeout.detach(); + reset_timeout.attach(this,&Alpha433::timeout,TIMEOUT); + ssReceivePointer = 0; + dataAvailable(cRXBuffer[0], &cRXBuffer[1]); + } + }else{ + disableFifoFill(); + enableFifoFill(); + ssReceivePointer = 0; + reset_timeout.detach(); + reset_timeout.attach(this,&Alpha433::timeout,TIMEOUT); + } + } + } +} + +// RF Set Datarate +void Alpha433::setDatarate(unsigned long ulValue) +{ + unsigned long ulRateCmd; + if(ulValue < 3000) ulRateCmd = 0x0080 | (10000000 / 29 / 8 / ulValue) - 1; + else ulRateCmd = 0x0000 | (10000000 / 29 / 1 / ulValue) - 1; + _write(0xC600 | ulRateCmd); +} + +// RF Set Frequency +void Alpha433::setFrequency(unsigned long ulValue) +{ + unsigned long ulRateCmd; + +#if (ALPHA433_FREQUENCY == ALPHA433_FREQUENCY_315) + ulRateCmd = (ulValue - 10000000 * 1 * 31) * 4 / 10000; + +#elif (ALPHA433_FREQUENCY == ALPHA433_FREQUENCY_433) + ulRateCmd = (ulValue - 10000000 * 1 * 43) * 4 / 10000; + +#elif (ALPHA433_FREQUENCY == ALPHA433_FREQUENCY_868) + ulRateCmd = (ulValue - 10000000 * 2 * 43) * 4 / 10000; + +#elif (ALPHA433_FREQUENCY == ALPHA433_FREQUENCY_915) + ulRateCmd = (ulValue - 10000000 * 3 * 30) * 4 / 10000; +#endif + + _write(0xA000 | ulRateCmd); +} + + + +// Enable RF Receiver FiFo fill +void Alpha433::enableFifoFill(void) +{ + _write(0xCA00 | ALPHA433_FIFO_LEVEL | ALPHA433_FIFO_FILL | ALPHA433_HI_SENS_RESET | 0x0002); + while((_read(0x0000) & ALPHA433_STATUS_FIFO_EMPTY) == 0); +} + +// Disable RF Receiver FiFo fill +void Alpha433::disableFifoFill(void) +{ + _write(0xCA00 | ALPHA433_FIFO_LEVEL | ALPHA433_FIFO_FILL | ALPHA433_HI_SENS_RESET); +} + +// Handle new RF Data +void Alpha433::dataAvailable(char cCount, char* cBuffer) +{ + char rstring [cCount+1]; + char checksum = 0; + int i; + for(i=0;i<cCount;i++){ + rstring[i]=cBuffer[i]; + checksum ^= rstring[i]; + } + rstring[cCount]=0; + if (cBuffer[cCount] != checksum){ + pc.printf("Received [%d] \"%s\" (checksum failed: expected %02X, received %02X)%02X %02X\n",cCount,rstring,checksum,cBuffer[cCount],cBuffer[cCount-1],cBuffer[cCount+1]); + }else { + pc.printf("Received [%d] \"%s\" (checksum passed)\n",cCount,rstring); + handleData(rstring, cCount); + } +} + + +int Alpha433::readStatusByte() +{ + pc.printf("Reading status byte\n"); + return _read(0x0000); +} + +//-----PRIVATE FUNCTIONS----- + +void Alpha433::_write(int address) { + _fss=0; //select the deivce + _spi.write(address); //write the address of where the data is to be written first + //pc.printf("Write data: %04X\n",address); + _fss=1; //deselect the device +} + +int Alpha433::_read(int address) { + int _data; + _fss=0; //select the device + _data = _spi.write(address); //select the register + //pc.printf("Read data: %04X\n",_data); + _fss=1; //deselect the device + return _data; //return the data + +} + +int Alpha433::_putc (int c) { + return(c); +} + +int Alpha433::_getc (void) { + char r = 0; + return(r); +} \ No newline at end of file