Xbee

XBEE.cpp

Committer:
renanbmx123
Date:
2018-10-14
Revision:
0:fbed291691a6

File content as of revision 0:fbed291691a6:

#include "XBEE.h"
#include <stdlib.h>

/* Class constructor */
XBEE::XBEE(Serial* serial, int baud):xbee(serial)
{
    xbee->baud(baud);
    /* Enable the reception of bytes on the serial interface by providing a cb */
    xbee->attach(callback(this, &XBEE::recvAttach), Serial::RxIrq);
}

/* Class destructor */
XBEE::~XBEE() 
{
    if (xbee != NULL) {
        delete xbee;
    }
}

/* Chamada por Interrupcao, RX */
void XBEE::recvAttach (void) 
{
    if (int_ctrl == 1)
        while(xbee->readable()) {
            buf_rx[count_rx%sizeof(buf_rx)] = xbee->getc();
            //buf_rx.push(xbee->getc());
            count_rx++;
        }
}

/* Initialize the Device XBEE */
void XBEE::init(void)
{
 //   memset(&NI,0,sizeof(NI));
    ID = 0;
    MY = 0;
    SH = 0;
    SL = 0;
    PL = 0;
    BD = 0;
    AO = 0;
    DB = 0;
    TP = 0;
    
    wait(0.5);
    
    memset(&buf_rx,0,sizeof(buf_rx));
    
    create_CMD("NI",0);    // Pan ID da rede
    sendBuffer();
    wait(0.5);
    
    recv_NI();
    read_cfg("ID", ID);
    read_cfg("SH", SH);
    read_cfg("SL", SL);
    read_cfg("PL", PL);
    read_cfg("BD", BD);
    read_cfg("AO", AO);
    read_cfg("DB", DB);
    read_cfg("TP", TP);
    
    count_rx = 0;
    memset(&buf_rx,0,sizeof(buf_rx));
}

/* Send message to the destination */
int XBEE::send_msg(char * str, int dest)
{
    int n = strlen(str);
    if(n > 92) {
        return -1;
    }
    create_TX(str,dest);
    sendBuffer();
    wait(0.2);
    return 0;
}

/* Sets a configuration value into the module device */
int XBEE::set_cfg(char * cmd, int value)
{
    int n = strlen(cmd);
    if(n != 2) {
        return -1;
    }
    create_CMD(cmd,hex2dec(value));
    sendBuffer();
    wait(0.2);
    
    create_CMD("WR",0);
    sendBuffer();
    wait(0.2);
    
    create_CMD("AC",0);
    sendBuffer();
    wait(0.2);
    return 0;
}

/* Receives a message, writes in str */
int XBEE::recv_msg(char * buf, int tam)
{
    pkt_tx *p;
    int i;
    int ptam = 0;
    int j = 0;
    
    memset(buf,0,tam);
    
    for(i = 0; i < count_rx; i++) {
        if(buf_rx[i] == 0x7E) {
            
            p = (pkt_tx *) &buf_rx[i];
            
            if(p->frame_type == 0x90) {
                ptam = p->length - 0x0C;
                if(tam < ptam + j) {
                    return -1;
                }
                // posicao aonde comeca a msg em um pacote de Receive
                memcpy(&buf[j], ((char *)(&p->broadcast_radius)), ptam);
                j += ptam;
            }
        }
    }
    return j;
}

/* Updates the command value, call a request from device configurations */
int XBEE::read_cfg(char * cmd, int & var)
{
    int n = strlen(cmd);
    if(n != 2) {
        return -1;    
    }
    count_rx = 0;
    memset(&buf_rx,0,sizeof(buf_rx));
    
    create_CMD(cmd,0);    // Pan ID da rede
    sendBuffer();
    wait(0.5);
    recv_CMD(var);
    return 0;
}

/* Clear all the Receive buffer */
void XBEE::clear_buf(void)
{
    count_rx = 0;
    memset(buf_rx,0,sizeof(buf_rx));
}

