xbee communication for UWB quadcopter project Originally by Greg Abdo Forking to reduce impact of interrupt by moving packetbuilder out of the interrupt and letting be handled in the main loop

Fork of com by Prosper Van

com.cpp

Committer:
oprospero
Date:
2014-09-25
Revision:
16:89695823d407
Parent:
15:3f742edaa359
Child:
17:acef0fb07510

File content as of revision 16:89695823d407:

/****************************** com.cpp **********************************/
/* Version: 1.0                                                          */
/* Last Updated: June 1, 2013                                            */
/*                                                                       */
/* The com class implements reliable data transfer between two nodes     */
/*using a checksum and a sequence number for guaranteed message delivery */
/*over an xbee modem connected to the passed in tx and rx pins. Messages */
/*are received and placed in the rxBuffer to be read when convenient.    */
/*Messages are encoded by sending a byte with the value of the command   */
/*then and int of the command.                                           */
/*                                                                       */
/* Commands:    0 -> Ack, does not get placed in rxQueue.                */
/*              1 -> Throttle                                            */
/*              2 -> Pitch                                               */
/*              3 -> Roll                                                */
/*              4 -> Yaw                                                 */
/*************************************************************************/

#include "com.h"
#ifdef DEBUG_COM
    Timer timerCom;
    #define NL "\n\r"
    #define PRINT(x)        xbeeTx.printf(x)   //Serial.print(x)
    #define PRINTF          xbeeTx.printf   //Serial.print(x, y)
    #define PRINTLN(x)      PRINT(x);PRINT(NL)
    #define START           timerCom.start(); 
    #define STOP            timerCom.stop()
    #define RESET           timerCom.reset()
    #define READ            timerCom.read_us()
    #define GET(x)          x = READ
#else
    #define PRINT(x)
    #define PRINTF(x, y)
    #define PRINTLN(x)
    #define PRINTLNF(x, y) 
    #define START 
    #define STOP  
    #define RESET 
    #define READ 
    #define GET(x)
#endif


/*********************** com( PinName, PinName ) *************************/
/*                                                                       */
/*************************************************************************/

com::com( PinName tx, PinName rx , PinName rssipin) : xbeeTx( tx, NC), xbeeRx( NC, rx), rssi(rssipin)
{
    index1 = 0;                             // How many bytes are in the buffer.
    index2 = 0;                             // How many bytes are in the buffer.
    pindex = 0;                             // How many bytes are in the buffer.
    rdy2build = false;                      // Xbee is in transparent mode.
    xbeeTx.baud(BAUDRATE);                  // Setup the serial baud rate.
    xbeeRx.baud(BAUDRATE);                  // Setup the serial baud rate.
    txBuffer = new queue();
    signalStrength = 0;
    xbeeRx.attach( this, &com::callback );    // Set callback as the interrupt handler. 
    #ifdef DEBUG_COM
    xbeeTx.printf("Communication.....Done\n\r");
    #endif
    START;
}


/************************ void write( char ) *****************************/
/* Write a packet out the xbee com port.                                 */
/*                                                                       */
/* Data format byte[]                                                    */
/*                byte[0] = command.                                     */
/*                byte[1] = upper 8 bits of value.                       */
/*                byte[2] = lower 8 bits of value.                       */
/*                byte[3] = Checksum byte[0] + byte[2].                  */
/*                byte[4] = Sequence Number.                             */
/*                byte[5] = 255 End of message.                          */
/*************************************************************************/

void com::write( short command, short value  )
{  
    xbeeTx.putc( 255 );                     // End of message.
    xbeeTx.putc( (char)command );           // Command
    xbeeTx.putc( (char) value);            // Second 8 bits in array.
    xbeeTx.putc( command + value );        // Checksum array[0] + array[1].
}

/*************************** char ackCheck()  ********************************/
/*                                                                       */
/*************************************************************************/

void com::sendACK()
{
    if( !txBuffer->isEmpty())
    {
    __disable_irq();
        short * pkt = txBuffer->pop();
        write(pkt[0],pkt[1]); //may need to disable interrupt
    __enable_irq();
//        #ifdef DEBUG_COM
        if(pkt[1] % 5 == 0) 
        {
            PRINTF("len: %d\n\r",txBuffer->queueLength());
        }
//        #endif
        delete[] pkt;
    
    }
}

bool com::rdy2ack()
{
    return !txBuffer->isEmpty();
}


/************************ void callback() ********************************/
/*                                                                       */
/*************************************************************************/

//void com::callback()
//{   
//    __disable_irq();
//    while( xbeeRx.readable() )
//    {
//        char data = xbeeRx.getc(); 
////        xbeeRx.putc(data);
//        if (isA1)
//        {
//            if ( data == 255 && index1 > 4 )
//            {
//                rdy2build = true;
//                pindex = index1;
//                index1 = 0;
//                isA1 = false;
//            }
//            else if ( index1 < BUFFERSIZE )
//            {
//                
//                buffer1[index1++] = data;
//            }
//        }
//        else
//        {
//            if ( data == 255 && index2 > 4 )
//            {
//                rdy2build = true;
//                pindex = index2;
//                index2 = 0;
//                isA1 = true;
//            }
//            else if ( index2 < BUFFERSIZE )
//            {
//                buffer2[index2++] = data;
//            }
//        }
//    }
//    __enable_irq();
//}

