Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Coordinator_node Router_node
xbee.cpp
- Committer:
- EmileArseneault
- Date:
- 2017-02-14
- Revision:
- 12:e62381cdc9de
- Parent:
- 11:7b5b9c1ab757
- Child:
- 13:e0c47bcc92e7
File content as of revision 12:e62381cdc9de:
#include "xbee.h"
XBee::XBee(PinName reset, PinName transfer, PinName receive, Mail<char, 250>* m) :
rst(reset), comm(transfer, receive)
{
// Constructor
mail = m;
rst = 0;
wait(0.4);
rst = 1;
wait(3); // waiting for initiation
}
char XBee::getChar()
{
while (!comm.readable())
{
wait(0.02);
}
return comm.getc();
}
void XBee::pcPrint(char* c)
{
int i = 0;
while( (c)[i] != '\0')
{
mail->put(&(c[i]));
i++;
}
}
void XBee::printInt(int i)
{
bool signe = i > 0;
char *c = mail->alloc();
if (signe)
{
*c = '-';
mail->put(c);
i *= -1;
}
int diviseur = 1;
int modulo = 10;
int j = 9;
char chiffre[10];
while (i / diviseur > 0 && j >= 0)
{
chiffre[j] = (char) (i % modulo)/diviseur;
modulo *= 10;
diviseur *= 10;
j--;
}
j = 0;
bool numberHasStarted = false;
while (j < 10)
{
if (chiffre[j] != 0 || numberHasStarted || j == 9)
{
numberHasStarted = true;
c = mail->alloc();
*c = chiffre[j] + 0x30;
mail->put(c);
}
j++;
}
}
void XBee::printHexa(char c)
{
char *msb = mail->alloc();
*msb = c >> 4;
char *lsb = mail->alloc();
*lsb = c & 0xF;
if (*msb < 10)
*msb += 0x30;
else
*msb += 0x37;
if (*lsb < 10)
*lsb += 0x30;
else
*lsb += 0x37;
char * str = "0x";
pcPrint(str);
mail->put(msb);
mail->put(lsb);
str = " ";
pcPrint(str);
}
void XBee::SendATCommand(char firstChar, char secondChar, char *optionalParam, int paramLen)
{
// Frame Type 0x08
// Two char as parameters
char cmdtosend[10];
char sum = 0;
int cmdlength = 8;
int i = 0;
cmdtosend[0] = FRAMEDELIMITER;
cmdtosend[1] = 0x00;
cmdtosend[2] = 0x04 + paramLen;
cmdtosend[3] = 0x08;
cmdtosend[4] = 0x52;
cmdtosend[5] = firstChar;
cmdtosend[6] = secondChar;
// Ajouter les parametres au message
if(optionalParam != NULL)
{
i = 0;
cmdlength += paramLen;
while (i < paramLen)
{
cmdtosend[7 + i] = (optionalParam)[i];
i++;
}
pcPrint("\r\n\0");
}
// Calculate checksum
i = 3;
while (i < (cmdlength - 1))
{
sum += cmdtosend[i];
i++;
}
cmdtosend[cmdlength - 1] = 0xFF - sum;
// Envoyer la commande sur UART
i = 0;
while (i < cmdlength)
{
comm.putc(cmdtosend[i]);
i++;
}
wait(0.2);
}
char* XBee::InterpretMessage()
{
char *response = "\0";
if (comm.readable())
{
char start = getChar(); // = FRAMEDELIMITER
//assert
if (start == FRAMEDELIMITER)
{
char len_msb = getChar();
char len_lsb = getChar();
int len = ((int) len_msb << 4) + (int) len_lsb;
char frame_data[len];
// Resolving frame type
char type = getChar();
len--;
switch (type){
case 0x88: ATCommandResponse(len);
break;
case 0x8A: ModemStatus(len);
break;
case 0x8B: ZigBeeTransmitStatus(len);
break;
case 0x90: ZigBeeReceivePacket(len);
break;
default: pcPrint("Please implement response of type ");
printHexa(type);
pcPrint("\r\n\0");
for (int i = 0; i <len; i++)
{
getChar();
}
}
}
}
return response;
}
void XBee::ATCommandResponse(int len)
{
char total = 0x88;
char id = getChar();
total += id;
char* command0 = mail->alloc();
char* command1 = mail->alloc();
*command0 = getChar();
total += *command0;
*command1 = getChar();
total += *command1;
char status = getChar();
total += status;
int i = 0;
len-= 4;
char data[len];
pcPrint("response to command \0");
mail->put(command0);
mail->put(command1);
pcPrint(" is \0");
if (len == 0)
{
switch (status)
{
case 0 : pcPrint("OK"); break;
case 1 : pcPrint("ERROR"); break;
case 2 : pcPrint("Invalid Command"); break;
case 3 : pcPrint("Invalid Parameter"); break;
case 4 : pcPrint("Tx Failure"); break;
default : pcPrint("Unknow error ..."); break;
}
}
while (i < len)
{
if (comm.readable())
{
data[i] = getChar();
total += data[i];
printHexa(data[i]);
i++;
}
}
char checksum = getChar();
total += checksum;
// Verify checksum
if (total != 0xFF)
{
pcPrint("Checksum is wrong\0");
}
pcPrint("\r\n\0");
}
void XBee::ModemStatus(int len)
{
char status = getChar();
switch (status){
case 0 : pcPrint("Hardware reset\r\n\0"); break;
case 1 : pcPrint("Watchdog timer reset\r\n\0"); break;
case 2 : pcPrint("Joined network (routers and end devices)\r\n\0"); break;
case 3 : pcPrint("Disassociated\r\n\0"); break;
case 6 : pcPrint("Coordinator started\r\n\0"); break;
case 7 : pcPrint("Network security key was updated\r\n\0"); break;
case 0x0D : pcPrint("Voltage supply limit exceeded\r\n\0"); break;
case 0x11 : pcPrint("Modem configuration changed while join in progress\r\n\0"); break;
default : pcPrint("stack error\r\n\0"); break;
}
char checksum = getChar();
checksum += 0x8A + status;
if (checksum != 0xFF)
{
pcPrint("Checksum is wrong\r\n\0");
}
}
void XBee::ZigBeeTransmitStatus(int len)
{
char id = getChar();
char msb = getChar();
char lsb = getChar();
char retry = getChar();
char status = getChar();
char discovery = getChar();
char checksum;
pcPrint("Response to transmit #");
printHexa(id);
pcPrint(" is : ");
if (status == 0)
{
pcPrint("Success\r\n");
}
else
{
switch (status){
case 0x01 : pcPrint("MAC ACK Failure\r\n"); break;
case 0x02 : pcPrint("CCA Failure\r\n"); break;
case 0x15 : pcPrint("Invalid destination endpoint\r\n"); break;
case 0x21 : pcPrint("Network ACK Failure\r\n"); break;
case 0x22 : pcPrint("Not Joined to Network\r\n"); break;
case 0x23 : pcPrint("Self-addressed\r\n"); break;
case 0x24 : pcPrint("Address Not Found\r\n"); break;
case 0x25 : pcPrint("Route Not Found\r\n"); break;
case 0x26 : pcPrint("Broadcast source failed to hear a neighbor relay the message\r\n"); break;
case 0x2B : pcPrint("Invalid binding table index\r\n"); break;
case 0x2C : pcPrint("Resource error lack of free buffers, timers, etc.\r\n"); break;
case 0x2D : pcPrint("Attempted broadcast with APS transmission\r\n"); break;
case 0x2E : pcPrint("Attempted unicast with APS transmission, but EE=0\r\n"); break;
case 0x32 : pcPrint("Resource error lack of free buffers, timers, etc.\r\n"); break;
case 0x74 : pcPrint("Data payload too large\r\n"); break;
default : pcPrint("Unknow error ...\r\n"); break;
}
}
checksum = getChar();
// Validate checksum TODO
}
void XBee::ZigBeeReceivePacket(int len)
{
int i = 0;
char adresse64bit[8];
char adresse16bit[2];
char receiveOptions;
char checksum;
char data = 0;
char total = 0x90;
printHexa(len+1); // DEBUG PRINT
pcPrint(" On recoit :"); // DEBUG PRINT
while(i < 8)
{
adresse64bit[i] = getChar();
pcPrint(" "); // DEBUG PRINT
printHexa(adresse64bit[i]); // DEBUG PRINT
total += adresse64bit[i];
i++;
}
adresse16bit[0] = getChar();
adresse16bit[1] = getChar();
total += adresse16bit[0];
total += adresse16bit[1];
pcPrint(" "); // DEBUG PRINT
printHexa(adresse16bit[0]); // DEBUG PRINT
pcPrint(" "); // DEBUG PRINT
printHexa(adresse16bit[1]); // DEBUG PRINT
receiveOptions = getChar();
pcPrint(" "); // DEBUG PRINT
printHexa(receiveOptions); // DEBUG PRINT
total += receiveOptions;
//printHexa(len - 11);
//pcPrint(" Data received : ");
i = 11;
while (i < len)
{
data = getChar();
total += data;
pcPrint(" "); // DEBUG PRINT
printHexa(data); // DEBUG PRINT
i++;
}
checksum = getChar();
total += checksum;
pcPrint(" "); // DEBUG PRINT
printHexa(checksum); // DEBUG PRINT
pcPrint("\r\n");
if (total != 0xFF)
{
pcPrint("Checksum is wrong\0");
}
pcPrint("\r\n\0");
// Validate checksum TODO
}
void XBee::ZigBeeTransmit(int adresse16, int adresse64msb, int adresse64lsb, char *data, int dataLength)
{
// Frame Type 0x10
// 0x0000000000000000 - Reserved 64-bit address for the coordinator
// 0x000000000000FFFF - Broadcast address
// The Transmit Status frame (0x8B) est la reponse
char cmdtosend[25];
char checksum = 0x00;
int cmdlength = 18;
int i = 3;
//ID command to set/read operating 64 bit PAN ID
//WR command to set operating 64 bit PAN ID across reboot
//OI command to read operating 16 bit PAN ID
//II command to set operating 16 bit PAN ID
cmdtosend[0] = FRAMEDELIMITER;
cmdtosend[1] = 0x00;
cmdtosend[2] = 0x0E + dataLength;
cmdtosend[3] = 0x10; // Frame type
cmdtosend[4] = 0x01; // Frame number
cmdtosend[5] = (adresse64msb & 0xFF000000) >> 24; // MSB adresse 64-bit
cmdtosend[6] = (adresse64msb & 0x00FF0000) >> 16;
cmdtosend[7] = (adresse64msb & 0x0000FF00) >> 8;
cmdtosend[8] = adresse64msb & 0x000000FF;
cmdtosend[9] = (adresse64lsb & 0xFF000000) >> 24;
cmdtosend[10] = (adresse64lsb & 0x00FF0000) >> 16;
cmdtosend[11] = (adresse64lsb & 0x0000FF00) >> 8;
cmdtosend[12] = adresse64lsb & 0x000000FF; // LSB adresse 64-bit
cmdtosend[13] = adresse16 >> 8; // MSB adresse 16-bit
cmdtosend[14] = adresse16 & 0x00FF; // LSB adresse 16-bit
cmdtosend[15] = 0x00; // Broadcast Radius
cmdtosend[16] = 0x00; // Options
pcPrint("lsb : ");
printHexa(adresse64lsb);
pcPrint("\r\n");
// Set RF DATA
if(data != NULL)
{
i = 0;
cmdlength += dataLength;
while (i < dataLength)
{
cmdtosend[17 + i] = (data)[i];
i++;
}
}
// Calculate checksum
i = 3;
while (i < (cmdlength - 1))
{
checksum += cmdtosend[i];
i++;
}
cmdtosend[cmdlength - 1] = 0xFF - checksum;
// Envoyer la commande sur UART
i = 0;
pcPrint("On envoie :"); // DEBUG PRINT
while (i < cmdlength)
{
comm.putc(cmdtosend[i]); // DEBUG PRINT
pcPrint(" ");
printHexa(cmdtosend[i]); // DEBUG PRINT
i++;
}
pcPrint("\r\n"); // DEBUG PRINT
wait(0.1);
}
void XBee::BroadcastHelloWorld()
{
char hello[5] = {'H', 'e', 'l', 'l', 'o'};
char world[5] = {'w', 'o', 'r', 'l', 'd'};
while (1)
{
ZigBeeTransmit(0x0000, 0x00000000, 0x00000000, &hello[0], 5);
ZigBeeTransmit(0x0000, 0x00000000, 0x00000000, &world[0], 5);
wait(2);
}
}