/* Cria pacote de mensagem */
int XBEE::create_TX(char * str, int dest) 
{
    int i = 0;
    int n = strlen(str);

    pkt_tx *p = (pkt_tx *) buf_tx; // ponteiro para buffer global
    
    uint8_t count = 0;

    if(n > 92) {
        // Error: data nao pode exceder 92 bytes
        return -1;
    }

    count_tx = 0;
    memset(&buf_tx,0,sizeof(buf_tx));

    p->start_delimiter = 0x7E;
    p->length = 0x0E + n;   // pacote vazio + dados
    p->frame_type = 0x10;   // transmit request
    p->frame_id = 1;

    if(dest == XBEE_COORD) {
        p->dest_addr64[6] = 0x00;   //SL_H
        p->dest_addr64[7] = 0x00;   //SL_L
    } else if(dest == XBEE_BROAD) {
        p->dest_addr64[6] = 0xFF;   //SL_H
        p->dest_addr64[7] = 0xFF;   //SL_L
    } else {
        p->dest_addr64[0] = 0x00;
        p->dest_addr64[1] = 0x13;
        p->dest_addr64[2] = 0xA2;
        p->dest_addr64[3] = 0x00;
        
        p->dest_addr64[4] = (dest >> 24);
        p->dest_addr64[5] = (dest & 0x00FF0000) >> 16;
        p->dest_addr64[6] = (dest & 0x0000FF00) >> 8;
        p->dest_addr64[7] = (dest & 0x000000FF);
    }
    p->dest_addr16[0] = 0xFF;   //MY_H
    p->dest_addr16[1] = 0xFF;   //MY_L
    
    memcpy(&p->rf_data, str, n);

    // Calcula Checksum

    // comeca 3 pra frente, tenq passar 3 adiante no final
    // para ler o mesmo tamanho de pacote
    for(i = 3; i < p->length + 3; i++) {
        count += buf_tx[i];
        //printf("\n%d\n", count);
    }
    count = 0xFF - count;

    p->rf_data[n] = count;

    //p->length tem o tamanho soh do frame, 
    //pacote total eh o starter + length alto + length baixo + checksum
    count_tx = p->length + 4;
    return count_tx;
}

/* Cria pacote de comando */
int XBEE::create_CMD(char * cmd, int val) 
{
    pkt_cmd *p = (pkt_cmd *) buf_tx; // ponteiro para buffer global
    char str[4];    // string do val
    int size_cmd = strlen(cmd);
    //int value = dec2hex(val);
    int value = val;
    int n = 0;  // tamanho em bytes do parametro do comando
    int i;
    uint8_t count = 0;
    
    if(size_cmd != 2) {
        // Error: comando deve conter 2 chars
        return -1;
    }
    
    if(val != 0) {
        if( (value >> 24) & 0xFF ) {
            str[0] = (value >> 24) & 0xFF;
            str[1] = (value >> 16) & 0xFF;
            str[2] = (value >> 8) & 0xFF;
            str[3] = value & 0xFF;
            n = 4;
        } else if( (value >> 16) & 0xFF ) {
            str[0] = (value >> 16) & 0xFF;
            str[1] = (value >> 8) & 0xFF;
            str[2] = value & 0xFF;
            n = 3;
        } else if( (value >> 8) & 0xFF ) {
            str[0] = (value >> 8) & 0xFF;
            str[1] = value & 0xFF;
            n = 2;
        } else {
            str[0] = value & 0xFF;
            n = 1;
        }
    }

    count_tx = 0;
    memset(&buf_tx,0,sizeof(buf_tx));

    p->start_delimiter = 0x7E;
    p->length = 0x04 + n;   // pacote vazio + dados
    p->frame_type = 0x09;   // AT Command Queue
    p->frame_id = 1;
    
    p->command[0] = cmd[0];
    p->command[1] = cmd[1];
    
    if(val != 0) {
        memcpy(&p->rf_data, str, n);
    }

    // Calcula Checksum

    // comeca 3 pra frente, tenq passar 3 adiante no final
    // para ler o mesmo tamanho de pacote
    for(i = 3; i < p->length + 3; i++) {
        count += buf_tx[i];
        //printf("\n%d\n", count);
    }
    count = 0xFF - count;

    p->rf_data[n] = count;

    //p->length tem o tamanho soh do frame, 
    //pacote total eh o starter + length alto + length baixo + checksum
    count_tx = p->length + 4;
    return count_tx;
}

