Handheld controller (RF) for Pi Swarm system

Dependencies:   mbed

Fork of Pi_Swarm_Handheld_Controller by piswarm

alpha433.cpp

Committer:
jah128
Date:
2014-06-10
Revision:
0:d63a63feb104

File content as of revision 0:d63a63feb104:

/* 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);
}