Unfinished v0.7, added bearing detection

Fork of Pi_Swarm_Library_v06_alpha by piswarm

alpha433.cpp

Committer:
jah128
Date:
2014-06-30
Revision:
11:5ebcb52726cf
Parent:
10:5c111c07a2ed

File content as of revision 11:5ebcb52726cf:

/*******************************************************************************************
 *
 * University of York Robot Lab Pi Swarm Library: 433MHz Alpha Transceiver Driver
 *
 * (C) Dr James Hilder, Dept. Electronics & Computer Science, University of York
 *
 * Version 0.7  May 2014
 *
 * Designed for use with the Pi Swarm Board (enhanced MBED sensor board) v1.2
 *
 ******************************************************************************************/ 

#include "main.h"
#include "communications.h"

// Variables

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;

volatile int gi_RF_messages_sent =0;
volatile int gi_RF_messages_received =0;
volatile int gi_RF_bytes_sent=0;
volatile int gi_RF_bytes_received=0;
volatile int gi_RF_reset_cycles=0;
volatile int gi_RF_received_length_error=0;
volatile int gi_RF_received_checksum_failure=0;
volatile int gi_RF_received_invalid_sender=0;
volatile int gi_RF_received_invalid_target=0;
volatile int gi_RF_received_invalid_format=0;
volatile int gi_RF_received_not_for_me=0;
volatile int gi_RF_received_broadcast=0;
volatile int gi_RF_received_targeted_to_me=0;
volatile int gi_RF_received_unexpected_response=0;
volatile int gi_RF_received_invalid_response=0;
volatile int gi_RF_commands_actioned=0;
volatile int gi_RF_commands_invalid=0;
volatile int gi_RF_commands_blocked=0;
volatile int gi_RF_requests_actioned=0;
volatile int gi_RF_commands_sent=0;
volatile int gi_RF_responses_sent=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)
{

}

// Send data on the Alpha 433 transceiver, cCount = string length, cBuffer = data string
unsigned long Alpha433::sendString(char cCount, char* cBuffer)
{
    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
    
    gi_RF_messages_sent++;
    gi_RF_bytes_sent+=cCount;
    
    disableTransmitter();
    enableReceiver();
    ssReceivePointer = 0;
    cRFStatus = ALPHA433_MODE_RECEIVING;
    return 0;
}

// Handle new RF Data
void Alpha433::dataAvailable(char cCount, char* cBuffer)
{
    gi_RF_messages_received++;
    
    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;
    gi_RF_bytes_received += cCount;
    if (cBuffer[cCount] != checksum) {
        gi_RF_received_checksum_failure++;
        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);
        }
    }
}


// Enable RF Transmitter
void Alpha433::enableTransmitter(void)
{
    if(RF_VERBOSE == 1)pc.printf("RF Enable TX\n");
    //RFCommand(0x8229);
    _write(0x8229);
}

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


// Enable RF Receiver
void Alpha433::enableReceiver(void)
{
    if(RF_VERBOSE == 1)pc.printf("RF Enable RX\n");
    //RFCommand(0x8288);
    _write(0x8288);
    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)
{
    gi_RF_reset_cycles++;
    
    // 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;

}

// Timeout interrupt routine - reset chip
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 Called - handle received data
void Alpha433::interrupt(void)
{
    if(cRFStatus == ALPHA433_MODE_RECEIVING) {
        //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;
                    gi_RF_received_length_error++;
                    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);
}


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