Unfinished version 0.6 library for the Pi Swarm robot. NOTE: This library is not yet finished or fully tested - it will change.

Dependents:   Pi_Swarm_Blank Aggregation-Flocking_2 Pi_Swarm_User_Command_RF_Test

Fork of Pi_Swarm_Library by James Hilder

alpha433.cpp

Committer:
jah128
Date:
2014-01-31
Revision:
0:9ffe8ebd1c40
Child:
1:b067a08ff54e

File content as of revision 0:9ffe8ebd1c40:

/* University of York Robot Lab Pi Swarm Library: 433MHz Alpha Transceiver
 *
 * (C) Dr James Hilder, Dept. Electronics & Computer Science, University of York
 * 
 * Version 0.4  January 2014
 *
 * Designed for use with the Pi Swarm Board (enhanced MBED sensor board) v1.2
 *
 * Based on code developed by Tobias Dipper, University of Stuttgart (see copyright notice at end of file) 
 */
 
#include "main.h"
#include "communications.h"

// Variables

DigitalOut rf_led(LED1);
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");
    unsigned char i = 0;
    if(cRFStatus == ALPHA433_MODE_TRANSMITTING) {// RF already transmitting
        if(RF_VERBOSE == 1)pc.printf("RF Error: Already transmitting\n");
        return 1; // Error
        
        }
  
    if(cCount > 62) {// Amount of data to high
        if(RF_VERBOSE == 1)pc.printf("RF Error: Too much tx data\n");
        return 2; // Error
  
    }
    if(cCount == 0) {// No Data
        if(RF_VERBOSE == 1)pc.printf("RF 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;
    if(RF_VERBOSE == 1)pc.printf("RF 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; 
    
    if(RF_VERBOSE == 1)pc.printf("RF Transmitting");

    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)
{
    if(RF_VERBOSE == 1)pc.printf("RF Enable TX\n");
    //RFCommand(0x8229);
    _write(0x8229);
    rf_led = 1;
}

// Disable RF Transmitter
void Alpha433::disableTransmitter(void)
{
    if(RF_VERBOSE == 1)pc.printf("RF Disable TX\n");
    //RFCommand(0x8209);
    _write(0x8209);
    rf_led = 0;
}


// Enable RF Receiver
void Alpha433::enableReceiver(void)
{
    if(RF_VERBOSE == 1)pc.printf("RF Enable RX\n");
    //RFCommand(0x8288);
    _write(0x8288);
    //rx_led = 1;
    enableFifoFill();
}

// Disable RF Receiver
void Alpha433::disableReceiver(void)
{    
   if(RF_VERBOSE == 1)pc.printf("RF 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;
    //int_out=0;

}

void Alpha433::timeout(void)
{
    if(RF_VERBOSE == 1)pc.printf("RF Error on read; resetting chip\n");
    rf_init();
}

// Initialise RF
void Alpha433::rf_init(void)
{
    
    if(RF_VERBOSE == 1)pc.printf("RF Init start\n");
    rf_reset(); // RF Hardware Reset
    _write(0x0000);    // read status to cancel prior interrupt           
    _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();
    ssReceivePointer = 0;
    reset_timeout.attach(this,&Alpha433::timeout,TIMEOUT);
    if(RF_VERBOSE == 1)pc.printf("RF Init end\n");
    cRFStatus = ALPHA433_MODE_RECEIVING;
}
    
  
// RF Interrupt
void Alpha433::interrupt(void)
{
   if(cRFStatus == ALPHA433_MODE_RECEIVING){
      rf_led=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
              //pc.printf("\nBytes to receive: %d\n",ssReceiveCount);
           }
           
        }
        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){
        if(RF_VERBOSE == 1)pc.printf("RF Received [%d] \"%s\" (checksum failed: expected %02X, received %02X)%02X %02X\n",cCount,rstring,checksum,cBuffer[cCount],cBuffer[cCount-1],cBuffer[cCount+1]);
   }else {
       if(RF_VERBOSE == 1)pc.printf("RF Received [%d] \"%s\" (checksum passed)\n",cCount,rstring);
       if(USE_COMMUNICATION_STACK == 1){
            processRadioData(rstring, cCount);
       }else{processRawRFData(rstring, cCount);
       }
       }
}


int Alpha433::readStatusByte()
{
   if(RF_VERBOSE == 1)pc.printf("RF 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);
}