RadioLibSmol/src/modules/XBee.cpp
2018-06-29 11:05:53 +02:00

269 lines
6.5 KiB
C++

#include "XBee.h"
XBeeApiFrame::XBeeApiFrame(uint8_t apiId, uint8_t frameId) {
_apiId = apiId;
_frameId = frameId;
}
XBee::XBee(Module* module) {
_mod = module;
}
uint8_t XBee::begin(long speed) {
// set Arduino pins
pinMode(A4, OUTPUT);
pinMode(A5, OUTPUT);
pinMode(3, OUTPUT);
digitalWrite(A4, LOW);
digitalWrite(A5, LOW);
digitalWrite(3, HIGH);
// set module properties
_mod->AtLineFeed = "\r";
_mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE);
// empty UART buffer (garbage data)
_mod->ATemptyBuffer();
// enter command mode
DEBUG_PRINTLN_STR("Entering command mode ...");
if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED);
}
// test AT setup
DEBUG_PRINTLN_STR("Sending test command ...");
if(!_mod->ATsendCommand("AT")) {
return(ERR_AT_FAILED);
}
// exit command mode
DEBUG_PRINTLN_STR("Exiting command mode ...");
if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED);
}
delay(1000);
return(ERR_NONE);
}
uint8_t XBee::setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow) {
// enter command mode
DEBUG_PRINTLN_STR("Entering command mode ...");
if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED);
}
// set higher address bytes
DEBUG_PRINTLN_STR("Setting address (high) ...");
char* addressHigh = new char[strlen(destinationAddressHigh) + 4];
strcpy(addressHigh, "ATDH");
strcat(addressHigh, destinationAddressHigh);
bool res = _mod->ATsendCommand(addressHigh);
delete[] addressHigh;
if(!res) {
return(ERR_AT_FAILED);
}
// set lower address bytes
DEBUG_PRINTLN_STR("Setting address (low) ...");
char* addressLow = new char[strlen(destinationAddressLow) + 4];
strcpy(addressLow, "ATDL");
strcat(addressLow, destinationAddressLow);
res = _mod->ATsendCommand(addressLow);
delete[] addressLow;
if(!res) {
return(ERR_AT_FAILED);
}
// exit command mode
DEBUG_PRINTLN_STR("Exiting command mode ...");
if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED);
}
return(ERR_NONE);
}
uint8_t XBee::setPanId(const char* panId) {
// enter command mode
DEBUG_PRINTLN_STR("Entering command mode ...");
if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED);
}
// set PAN ID
DEBUG_PRINTLN_STR("Setting PAN ID ...");
char* cmd = new char[strlen(panId) + 4];
strcpy(cmd, "ATID");
strcat(cmd, panId);
bool res = _mod->ATsendCommand(cmd);
delete[] cmd;
if(!res) {
return(ERR_AT_FAILED);
}
// exit command mode
DEBUG_PRINTLN_STR("Exiting command mode ...");
if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED);
}
return(ERR_NONE);
}
bool XBee::enterCmdMode() {
for(uint8_t i = 0; i < 10; i++) {
delay(1000);
_mod->ModuleSerial->write('+');
_mod->ModuleSerial->write('+');
_mod->ModuleSerial->write('+');
delay(1000);
if(_mod->ATgetResponse()) {
return(true);
} else {
DEBUG_PRINT_STR("Unable to enter command mode! (");
DEBUG_PRINT(i + 1);
DEBUG_PRINTLN_STR(" of 10 tries)");
pinMode(3, OUTPUT);
delay(10);
digitalWrite(3, HIGH);
delay(500);
digitalWrite(3, LOW);
delay(500);
pinMode(3, INPUT);
delay(500);
_mod->ATsendCommand("ATCN");
if(i == 9) {
DEBUG_PRINTLN_STR("Terminated, check your wiring. Is AT FW uploaded?");
return(false);
}
}
}
}
/*uint8_t XBee::transmit(uint32_t destinationAddressHigh, uint32_t destinationAddressLow, const char* data, uint8_t length) {
//build the API frame
uint8_t frameLength = length + 12;
uint8_t * frameData = new uint8_t[frameLength];
//set the destination address
frameData[0] = (destinationAddressHigh >> 24) & 0xFF;
frameData[1] = (destinationAddressHigh >> 16) & 0xFF;
frameData[2] = (destinationAddressHigh >> 8) & 0xFF;
frameData[3] = destinationAddressHigh & 0xFF;
frameData[4] = (destinationAddressLow >> 24) & 0xFF;
frameData[5] = (destinationAddressLow >> 16) & 0xFF;
frameData[6] = (destinationAddressLow >> 8) & 0xFF;
frameData[7] = destinationAddressLow & 0xFF;
//set the destination network address
frameData[8] = 0xFF;
frameData[9] = 0xFE;
//set broadcast radius (number of allowed hops, 0 - maximum)
frameData[10] = 0x00;
//set the options
frameData[11] = 0x00;
//copy payload data
for(uint8_t i = 0; i < length; i++) {
frameData[12 + i] = (uint8_t)data[i];
}
//send the frame to XBee
sendApiFrame(XBEE_API_FRAME_ZIGBEE_TRANSMIT_REQUEST, frameData, frameLength);
//deallocate memory
delete frameData;
//wait for status frame
readApiFrame(1000);
}*/
/*void XBee::sendApiFrame(uint8_t apiId, uint8_t* data, uint16_t length) {
//send frame start delimiter
_mod->ModuleSerial->write(XBEE_API_START);
//send frame length (API ID, frame ID and data length)
write(((length + 2) >> 8) & 0xFF);
write((length + 2) & 0xFF);
//send API ID
write(apiId);
//send default frame ID (value 0x00 would disable some feedback)
write(XBEE_API_DEFAULT_FRAME_ID);
//checksum is calculated from API ID, frame ID and data
uint8_t checksum = apiId;
checksum += XBEE_API_DEFAULT_FRAME_ID;
//send the data and calculate checksum
for(uint16_t i = 0; i < length; i++) {
write(data[i]);
checksum += data[i];
}
//send the checksum
checksum = 0xFF - checksum;
write(checksum);
}*/
/*uint8_t XBee::readApiFrame(uint16_t timeout) {
//start the timer
unsigned long start = millis();
Serial.println("reading");
//array to store frame length, type and ID
uint8_t header[4];
while(millis() - start < timeout) {
Serial.println(_mod->ModuleSerial->available());
//check buffer for new data
while(_mod->ModuleSerial->available()) {
uint8_t b = _mod->ModuleSerial->read();
Serial.write(b);
Serial.print('\t');
Serial.println(b, HEX);
if(b == XBEE_API_START) {
//received the start character
n = 0;
} else {
n++;
}
//check escaped characters
if(b == XBEE_API_ESCAPE) {
//wait for the next byte
while(!_mod->ModuleSerial->available());
//resolve the escaped character
b =_mod->ModuleSerial->read();
b = 0x20 ^ b;
}
}
}
}*/
/*void XBee::write(uint8_t b) {
if((b == XBEE_API_START) || (b == XBEE_API_ESCAPE) || (b == XBEE_API_XON) || (b == XBEE_API_XOFF)) {
_mod->ModuleSerial->write(XBEE_API_ESCAPE);
_mod->ModuleSerial->write(b ^ 0x20);
} else {
_mod->ModuleSerial->write(b);
}
}*/