Projet_S5 / Mbed 2 deprecated Repo_Noeud_Mobile_refactor

Dependencies:   mbed-rtos mbed

Fork of Repo_Noeud_Mobile by Projet_S5

Communication/Xbee.cpp

Committer:
groygirard
Date:
2015-04-12
Revision:
57:ce80fbd67161
Parent:
56:6af8f2c9ddbe
Child:
58:4cdc85ed04a9

File content as of revision 57:ce80fbd67161:

#include "Xbee.h"

Serial x_pc(USBTX, USBRX);

inline void PrintChar(char c);
inline void PrintEndline();

Xbee::Xbee()
{
    //PanId = 0x1337;
    //SetPanId(PanId);
}

Xbee::Xbee(short panId, PinName pinTx, PinName pinRx)
{
    this->XbeePin = new Serial(pinTx, pinRx);
    PanId = panId;
    SetPanId(PanId);
}

Xbee::~Xbee()
{
    delete XbeePin;
}

//send frames to XBee (to set PanID and do the WR)
void Xbee::SendXBee(char array[], int size)//SendXbee
{
    for(int i = 0; i < size; i++) {
        XbeePin->putc(array[i]);
    }
}

void Xbee::EnvoyerStructure(Mobile_Vers_Fixe mvf)
{
    char data[2] = {0x00, 0x00};
    //x_pc.printf(" \r\n Gants id %c", mvf->gants);
    data[0] = mvf.gants;
    mvf.flexSensor.index == 1 ? data[1] = 0x04 : data[1] = 0;
    mvf.flexSensor.majeur == 1 ? data[1] += 0x02 : data[1] += 0;
    mvf.flexSensor.annulaire == 1 ? data[1] += 0x01 : data[1] += 0;

    SendData(data, 2);
}

//function to set the PAN ID
void Xbee::SetPanId(short panId)
{
    char c1 = panId >> 8; //PAN ID char 1
    char c2 = panId; //PAN ID char 2
    char checksum = 0xFF - (0x08 + 0x01 + 0x49 + 0x44 + c1 + c2); //calculate checksum

    //ID and WR AT Commands
    char array[] = {0x7E, 0x00, 0x06, 0x08, 0x01, 0x49, 0x44, c1, c2, checksum};
    char wr[] = {0x7E, 0x00, 0x04, 0x08, 0x01, 0x57, 0x52, 0x4D};

    SendXBee(array, sizeof(array)); //send ID AT Command frame
    SendXBee(wr, sizeof(wr)); //send WR AT Command frame
}

//Patate

//function to set the PAN ID




//initialise HexToAscii table for correct output on Websocket Server
void Xbee::BuildHexToAsciiTable()
{
    HexToAscii[0x0] = '0';
    HexToAscii[0x1] = '1';
    HexToAscii[0x2] = '2';
    HexToAscii[0x3] = '3';
    HexToAscii[0x4] = '4';
    HexToAscii[0x5] = '5';
    HexToAscii[0x6] = '6';
    HexToAscii[0x7] = '7';
    HexToAscii[0x8] = '8';
    HexToAscii[0x9] = '9';
    HexToAscii[0xa] = 'A';
    HexToAscii[0xb] = 'B';
    HexToAscii[0xc] = 'C';
    HexToAscii[0xd] = 'D';
    HexToAscii[0xe] = 'E';
    HexToAscii[0xf] = 'F';
}

//get data from xbee thread
void Xbee::GetData()
{
    data* input;
    while(true) {
        if(XbeePin->readable()) { //gets 1 full frame and store in mailbox
            input = mailbox.alloc(); //alloc in mailbox

            if(input != NULL) { //if alloc was successful
                char c = XbeePin->getc(); //start delimiter
                char c1 = XbeePin->getc(); //length byte 1
                char c2 = XbeePin->getc(); //length byte 2
                short length = c1 << 8 | c2; //calculate length
                input->size = length + 4; //length = dataLength + start delimiter + length (2) + checksum
                input->array[0] = c;
                input->array[1] = c1;
                input->array[2] = c2;
                short pos = 3;
                while(length+1 > 0) { //include checksum
                    c = XbeePin->getc(); //get char
                    input->array[pos] = c; //store data
                    pos++; //current position
                    length--; //length left until the end of frame
                }

                mailbox.put(input); //put data in mailbox
            } else { //if mailbox is full
                x_pc.printf("Mailbox is full!\r\n");
            }
        }
    }
}