void com::callback()
{   
    __disable_irq();
    PRINTF("Reading\n\r");
    while( xbeeRx.readable() )
    {
        short *data = new short;
        data[0] = xbeeRx.getc(); 
        PRINTF("d: %d\n\r", data[0]);
        rxBuffer->add( data );
    }
    __enable_irq();
}

/********************** void packetBuilder() *****************************/
/* Creates a packet from the buffered data and places it in the rxBuffer */
/* queue to be read whenever convenient. Max value of +/- 8063.          */
/*************************************************************************/

//short * com::read()
//{
//    if (rdy2build)
//    {
//        rdy2build = false;
//        char * commandData = new char[5];
//        if (!isA1)
//        {
//            commandData[4] = buffer1[--pindex];     // Sequence Number.
//            commandData[3] = buffer1[--pindex];     // CheckSum value.
//            commandData[2] = buffer1[--pindex];     // Second 7 bits.
//            commandData[1] = buffer1[--pindex];     // Fisrt 7 bits.
//            commandData[0] = buffer1[--pindex];     // Command.
//        }
//        else 
//        {
//            commandData[4] = buffer2[--pindex];     // Sequence Number.
//            commandData[3] = buffer2[--pindex];     // CheckSum value.
//            commandData[2] = buffer2[--pindex];     // Second 7 bits.
//            commandData[1] = buffer2[--pindex];     // Fisrt 7 bits.
//            commandData[0] = buffer2[--pindex];     // Command.
//        }
//        
////        xbeeTx.printf("Copied: %d %d %d %d %d\n\r",commandData[0],commandData[1],commandData[2],commandData[3],commandData[4]);
//          
//        if( commandData[0] + commandData[2] == commandData[3] ) // Validate checksum.
//        {
//            short * array = new short[2];
//            array[0] = (short)commandData[0];
//            
//            short value = (short)(commandData[1] * 128 + commandData[2]);
//            
//            if( value > 8062 )
//                value = (short)value + 57344;
//            
//            array[1] = value;
//            if ( commandData[0] != 0)
//            {
//                short * ackPacket = new short[2];
//                ackPacket[0] = commandData[0];
//                ackPacket[1] = commandData[4];
//                txBuffer->add( ackPacket ); // Ack the packet with sequence nuber.
//            }
//            
//            delete[] commandData;
//            return array;
//        } 
//        delete[] commandData; 
//    }        
//    return NULL;                                 
//}

short * com::read()
{
    if ( !cmdBuffer->isEmpty() )
        return cmdBuffer->pop();
    else
        return NULL;    
}


/************************* bool isData()  ********************************/
/*                                                                       */
/*************************************************************************/

//bool com::isData()
//{
//    return rdy2build;
//}

bool com::isData()
{
    static short packetIndex = 0;
    static short pack_cmd = 0;
    static short pack_value[2] = {0,0};
    static short pack_seq = 0;
    static short pack_checksum = 0;
    
    __disable_irq();
    while ( !rxBuffer->isEmpty() )
    {
        short * data = rxBuffer->pop();
        __enable_irq();
        PRINTF("d: %d \n\r", *data);
        switch (packetIndex)
        {
            case 0:
            {
                if ( *data == 255 )
                packetIndex++;
                break;
            }
            case 1:
            {
                if ( *data < 13 )
                {
                    pack_cmd = *data;
                    packetIndex++;
                }
                else
                    packetIndex = 0;
                break;
            }
            case 2:
            {
                pack_value[1] = *data;
                packetIndex++;
                break;
            }
            case 3:
            {
                if ( *data < 128 )
                {
                    pack_value[0] = *data;
                    packetIndex++;
                }
                else
                    packetIndex = 0;
                break;
            }
            case 4:
            {
                pack_seq = *data;
                packetIndex++;
                break;   
            }
            case 5:
            {
                short temp = pack_value[0] + pack_cmd;
                pack_checksum = *data;
                if ( temp == pack_checksum )
                {
                    short * ackPacket = new short[2];
                    ackPacket[0] = pack_cmd;
                    ackPacket[1] = pack_seq;
                    txBuffer->add( ackPacket ); // Ack the packet with sequence nuber.
                    
                    short * array = new short[2];
                    array[0] = pack_cmd;
                    array[1] = pack_value[1] * 128 + pack_value[0];
                    cmdBuffer->add( array );
                }
                
                packetIndex = 0;
                break;   
            }
            default:
            packetIndex = 0;
            break;
        }
        
        __disable_irq();
        delete[] data;
        
    }
    __enable_irq();
    return !cmdBuffer->isEmpty();
}


/********************** bool isSignalGood() ******************************/
/* For future use   */
/*************************************************************************/
bool com::isSignalGood()
{
    signalStrength = rssi.dutycycle();
    if (signalStrength > RSSI_THRES) return true;
    else return false;
}