Class containing functions usefull to communication between PC and Xbee device
Dependents: Coordinator_node Router_node
xbee.cpp
- Committer:
- EmileArseneault
- Date:
- 2017-02-15
- Revision:
- 20:e119856dbc5e
- Parent:
- 19:8da8068315da
File content as of revision 20:e119856dbc5e:
#include "xbee.h" char TransmissionNumber = 2; Mutex mTransmissionNumber; char GetTransmissionNumber() { char nextnumber = 0; mTransmissionNumber.lock(); nextnumber = TransmissionNumber; if(nextnumber == 255) { TransmissionNumber = 2; } else { TransmissionNumber++; } mTransmissionNumber.unlock(); return nextnumber; } XBee::XBee(PinName reset, PinName transfer, PinName receive, Mail<char, 250>* m, Mail<char[256], 16>* w, Mail<char[254], 25>* r) : rst(reset), comm(transfer, receive) { // Constructor mail = m; webmail = w; frameresponsemail = r; rst = 0; wait(0.4); rst = 1; wait(3); // waiting for initiation buffer[0] = '\0'; } void XBee::appendBuffer(char* c) { int i = 0; int j = 0; while (buffer[i] != '\0') i++; while (c[j]!= '\0' || i < 255) { buffer[i] = c[j]; i++;j++; } buffer[i] = '\0'; } void XBee::sendBuffer() { char* s = (char *) webmail->alloc(); int i = 0; while (buffer[i]!= '\0' || i < 255) { s[i] = buffer[i]; i++; } s[i] = '\0'; webmail->put((char(*)[256]) s); buffer[0] = '\0'; } 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); } char 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] = GetTransmissionNumber(); 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); return cmdtosend[4]; } void XBee::InterpretMessage() { 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; // 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(); } } } else { pcPrint("Not valid Frame\r\n"); } } } void XBee::ATCommandResponse(int len) { //char *receivedResponse = (char *)frameresponsemail->alloc(); //receivedResponse[0] = FRAMEDELIMITER; //receivedResponse[1] = len >> 4; //receivedResponse[2] = len; //receivedResponse[3] = 0x88; char total = 0x88; char id; char command[2]; char status; int i = 0; char data[255]; char checksum = 0; id = getChar(); command[0] = getChar(); command[1] = getChar(); total += command[0]; total += command[1]; status = getChar(); len -= 4; pcPrint("ID:"); printHexa(id); pcPrint(" response to command \0"); printHexa(command[0]); printHexa(command[1]); 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; } } //receivedResponse[4] = id; //receivedResponse[5] = command[0]; //receivedResponse[6] = command[1]; //receivedResponse[7] = status; while (i < len) { if (comm.readable()) { data[i] = getChar(); //receivedResponse[8 + i] = data[i]; total += data[i]; printHexa(data[i]); i++; } } checksum = getChar(); //receivedResponse[8 + i] = checksum; //frameresponsemail->put((char(*)[254])&receivedResponse[0]); // Verify checksum total += id; total += status; total += 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 // 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); } }