//output data on PC terminal thread
void Xbee::OutputData()
{
    osEvent event;
    data* mail;
    while(true) {
        event = mailbox.get(); //get data from mailbox  blocking function
        mail = (data*)event.value.p; //this mail is of type data*, our own struct defined at the top
        if (event.status == osEventMail) { //if Event
            if(mail->array[0] != 0x7e) { //verify header is correct
                x_pc.printf("Header error! ");
            }

            char sum = 0x00; //to calculate checksum
            PrintChar(mail->array[0]); //print start delimiter
            PrintChar(mail->array[1]); //print length byte 1
            PrintChar(mail->array[2]); //print length byte 2
            for(int i = 3; i < mail->size-1; i++) { //data
                PrintChar(mail->array[i]); //print data
                sum+= mail->array[i]; //calculate checksum
            }
            PrintChar(mail->array[(mail->size)-1]); //print checksum
            char expected = 0xFF - sum; //expected checksum
            if(mail->array[mail->size-1] != expected) { //verify checksum is OK
                x_pc.printf(" Checksum Error! expected: %x, received: %x", expected, mail->array[mail->size-1]);
            }
        } else { //not an event mail
            x_pc.printf("Status != osEventMail\r\n");
        }

        //POINTER based on the FRAME TYPE (4th byte of the trame)
        ReceivePacket(mail);

        mailbox.free(mail); //free the space in the mailbox
        PrintEndline();
    }
}

//function that generates the Transmit Request frame
//and the data[] parameter is only the data we want to send
void Xbee::SendData(char data[], int messageSize)
{
    int size = 18 + messageSize; //18 bytes + message
    int dataSize = 14 + messageSize; //14 bytes + message
        
    char length1 = dataSize >> 8; //get length char 1
    char length2 = dataSize; //get length char 2
    
    char sum = 0x00; //to calculate the checksum char
    
    char command[size];
    command[0] = 0x7E; //start delimiter
    command[1] = length1; //length first char
    command[2] = length2; //length second char
    command[3] = 0x10; //frame type
    command[4] = 0x01; //frame ID
    sum += 0x10;
    sum += 0x01;
    
    for(int i = 5; i <= 12; i++)
    {
        command[i] = 0x00; //64 bit address
    }
    
    command[13] = 0xFF; //16 bit address
    command[14] = 0xFE; //16 bit address
    sum += 0xFF;
    sum += 0xFE;
    
    command[15] = 0x00; //broadcast radius
    command[16] = 0x00; //options
    
    for(int i = 17; i < size-1; i++) //data
    {
        command[i] = data[i-17]; //data
        sum += command[i]; //keep calculating for checksum
        x_pc.printf("");
    }

    command[size-1] = 0xFF - sum; //checksum

    SendXBee(command, size); //send frame array to XBee
}

//receive packet frame
//this function analyses it and puts in wsMailbox to send to websocket
void Xbee::ReceivePacket(data* trame)
{
    Fixe_Vers_Mobile* fvm = fvm_mailbox.alloc(); //alloc in mailbox

    if(fvm != NULL) { //if alloc was successful
        x_pc.printf("Receive Packet Info");

        switch(trame->array[14]) { //print receive option
            case 0x01:
                x_pc.printf("\r\nPacket acknowledged");
                break;
            case 0x02:
                x_pc.printf("\r\nPacket was a broadcast packet");
                break;
            case 0x20:
                x_pc.printf("\r\nPacket encrypted with APS encryption");
                break;
            case 0x40:
                x_pc.printf("\r\nPacket was sent from an end device");
                break;
            default:
                x_pc.printf("\r\nUnknown option: %x", trame->array[14]);
                break;
        }
        // Data aquisition
        fvm->game = (GameMode_e)trame->array[15];

        fvm_mailbox.put(fvm); //put data in mailbox
    } else {
        x_pc.printf("Mobile Vers Fixe mailbox is full!\r\n");
    }
}

//utility function for proper output on PC Terminal
inline void PrintChar(char c)
{
    if(c < 0x10) { //if char is between 0 and F, put a 0 before
        x_pc.printf("0%x ", c);
    } else {
        x_pc.printf("%x ", c);
    }
}

//utility function to print an endline
inline void PrintEndline()
{
    x_pc.printf("\r\n");
}