/* Envia pacote do buffer_tx */
void XBEE::sendBuffer(void) 
{
    if(xbee->writeable()) {
        for(int i = 0; i < count_tx; i++) {
            xbee->putc(buf_tx[i]);
        }
        //pode zerar pacote aqui
    }
}

/* Printa todo o buffer de Receive, e limpa */
/*
void XBEE::printBuffer(void) 
{
    char flag_msg = 0;
    int size = sizeof(buf_rx);
    if(count_rx < size) {
        size = count_rx;
    }
    for(int i = 0; i < size; i++) {
        printf("%c", buf_rx[i]);
        flag_msg++;
    }
    if (flag_msg) {
        printf("\n");
    }
    
    //Limpa buffer
    count_rx = 0;
    memset(&buf_rx,0,sizeof(buf_rx));
} 
*/

/* Receive and update NI variable */
void XBEE::recv_NI(void)
{
    pkt_cmd *p;
    int i;
    for(i = 0; i < count_rx; i++) {
        if(buf_rx[i] == 0x7E) {
            p = (pkt_cmd *) &buf_rx[i];
        }
    }
    if(p->frame_type == 0x88) {
        memcpy(NI, ((char *)(&p->rf_data))+2, 16);
        // remove o checksum do nome
        for(i = 15; i >= 0; i--) {
            if(NI[i] != 0) {
                NI[i] = '\0';
                break;
            }
        }
    }
}

/* Receive and update CMD variable */
void XBEE::recv_CMD(int &cmd)
{
    char data[16];
    pkt_cmd *p;
    int i;
    int j = -1;
    
    for(i = 0; i < count_rx; i++) {
        if(buf_rx[i] == 0x7E) {
            p = (pkt_cmd *) &buf_rx[i];
        }
    }
    if(p->frame_type == 0x88) {
        memcpy(data, &p->rf_data, 16);
        for(i = 15; i > -1; i--) {
            if(data[i] != 0 || j != -1) {
                // pular o checksum
                if(j==-1) {
                    j++;
                } else {
                    //ID = (int)(dec2hex((data[i] << 8)) + dec2hex(data[i+1]));
                    cmd += data[i] << 8*j;
                    j++;
                }
            }
        }
    }
}

/* Verify Packet Checksum return 0 if msg OK, just work with Transmit Package*/
/*
char XBEE::validPackage(uint8_t * buf, int tam) 
{
    int i = 0;
    uint8_t count = 0;
    
    if(buf[0] != 0x7E) return 1;
    if(buf[1] != 0) return 2;
    if(buf[2] != tam-4) return 3;
    
    for(i = 3; i < tam; i++) {
        count += buf[i];
    }
    if(count != 0xFF) return 4;
    
    return 0; // OK
}
*/

/* Convert Dec to Hex, OBS: just for Hex number without Letter */
int XBEE::dec2hex(int nbr)
{
    char hexa[8];
    int temp;
    int result = 0;
    int i = 0;
    char hasLetter = 0;
    
    while(nbr != 0)
    {
        temp = nbr % 16;
        hexa[i] = temp;
        nbr = nbr / 16;
        i++;
        if(temp > 9) {
            hasLetter++;
        }
    }
    // concat number
    for(i=i-1; i > -1; i--) {
        result += hexa[i] * pow(10.0,(double)i);
    }
    
    return result;
}

/* Convert Hex to Dec */
int XBEE::hex2dec(int nbr)
{
    char deci[8];
    int result = 0;
    int i = 0;
    int temp;
    char hasLetter = 0;
    
    while(nbr != 0) {
        temp = nbr % 10;
        deci[i] = temp;
        nbr = nbr / 10;
        i++;
        if(temp > 9) {
            hasLetter++;
        }
    }
    // concat number
    for(i=i-1; i > -1; i--) {
        result += (deci[i] * pow(16.0,(double)i) );
    }
    return result;
}
void XBEE::int_mng(int value){
    int_ctrl = value;
}