EmbeddedArtists AB
/
lpc812_exp_solution_exp-port-xbee
Solutions for the XBee experiments for LPC812 MAX
Revision 0:54828b08e71d, committed 2013-11-20
- Comitter:
- embeddedartists
- Date:
- Wed Nov 20 08:26:28 2013 +0000
- Commit message:
- First Version
Changed in this revision
diff -r 000000000000 -r 54828b08e71d XBee.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XBee.cpp Wed Nov 20 08:26:28 2013 +0000 @@ -0,0 +1,751 @@ + +#include "mbed.h" +#include "mbed_debug.h" +#include "XBee.h" + +#define XBEE_END_CMD ("\r") +#define CR (0x0D) +#define RESP_OK ("OK") + +#define XBEE_START_DEL (0x7E) + +#define XBEE_API_ID_TX_64 (0x00) +#define XBEE_API_ID_AT_CMD (0x08) +#define XBEE_API_ID_AT_RESP (0x88) +#define XBEE_API_ID_TX_STAT (0x89) +#define XBEE_API_ID_RX_64 (0x80) +#define XBEE_API_ID_RX_16 (0x81) +#define XBEE_API_ID_MOD_STAT (0x8A) + +#define XBEE_MOD_STAT_HW_RESET (0) +#define XBEE_MOD_STAT_WD_RESET (1) +#define XBEE_MOD_STAT_ASSOC (2) +#define XBEE_MOD_STAT_DIASSOC (3) +#define XBEE_MOD_STAT_SYNC_LOST (4) +#define XBEE_MOD_STAT_COORD_REALG (5) +#define XBEE_MOD_STAT_COORD_START (6) + +#define XBEE_TX_STAT_SUCCESS (0) +#define XBEE_TX_STAT_NOACK (1) +#define XBEE_TX_STAT_CCA_FAIL (2) +#define XBEE_TX_STAT_PURGED (3) + +#define XBEE_RECV_FRAME_TO (2000) + +XBee::XBee(PinName tx, PinName rx, PinName reset, PinName sleep) : + _serial(tx, rx), _reset(reset), _sleep(sleep) { + _serial.baud(9600); + //_serial.format(8, Serial::None, 1); + + _serial.attach(this, &XBee::uartRxIrq, Serial::RxIrq); + + rxqIn = 0; + rxqOut = 0; + _rfFrameTimeout = 0; + _rfFrameTimer.reset(); + + _rfState = RfStateFrame; + _rfPos = 0; + _rfFrameLen = 0; + _rfFrameId = 0; + + _initialized = false; + _type = Coordinator; + + _addrHi = 0; + _addrLo = 0; + _rssi = 0; + _frameId = 0; + _txStatus = TxStatusOk; + _recvData = NULL; + _recvLen = 0; + + // we enter sleep when sleep pin is high + _sleep = 0; +} + +XBee::XBeeError XBee::init(XBeeType type, const char* panId) { + XBeeError err = Ok; + char idBuf[10]; + + resetModule(); + + _type = type; + + do { + + if (panId == NULL || strlen(panId) != 4) { + err = ArgumentError; + break; + } + + err = commandMode(); + if (err != Ok) { + debug("XBee: +++ failed\n"); + break; + } + + // set the sleep mode to Hibernate + err = atSet("ATSM1"); + if (err != Ok) { + debug("Xbee: ATSM1 failed\r\n"); + break; + } + + // change PAN ID to EAEA + sprintf(idBuf, "ATID%s", panId); + err = atSet(idBuf); + if (err != Ok) { + debug("Xbee: ATID failed\r\n"); + break; + } + + // use 64-bit addressing + err = atSet("ATMYFFFE"); + if (err != Ok) { + debug("Xbee: ATMYFFFE failed\r\n"); + break; + } + + // Coordinator + if (type == Coordinator) { + + // - will not perform Active Scan to locate PAN ID + // - will not perform Energy Scan to determine free channel + // - allow End devices to associate with this coordinator + err = atSet("ATA24"); + if (err != Ok) { + debug("Xbee: ATA24 failed\r\n"); + break; + } + + // set this node as coordinator + err = atSet("ATCE1"); + if (err != Ok) { + debug("Xbee: ATCE1 failed\r\n"); + break; + } + } + else { + // - only associates with Coordinator on matching PAN ID + // - only associates with Coordinator on matching channel + // - device attempts association until success + err = atSet("ATA14"); + if (err != Ok) { + debug("Xbee: ATA14 failed\r\n"); + break; + } + } + + + // change to API mode + err = atSet("ATAP1"); + if (err != Ok) { + debug("Xbee: ATAP1 failed\r\n"); + break; + } + + } while(0); + + + return err; +} + +void XBee::process() { + uint32_t len = 0; + char data = 0; + + if (_rfFrameTimeout > 0 && (int)_rfFrameTimeout < _rfFrameTimer.read_ms()) { + _rfState = RfStateFrame; + debug("Xbee: Frame timer expired\r\n"); + _rfFrameTimeout = 0; + _rfFrameTimer.stop(); + } + + if (!uartRxQIsEmpty()) { + + len = uartReceive(&data, 1); + if (len > 0) { + processByte(data); + } + + } +} + +XBee::XBeeError XBee::getRemoteAddress(uint32_t* addrHi, uint32_t* addrLo) { + if (!_initialized) { + return NotInitializedError; + } + + if (addrHi == NULL || addrLo == NULL) { + return ArgumentError; + } + + *addrHi = _addrHi; + *addrLo = _addrLo; + + return Ok; +} + +XBee::XBeeError XBee::getRssi(uint8_t* rssi ) { + if (!_initialized) { + return NotInitializedError; + } + + if (rssi == NULL) { + return ArgumentError; + } + + *rssi = _rssi; + + return Ok; +} + +XBee::XBeeError XBee::getTxStatus(uint8_t* frameId, XBeeTxStatus* status) { + if (!_initialized) { + return NotInitializedError; + } + + if (frameId == NULL || status == NULL) { + return ArgumentError; + } + + *frameId = _frameId; + *status = _txStatus; + + return Ok; +} + +XBee::XBeeError XBee::getData(char** data, uint8_t* len) { + if (!_initialized) { + return NotInitializedError; + } + + if (data == NULL || len == NULL) { + return ArgumentError; + } + + *data = _recvData; + *len = _recvLen; + + return Ok; +} + +XBee::XBeeError XBee::send(uint32_t addrHi, uint32_t addrLo, char* data, + uint8_t len, uint8_t* frameId) +{ + if (!_initialized) { + return NotInitializedError; + } + + return apiTx64(addrHi, addrLo, data, len, frameId); +} + +XBee::XBeeError XBee::discoverNodes() { + if (!_initialized) { + return NotInitializedError; + } + + return apiAtCmd("ND", 0, false); +} + + +XBee::XBeeError XBee::enterSleep() { + _sleep = 1; + + return Ok; +} + +XBee::XBeeError XBee::exitSleep() { + _sleep = 0; + + return Ok; +} + + +void XBee::uartRxIrq() { + while(_serial.readable()) { + uartRxQPut(_serial.getc()); + } +} + +void XBee::uartRxQPut(uint8_t data) +{ + // full + if (rxqOut == (rxqIn + 1) % RX_BUF_SIZE) { + return; + } + + rxq[rxqIn] = data; + rxqIn = (rxqIn + 1) % RX_BUF_SIZE; +} + +uint8_t XBee::uartRxQGet() +{ + uint8_t d = 0; + // empty + if (rxqIn == rxqOut) { + return 0; + } + + d = rxq[rxqOut]; + rxqOut = (rxqOut + 1) % RX_BUF_SIZE; + + return d; +} + +bool XBee::uartRxQIsEmpty() +{ + return (rxqIn == rxqOut); +} + +uint32_t XBee::uartReceive(char *buf, uint32_t buflen) +{ + + uint32_t pos = 0; + + while(buflen > 0 && !uartRxQIsEmpty()) { + buf[pos] = uartRxQGet(); + pos++; + buflen--; + } + + return pos; +} + +int32_t XBee::uartReadLine(char* buf, uint32_t bufLen, uint32_t timeout) +{ + uint32_t pos = 0; + uint32_t len = 0; + Timer tim; + + tim.reset(); + tim.start(); + + while(pos < bufLen && tim.read_ms() < (int)timeout) { + + len = uartReceive(&buf[pos], 1); + if (len > 0 && buf[pos] == CR) { + buf[pos] = '\0'; + break; + } + + pos += len; + } + + if (pos >= bufLen) { + return BufTooSmallError; + } + + if (tim.read_ms() > (int)timeout) { + return TimeOutError; + } + + return pos; +} + +void XBee::resetModule() { + // reset pulse must be at least 200 ns. Using 1 ms. + _reset = 0; + wait_ms(1); + _reset = 1; + + // wait to make sure the module has started + wait_ms(500); + rxqIn = 0; + rxqOut = 0; +} + +XBee::XBeeError XBee::commandMode() { + XBeeError err = Ok; + int32_t lineLen = 0; + char ebuf[10]; + + _serial.printf("+++"); + + lineLen = uartReadLine(ebuf, 10, 1200); + + do { + if (lineLen < 0) { + // error while reading + err = ReadError; + break; + } + + if (strcmp(RESP_OK, (char*)ebuf) != 0) { + // didn't receive OK + err = CmdError; + break; + } + } while(0); + + return err; +} + +XBee::XBeeError XBee::atGet(const char* atCmd, char* resp, uint32_t respLen) +{ + + int32_t lineLen = 0; + XBeeError err = Ok; + + _serial.printf("%s%s", atCmd, XBEE_END_CMD); + + do { + + // a response is expected + if (resp != NULL && respLen > 0) { + lineLen = uartReadLine(resp, respLen, 1000); + + if (lineLen < 0) { + // error while reading + err = ReadError; + break; + } + + } + + } while(0); + + return err; +} + +XBee::XBeeError XBee::atSet(const char* atCmd) +{ + char b[10]; + XBeeError err = Ok; + + err = atGet(atCmd, b, 10); + if (err == Ok) { + + if (strcmp(RESP_OK, (char*)b) != 0) { + // didn't receive OK + err = CmdError; + } + } + + return err; +} + +void XBee::processByte(char data) +{ + switch(_rfState) { + case RfStateFrame: + if (data == XBEE_START_DEL) { + _rfPos = 0; + _rfFrameLen = 0; + _rfState = RfStateLength; + + // start timer to make sure an entire frame is received + // within a specific time + _rfFrameTimeout = XBEE_RECV_FRAME_TO; + _rfFrameTimer.reset(); + _rfFrameTimer.start(); + } + + break; + case RfStateLength: + _rfFrameLen |= (data << (8*(1-_rfPos))); + _rfPos++; + if (_rfPos == 2) { + _rfPos = 0; + _rfState = RfStateData; + + if (_rfFrameLen > XBEE_BUF_SZ) { + debug("Xbee: Frame len %d > max buffer len %d\r\n", + (int)_rfFrameLen, (int)XBEE_BUF_SZ); + _rfFrameLen = XBEE_BUF_SZ; + } + + } + break; + case RfStateData: + _rfBuf[_rfPos++] = data; + // read up until checksum (1 byte) + if (_rfPos == _rfFrameLen+1) { + _rfState = RfStateFrame; + + // cancel timer + _rfFrameTimeout = 0; + _rfFrameTimer.stop(); + + processFrame(_rfBuf, _rfPos); + } + break; + + } +} + +void XBee::processFrame(char* buf, uint32_t len) +{ + + uint32_t addrLo = 0; + uint32_t addrHi = 0; + char* b = NULL; + uint32_t bLen = 0; + + if (len < 2) { + debug("Xbee: Invalid frame length (%d)\r\n", (int)len); + return; + } + + // verify checksum + if (checksum(buf, len) != 0) { + debug("Xbee: Invalid checksum\r\n"); + return; + } + + switch(buf[0]) { + case XBEE_API_ID_AT_RESP: + if (len < 5) { + debug("Xbee: AT resp data too small: %d\r\n ", (int)len); + return; + } + + // there is a value + if (len > 6) { + b = &buf[5]; + bLen = len-5-1; + } + + handleAtResponse(buf[1], &buf[2], buf[4], b, bLen); + break; + case XBEE_API_ID_TX_STAT: + handleTxStatus(buf[1], buf[2]); + break; + case XBEE_API_ID_RX_64: + if (len < 12) { + debug("Xbee: RX data too small: %d\r\n ", (int)len); + return; + } + addrHi = bufTo32bitInt(&buf[1]); + addrLo = bufTo32bitInt(&buf[5]); + + processData(addrHi, addrLo, buf[9], buf[10], &buf[11], len-11-1); + break; + case XBEE_API_ID_RX_16: + debug("Xbee: RX 16 bit (unhandled)\r\n"); + break; + case XBEE_API_ID_MOD_STAT: + handleModemStatus(buf[1]); + break; + default: + debug("Xbee: Unhandled API ID: %x\r\n ", buf[0]); + + break; + } + +} + +void XBee::handleAtResponse(uint8_t frameId, char* atBuf, uint8_t status, + char* valueBuf, uint32_t valueLen) +{ + + if (strncmp("ND", (char*)atBuf, 2) == 0) { + handleDiscovery(status, valueBuf, valueLen); + } + +} + +void XBee::handleDiscovery(uint8_t status, char* buf, uint32_t len) +{ + + if (status == 0 && len >= 11) { + _addrHi = bufTo32bitInt(&buf[2]); + _addrLo = bufTo32bitInt(&buf[6]); + _rssi = buf[10]; + + _callbacks[CbNodeFound].call(); + + } +} + +void XBee::handleTxStatus(uint8_t frameId, uint8_t status) +{ + _frameId = frameId; + switch(status) { + case XBEE_TX_STAT_SUCCESS: + _txStatus = TxStatusOk; + break; + case XBEE_TX_STAT_NOACK: + _txStatus = TxStatusNoAck; + break; + case XBEE_TX_STAT_CCA_FAIL: + _txStatus = TxStatusCCA; + break; + case XBEE_TX_STAT_PURGED: + _txStatus = TxStatusPurged; + break; + } + + _callbacks[CbTxStat].call(); + +} + +void XBee::processData(uint32_t addrHi, uint32_t addrLo, uint8_t rssi, + uint8_t opt, char* buf, uint32_t len) +{ + _addrHi = addrHi; + _addrLo = addrLo; + _rssi = rssi; + _recvData = buf; + _recvLen = len; + + _callbacks[CbDataAvailable].call(); +} + +void XBee::handleModemStatus(uint8_t status) { + + if (_type == Coordinator && status == XBEE_MOD_STAT_COORD_START) { + _initialized = true; + _callbacks[CbDeviceUp].call(); + } + else if (_type == EndDevice && status == XBEE_MOD_STAT_ASSOC) { + _initialized = 1; + _callbacks[CbDeviceUp].call(); + } + else if (_type == EndDevice && status == XBEE_MOD_STAT_DIASSOC) { + _initialized = false; + _callbacks[CbDeviceDown].call(); + } + +} + +char XBee::checksum(char* buf, uint32_t len) +{ + int i = 0; + char cs = 0; + + for (i = 0; i < (int)len; i++) { + cs += buf[i]; + } + + return (0xFF - cs); +} + +uint32_t XBee::bufTo32bitInt(const char* buf) +{ + uint32_t v = 0; + + v |= (buf[0] << 24); + v |= (buf[1] << 16); + v |= (buf[2] << 8); + v |= (buf[3]); + + return v; +} + +void XBee::int32bitToBuf(uint32_t v, char* buf) +{ + + buf[0] = ((v >> 24) & 0xff); + buf[1] = ((v >> 16) & 0xff); + buf[2] = ((v >> 8) & 0xff); + buf[3] = ((v >> 0) & 0xff); + +} + + +XBee::XBeeError XBee::apiTx64(uint32_t addrHi, uint32_t addrLo, char* data, + uint32_t len, uint8_t* frameId) +{ + char buf[100]; + + + // limiting to 85 bytes data. Remaining 15 bytes belong to the + // frame + if (len > 85) { + return ArgumentError; + } + + buf[0] = XBEE_START_DEL; + + // length + buf[1] = 0; + buf[2] = 11+len; + + // AP ID + buf[3] = XBEE_API_ID_TX_64; + + // frame ID + buf[4] = getFrameId(); + + + // address + int32bitToBuf(addrHi, &buf[5]); + int32bitToBuf(addrLo, &buf[9]); + + // options + buf[13] = 0; + + // data + memcpy(&buf[14], data, len); + + // checksum + buf[14+len] = checksum(&buf[3], buf[2]); + + if (frameId != NULL) { + *frameId = buf[4]; + } + + + for (int i = 0; i < (15+len); i++) { + _serial.putc(buf[i]); + } + + + return Ok; +} + +XBee::XBeeError XBee::apiAtCmd(const char* atCmd, uint32_t param, bool useParameter) +{ + char buf[12]; + int pos = 0; + + buf[0] = XBEE_START_DEL; + + // length + buf[1] = 0; + buf[2] = 4; + if (useParameter) { + buf[2] += 4; + } + + // AP ID + buf[3] = XBEE_API_ID_AT_CMD; + + // frame ID + buf[4] = getFrameId(); + + // AT cmd + buf[5] = atCmd[0]; + buf[6] = atCmd[1]; + pos = 7; + + // AT parameter + if (useParameter) { + buf[pos++] = ((param >> 24) & 0xff); + buf[pos++] = ((param >> 16) & 0xff); + buf[pos++] = ((param >> 8) & 0xff); + buf[pos++] = ((param >> 0) & 0xff); + } + + // checksum + buf[pos] = checksum(&buf[3], pos-3); + pos++; + + for (int i = 0; i < pos; i++) { + _serial.putc(buf[i]); + } + + return Ok; +} + +uint8_t XBee::getFrameId(void) +{ + _rfFrameId++; + if (_rfFrameId == 0) { + _rfFrameId = 1; + } + + return _rfFrameId; +}
diff -r 000000000000 -r 54828b08e71d XBee.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XBee.h Wed Nov 20 08:26:28 2013 +0000 @@ -0,0 +1,266 @@ + +#ifndef XBEE_H +#define XBEE_H + +#define RX_BUF_SIZE (512) +#define XBEE_BUF_SZ (200) + +#define XBEE_ADDRLO_BROADCAST (0x0000FFFF) +#define XBEE_ADDRHI_BROADCAST (0x00000000) + +/** + * Interface to Digi International's XBee module. The XBee S1 module has + * been used during testing of this interface. + */ +class XBee { +public: + + /** Error codes returned from public methods */ + enum XBeeError { + Ok = 0, + ReadError = -1, + CmdError = -2, + BufTooSmallError = -3, + TimeOutError = -4, + NotInitializedError = -5, + ArgumentError = -6 + + }; + + /** Callback function/method types. See registerCallback() */ + enum CallbackType { + /** Device is up and ready */ + CbDeviceUp = 0, + /** Device is down (disconnected) */ + CbDeviceDown, + /** A node has been found */ + CbNodeFound, + /** Transmit status */ + CbTxStat, + /** Data is available */ + CbDataAvailable, + CbNum // must be last + + }; + + /** Xbee types */ + enum XBeeType { + EndDevice = 0, + Coordinator + }; + + /** Transmit status */ + enum XBeeTxStatus { + TxStatusOk = 0, + TxStatusNoAck, + TxStatusCCA, + TxStatusPurged + }; + + /** + * Create an interface to an XBee module. + * + * @param tx UART TX line + * @param tx UART rx line + * @param reset reset pin + * @param sleep sleep request pin + */ + XBee(PinName tx, PinName rx, PinName reset, PinName sleep); + + /** + * Initialize the XBee module and configure it to be of a + * specific type. + * + * Note: This implementation will always configure the XBee module to + * work in API mode. + * + * @param type the type of this XBee node + * @param panId the PAN ID to use for the XBee network. This argument + * must contain 4 characters representing hexadecimal values + * (e.g. "A1E0" means the hexadecimal value 0xA1E0); + */ + XBeeError init(XBeeType type, const char* panId); + + /** + * Register a callback function + * + * @param fptr Callback function to register + * @param type The type of event that will trigger a call to the function. + */ + void registerCallback(void (*fptr)(void), CallbackType type) { + if (fptr) { + _callbacks[type].attach(fptr); + } + } + + /** + * Register a callback method + * + * @param tptr pointer to the object to call the member function on + * @param mptr pointer to the member function to be called + * @param type The type of event that will trigger a call to the method. + */ + template<typename T> + void registerCallback(T* tptr, void (T::*mptr)(void), CallbackType type) { + if((mptr != NULL) && (tptr != NULL)) { + _callbacks[type].attach(tptr, mptr); + } + } + + /** + * Call this method repeatedly to process incoming data. + */ + void process(); + + /** + * Get address of remote node. This method will only return valid data + * when called in the context of the CbDataAvailable and CbNodeFound + * callbacks + * + * @param addrHi Top 32 bits of address will be written to this argument + * @param addrLo Bottom 32 bits of address will be written to this argument + */ + XBeeError getRemoteAddress(uint32_t* addrHi, uint32_t* addrLo); + + /** + * Get signal strength indicator value (RSSI). This method will only + * return valid data when called in the context of the + * CbDataAvailable and CbNodeFound callbacks + * + * @param rssi RSSI value will be written to this argument + */ + XBeeError getRssi(uint8_t* rssi ); + + /** + * Get the transmit status. This method will only return valid data when + * called in the context of the CbTxStat callback. + * + * @param frameId the frame ID will be written to this argument + * @param status the status will be written to this argument + */ + XBeeError getTxStatus(uint8_t* frameId, XBeeTxStatus* status); + + /** + * Get received data. This method will only return valid data when called + * in the context of the CbDataAvailable callback + * + * @param data will point to a buffer with received data + * @param len will contain the length of the received data + */ + XBeeError getData(char** data, uint8_t* len); + + /** + * Send data to a node with specified address. It is also possible to + * broadcast a message using broadcast address (XBEE_ADDRHI_BROADCAST, + * XBEE_ADDRLO_BROADCAST). + * + * @param addrHi Top 32 bits of address + * @param addrLo Bottom 32 bits of address + * @param data buffer containing data to send + * @param len number of bytes to send + * @param frameId the ID of the frame will be written to this argument. + * The ID can then be used to match this request with the status returned + * in the CbTxStat callback. + */ + XBeeError send(uint32_t addrHi, uint32_t addrLo, char* data, + uint8_t len, uint8_t* frameId); + + /** + * Send a Node Discover request. All modules on the operating channel and + * PAN ID should respond. The responses will be reported in the CbNodeFound + * callback. + */ + XBeeError discoverNodes(); + + /** + * Request the module to enter sleep mode. + */ + XBeeError enterSleep(); + + /** + * Request the module to exit sleep mode. + */ + XBeeError exitSleep(); + + +protected: + + +private: + + enum RfState { + RfStateFrame = 0, + RfStateLength, + RfStateData + }; + + + bool _initialized; + Serial _serial; + XBeeType _type; + DigitalOut _reset; + DigitalOut _sleep; + + uint8_t rxqIn; + uint8_t rxqOut; + uint8_t rxq[RX_BUF_SIZE]; + + uint32_t _rfFrameTimeout; + Timer _rfFrameTimer; + + RfState _rfState; + uint32_t _rfPos; + uint32_t _rfFrameLen; + char _rfBuf[XBEE_BUF_SZ]; + uint8_t _rfFrameId; + + uint32_t _addrHi; + uint32_t _addrLo; + uint8_t _rssi; + uint8_t _frameId; + XBeeTxStatus _txStatus; + char* _recvData; + uint8_t _recvLen; + + + FunctionPointer _callbacks[CbNum]; + + + void uartRxIrq(); + void uartRxQPut(uint8_t data); + uint8_t uartRxQGet(); + bool uartRxQIsEmpty(); + uint32_t uartReceive(char *buf, uint32_t buflen); + int32_t uartReadLine(char* buf, uint32_t bufLen, uint32_t timeout); + + void resetModule(); + XBeeError commandMode(); + XBeeError atGet(const char* atCmd, char* resp, uint32_t respLen); + XBeeError atSet(const char* atCmd); + + void processByte(char data); + void processFrame(char* buf, uint32_t len); + + void handleAtResponse(uint8_t frameId, char* atBuf, uint8_t status, + char* valueBuf, uint32_t valueLen); + + void handleDiscovery(uint8_t status, char* buf, uint32_t len); + void handleTxStatus(uint8_t frameId, uint8_t status); + void processData(uint32_t addrHi, uint32_t addrLo, uint8_t rssi, + uint8_t opt, char* buf, uint32_t len); + void handleModemStatus(uint8_t status); + + char checksum(char* buf, uint32_t len); + uint32_t bufTo32bitInt(const char* buf); + void int32bitToBuf(uint32_t v, char* buf); + + XBeeError apiTx64(uint32_t addrHi, uint32_t addrLo, char* data, + uint32_t len, uint8_t* frameId); + XBeeError apiAtCmd(const char* atCmd, uint32_t param, bool useParameter); + + uint8_t getFrameId(); + + +}; + +#endif
diff -r 000000000000 -r 54828b08e71d main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Nov 20 08:26:28 2013 +0000 @@ -0,0 +1,228 @@ +/****************************************************************************** + * Includes + *****************************************************************************/ +#include "mbed.h" +#include "XBee.h" + +/****************************************************************************** + * Typedefs and defines + *****************************************************************************/ + +// define NODE_IS_COORDINATOR if this board should act +// as XBee coordinator. Make sure it is undefined it the board +// should act as End-Device +#define NODE_IS_COORDINATOR (1) + +#define CMD_BTN_MSG (0) +#define CMD_ACK_MSG (1) + +/****************************************************************************** + * Local variables + *****************************************************************************/ + +static XBee xbee(P0_4, P0_0, P0_17, P0_7); //tx,rx,reset,sleep + +static Serial pc(USBTX, USBRX); // tx, rx + +// all LEDs active low +static DigitalOut xbeeInitLed(D13); +static DigitalOut remoteBtnLed(D12); +static DigitalOut ackLed(D11); +static DigitalOut led4(D10); + +static DigitalIn button(D3); +static bool xbeeIsUp = false; + +/****************************************************************************** + * Local functions + *****************************************************************************/ + +static void xbeeDeviceUp(void) { + xbeeIsUp = true; +} + +static void xbeeDeviceDown(void) { + xbeeIsUp = false; +} + +static void xbeeNodeFound(void) { + uint32_t addrHi = 0; + uint32_t addrLo = 0; + uint8_t rssi = 0; + + xbee.getRemoteAddress(&addrHi, &addrLo); + xbee.getRssi(&rssi); + + pc.printf("XBee: node found: hi=%lx, lo=%lx, rssi=%d\n", + addrHi, addrLo, rssi); +} + +static void xbeeTxStat(void) { + + uint8_t frameId = 0; + XBee::XBeeTxStatus status = XBee::TxStatusOk; + + xbee.getTxStatus(&frameId, &status); + + pc.printf("XBee: Tx Stat. Id=%u, status=%d\n", frameId, (int)status); +} + + + +static void xbeeDataAvailable(void) { + char* data = NULL; + char ackMsg = CMD_ACK_MSG; + uint8_t frameId = 0; + uint8_t len = 0; + uint32_t addrHi = 0; + uint32_t addrLo = 0; + uint8_t rssi = 0; + + xbee.getRemoteAddress(&addrHi, &addrLo); + xbee.getData(&data, &len); + xbee.getRssi(&rssi); + + pc.printf("XBee: Data available: len=%d hi=%lx, lo=%lx, rssi=%d\n", + (int)len, addrHi, addrLo, rssi); + + if (len > 0) { + + switch(data[0]) { + case CMD_BTN_MSG: + if (len > 1) { + // change led to indicate button state + remoteBtnLed = ((data[1] == 1) ? 1 : 0); + + + // Send an ACK directly to the remote node (only for + // buttons state == 0) + if (data[1] == 0) { + xbee.send(addrHi, addrLo, &ackMsg, 1, &frameId); + } + } + break; + case CMD_ACK_MSG: + for (int i = 0; i < 3; i++) { + ackLed = 0; + wait_ms(100); + ackLed = 1; + wait_ms(100); + } + break; + } + + } + +} + +static bool xbeeInit() +{ + xbee.registerCallback(xbeeDeviceUp, XBee::CbDeviceUp); + xbee.registerCallback(xbeeDeviceDown, XBee::CbDeviceDown); + xbee.registerCallback(xbeeNodeFound, XBee::CbNodeFound); + xbee.registerCallback(xbeeTxStat, XBee::CbTxStat); + xbee.registerCallback(xbeeDataAvailable, XBee::CbDataAvailable); + +#ifdef NODE_IS_COORDINATOR + XBee::XBeeError err = xbee.init(XBee::Coordinator, "EAEA"); +#else + XBee::XBeeError err = xbee.init(XBee::EndDevice, "EAEA"); +#endif + if (err != XBee::Ok) { + return false; + } + + return true; + +} + +static void reportInitFailed() { + while (true) { + xbeeInitLed = !xbeeInitLed; + wait_ms(200); + } +} + +static void ledInit() { + xbeeInitLed = 0; // turn on + remoteBtnLed = 1; // turn off + ackLed = 1; // turn off + led4 = 1; // turn off +} + + +/****************************************************************************** + * Main function + *****************************************************************************/ + +int main() { + + /* + * For this example to work at least two boards with XBee nodes must + * be available; one which is configured as Coordinator and another + * which is configured as End-Device. + * + * LED1 shows the state of XBee initialization. This LED is turned + * on when initialization starts and turned off when initialization + * is ready and the device us up. If initialization fails LED1 + * will blink. + * + * When the Push-button on the LPC4088 QuickStart Board is pushed + * a message will be broadcasted. The board(s) that receives the message + * will show the state of the remote board's button by turning LED2 + * on or off. + * + * The board that receives the button state message will send back + * an ACK message (only for button down). The board that receives + * the ACK message will blink with LED3. This can be used to verify + * that a board that is not close to you actually received a message + * without having to look at that board's LED2. + */ + + int buttonState = 1; + char data[2]; + uint8_t frameId = 0; + + // pull-up must be enabled for button + button.mode(PullUp); + + ledInit(); + + pc.printf("Initializing\n"); + if (!xbeeInit()) { + reportInitFailed(); + } + + // Wait until XBee node is reported to be up. + // - For End-device this means that the node is associated with a + // coordinator + // - For a coordinator this means that the node is initialized and ready + pc.printf("Wait until up\n"); + while(!xbeeIsUp) { + xbee.process(); + } + + // turn off led to indicate initialization is okay and node is up + xbeeInitLed = 1; + + pc.printf("Node is Up\n"); + while (1) { + + if (button != buttonState) { + buttonState = button; + + data[0] = CMD_BTN_MSG; + data[1] = buttonState; + + // Send the button state. In this example we are broadcasting the + // message to all nodes on the same network (PAN ID). In reality + // direct messaging is preferred. + xbee.send(XBEE_ADDRHI_BROADCAST, XBEE_ADDRLO_BROADCAST, + data, 2, &frameId); + } + + + xbee.process(); + + } +}
diff -r 000000000000 -r 54828b08e71d mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Nov 20 08:26:28 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/a9913a65894f \ No newline at end of file