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.
Revision 0:12a6db2d1600, committed 2010-11-22
- Comitter:
- okini3939
- Date:
- Mon Nov 22 10:38:08 2010 +0000
- Child:
- 1:f9ececd7aa01
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee/XBee.cpp Mon Nov 22 10:38:08 2010 +0000
@@ -0,0 +1,1362 @@
+/**
+ * XBee-mbed library
+ * Modified for mbed, 2010 Suga.
+ *
+ *
+ * Copyright (c) 2009 Andrew Rapp. All rights reserved.
+ *
+ * This file is part of XBee-Arduino.
+ *
+ * XBee-Arduino is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * XBee-Arduino is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBee-Arduino. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mbed.h"
+#include "XBee.h"
+
+XBeeResponse::XBeeResponse() {
+
+}
+
+uint8_t XBeeResponse::getApiId() {
+ return _apiId;
+}
+
+void XBeeResponse::setApiId(uint8_t apiId) {
+ _apiId = apiId;
+}
+
+uint8_t XBeeResponse::getMsbLength() {
+ return _msbLength;
+}
+
+void XBeeResponse::setMsbLength(uint8_t msbLength) {
+ _msbLength = msbLength;
+}
+
+uint8_t XBeeResponse::getLsbLength() {
+ return _lsbLength;
+}
+
+void XBeeResponse::setLsbLength(uint8_t lsbLength) {
+ _lsbLength = lsbLength;
+}
+
+uint8_t XBeeResponse::getChecksum() {
+ return _checksum;
+}
+
+void XBeeResponse::setChecksum(uint8_t checksum) {
+ _checksum = checksum;
+}
+
+uint8_t XBeeResponse::getFrameDataLength() {
+ return _frameLength;
+}
+
+void XBeeResponse::setFrameLength(uint8_t frameLength) {
+ _frameLength = frameLength;
+}
+
+bool XBeeResponse::isAvailable() {
+ return _complete;
+}
+
+void XBeeResponse::setAvailable(bool complete) {
+ _complete = complete;
+}
+
+bool XBeeResponse::isError() {
+ return _errorCode > 0;
+}
+
+uint8_t XBeeResponse::getErrorCode() {
+ return _errorCode;
+}
+
+void XBeeResponse::setErrorCode(uint8_t errorCode) {
+ _errorCode = errorCode;
+}
+
+// copy common fields from xbee response to target response
+void XBeeResponse::setCommon(XBeeResponse &target) {
+ target.setApiId(getApiId());
+ target.setAvailable(isAvailable());
+ target.setChecksum(getChecksum());
+ target.setErrorCode(getErrorCode());
+ target.setFrameLength(getFrameDataLength());
+ target.setMsbLength(getMsbLength());
+ target.setLsbLength(getLsbLength());
+}
+
+#ifdef SERIES_2
+
+ZBTxStatusResponse::ZBTxStatusResponse() : FrameIdResponse() {
+
+}
+
+uint16_t ZBTxStatusResponse::getRemoteAddress() {
+ return (getFrameData()[1] << 8) + getFrameData()[2];
+}
+
+uint8_t ZBTxStatusResponse::getTxRetryCount() {
+ return getFrameData()[3];
+}
+
+uint8_t ZBTxStatusResponse::getDeliveryStatus() {
+ return getFrameData()[4];
+}
+
+uint8_t ZBTxStatusResponse::getDiscoveryStatus() {
+ return getFrameData()[5];
+}
+
+bool ZBTxStatusResponse::isSuccess() {
+ return getDeliveryStatus() == SUCCESS;
+}
+
+void XBeeResponse::getZBTxStatusResponse(XBeeResponse &zbXBeeResponse) {
+
+ // way off?
+ ZBTxStatusResponse* zb = static_cast<ZBTxStatusResponse*>(&zbXBeeResponse);
+ // pass pointer array to subclass
+ zb->setFrameData(getFrameData());
+ setCommon(zbXBeeResponse);
+}
+
+ZBRxResponse::ZBRxResponse(): RxDataResponse() {
+ _remoteAddress64 = XBeeAddress64();
+}
+
+uint16_t ZBRxResponse::getRemoteAddress16() {
+ return (getFrameData()[8] << 8) + getFrameData()[9];
+}
+
+uint8_t ZBRxResponse::getOption() {
+ return getFrameData()[10];
+}
+
+// markers to read data from packet array. this is the index, so the 12th item in the array
+uint8_t ZBRxResponse::getDataOffset() {
+ return 11;
+}
+
+uint8_t ZBRxResponse::getDataLength() {
+ return getPacketLength() - getDataOffset() - 1;
+}
+
+XBeeAddress64& ZBRxResponse::getRemoteAddress64() {
+ return _remoteAddress64;
+}
+
+void XBeeResponse::getZBRxResponse(XBeeResponse &rxResponse) {
+
+ ZBRxResponse* zb = static_cast<ZBRxResponse*>(&rxResponse);
+
+ //TODO verify response api id matches this api for this response
+
+ // pass pointer array to subclass
+ zb->setFrameData(getFrameData());
+ setCommon(rxResponse);
+
+ zb->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
+ zb->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + (getFrameData()[7]));
+}
+
+
+ZBRxIoSampleResponse::ZBRxIoSampleResponse() : ZBRxResponse() {
+
+}
+
+// 64 + 16 addresses, sample size, option = 12 (index 11), so this starts at 12
+uint8_t ZBRxIoSampleResponse::getDigitalMaskMsb() {
+ return getFrameData()[12] & 0x1c;
+}
+
+uint8_t ZBRxIoSampleResponse::getDigitalMaskLsb() {
+ return getFrameData()[13];
+}
+
+uint8_t ZBRxIoSampleResponse::getAnalogMask() {
+ return getFrameData()[14] & 0x8f;
+}
+
+bool ZBRxIoSampleResponse::containsAnalog() {
+ return getAnalogMask() > 0;
+}
+
+bool ZBRxIoSampleResponse::containsDigital() {
+ return getDigitalMaskMsb() > 0 || getDigitalMaskLsb() > 0;
+}
+
+bool ZBRxIoSampleResponse::isAnalogEnabled(uint8_t pin) {
+ return ((getAnalogMask() >> pin) & 1) == 1;
+}
+
+bool ZBRxIoSampleResponse::isDigitalEnabled(uint8_t pin) {
+ if (pin <= 7) {
+ // added extra parens to calm avr compiler
+ return ((getDigitalMaskLsb() >> pin) & 1) == 1;
+ } else {
+ return ((getDigitalMaskMsb() >> (pin - 8)) & 1) == 1;
+ }
+}
+
+uint16_t ZBRxIoSampleResponse::getAnalog(uint8_t pin) {
+ // analog starts 13 bytes after sample size, if no dio enabled
+ uint8_t start = 15;
+
+ if (containsDigital()) {
+ // make room for digital i/o
+ start+=2;
+ }
+
+// std::cout << "spacing is " << static_cast<unsigned int>(spacing) << std::endl;
+
+ // start depends on how many pins before this pin are enabled
+ for (int i = 0; i < pin; i++) {
+ if (isAnalogEnabled(pin)) {
+ start+=2;
+ }
+ }
+
+// std::cout << "start for analog pin ["<< static_cast<unsigned int>(pin) << "]/sample " << static_cast<unsigned int>(sample) << " is " << static_cast<unsigned int>(start) << std::endl;
+
+// std::cout << "returning index " << static_cast<unsigned int>(getSampleOffset() + start) << " and index " << static_cast<unsigned int>(getSampleOffset() + start + 1) << ", val is " << static_cast<unsigned int>(getFrameData()[getSampleOffset() + start] << 8) << " and " << + static_cast<unsigned int>(getFrameData()[getSampleOffset() + start + 1]) << std::endl;
+
+ return (uint16_t)((getFrameData()[start] << 8) + getFrameData()[start + 1]);
+}
+
+bool ZBRxIoSampleResponse::isDigitalOn(uint8_t pin) {
+ if (pin <= 7) {
+ // D0-7
+ // DIO LSB is index 5
+ return ((getFrameData()[16] >> pin) & 1) == 1;
+ } else {
+ // D10-12
+ // DIO MSB is index 4
+ return ((getFrameData()[15] >> (pin - 8)) & 1) == 1;
+ }
+}
+
+void XBeeResponse::getZBRxIoSampleResponse(XBeeResponse &response) {
+ ZBRxIoSampleResponse* zb = static_cast<ZBRxIoSampleResponse*>(&response);
+
+
+ // pass pointer array to subclass
+ zb->setFrameData(getFrameData());
+ setCommon(response);
+
+ zb->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
+ zb->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + (getFrameData()[7]));
+}
+
+#endif
+
+#ifdef SERIES_1
+
+RxResponse::RxResponse() : RxDataResponse() {
+
+}
+
+uint16_t Rx16Response::getRemoteAddress16() {
+ return (getFrameData()[0] << 8) + getFrameData()[1];
+}
+
+XBeeAddress64& Rx64Response::getRemoteAddress64() {
+ return _remoteAddress;
+}
+
+Rx64Response::Rx64Response() : RxResponse() {
+ _remoteAddress = XBeeAddress64();
+}
+
+Rx16Response::Rx16Response() : RxResponse() {
+
+}
+
+RxIoSampleBaseResponse::RxIoSampleBaseResponse() : RxResponse() {
+
+}
+
+uint8_t RxIoSampleBaseResponse::getSampleOffset() {
+ // sample starts 2 bytes after rssi
+ return getRssiOffset() + 2;
+}
+
+
+uint8_t RxIoSampleBaseResponse::getSampleSize() {
+ return getFrameData()[getSampleOffset()];
+}
+
+bool RxIoSampleBaseResponse::containsAnalog() {
+ return (getFrameData()[getSampleOffset() + 1] & 0x7e) > 0;
+}
+
+bool RxIoSampleBaseResponse::containsDigital() {
+ return (getFrameData()[getSampleOffset() + 1] & 0x1) > 0 || getFrameData()[getSampleOffset() + 2] > 0;
+}
+
+//uint16_t RxIoSampleBaseResponse::getAnalog0(uint8_t sample) {
+// return getAnalog(0, sample);
+//}
+
+bool RxIoSampleBaseResponse::isAnalogEnabled(uint8_t pin) {
+ return (((getFrameData()[getSampleOffset() + 1] >> (pin + 1)) & 1) == 1);
+}
+
+bool RxIoSampleBaseResponse::isDigitalEnabled(uint8_t pin) {
+ if (pin < 8) {
+ return ((getFrameData()[getSampleOffset() + 4] >> pin) & 1) == 1;
+ } else {
+ return (getFrameData()[getSampleOffset() + 3] & 1) == 1;
+ }
+}
+
+uint16_t RxIoSampleBaseResponse::getAnalog(uint8_t pin, uint8_t sample) {
+
+ // analog starts 3 bytes after sample size, if no dio enabled
+ uint8_t start = 3;
+
+ if (containsDigital()) {
+ // make room for digital i/o sample (2 bytes per sample)
+ start+=2*(sample + 1);
+ }
+
+ uint8_t spacing = 0;
+
+ // spacing between samples depends on how many are enabled. add one for each analog that's enabled
+ for (int i = 0; i <= 5; i++) {
+ if (isAnalogEnabled(i)) {
+ // each analog is two bytes
+ spacing+=2;
+ }
+ }
+
+// std::cout << "spacing is " << static_cast<unsigned int>(spacing) << std::endl;
+
+ // start depends on how many pins before this pin are enabled
+ for (int i = 0; i < pin; i++) {
+ if (isAnalogEnabled(pin)) {
+ start+=2;
+ }
+ }
+
+ start+= sample * spacing;
+
+// std::cout << "start for analog pin ["<< static_cast<unsigned int>(pin) << "]/sample " << static_cast<unsigned int>(sample) << " is " << static_cast<unsigned int>(start) << std::endl;
+
+// std::cout << "returning index " << static_cast<unsigned int>(getSampleOffset() + start) << " and index " << static_cast<unsigned int>(getSampleOffset() + start + 1) << ", val is " << static_cast<unsigned int>(getFrameData()[getSampleOffset() + start] << 8) << " and " << + static_cast<unsigned int>(getFrameData()[getSampleOffset() + start + 1]) << std::endl;
+
+ return (uint16_t)((getFrameData()[getSampleOffset() + start] << 8) + getFrameData()[getSampleOffset() + start + 1]);
+}
+
+bool RxIoSampleBaseResponse::isDigitalOn(uint8_t pin, uint8_t sample) {
+ if (pin < 8) {
+ return ((getFrameData()[getSampleOffset() + 4] >> pin) & 1) == 1;
+ } else {
+ return (getFrameData()[getSampleOffset() + 3] & 1) == 1;
+ }
+}
+
+
+//bool RxIoSampleBaseResponse::isDigital0On(uint8_t sample) {
+// return isDigitalOn(0, sample);
+//}
+
+Rx16IoSampleResponse::Rx16IoSampleResponse() : RxIoSampleBaseResponse() {
+
+}
+
+uint16_t Rx16IoSampleResponse::getRemoteAddress16() {
+ return (uint16_t)((getFrameData()[0] << 8) + getFrameData()[1]);
+}
+
+uint8_t Rx16IoSampleResponse::getRssiOffset() {
+ return 2;
+}
+
+void XBeeResponse::getRx16IoSampleResponse(XBeeResponse &response) {
+ Rx16IoSampleResponse* rx = static_cast<Rx16IoSampleResponse*>(&response);
+
+ rx->setFrameData(getFrameData());
+ setCommon(response);
+}
+
+
+Rx64IoSampleResponse::Rx64IoSampleResponse() : RxIoSampleBaseResponse() {
+ _remoteAddress = XBeeAddress64();
+}
+
+XBeeAddress64& Rx64IoSampleResponse::getRemoteAddress64() {
+ return _remoteAddress;
+}
+
+uint8_t Rx64IoSampleResponse::getRssiOffset() {
+ return 8;
+}
+
+void XBeeResponse::getRx64IoSampleResponse(XBeeResponse &response) {
+ Rx64IoSampleResponse* rx = static_cast<Rx64IoSampleResponse*>(&response);
+
+ rx->setFrameData(getFrameData());
+ setCommon(response);
+
+ rx->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
+ rx->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + getFrameData()[7]);
+}
+
+TxStatusResponse::TxStatusResponse() : FrameIdResponse() {
+
+}
+
+uint8_t TxStatusResponse::getStatus() {
+ return getFrameData()[1];
+}
+
+bool TxStatusResponse::isSuccess() {
+ return getStatus() == SUCCESS;
+}
+
+void XBeeResponse::getTxStatusResponse(XBeeResponse &txResponse) {
+
+ TxStatusResponse* txStatus = static_cast<TxStatusResponse*>(&txResponse);
+
+ // pass pointer array to subclass
+ txStatus->setFrameData(getFrameData());
+ setCommon(txResponse);
+}
+
+uint8_t RxResponse::getRssi() {
+ return getFrameData()[getRssiOffset()];
+}
+
+uint8_t RxResponse::getOption() {
+ return getFrameData()[getRssiOffset() + 1];
+}
+
+bool RxResponse::isAddressBroadcast() {
+ return (getOption() & 2) == 2;
+}
+
+bool RxResponse::isPanBroadcast() {
+ return (getOption() & 4) == 4;
+}
+
+uint8_t RxResponse::getDataLength() {
+ return getPacketLength() - getDataOffset() - 1;
+}
+
+uint8_t RxResponse::getDataOffset() {
+ return getRssiOffset() + 2;
+}
+
+uint8_t Rx16Response::getRssiOffset() {
+ return RX_16_RSSI_OFFSET;
+}
+
+void XBeeResponse::getRx16Response(XBeeResponse &rx16Response) {
+
+ Rx16Response* rx16 = static_cast<Rx16Response*>(&rx16Response);
+
+ // pass pointer array to subclass
+ rx16->setFrameData(getFrameData());
+ setCommon(rx16Response);
+
+// rx16->getRemoteAddress16().setAddress((getFrameData()[0] << 8) + getFrameData()[1]);
+}
+
+uint8_t Rx64Response::getRssiOffset() {
+ return RX_64_RSSI_OFFSET;
+}
+
+void XBeeResponse::getRx64Response(XBeeResponse &rx64Response) {
+
+ Rx64Response* rx64 = static_cast<Rx64Response*>(&rx64Response);
+
+ // pass pointer array to subclass
+ rx64->setFrameData(getFrameData());
+ setCommon(rx64Response);
+
+ rx64->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
+ rx64->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + getFrameData()[7]);
+}
+
+#endif
+
+RemoteAtCommandResponse::RemoteAtCommandResponse() : AtCommandResponse() {
+
+}
+
+uint8_t* RemoteAtCommandResponse::getCommand() {
+ return getFrameData() + 11;
+}
+
+uint8_t RemoteAtCommandResponse::getStatus() {
+ return getFrameData()[13];
+}
+
+bool RemoteAtCommandResponse::isOk() {
+ // weird c++ behavior. w/o this method, it calls AtCommandResponse::isOk(), which calls the AtCommandResponse::getStatus, not this.getStatus!!!
+ return getStatus() == AT_OK;
+}
+
+uint8_t RemoteAtCommandResponse::getValueLength() {
+ return getFrameDataLength() - 14;
+}
+
+uint8_t* RemoteAtCommandResponse::getValue() {
+ if (getValueLength() > 0) {
+ // value is only included for query commands. set commands does not return a value
+ return getFrameData() + 14;
+ }
+
+ return NULL;
+}
+
+uint16_t RemoteAtCommandResponse::getRemoteAddress16() {
+ return uint16_t((getFrameData()[9] << 8) + getFrameData()[10]);
+}
+
+XBeeAddress64& RemoteAtCommandResponse::getRemoteAddress64() {
+ return _remoteAddress64;
+}
+
+void XBeeResponse::getRemoteAtCommandResponse(XBeeResponse &response) {
+
+ // TODO no real need to cast. change arg to match expected class
+ RemoteAtCommandResponse* at = static_cast<RemoteAtCommandResponse*>(&response);
+
+ // pass pointer array to subclass
+ at->setFrameData(getFrameData());
+ setCommon(response);
+
+ at->getRemoteAddress64().setMsb((uint32_t(getFrameData()[1]) << 24) + (uint32_t(getFrameData()[2]) << 16) + (uint16_t(getFrameData()[3]) << 8) + getFrameData()[4]);
+ at->getRemoteAddress64().setLsb((uint32_t(getFrameData()[5]) << 24) + (uint32_t(getFrameData()[6]) << 16) + (uint16_t(getFrameData()[7]) << 8) + (getFrameData()[8]));
+
+}
+
+RxDataResponse::RxDataResponse() : XBeeResponse() {
+
+}
+
+uint8_t RxDataResponse::getData(int index) {
+ return getFrameData()[getDataOffset() + index];
+}
+
+uint8_t* RxDataResponse::getData() {
+ return getFrameData() + getDataOffset();
+}
+
+FrameIdResponse::FrameIdResponse() {
+
+}
+
+uint8_t FrameIdResponse::getFrameId() {
+ return getFrameData()[0];
+}
+
+
+ModemStatusResponse::ModemStatusResponse() {
+
+}
+
+uint8_t ModemStatusResponse::getStatus() {
+ return getFrameData()[0];
+}
+
+void XBeeResponse::getModemStatusResponse(XBeeResponse &modemStatusResponse) {
+
+ ModemStatusResponse* modem = static_cast<ModemStatusResponse*>(&modemStatusResponse);
+
+ // pass pointer array to subclass
+ modem->setFrameData(getFrameData());
+ setCommon(modemStatusResponse);
+
+}
+
+AtCommandResponse::AtCommandResponse() {
+
+}
+
+uint8_t* AtCommandResponse::getCommand() {
+ return getFrameData() + 1;
+}
+
+uint8_t AtCommandResponse::getStatus() {
+ return getFrameData()[3];
+}
+
+uint8_t AtCommandResponse::getValueLength() {
+ return getFrameDataLength() - 4;
+}
+
+uint8_t* AtCommandResponse::getValue() {
+ if (getValueLength() > 0) {
+ // value is only included for query commands. set commands does not return a value
+ return getFrameData() + 4;
+ }
+
+ return NULL;
+}
+
+bool AtCommandResponse::isOk() {
+ return getStatus() == AT_OK;
+}
+
+void XBeeResponse::getAtCommandResponse(XBeeResponse &atCommandResponse) {
+
+ AtCommandResponse* at = static_cast<AtCommandResponse*>(&atCommandResponse);
+
+ // pass pointer array to subclass
+ at->setFrameData(getFrameData());
+ setCommon(atCommandResponse);
+}
+
+uint16_t XBeeResponse::getPacketLength() {
+ return ((_msbLength << 8) & 0xff) + (_lsbLength & 0xff);
+}
+
+uint8_t* XBeeResponse::getFrameData() {
+ return _frameDataPtr;
+}
+
+void XBeeResponse::setFrameData(uint8_t* frameDataPtr) {
+ _frameDataPtr = frameDataPtr;
+}
+
+void XBeeResponse::init() {
+ _complete = false;
+ _errorCode = NO_ERROR;
+ _checksum = 0;
+}
+
+void XBeeResponse::reset() {
+ init();
+ _apiId = 0;
+ _msbLength = 0;
+ _lsbLength = 0;
+ _checksum = 0;
+ _frameLength = 0;
+
+ for (int i = 0; i < MAX_FRAME_DATA_SIZE; i++) {
+ getFrameData()[i] = 0;
+ }
+}
+
+void XBee::resetResponse() {
+ _pos = 0;
+ _escape = false;
+ _response.reset();
+}
+
+XBee::XBee(PinName p_tx, PinName p_rx): _xbee(p_tx, p_rx), _response(XBeeResponse()) {
+ _pos = 0;
+ _escape = false;
+ _checksumTotal = 0;
+ _nextFrameId = 0;
+
+ _response.init();
+ _response.setFrameData(_responseFrameData);
+}
+
+uint8_t XBee::getNextFrameId() {
+
+ _nextFrameId++;
+
+ if (_nextFrameId == 0) {
+ // can't send 0 because that disables status response
+ _nextFrameId = 1;
+ }
+
+ return _nextFrameId;
+}
+
+void XBee::begin(long baud) {
+ _xbee.baud(baud);
+}
+
+/*
+void XBee::setSerial(HardwareSerial serial) {
+ Serial = serial;
+}
+*/
+
+XBeeResponse& XBee::getResponse() {
+ return _response;
+}
+
+// TODO how to convert response to proper subclass?
+void XBee::getResponse(XBeeResponse &response) {
+
+ response.setMsbLength(_response.getMsbLength());
+ response.setLsbLength(_response.getLsbLength());
+ response.setApiId(_response.getApiId());
+ response.setFrameLength(_response.getFrameDataLength());
+
+ response.setFrameData(_response.getFrameData());
+}
+
+void XBee::readPacketUntilAvailable() {
+ while (!(getResponse().isAvailable() || getResponse().isError())) {
+ // read some more
+ readPacket();
+ }
+}
+
+bool XBee::readPacket(int timeout) {
+ Timer t;
+
+ if (timeout < 0) {
+ return false;
+ }
+
+/*
+ unsigned long start = millis();
+
+ while (int((millis() - start)) < timeout) {
+*/
+ t.start();
+ while (t.read_ms() < timeout) {
+ readPacket();
+
+ if (getResponse().isAvailable()) {
+ t.stop();
+ return true;
+ } else if (getResponse().isError()) {
+ t.stop();
+ return false;
+ }
+ }
+
+ // timed out
+ t.stop();
+ return false;
+}
+
+void XBee::readPacket() {
+ // reset previous response
+ if (_response.isAvailable() || _response.isError()) {
+ // discard previous packet and start over
+ resetResponse();
+ }
+
+ while (_xbee.readable()) {
+
+ b = _xbee.getc();
+
+ if (_pos > 0 && b == START_BYTE && ATAP == 2) {
+ // new packet start before previous packeted completed -- discard previous packet and start over
+ _response.setErrorCode(UNEXPECTED_START_BYTE);
+ return;
+ }
+
+ if (_pos > 0 && b == ESCAPE) {
+ if (_xbee.readable()) {
+ b = _xbee.getc();
+ b = 0x20 ^ b;
+ } else {
+ // escape byte. next byte will be
+ _escape = true;
+ continue;
+ }
+ }
+
+ if (_escape == true) {
+ b = 0x20 ^ b;
+ _escape = false;
+ }
+
+ // checksum includes all bytes starting with api id
+ if (_pos >= API_ID_INDEX) {
+ _checksumTotal+= b;
+ }
+
+ switch(_pos) {
+ case 0:
+ if (b == START_BYTE) {
+ _pos++;
+ }
+
+ break;
+ case 1:
+ // length msb
+ _response.setMsbLength(b);
+ _pos++;
+
+ break;
+ case 2:
+ // length lsb
+ _response.setLsbLength(b);
+ _pos++;
+
+ break;
+ case 3:
+ _response.setApiId(b);
+ _pos++;
+
+ break;
+ default:
+ // starts at fifth byte
+
+ if (_pos > MAX_FRAME_DATA_SIZE) {
+ // exceed max size. should never occur
+ _response.setErrorCode(PACKET_EXCEEDS_BYTE_ARRAY_LENGTH);
+ return;
+ }
+
+ // check if we're at the end of the packet
+ // packet length does not include start, length, or checksum bytes, so add 3
+ if (_pos == (_response.getPacketLength() + 3)) {
+ // verify checksum
+
+ //std::cout << "read checksum " << static_cast<unsigned int>(b) << " at pos " << static_cast<unsigned int>(_pos) << std::endl;
+
+ if ((_checksumTotal & 0xff) == 0xff) {
+ _response.setChecksum(b);
+ _response.setAvailable(true);
+
+ _response.setErrorCode(NO_ERROR);
+ } else {
+ // checksum failed
+ _response.setErrorCode(CHECKSUM_FAILURE);
+ }
+
+ // minus 4 because we start after start,msb,lsb,api and up to but not including checksum
+ // e.g. if frame was one byte, _pos=4 would be the byte, pos=5 is the checksum, where end stop reading
+ _response.setFrameLength(_pos - 4);
+
+ // reset state vars
+ _pos = 0;
+
+ _checksumTotal = 0;
+
+ return;
+ } else {
+ // add to packet array, starting with the fourth byte of the apiFrame
+ _response.getFrameData()[_pos - 4] = b;
+ _pos++;
+ }
+ }
+ }
+}
+
+// it's peanut butter jelly time!!
+
+XBeeRequest::XBeeRequest(uint8_t apiId, uint8_t frameId) {
+ _apiId = apiId;
+ _frameId = frameId;
+}
+
+void XBeeRequest::setFrameId(uint8_t frameId) {
+ _frameId = frameId;
+}
+
+uint8_t XBeeRequest::getFrameId() {
+ return _frameId;
+}
+
+uint8_t XBeeRequest::getApiId() {
+ return _apiId;
+}
+
+void XBeeRequest::setApiId(uint8_t apiId) {
+ _apiId = apiId;
+}
+
+//void XBeeRequest::reset() {
+// _frameId = DEFAULT_FRAME_ID;
+//}
+
+//uint8_t XBeeRequest::getPayloadOffset() {
+// return _payloadOffset;
+//}
+//
+//uint8_t XBeeRequest::setPayloadOffset(uint8_t payloadOffset) {
+// _payloadOffset = payloadOffset;
+//}
+
+
+PayloadRequest::PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength) : XBeeRequest(apiId, frameId) {
+ _payloadPtr = payload;
+ _payloadLength = payloadLength;
+}
+
+uint8_t* PayloadRequest::getPayload() {
+ return _payloadPtr;
+}
+
+void PayloadRequest::setPayload(uint8_t* payload) {
+ _payloadPtr = payload;
+}
+
+uint8_t PayloadRequest::getPayloadLength() {
+ return _payloadLength;
+}
+
+void PayloadRequest::setPayloadLength(uint8_t payloadLength) {
+ _payloadLength = payloadLength;
+}
+
+
+XBeeAddress::XBeeAddress() {
+
+}
+
+XBeeAddress64::XBeeAddress64() : XBeeAddress() {
+
+}
+
+XBeeAddress64::XBeeAddress64(uint32_t msb, uint32_t lsb) : XBeeAddress() {
+ _msb = msb;
+ _lsb = lsb;
+}
+
+uint32_t XBeeAddress64::getMsb() {
+ return _msb;
+}
+
+void XBeeAddress64::setMsb(uint32_t msb) {
+ _msb = msb;
+}
+
+uint32_t XBeeAddress64::getLsb() {
+ return _lsb;
+}
+
+void XBeeAddress64::setLsb(uint32_t lsb) {
+ _lsb = lsb;
+}
+
+
+#ifdef SERIES_2
+
+ZBTxRequest::ZBTxRequest() : PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
+
+}
+
+ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId): PayloadRequest(ZB_TX_REQUEST, frameId, data, dataLength) {
+ _addr64 = addr64;
+ _addr16 = addr16;
+ _broadcastRadius = broadcastRadius;
+ _option = option;
+}
+
+ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength): PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
+ _addr64 = addr64;
+ _addr16 = ZB_BROADCAST_ADDRESS;
+ _broadcastRadius = ZB_BROADCAST_RADIUS_MAX_HOPS;
+ _option = ZB_TX_UNICAST;
+}
+
+uint8_t ZBTxRequest::getFrameData(uint8_t pos) {
+ if (pos == 0) {
+ return (_addr64.getMsb() >> 24) & 0xff;
+ } else if (pos == 1) {
+ return (_addr64.getMsb() >> 16) & 0xff;
+ } else if (pos == 2) {
+ return (_addr64.getMsb() >> 8) & 0xff;
+ } else if (pos == 3) {
+ return _addr64.getMsb() & 0xff;
+ } else if (pos == 4) {
+ return (_addr64.getLsb() >> 24) & 0xff;
+ } else if (pos == 5) {
+ return (_addr64.getLsb() >> 16) & 0xff;
+ } else if (pos == 6) {
+ return (_addr64.getLsb() >> 8) & 0xff;
+ } else if (pos == 7) {
+ return _addr64.getLsb() & 0xff;
+ } else if (pos == 8) {
+ return (_addr16 >> 8) & 0xff;
+ } else if (pos == 9) {
+ return _addr16 & 0xff;
+ } else if (pos == 10) {
+ return _broadcastRadius;
+ } else if (pos == 11) {
+ return _option;
+ } else {
+ return getPayload()[pos - ZB_TX_API_LENGTH];
+ }
+}
+
+uint8_t ZBTxRequest::getFrameDataLength() {
+ return ZB_TX_API_LENGTH + getPayloadLength();
+}
+
+XBeeAddress64& ZBTxRequest::getAddress64() {
+ return _addr64;
+}
+
+uint16_t ZBTxRequest::getAddress16() {
+ return _addr16;
+}
+
+uint8_t ZBTxRequest::getBroadcastRadius() {
+ return _broadcastRadius;
+}
+
+uint8_t ZBTxRequest::getOption() {
+ return _option;
+}
+
+void ZBTxRequest::setAddress64(XBeeAddress64& addr64) {
+ _addr64 = addr64;
+}
+
+void ZBTxRequest::setAddress16(uint16_t addr16) {
+ _addr16 = addr16;
+}
+
+void ZBTxRequest::setBroadcastRadius(uint8_t broadcastRadius) {
+ _broadcastRadius = broadcastRadius;
+}
+
+void ZBTxRequest::setOption(uint8_t option) {
+ _option = option;
+}
+
+#endif
+
+#ifdef SERIES_1
+
+Tx16Request::Tx16Request() : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
+
+}
+
+Tx16Request::Tx16Request(uint16_t addr16, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_16_REQUEST, frameId, data, dataLength) {
+ _addr16 = addr16;
+ _option = option;
+}
+
+Tx16Request::Tx16Request(uint16_t addr16, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
+ _addr16 = addr16;
+ _option = ACK_OPTION;
+}
+
+uint8_t Tx16Request::getFrameData(uint8_t pos) {
+
+ if (pos == 0) {
+ return (_addr16 >> 8) & 0xff;
+ } else if (pos == 1) {
+ return _addr16 & 0xff;
+ } else if (pos == 2) {
+ return _option;
+ } else {
+ return getPayload()[pos - TX_16_API_LENGTH];
+ }
+}
+
+uint8_t Tx16Request::getFrameDataLength() {
+ return TX_16_API_LENGTH + getPayloadLength();
+}
+
+uint16_t Tx16Request::getAddress16() {
+ return _addr16;
+}
+
+void Tx16Request::setAddress16(uint16_t addr16) {
+ _addr16 = addr16;
+}
+
+uint8_t Tx16Request::getOption() {
+ return _option;
+}
+
+void Tx16Request::setOption(uint8_t option) {
+ _option = option;
+}
+
+Tx64Request::Tx64Request() : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
+
+}
+
+Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_64_REQUEST, frameId, data, dataLength) {
+ _addr64 = addr64;
+ _option = option;
+}
+
+Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
+ _addr64 = addr64;
+ _option = ACK_OPTION;
+}
+
+uint8_t Tx64Request::getFrameData(uint8_t pos) {
+
+ if (pos == 0) {
+ return (_addr64.getMsb() >> 24) & 0xff;
+ } else if (pos == 1) {
+ return (_addr64.getMsb() >> 16) & 0xff;
+ } else if (pos == 2) {
+ return (_addr64.getMsb() >> 8) & 0xff;
+ } else if (pos == 3) {
+ return _addr64.getMsb() & 0xff;
+ } else if (pos == 4) {
+ return (_addr64.getLsb() >> 24) & 0xff;
+ } else if (pos == 5) {
+ return (_addr64.getLsb() >> 16) & 0xff;
+ } else if (pos == 6) {
+ return(_addr64.getLsb() >> 8) & 0xff;
+ } else if (pos == 7) {
+ return _addr64.getLsb() & 0xff;
+ } else if (pos == 8) {
+ return _option;
+ } else {
+ return getPayload()[pos - TX_64_API_LENGTH];
+ }
+}
+
+uint8_t Tx64Request::getFrameDataLength() {
+ return TX_64_API_LENGTH + getPayloadLength();
+}
+
+XBeeAddress64& Tx64Request::getAddress64() {
+ return _addr64;
+}
+
+void Tx64Request::setAddress64(XBeeAddress64& addr64) {
+ _addr64 = addr64;
+}
+
+uint8_t Tx64Request::getOption() {
+ return _option;
+}
+
+void Tx64Request::setOption(uint8_t option) {
+ _option = option;
+}
+
+#endif
+
+AtCommandRequest::AtCommandRequest() : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
+ _command = NULL;
+ clearCommandValue();
+}
+
+AtCommandRequest::AtCommandRequest(uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
+ _command = command;
+ _commandValue = commandValue;
+ _commandValueLength = commandValueLength;
+}
+
+AtCommandRequest::AtCommandRequest(uint8_t *command) : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
+ _command = command;
+ clearCommandValue();
+}
+
+uint8_t* AtCommandRequest::getCommand() {
+ return _command;
+}
+
+uint8_t* AtCommandRequest::getCommandValue() {
+ return _commandValue;
+}
+
+uint8_t AtCommandRequest::getCommandValueLength() {
+ return _commandValueLength;
+}
+
+void AtCommandRequest::setCommand(uint8_t* command) {
+ _command = command;
+}
+
+void AtCommandRequest::setCommandValue(uint8_t* value) {
+ _commandValue = value;
+}
+
+void AtCommandRequest::setCommandValueLength(uint8_t length) {
+ _commandValueLength = length;
+}
+
+uint8_t AtCommandRequest::getFrameData(uint8_t pos) {
+
+ if (pos == 0) {
+ return _command[0];
+ } else if (pos == 1) {
+ return _command[1];
+ } else {
+ return _commandValue[pos - AT_COMMAND_API_LENGTH];
+ }
+}
+
+void AtCommandRequest::clearCommandValue() {
+ _commandValue = NULL;
+ _commandValueLength = 0;
+}
+
+//void AtCommandRequest::reset() {
+// XBeeRequest::reset();
+//}
+
+uint8_t AtCommandRequest::getFrameDataLength() {
+ // command is 2 byte + length of value
+ return AT_COMMAND_API_LENGTH + _commandValueLength;
+}
+
+XBeeAddress64 RemoteAtCommandRequest::broadcastAddress64 = XBeeAddress64(0x0, BROADCAST_ADDRESS);
+
+RemoteAtCommandRequest::RemoteAtCommandRequest() : AtCommandRequest(NULL, NULL, 0) {
+ _remoteAddress16 = 0;
+ _applyChanges = false;
+ setApiId(REMOTE_AT_REQUEST);
+}
+
+RemoteAtCommandRequest::RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : AtCommandRequest(command, commandValue, commandValueLength) {
+ _remoteAddress64 = broadcastAddress64;
+ _remoteAddress16 = remoteAddress16;
+ _applyChanges = true;
+ setApiId(REMOTE_AT_REQUEST);
+}
+
+RemoteAtCommandRequest::RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command) : AtCommandRequest(command, NULL, 0) {
+ _remoteAddress64 = broadcastAddress64;
+ _remoteAddress16 = remoteAddress16;
+ _applyChanges = false;
+ setApiId(REMOTE_AT_REQUEST);
+}
+
+RemoteAtCommandRequest::RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : AtCommandRequest(command, commandValue, commandValueLength) {
+ _remoteAddress64 = remoteAddress64;
+ // don't worry.. works for series 1 too!
+ _remoteAddress16 = ZB_BROADCAST_ADDRESS;
+ _applyChanges = true;
+ setApiId(REMOTE_AT_REQUEST);
+}
+
+RemoteAtCommandRequest::RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command) : AtCommandRequest(command, NULL, 0) {
+ _remoteAddress64 = remoteAddress64;
+ _remoteAddress16 = ZB_BROADCAST_ADDRESS;
+ _applyChanges = false;
+ setApiId(REMOTE_AT_REQUEST);
+}
+
+uint16_t RemoteAtCommandRequest::getRemoteAddress16() {
+ return _remoteAddress16;
+}
+
+void RemoteAtCommandRequest::setRemoteAddress16(uint16_t remoteAddress16) {
+ _remoteAddress16 = remoteAddress16;
+}
+
+XBeeAddress64& RemoteAtCommandRequest::getRemoteAddress64() {
+ return _remoteAddress64;
+}
+
+void RemoteAtCommandRequest::setRemoteAddress64(XBeeAddress64 &remoteAddress64) {
+ _remoteAddress64 = remoteAddress64;
+}
+
+bool RemoteAtCommandRequest::getApplyChanges() {
+ return _applyChanges;
+}
+
+void RemoteAtCommandRequest::setApplyChanges(bool applyChanges) {
+ _applyChanges = applyChanges;
+}
+
+
+uint8_t RemoteAtCommandRequest::getFrameData(uint8_t pos) {
+ if (pos == 0) {
+ return (_remoteAddress64.getMsb() >> 24) & 0xff;
+ } else if (pos == 1) {
+ return (_remoteAddress64.getMsb() >> 16) & 0xff;
+ } else if (pos == 2) {
+ return (_remoteAddress64.getMsb() >> 8) & 0xff;
+ } else if (pos == 3) {
+ return _remoteAddress64.getMsb() & 0xff;
+ } else if (pos == 4) {
+ return (_remoteAddress64.getLsb() >> 24) & 0xff;
+ } else if (pos == 5) {
+ return (_remoteAddress64.getLsb() >> 16) & 0xff;
+ } else if (pos == 6) {
+ return(_remoteAddress64.getLsb() >> 8) & 0xff;
+ } else if (pos == 7) {
+ return _remoteAddress64.getLsb() & 0xff;
+ } else if (pos == 8) {
+ return (_remoteAddress16 >> 8) & 0xff;
+ } else if (pos == 9) {
+ return _remoteAddress16 & 0xff;
+ } else if (pos == 10) {
+ return _applyChanges ? 2: 0;
+ } else if (pos == 11) {
+ return getCommand()[0];
+ } else if (pos == 12) {
+ return getCommand()[1];
+ } else {
+ return getCommandValue()[pos - REMOTE_AT_COMMAND_API_LENGTH];
+ }
+}
+
+uint8_t RemoteAtCommandRequest::getFrameDataLength() {
+ return REMOTE_AT_COMMAND_API_LENGTH + getCommandValueLength();
+}
+
+
+// TODO
+//GenericRequest::GenericRequest(uint8_t* frame, uint8_t len, uint8_t apiId): XBeeRequest(apiId, *(frame), len) {
+// _frame = frame;
+//}
+
+void XBee::send(XBeeRequest &request) {
+ // the new new deal
+
+ sendByte(START_BYTE, false);
+
+ // send length
+ uint8_t msbLen = ((request.getFrameDataLength() + 2) >> 8) & 0xff;
+ uint8_t lsbLen = (request.getFrameDataLength() + 2) & 0xff;
+
+ sendByte(msbLen, true);
+ sendByte(lsbLen, true);
+
+ // api id
+ sendByte(request.getApiId(), true);
+ sendByte(request.getFrameId(), true);
+
+ uint8_t checksum = 0;
+
+ // compute checksum, start at api id
+ checksum+= request.getApiId();
+ checksum+= request.getFrameId();
+
+ //std::cout << "frame length is " << static_cast<unsigned int>(request.getFrameDataLength()) << std::endl;
+
+ for (int i = 0; i < request.getFrameDataLength(); i++) {
+// std::cout << "sending byte [" << static_cast<unsigned int>(i) << "] " << std::endl;
+ sendByte(request.getFrameData(i), true);
+ checksum+= request.getFrameData(i);
+ }
+
+ // perform 2s complement
+ checksum = 0xff - checksum;
+
+// std::cout << "checksum is " << static_cast<unsigned int>(checksum) << std::endl;
+
+ // send checksum
+ sendByte(checksum, true);
+/*
+ // send packet
+ Serial.flush();
+*/
+}
+
+void XBee::sendByte(uint8_t b, bool escape) {
+
+ if (escape && (b == START_BYTE || b == ESCAPE || b == XON || b == XOFF)) {
+// std::cout << "escaping byte [" << toHexString(b) << "] " << std::endl;
+ _xbee.putc(ESCAPE);
+ _xbee.putc(b ^ 0x20);
+ } else {
+ _xbee.putc(b);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee/XBee.h Mon Nov 22 10:38:08 2010 +0000
@@ -0,0 +1,955 @@
+/**
+ * XBee-mbed library
+ * Modified for mbed, 2010 Suga.
+ *
+ *
+ * Copyright (c) 2009 Andrew Rapp. All rights reserved.
+ *
+ * This file is part of XBee-Arduino.
+ *
+ * XBee-Arduino is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * XBee-Arduino is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBee-Arduino. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XBee_h
+#define XBee_h
+
+#include "mbed.h"
+#include <inttypes.h>
+
+#define SERIES_1
+#define SERIES_2
+
+// set to ATAP value of XBee. AP=2 is recommended
+#define ATAP 2
+
+#define START_BYTE 0x7e
+#define ESCAPE 0x7d
+#define XON 0x11
+#define XOFF 0x13
+
+// This value determines the size of the byte array for receiving RX packets
+// Most users won't be dealing with packets this large so you can adjust this
+// value to reduce memory consumption. But, remember that
+// if a RX packet exceeds this size, it cannot be parsed!
+
+// This value is determined by the largest packet size (100 byte payload + 64-bit address + option byte and rssi byte) of a series 1 radio
+#define MAX_FRAME_DATA_SIZE 110
+
+#define BROADCAST_ADDRESS 0xffff
+#define ZB_BROADCAST_ADDRESS 0xfffe
+
+// the non-variable length of the frame data (not including frame id or api id or variable data size (e.g. payload, at command set value)
+#define ZB_TX_API_LENGTH 12
+#define TX_16_API_LENGTH 3
+#define TX_64_API_LENGTH 9
+#define AT_COMMAND_API_LENGTH 2
+#define REMOTE_AT_COMMAND_API_LENGTH 13
+// start/length(2)/api/frameid/checksum bytes
+#define PACKET_OVERHEAD_LENGTH 6
+// api is always the third byte in packet
+#define API_ID_INDEX 3
+
+// frame position of rssi byte
+#define RX_16_RSSI_OFFSET 2
+#define RX_64_RSSI_OFFSET 8
+
+#define DEFAULT_FRAME_ID 1
+#define NO_RESPONSE_FRAME_ID 0
+
+// TODO put in tx16 class
+#define ACK_OPTION 0
+#define DISABLE_ACK_OPTION 1
+#define BROADCAST_OPTION 4
+
+// RX options
+#define ZB_PACKET_ACKNOWLEDGED 0x01
+#define ZB_BROADCAST_PACKET 0x02
+
+// not everything is implemented!
+/**
+ * Api Id constants
+ */
+#define TX_64_REQUEST 0x0
+#define TX_16_REQUEST 0x1
+#define AT_COMMAND_REQUEST 0x08
+#define AT_COMMAND_QUEUE_REQUEST 0x09
+#define REMOTE_AT_REQUEST 0x17
+#define ZB_TX_REQUEST 0x10
+#define ZB_EXPLICIT_TX_REQUEST 0x11
+#define RX_64_RESPONSE 0x80
+#define RX_16_RESPONSE 0x81
+#define RX_64_IO_RESPONSE 0x82
+#define RX_16_IO_RESPONSE 0x83
+#define AT_RESPONSE 0x88
+#define TX_STATUS_RESPONSE 0x89
+#define MODEM_STATUS_RESPONSE 0x8a
+#define ZB_RX_RESPONSE 0x90
+#define ZB_EXPLICIT_RX_RESPONSE 0x91
+#define ZB_TX_STATUS_RESPONSE 0x8b
+#define ZB_IO_SAMPLE_RESPONSE 0x92
+#define ZB_IO_NODE_IDENTIFIER_RESPONSE 0x95
+#define AT_COMMAND_RESPONSE 0x88
+#define REMOTE_AT_COMMAND_RESPONSE 0x97
+
+
+/**
+ * TX STATUS constants
+ */
+#define SUCCESS 0x0
+#define CCA_FAILURE 0x2
+#define INVALID_DESTINATION_ENDPOINT_SUCCESS 0x15
+#define NETWORK_ACK_FAILURE 0x21
+#define NOT_JOINED_TO_NETWORK 0x22
+#define SELF_ADDRESSED 0x23
+#define ADDRESS_NOT_FOUND 0x24
+#define ROUTE_NOT_FOUND 0x25
+#define PAYLOAD_TOO_LARGE 0x74
+
+// modem status
+#define HARDWARE_RESET 0
+#define WATCHDOG_TIMER_RESET 1
+#define ASSOCIATED 2
+#define DISASSOCIATED 3
+#define SYNCHRONIZATION_LOST 4
+#define COORDINATOR_REALIGNMENT 5
+#define COORDINATOR_STARTED 6
+
+#define ZB_BROADCAST_RADIUS_MAX_HOPS 0
+
+#define ZB_TX_UNICAST 0
+#define ZB_TX_BROADCAST 8
+
+#define AT_OK 0
+#define AT_ERROR 1
+#define AT_INVALID_COMMAND 2
+#define AT_INVALID_PARAMETER 3
+#define AT_NO_RESPONSE 4
+
+#define NO_ERROR 0
+#define CHECKSUM_FAILURE 1
+#define PACKET_EXCEEDS_BYTE_ARRAY_LENGTH 2
+#define UNEXPECTED_START_BYTE 3
+
+/**
+ * The super class of all XBee responses (RX packets)
+ * Users should never attempt to create an instance of this class; instead
+ * create an instance of a subclass
+ * It is recommend to reuse subclasses to conserve memory
+ */
+class XBeeResponse {
+public:
+ //static const int MODEM_STATUS = 0x8a;
+ /**
+ * Default constructor
+ */
+ XBeeResponse();
+ /**
+ * Returns Api Id of the response
+ */
+ uint8_t getApiId();
+ void setApiId(uint8_t apiId);
+ /**
+ * Returns the MSB length of the packet
+ */
+ uint8_t getMsbLength();
+ void setMsbLength(uint8_t msbLength);
+ /**
+ * Returns the LSB length of the packet
+ */
+ uint8_t getLsbLength();
+ void setLsbLength(uint8_t lsbLength);
+ /**
+ * Returns the packet checksum
+ */
+ uint8_t getChecksum();
+ void setChecksum(uint8_t checksum);
+ /**
+ * Returns the length of the frame data: all bytes after the api id, and prior to the checksum
+ * Note up to release 0.1.2, this was incorrectly including the checksum in the length.
+ */
+ uint8_t getFrameDataLength();
+ void setFrameData(uint8_t* frameDataPtr);
+ /**
+ * Returns the buffer that contains the response.
+ * Starts with byte that follows API ID and includes all bytes prior to the checksum
+ * Length is specified by getFrameDataLength()
+ * Note: Unlike Digi's definition of the frame data, this does not start with the API ID..
+ * The reason for this is all responses include an API ID, whereas my frame data
+ * includes only the API specific data.
+ */
+ uint8_t* getFrameData();
+
+ void setFrameLength(uint8_t frameLength);
+ // to support future 65535 byte packets I guess
+ /**
+ * Returns the length of the packet
+ */
+ uint16_t getPacketLength();
+ /**
+ * Resets the response to default values
+ */
+ void reset();
+ /**
+ * Initializes the response
+ */
+ void init();
+#ifdef SERIES_2
+ /**
+ * Call with instance of ZBTxStatusResponse class only if getApiId() == ZB_TX_STATUS_RESPONSE
+ * to populate response
+ */
+ void getZBTxStatusResponse(XBeeResponse &response);
+ /**
+ * Call with instance of ZBRxResponse class only if getApiId() == ZB_RX_RESPONSE
+ * to populate response
+ */
+ void getZBRxResponse(XBeeResponse &response);
+ /**
+ * Call with instance of ZBRxIoSampleResponse class only if getApiId() == ZB_IO_SAMPLE_RESPONSE
+ * to populate response
+ */
+ void getZBRxIoSampleResponse(XBeeResponse &response);
+#endif
+#ifdef SERIES_1
+ /**
+ * Call with instance of TxStatusResponse only if getApiId() == TX_STATUS_RESPONSE
+ */
+ void getTxStatusResponse(XBeeResponse &response);
+ /**
+ * Call with instance of Rx16Response only if getApiId() == RX_16_RESPONSE
+ */
+ void getRx16Response(XBeeResponse &response);
+ /**
+ * Call with instance of Rx64Response only if getApiId() == RX_64_RESPONSE
+ */
+ void getRx64Response(XBeeResponse &response);
+ /**
+ * Call with instance of Rx16IoSampleResponse only if getApiId() == RX_16_IO_RESPONSE
+ */
+ void getRx16IoSampleResponse(XBeeResponse &response);
+ /**
+ * Call with instance of Rx64IoSampleResponse only if getApiId() == RX_64_IO_RESPONSE
+ */
+ void getRx64IoSampleResponse(XBeeResponse &response);
+#endif
+ /**
+ * Call with instance of AtCommandResponse only if getApiId() == AT_COMMAND_RESPONSE
+ */
+ void getAtCommandResponse(XBeeResponse &responses);
+ /**
+ * Call with instance of RemoteAtCommandResponse only if getApiId() == REMOTE_AT_COMMAND_RESPONSE
+ */
+ void getRemoteAtCommandResponse(XBeeResponse &response);
+ /**
+ * Call with instance of ModemStatusResponse only if getApiId() == MODEM_STATUS_RESPONSE
+ */
+ void getModemStatusResponse(XBeeResponse &response);
+ /**
+ * Returns true if the response has been successfully parsed and is complete and ready for use
+ */
+ bool isAvailable();
+ void setAvailable(bool complete);
+ /**
+ * Returns true if the response contains errors
+ */
+ bool isError();
+ /**
+ * Returns an error code, or zero, if successful.
+ * Error codes include: CHECKSUM_FAILURE, PACKET_EXCEEDS_BYTE_ARRAY_LENGTH, UNEXPECTED_START_BYTE
+ */
+ uint8_t getErrorCode();
+ void setErrorCode(uint8_t errorCode);
+protected:
+ // pointer to frameData
+ uint8_t* _frameDataPtr;
+private:
+ void setCommon(XBeeResponse &target);
+ uint8_t _apiId;
+ uint8_t _msbLength;
+ uint8_t _lsbLength;
+ uint8_t _checksum;
+ uint8_t _frameLength;
+ bool _complete;
+ uint8_t _errorCode;
+};
+
+class XBeeAddress {
+public:
+ XBeeAddress();
+};
+
+/**
+ * Represents a 64-bit XBee Address
+ */
+class XBeeAddress64 : public XBeeAddress {
+public:
+ XBeeAddress64(uint32_t msb, uint32_t lsb);
+ XBeeAddress64();
+ uint32_t getMsb();
+ uint32_t getLsb();
+ void setMsb(uint32_t msb);
+ void setLsb(uint32_t lsb);
+private:
+ uint32_t _msb;
+ uint32_t _lsb;
+};
+
+//class XBeeAddress16 : public XBeeAddress {
+//public:
+// XBeeAddress16(uint16_t addr);
+// XBeeAddress16();
+// uint16_t getAddress();
+// void setAddress(uint16_t addr);
+//private:
+// uint16_t _addr;
+//};
+
+/**
+ * This class is extended by all Responses that include a frame id
+ */
+class FrameIdResponse : public XBeeResponse {
+public:
+ FrameIdResponse();
+ uint8_t getFrameId();
+private:
+ uint8_t _frameId;
+};
+
+/**
+ * Common functionality for both Series 1 and 2 data RX data packets
+ */
+class RxDataResponse : public XBeeResponse {
+public:
+ RxDataResponse();
+ /**
+ * Returns the specified index of the payload. The index may be 0 to getDataLength() - 1
+ * This method is deprecated; use uint8_t* getData()
+ */
+ uint8_t getData(int index);
+ /**
+ * Returns the payload array. This may be accessed from index 0 to getDataLength() - 1
+ */
+ uint8_t* getData();
+ /**
+ * Returns the length of the payload
+ */
+ virtual uint8_t getDataLength() = 0;
+ /**
+ * Returns the position in the frame data where the data begins
+ */
+ virtual uint8_t getDataOffset() = 0;
+};
+
+// getResponse to return the proper subclass:
+// we maintain a pointer to each type of response, when a response is parsed, it is allocated only if NULL
+// can we allocate an object in a function?
+
+#ifdef SERIES_2
+/**
+ * Represents a Series 2 TX status packet
+ */
+class ZBTxStatusResponse : public FrameIdResponse {
+ public:
+ ZBTxStatusResponse();
+ uint16_t getRemoteAddress();
+ uint8_t getTxRetryCount();
+ uint8_t getDeliveryStatus();
+ uint8_t getDiscoveryStatus();
+ bool isSuccess();
+};
+
+/**
+ * Represents a Series 2 RX packet
+ */
+class ZBRxResponse : public RxDataResponse {
+public:
+ ZBRxResponse();
+ XBeeAddress64& getRemoteAddress64();
+ uint16_t getRemoteAddress16();
+ uint8_t getOption();
+ virtual uint8_t getDataLength();
+ // frame position where data starts
+ virtual uint8_t getDataOffset();
+private:
+ XBeeAddress64 _remoteAddress64;
+};
+
+/**
+ * Represents a Series 2 RX I/O Sample packet
+ */
+class ZBRxIoSampleResponse : public ZBRxResponse {
+public:
+ ZBRxIoSampleResponse();
+ bool containsAnalog();
+ bool containsDigital();
+ /**
+ * Returns true if the pin is enabled
+ */
+ bool isAnalogEnabled(uint8_t pin);
+ /**
+ * Returns true if the pin is enabled
+ */
+ bool isDigitalEnabled(uint8_t pin);
+ /**
+ * Returns the 10-bit analog reading of the specified pin.
+ * Valid pins include ADC:xxx.
+ */
+ uint16_t getAnalog(uint8_t pin);
+ /**
+ * Returns true if the specified pin is high/on.
+ * Valid pins include DIO:xxx.
+ */
+ bool isDigitalOn(uint8_t pin);
+ uint8_t getDigitalMaskMsb();
+ uint8_t getDigitalMaskLsb();
+ uint8_t getAnalogMask();
+};
+
+#endif
+
+#ifdef SERIES_1
+/**
+ * Represents a Series 1 TX Status packet
+ */
+class TxStatusResponse : public FrameIdResponse {
+ public:
+ TxStatusResponse();
+ uint8_t getStatus();
+ bool isSuccess();
+};
+
+/**
+ * Represents a Series 1 RX packet
+ */
+class RxResponse : public RxDataResponse {
+public:
+ RxResponse();
+ // remember rssi is negative but this is unsigned byte so it's up to you to convert
+ uint8_t getRssi();
+ uint8_t getOption();
+ bool isAddressBroadcast();
+ bool isPanBroadcast();
+ virtual uint8_t getDataLength();
+ virtual uint8_t getDataOffset();
+ virtual uint8_t getRssiOffset() = 0;
+};
+
+/**
+ * Represents a Series 1 16-bit address RX packet
+ */
+class Rx16Response : public RxResponse {
+public:
+ Rx16Response();
+ virtual uint8_t getRssiOffset();
+ uint16_t getRemoteAddress16();
+protected:
+ uint16_t _remoteAddress;
+};
+
+/**
+ * Represents a Series 1 64-bit address RX packet
+ */
+class Rx64Response : public RxResponse {
+public:
+ Rx64Response();
+ virtual uint8_t getRssiOffset();
+ XBeeAddress64& getRemoteAddress64();
+private:
+ XBeeAddress64 _remoteAddress;
+};
+
+/**
+ * Represents a Series 1 RX I/O Sample packet
+ */
+class RxIoSampleBaseResponse : public RxResponse {
+ public:
+ RxIoSampleBaseResponse();
+ /**
+ * Returns the number of samples in this packet
+ */
+ uint8_t getSampleSize();
+ bool containsAnalog();
+ bool containsDigital();
+ /**
+ * Returns true if the specified analog pin is enabled
+ */
+ bool isAnalogEnabled(uint8_t pin);
+ /**
+ * Returns true if the specified digital pin is enabled
+ */
+ bool isDigitalEnabled(uint8_t pin);
+ /**
+ * Returns the 10-bit analog reading of the specified pin.
+ * Valid pins include ADC:0-5. Sample index starts at 0
+ */
+ uint16_t getAnalog(uint8_t pin, uint8_t sample);
+ /**
+ * Returns true if the specified pin is high/on.
+ * Valid pins include DIO:0-8. Sample index starts at 0
+ */
+ bool isDigitalOn(uint8_t pin, uint8_t sample);
+ uint8_t getSampleOffset();
+ private:
+};
+
+class Rx16IoSampleResponse : public RxIoSampleBaseResponse {
+public:
+ Rx16IoSampleResponse();
+ uint16_t getRemoteAddress16();
+ virtual uint8_t getRssiOffset();
+
+};
+
+class Rx64IoSampleResponse : public RxIoSampleBaseResponse {
+public:
+ Rx64IoSampleResponse();
+ XBeeAddress64& getRemoteAddress64();
+ virtual uint8_t getRssiOffset();
+private:
+ XBeeAddress64 _remoteAddress;
+};
+
+#endif
+
+/**
+ * Represents a Modem Status RX packet
+ */
+class ModemStatusResponse : public XBeeResponse {
+public:
+ ModemStatusResponse();
+ uint8_t getStatus();
+};
+
+/**
+ * Represents an AT Command RX packet
+ */
+class AtCommandResponse : public FrameIdResponse {
+ public:
+ AtCommandResponse();
+ /**
+ * Returns an array containing the two character command
+ */
+ uint8_t* getCommand();
+ /**
+ * Returns the command status code.
+ * Zero represents a successful command
+ */
+ uint8_t getStatus();
+ /**
+ * Returns an array containing the command value.
+ * This is only applicable to query commands.
+ */
+ uint8_t* getValue();
+ /**
+ * Returns the length of the command value array.
+ */
+ uint8_t getValueLength();
+ /**
+ * Returns true if status equals AT_OK
+ */
+ bool isOk();
+};
+
+/**
+ * Represents a Remote AT Command RX packet
+ */
+class RemoteAtCommandResponse : public AtCommandResponse {
+ public:
+ RemoteAtCommandResponse();
+ /**
+ * Returns an array containing the two character command
+ */
+ uint8_t* getCommand();
+ /**
+ * Returns the command status code.
+ * Zero represents a successful command
+ */
+ uint8_t getStatus();
+ /**
+ * Returns an array containing the command value.
+ * This is only applicable to query commands.
+ */
+ uint8_t* getValue();
+ /**
+ * Returns the length of the command value array.
+ */
+ uint8_t getValueLength();
+ /**
+ * Returns the 16-bit address of the remote radio
+ */
+ uint16_t getRemoteAddress16();
+ /**
+ * Returns the 64-bit address of the remote radio
+ */
+ XBeeAddress64& getRemoteAddress64();
+ /**
+ * Returns true if command was successful
+ */
+ bool isOk();
+ private:
+ XBeeAddress64 _remoteAddress64;
+};
+
+
+/**
+ * Super class of all XBee requests (TX packets)
+ * Users should never create an instance of this class; instead use an subclass of this class
+ * It is recommended to reuse Subclasses of the class to conserve memory
+ * <p/>
+ * This class allocates a buffer to
+ */
+class XBeeRequest {
+public:
+ /**
+ * Constructor
+ * TODO make protected
+ */
+ XBeeRequest(uint8_t apiId, uint8_t frameId);
+ /**
+ * Sets the frame id. Must be between 1 and 255 inclusive to get a TX status response.
+ */
+ void setFrameId(uint8_t frameId);
+ /**
+ * Returns the frame id
+ */
+ uint8_t getFrameId();
+ /**
+ * Returns the API id
+ */
+ uint8_t getApiId();
+ // setting = 0 makes this a pure virtual function, meaning the subclass must implement, like abstract in java
+ /**
+ * Starting after the frame id (pos = 0) and up to but not including the checksum
+ * Note: Unlike Digi's definition of the frame data, this does not start with the API ID.
+ * The reason for this is the API ID and Frame ID are common to all requests, whereas my definition of
+ * frame data is only the API specific data.
+ */
+ virtual uint8_t getFrameData(uint8_t pos) = 0;
+ /**
+ * Returns the size of the api frame (not including frame id or api id or checksum).
+ */
+ virtual uint8_t getFrameDataLength() = 0;
+ //void reset();
+protected:
+ void setApiId(uint8_t apiId);
+private:
+ uint8_t _apiId;
+ uint8_t _frameId;
+};
+
+// TODO add reset/clear method since responses are often reused
+/**
+ * Primary interface for communicating with an XBee Radio.
+ * This class provides methods for sending and receiving packets with an XBee radio via the serial port.
+ * The XBee radio must be configured in API (packet) mode (AP=2)
+ * in order to use this software.
+ * <p/>
+ * Since this code is designed to run on a microcontroller, with only one thread, you are responsible for reading the
+ * data off the serial buffer in a timely manner. This involves a call to a variant of readPacket(...).
+ * If your serial port is receiving data faster than you are reading, you can expect to lose packets.
+ * Arduino only has a 128 byte serial buffer so it can easily overflow if two or more packets arrive
+ * without a call to readPacket(...)
+ * <p/>
+ * In order to conserve resources, this class only supports storing one response packet in memory at a time.
+ * This means that you must fully consume the packet prior to calling readPacket(...), because calling
+ * readPacket(...) overwrites the previous response.
+ * <p/>
+ * This class creates an array of size MAX_FRAME_DATA_SIZE for storing the response packet. You may want
+ * to adjust this value to conserve memory.
+ *
+ * \author Andrew Rapp
+ */
+class XBee : public Base {
+public:
+ XBee(PinName p_tx, PinName p_rx);
+ // for eclipse dev only
+// void setSerial(HardwareSerial serial);
+ /**
+ * Reads all available serial bytes until a packet is parsed, an error occurs, or the buffer is empty.
+ * You may call <i>xbee</i>.getResponse().isAvailable() after calling this method to determine if
+ * a packet is ready, or <i>xbee</i>.getResponse().isError() to determine if
+ * a error occurred.
+ * <p/>
+ * This method should always return quickly since it does not wait for serial data to arrive.
+ * You will want to use this method if you are doing other timely stuff in your loop, where
+ * a delay would cause problems.
+ * NOTE: calling this method resets the current response, so make sure you first consume the
+ * current response
+ */
+ void readPacket();
+ /**
+ * Waits a maximum of <i>timeout</i> milliseconds for a response packet before timing out; returns true if packet is read.
+ * Returns false if timeout or error occurs.
+ */
+ bool readPacket(int timeout);
+ /**
+ * Reads until a packet is received or an error occurs.
+ * Caution: use this carefully since if you don't get a response, your Arduino code will hang on this
+ * call forever!! often it's better to use a timeout: readPacket(int)
+ */
+ void readPacketUntilAvailable();
+ /**
+ * Starts the serial connection at the supplied baud rate
+ */
+ void begin(long baud);
+ void getResponse(XBeeResponse &response);
+ /**
+ * Returns a reference to the current response
+ * Note: once readPacket is called again this response will be overwritten!
+ */
+ XBeeResponse& getResponse();
+ /**
+ * Sends a XBeeRequest (TX packet) out the serial port
+ */
+ void send(XBeeRequest &request);
+ //uint8_t sendAndWaitForResponse(XBeeRequest &request, int timeout);
+ /**
+ * Returns a sequential frame id between 1 and 255
+ */
+ uint8_t getNextFrameId();
+private:
+ Serial _xbee;
+ void sendByte(uint8_t b, bool escape);
+ void resetResponse();
+ XBeeResponse _response;
+ bool _escape;
+ // current packet position for response. just a state variable for packet parsing and has no relevance for the response otherwise
+ uint8_t _pos;
+ // last byte read
+ uint8_t b;
+ uint8_t _checksumTotal;
+ uint8_t _nextFrameId;
+ // buffer for incoming RX packets. holds only the api specific frame data, starting after the api id byte and prior to checksum
+ uint8_t _responseFrameData[MAX_FRAME_DATA_SIZE];
+};
+
+/**
+ * All TX packets that support payloads extend this class
+ */
+class PayloadRequest : public XBeeRequest {
+public:
+ PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength);
+ /**
+ * Returns the payload of the packet, if not null
+ */
+ uint8_t* getPayload();
+ /**
+ * Sets the payload array
+ */
+ void setPayload(uint8_t* payloadPtr);
+ /**
+ * Returns the length of the payload array, as specified by the user.
+ */
+ uint8_t getPayloadLength();
+ /**
+ * Sets the length of the payload to include in the request. For example if the payload array
+ * is 50 bytes and you only want the first 10 to be included in the packet, set the length to 10.
+ * Length must be <= to the array length.
+ */
+ void setPayloadLength(uint8_t payloadLength);
+private:
+ uint8_t* _payloadPtr;
+ uint8_t _payloadLength;
+};
+
+#ifdef SERIES_1
+
+/**
+ * Represents a Series 1 TX packet that corresponds to Api Id: TX_16_REQUEST
+ * <p/>
+ * Be careful not to send a data array larger than the max packet size of your radio.
+ * This class does not perform any validation of packet size and there will be no indication
+ * if the packet is too large, other than you will not get a TX Status response.
+ * The datasheet says 100 bytes is the maximum, although that could change in future firmware.
+ */
+class Tx16Request : public PayloadRequest {
+public:
+ Tx16Request(uint16_t addr16, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId);
+ /**
+ * Creates a Unicast Tx16Request with the ACK option and DEFAULT_FRAME_ID
+ */
+ Tx16Request(uint16_t addr16, uint8_t *payload, uint8_t payloadLength);
+ /**
+ * Creates a default instance of this class. At a minimum you must specify
+ * a payload, payload length and a destination address before sending this request.
+ */
+ Tx16Request();
+ uint16_t getAddress16();
+ void setAddress16(uint16_t addr16);
+ uint8_t getOption();
+ void setOption(uint8_t option);
+ virtual uint8_t getFrameData(uint8_t pos);
+ virtual uint8_t getFrameDataLength();
+protected:
+private:
+ uint16_t _addr16;
+ uint8_t _option;
+};
+
+/**
+ * Represents a Series 1 TX packet that corresponds to Api Id: TX_64_REQUEST
+ *
+ * Be careful not to send a data array larger than the max packet size of your radio.
+ * This class does not perform any validation of packet size and there will be no indication
+ * if the packet is too large, other than you will not get a TX Status response.
+ * The datasheet says 100 bytes is the maximum, although that could change in future firmware.
+ */
+class Tx64Request : public PayloadRequest {
+public:
+ Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId);
+ /**
+ * Creates a unicast Tx64Request with the ACK option and DEFAULT_FRAME_ID
+ */
+ Tx64Request(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength);
+ /**
+ * Creates a default instance of this class. At a minimum you must specify
+ * a payload, payload length and a destination address before sending this request.
+ */
+ Tx64Request();
+ XBeeAddress64& getAddress64();
+ void setAddress64(XBeeAddress64& addr64);
+ // TODO move option to superclass
+ uint8_t getOption();
+ void setOption(uint8_t option);
+ virtual uint8_t getFrameData(uint8_t pos);
+ virtual uint8_t getFrameDataLength();
+private:
+ XBeeAddress64 _addr64;
+ uint8_t _option;
+};
+
+#endif
+
+
+#ifdef SERIES_2
+
+/**
+ * Represents a Series 2 TX packet that corresponds to Api Id: ZB_TX_REQUEST
+ *
+ * Be careful not to send a data array larger than the max packet size of your radio.
+ * This class does not perform any validation of packet size and there will be no indication
+ * if the packet is too large, other than you will not get a TX Status response.
+ * The datasheet says 72 bytes is the maximum for ZNet firmware and ZB Pro firmware provides
+ * the ATNP command to get the max supported payload size. This command is useful since the
+ * maximum payload size varies according to certain settings, such as encryption.
+ * ZB Pro firmware provides a PAYLOAD_TOO_LARGE that is returned if payload size
+ * exceeds the maximum.
+ */
+class ZBTxRequest : public PayloadRequest {
+public:
+ /**
+ * Creates a unicast ZBTxRequest with the ACK option and DEFAULT_FRAME_ID
+ */
+ ZBTxRequest(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength);
+ ZBTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId);
+ /**
+ * Creates a default instance of this class. At a minimum you must specify
+ * a payload, payload length and a destination address before sending this request.
+ */
+ ZBTxRequest();
+ XBeeAddress64& getAddress64();
+ uint16_t getAddress16();
+ uint8_t getBroadcastRadius();
+ uint8_t getOption();
+ void setAddress64(XBeeAddress64& addr64);
+ void setAddress16(uint16_t addr16);
+ void setBroadcastRadius(uint8_t broadcastRadius);
+ void setOption(uint8_t option);
+protected:
+ // declare virtual functions
+ virtual uint8_t getFrameData(uint8_t pos);
+ virtual uint8_t getFrameDataLength();
+private:
+ XBeeAddress64 _addr64;
+ uint16_t _addr16;
+ uint8_t _broadcastRadius;
+ uint8_t _option;
+};
+
+#endif
+
+/**
+ * Represents an AT Command TX packet
+ * The command is used to configure the serially connected XBee radio
+ */
+class AtCommandRequest : public XBeeRequest {
+public:
+ AtCommandRequest();
+ AtCommandRequest(uint8_t *command);
+ AtCommandRequest(uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength);
+ virtual uint8_t getFrameData(uint8_t pos);
+ virtual uint8_t getFrameDataLength();
+ uint8_t* getCommand();
+ void setCommand(uint8_t* command);
+ uint8_t* getCommandValue();
+ void setCommandValue(uint8_t* command);
+ uint8_t getCommandValueLength();
+ void setCommandValueLength(uint8_t length);
+ /**
+ * Clears the optional commandValue and commandValueLength so that a query may be sent
+ */
+ void clearCommandValue();
+ //void reset();
+private:
+ uint8_t *_command;
+ uint8_t *_commandValue;
+ uint8_t _commandValueLength;
+};
+
+/**
+ * Represents an Remote AT Command TX packet
+ * The command is used to configure a remote XBee radio
+ */
+class RemoteAtCommandRequest : public AtCommandRequest {
+public:
+ RemoteAtCommandRequest();
+ /**
+ * Creates a RemoteAtCommandRequest with 16-bit address to set a command.
+ * 64-bit address defaults to broadcast and applyChanges is true.
+ */
+ RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength);
+ /**
+ * Creates a RemoteAtCommandRequest with 16-bit address to query a command.
+ * 64-bit address defaults to broadcast and applyChanges is true.
+ */
+ RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command);
+ /**
+ * Creates a RemoteAtCommandRequest with 64-bit address to set a command.
+ * 16-bit address defaults to broadcast and applyChanges is true.
+ */
+ RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength);
+ /**
+ * Creates a RemoteAtCommandRequest with 16-bit address to query a command.
+ * 16-bit address defaults to broadcast and applyChanges is true.
+ */
+ RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command);
+ uint16_t getRemoteAddress16();
+ void setRemoteAddress16(uint16_t remoteAddress16);
+ XBeeAddress64& getRemoteAddress64();
+ void setRemoteAddress64(XBeeAddress64 &remoteAddress64);
+ bool getApplyChanges();
+ void setApplyChanges(bool applyChanges);
+ virtual uint8_t getFrameData(uint8_t pos);
+ virtual uint8_t getFrameDataLength();
+ static XBeeAddress64 broadcastAddress64;
+// static uint16_t broadcast16Address;
+private:
+ XBeeAddress64 _remoteAddress64;
+ uint16_t _remoteAddress16;
+ bool _applyChanges;
+};
+
+
+
+#endif //XBee_h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Mon Nov 22 10:38:08 2010 +0000
@@ -0,0 +1,35 @@
+#include "mbed.h"
+#include "XBee.h"
+
+DigitalOut myled(LED1);
+XBee xbee(p13, p14);
+XBeeAddress64 remoteAddress = XBeeAddress64(0x0013A200, 0x40319F25);
+
+int main() {
+ uint8_t p2Cmd[] = {'D', '4'};
+ uint8_t p2Low[] = {0x04};
+ uint8_t p2High[] = {0x05};
+ RemoteAtCommandRequest remoteAtRequest;
+
+ wait(1);
+ xbee.begin(9800);
+
+ remoteAtRequest = RemoteAtCommandRequest(remoteAddress, p2Cmd, p2Low, sizeof(p2Low));
+ remoteAtRequest.setApplyChanges(true); // I/OóÔð¦½f³¹é
+
+ while(1) {
+ myled = 1;
+ remoteAtRequest.setCommandValue(p2Low);
+ remoteAtRequest.setCommandValueLength(sizeof(p2Low));
+ xbee.send(remoteAtRequest);
+ myled = 0;
+ wait(1);
+
+ myled = 1;
+ remoteAtRequest.setCommandValue(p2High);
+ remoteAtRequest.setCommandValueLength(sizeof(p2High));
+ xbee.send(remoteAtRequest);
+ myled = 0;
+ wait(1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Nov 22 10:38:08 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e