A library with drivers for different peripherals on the LPC4088 QuickStart Board or related add-on boards.
Dependencies: FATFileSystem
Fork of EALib by
XBee.cpp@10:f2409dc07e49, 2014-01-10 (annotated)
- Committer:
- embeddedartists
- Date:
- Fri Jan 10 08:24:42 2014 +0000
- Revision:
- 10:f2409dc07e49
- Parent:
- 7:e431d9d47db6
- Child:
- 12:15597e45eea0
Fixed example in QSPIFileSystem documentation
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
embeddedartists | 7:e431d9d47db6 | 1 | |
embeddedartists | 7:e431d9d47db6 | 2 | #include "mbed.h" |
embeddedartists | 7:e431d9d47db6 | 3 | #include "mbed_debug.h" |
embeddedartists | 7:e431d9d47db6 | 4 | #include "XBee.h" |
embeddedartists | 7:e431d9d47db6 | 5 | |
embeddedartists | 7:e431d9d47db6 | 6 | #define XBEE_END_CMD ("\r") |
embeddedartists | 7:e431d9d47db6 | 7 | #define CR (0x0D) |
embeddedartists | 7:e431d9d47db6 | 8 | #define RESP_OK ("OK") |
embeddedartists | 7:e431d9d47db6 | 9 | |
embeddedartists | 7:e431d9d47db6 | 10 | #define XBEE_START_DEL (0x7E) |
embeddedartists | 7:e431d9d47db6 | 11 | |
embeddedartists | 7:e431d9d47db6 | 12 | #define XBEE_API_ID_TX_64 (0x00) |
embeddedartists | 7:e431d9d47db6 | 13 | #define XBEE_API_ID_AT_CMD (0x08) |
embeddedartists | 7:e431d9d47db6 | 14 | #define XBEE_API_ID_AT_RESP (0x88) |
embeddedartists | 7:e431d9d47db6 | 15 | #define XBEE_API_ID_TX_STAT (0x89) |
embeddedartists | 7:e431d9d47db6 | 16 | #define XBEE_API_ID_RX_64 (0x80) |
embeddedartists | 7:e431d9d47db6 | 17 | #define XBEE_API_ID_RX_16 (0x81) |
embeddedartists | 7:e431d9d47db6 | 18 | #define XBEE_API_ID_MOD_STAT (0x8A) |
embeddedartists | 7:e431d9d47db6 | 19 | |
embeddedartists | 7:e431d9d47db6 | 20 | #define XBEE_MOD_STAT_HW_RESET (0) |
embeddedartists | 7:e431d9d47db6 | 21 | #define XBEE_MOD_STAT_WD_RESET (1) |
embeddedartists | 7:e431d9d47db6 | 22 | #define XBEE_MOD_STAT_ASSOC (2) |
embeddedartists | 7:e431d9d47db6 | 23 | #define XBEE_MOD_STAT_DIASSOC (3) |
embeddedartists | 7:e431d9d47db6 | 24 | #define XBEE_MOD_STAT_SYNC_LOST (4) |
embeddedartists | 7:e431d9d47db6 | 25 | #define XBEE_MOD_STAT_COORD_REALG (5) |
embeddedartists | 7:e431d9d47db6 | 26 | #define XBEE_MOD_STAT_COORD_START (6) |
embeddedartists | 7:e431d9d47db6 | 27 | |
embeddedartists | 7:e431d9d47db6 | 28 | #define XBEE_TX_STAT_SUCCESS (0) |
embeddedartists | 7:e431d9d47db6 | 29 | #define XBEE_TX_STAT_NOACK (1) |
embeddedartists | 7:e431d9d47db6 | 30 | #define XBEE_TX_STAT_CCA_FAIL (2) |
embeddedartists | 7:e431d9d47db6 | 31 | #define XBEE_TX_STAT_PURGED (3) |
embeddedartists | 7:e431d9d47db6 | 32 | |
embeddedartists | 7:e431d9d47db6 | 33 | #define XBEE_RECV_FRAME_TO (2000) |
embeddedartists | 7:e431d9d47db6 | 34 | |
embeddedartists | 7:e431d9d47db6 | 35 | XBee::XBee(PinName tx, PinName rx, PinName reset, PinName sleep) : |
embeddedartists | 7:e431d9d47db6 | 36 | _serial(tx, rx), _reset(reset), _sleep(sleep) { |
embeddedartists | 7:e431d9d47db6 | 37 | _serial.baud(9600); |
embeddedartists | 7:e431d9d47db6 | 38 | _serial.format(8, Serial::None, 1); |
embeddedartists | 7:e431d9d47db6 | 39 | |
embeddedartists | 7:e431d9d47db6 | 40 | _serial.attach(this, &XBee::uartRxIrq, Serial::RxIrq); |
embeddedartists | 7:e431d9d47db6 | 41 | |
embeddedartists | 7:e431d9d47db6 | 42 | rxqIn = 0; |
embeddedartists | 7:e431d9d47db6 | 43 | rxqOut = 0; |
embeddedartists | 7:e431d9d47db6 | 44 | _rfFrameTimeout = 0; |
embeddedartists | 7:e431d9d47db6 | 45 | _rfFrameTimer.reset(); |
embeddedartists | 7:e431d9d47db6 | 46 | |
embeddedartists | 7:e431d9d47db6 | 47 | _rfState = RfStateFrame; |
embeddedartists | 7:e431d9d47db6 | 48 | _rfPos = 0; |
embeddedartists | 7:e431d9d47db6 | 49 | _rfFrameLen = 0; |
embeddedartists | 7:e431d9d47db6 | 50 | _rfFrameId = 0; |
embeddedartists | 7:e431d9d47db6 | 51 | |
embeddedartists | 7:e431d9d47db6 | 52 | _initialized = false; |
embeddedartists | 7:e431d9d47db6 | 53 | _type = Coordinator; |
embeddedartists | 7:e431d9d47db6 | 54 | |
embeddedartists | 7:e431d9d47db6 | 55 | _addrHi = 0; |
embeddedartists | 7:e431d9d47db6 | 56 | _addrLo = 0; |
embeddedartists | 7:e431d9d47db6 | 57 | _rssi = 0; |
embeddedartists | 7:e431d9d47db6 | 58 | _frameId = 0; |
embeddedartists | 7:e431d9d47db6 | 59 | _txStatus = TxStatusOk; |
embeddedartists | 7:e431d9d47db6 | 60 | _recvData = NULL; |
embeddedartists | 7:e431d9d47db6 | 61 | _recvLen = 0; |
embeddedartists | 7:e431d9d47db6 | 62 | |
embeddedartists | 7:e431d9d47db6 | 63 | // we enter sleep when sleep pin is high |
embeddedartists | 7:e431d9d47db6 | 64 | _sleep = 0; |
embeddedartists | 7:e431d9d47db6 | 65 | } |
embeddedartists | 7:e431d9d47db6 | 66 | |
embeddedartists | 7:e431d9d47db6 | 67 | XBee::XBeeError XBee::init(XBeeType type, const char* panId) { |
embeddedartists | 7:e431d9d47db6 | 68 | XBeeError err = Ok; |
embeddedartists | 7:e431d9d47db6 | 69 | char idBuf[10]; |
embeddedartists | 7:e431d9d47db6 | 70 | |
embeddedartists | 7:e431d9d47db6 | 71 | resetModule(); |
embeddedartists | 7:e431d9d47db6 | 72 | |
embeddedartists | 7:e431d9d47db6 | 73 | _type = type; |
embeddedartists | 7:e431d9d47db6 | 74 | |
embeddedartists | 7:e431d9d47db6 | 75 | do { |
embeddedartists | 7:e431d9d47db6 | 76 | |
embeddedartists | 7:e431d9d47db6 | 77 | if (panId == NULL || strlen(panId) != 4) { |
embeddedartists | 7:e431d9d47db6 | 78 | err = ArgumentError; |
embeddedartists | 7:e431d9d47db6 | 79 | break; |
embeddedartists | 7:e431d9d47db6 | 80 | } |
embeddedartists | 7:e431d9d47db6 | 81 | |
embeddedartists | 7:e431d9d47db6 | 82 | err = commandMode(); |
embeddedartists | 7:e431d9d47db6 | 83 | if (err != Ok) { |
embeddedartists | 7:e431d9d47db6 | 84 | debug("XBee: +++ failed\n"); |
embeddedartists | 7:e431d9d47db6 | 85 | break; |
embeddedartists | 7:e431d9d47db6 | 86 | } |
embeddedartists | 7:e431d9d47db6 | 87 | |
embeddedartists | 7:e431d9d47db6 | 88 | // set the sleep mode to Hibernate |
embeddedartists | 7:e431d9d47db6 | 89 | err = atSet("ATSM1"); |
embeddedartists | 7:e431d9d47db6 | 90 | if (err != Ok) { |
embeddedartists | 7:e431d9d47db6 | 91 | debug("Xbee: ATSM1 failed\r\n"); |
embeddedartists | 7:e431d9d47db6 | 92 | break; |
embeddedartists | 7:e431d9d47db6 | 93 | } |
embeddedartists | 7:e431d9d47db6 | 94 | |
embeddedartists | 7:e431d9d47db6 | 95 | // change PAN ID to EAEA |
embeddedartists | 7:e431d9d47db6 | 96 | sprintf(idBuf, "ATID%s", panId); |
embeddedartists | 7:e431d9d47db6 | 97 | err = atSet(idBuf); |
embeddedartists | 7:e431d9d47db6 | 98 | if (err != Ok) { |
embeddedartists | 7:e431d9d47db6 | 99 | debug("Xbee: ATID failed\r\n"); |
embeddedartists | 7:e431d9d47db6 | 100 | break; |
embeddedartists | 7:e431d9d47db6 | 101 | } |
embeddedartists | 7:e431d9d47db6 | 102 | |
embeddedartists | 7:e431d9d47db6 | 103 | // use 64-bit addressing |
embeddedartists | 7:e431d9d47db6 | 104 | err = atSet("ATMYFFFE"); |
embeddedartists | 7:e431d9d47db6 | 105 | if (err != Ok) { |
embeddedartists | 7:e431d9d47db6 | 106 | debug("Xbee: ATMYFFFE failed\r\n"); |
embeddedartists | 7:e431d9d47db6 | 107 | break; |
embeddedartists | 7:e431d9d47db6 | 108 | } |
embeddedartists | 7:e431d9d47db6 | 109 | |
embeddedartists | 7:e431d9d47db6 | 110 | // Coordinator |
embeddedartists | 7:e431d9d47db6 | 111 | if (type == Coordinator) { |
embeddedartists | 7:e431d9d47db6 | 112 | |
embeddedartists | 7:e431d9d47db6 | 113 | // - will not perform Active Scan to locate PAN ID |
embeddedartists | 7:e431d9d47db6 | 114 | // - will not perform Energy Scan to determine free channel |
embeddedartists | 7:e431d9d47db6 | 115 | // - allow End devices to associate with this coordinator |
embeddedartists | 7:e431d9d47db6 | 116 | err = atSet("ATA24"); |
embeddedartists | 7:e431d9d47db6 | 117 | if (err != Ok) { |
embeddedartists | 7:e431d9d47db6 | 118 | debug("Xbee: ATA24 failed\r\n"); |
embeddedartists | 7:e431d9d47db6 | 119 | break; |
embeddedartists | 7:e431d9d47db6 | 120 | } |
embeddedartists | 7:e431d9d47db6 | 121 | |
embeddedartists | 7:e431d9d47db6 | 122 | // set this node as coordinator |
embeddedartists | 7:e431d9d47db6 | 123 | err = atSet("ATCE1"); |
embeddedartists | 7:e431d9d47db6 | 124 | if (err != Ok) { |
embeddedartists | 7:e431d9d47db6 | 125 | debug("Xbee: ATCE1 failed\r\n"); |
embeddedartists | 7:e431d9d47db6 | 126 | break; |
embeddedartists | 7:e431d9d47db6 | 127 | } |
embeddedartists | 7:e431d9d47db6 | 128 | } |
embeddedartists | 7:e431d9d47db6 | 129 | else { |
embeddedartists | 7:e431d9d47db6 | 130 | // - only associates with Coordinator on matching PAN ID |
embeddedartists | 7:e431d9d47db6 | 131 | // - only associates with Coordinator on matching channel |
embeddedartists | 7:e431d9d47db6 | 132 | // - device attempts association until success |
embeddedartists | 7:e431d9d47db6 | 133 | err = atSet("ATA14"); |
embeddedartists | 7:e431d9d47db6 | 134 | if (err != Ok) { |
embeddedartists | 7:e431d9d47db6 | 135 | debug("Xbee: ATA14 failed\r\n"); |
embeddedartists | 7:e431d9d47db6 | 136 | break; |
embeddedartists | 7:e431d9d47db6 | 137 | } |
embeddedartists | 7:e431d9d47db6 | 138 | } |
embeddedartists | 7:e431d9d47db6 | 139 | |
embeddedartists | 7:e431d9d47db6 | 140 | |
embeddedartists | 7:e431d9d47db6 | 141 | // change to API mode |
embeddedartists | 7:e431d9d47db6 | 142 | err = atSet("ATAP1"); |
embeddedartists | 7:e431d9d47db6 | 143 | if (err != Ok) { |
embeddedartists | 7:e431d9d47db6 | 144 | debug("Xbee: ATAP1 failed\r\n"); |
embeddedartists | 7:e431d9d47db6 | 145 | break; |
embeddedartists | 7:e431d9d47db6 | 146 | } |
embeddedartists | 7:e431d9d47db6 | 147 | |
embeddedartists | 7:e431d9d47db6 | 148 | } while(0); |
embeddedartists | 7:e431d9d47db6 | 149 | |
embeddedartists | 7:e431d9d47db6 | 150 | |
embeddedartists | 7:e431d9d47db6 | 151 | return err; |
embeddedartists | 7:e431d9d47db6 | 152 | } |
embeddedartists | 7:e431d9d47db6 | 153 | |
embeddedartists | 7:e431d9d47db6 | 154 | void XBee::process() { |
embeddedartists | 7:e431d9d47db6 | 155 | uint32_t len = 0; |
embeddedartists | 7:e431d9d47db6 | 156 | char data = 0; |
embeddedartists | 7:e431d9d47db6 | 157 | |
embeddedartists | 7:e431d9d47db6 | 158 | if (_rfFrameTimeout > 0 && (int)_rfFrameTimeout < _rfFrameTimer.read_ms()) { |
embeddedartists | 7:e431d9d47db6 | 159 | _rfState = RfStateFrame; |
embeddedartists | 7:e431d9d47db6 | 160 | debug("Xbee: Frame timer expired\r\n"); |
embeddedartists | 7:e431d9d47db6 | 161 | _rfFrameTimeout = 0; |
embeddedartists | 7:e431d9d47db6 | 162 | _rfFrameTimer.stop(); |
embeddedartists | 7:e431d9d47db6 | 163 | } |
embeddedartists | 7:e431d9d47db6 | 164 | |
embeddedartists | 7:e431d9d47db6 | 165 | if (!uartRxQIsEmpty()) { |
embeddedartists | 7:e431d9d47db6 | 166 | |
embeddedartists | 7:e431d9d47db6 | 167 | len = uartReceive(&data, 1); |
embeddedartists | 7:e431d9d47db6 | 168 | if (len > 0) { |
embeddedartists | 7:e431d9d47db6 | 169 | processByte(data); |
embeddedartists | 7:e431d9d47db6 | 170 | } |
embeddedartists | 7:e431d9d47db6 | 171 | |
embeddedartists | 7:e431d9d47db6 | 172 | } |
embeddedartists | 7:e431d9d47db6 | 173 | } |
embeddedartists | 7:e431d9d47db6 | 174 | |
embeddedartists | 7:e431d9d47db6 | 175 | XBee::XBeeError XBee::getRemoteAddress(uint32_t* addrHi, uint32_t* addrLo) { |
embeddedartists | 7:e431d9d47db6 | 176 | if (!_initialized) { |
embeddedartists | 7:e431d9d47db6 | 177 | return NotInitializedError; |
embeddedartists | 7:e431d9d47db6 | 178 | } |
embeddedartists | 7:e431d9d47db6 | 179 | |
embeddedartists | 7:e431d9d47db6 | 180 | if (addrHi == NULL || addrLo == NULL) { |
embeddedartists | 7:e431d9d47db6 | 181 | return ArgumentError; |
embeddedartists | 7:e431d9d47db6 | 182 | } |
embeddedartists | 7:e431d9d47db6 | 183 | |
embeddedartists | 7:e431d9d47db6 | 184 | *addrHi = _addrHi; |
embeddedartists | 7:e431d9d47db6 | 185 | *addrLo = _addrLo; |
embeddedartists | 7:e431d9d47db6 | 186 | |
embeddedartists | 7:e431d9d47db6 | 187 | return Ok; |
embeddedartists | 7:e431d9d47db6 | 188 | } |
embeddedartists | 7:e431d9d47db6 | 189 | |
embeddedartists | 7:e431d9d47db6 | 190 | XBee::XBeeError XBee::getRssi(uint8_t* rssi ) { |
embeddedartists | 7:e431d9d47db6 | 191 | if (!_initialized) { |
embeddedartists | 7:e431d9d47db6 | 192 | return NotInitializedError; |
embeddedartists | 7:e431d9d47db6 | 193 | } |
embeddedartists | 7:e431d9d47db6 | 194 | |
embeddedartists | 7:e431d9d47db6 | 195 | if (rssi == NULL) { |
embeddedartists | 7:e431d9d47db6 | 196 | return ArgumentError; |
embeddedartists | 7:e431d9d47db6 | 197 | } |
embeddedartists | 7:e431d9d47db6 | 198 | |
embeddedartists | 7:e431d9d47db6 | 199 | *rssi = _rssi; |
embeddedartists | 7:e431d9d47db6 | 200 | |
embeddedartists | 7:e431d9d47db6 | 201 | return Ok; |
embeddedartists | 7:e431d9d47db6 | 202 | } |
embeddedartists | 7:e431d9d47db6 | 203 | |
embeddedartists | 7:e431d9d47db6 | 204 | XBee::XBeeError XBee::getTxStatus(uint8_t* frameId, XBeeTxStatus* status) { |
embeddedartists | 7:e431d9d47db6 | 205 | if (!_initialized) { |
embeddedartists | 7:e431d9d47db6 | 206 | return NotInitializedError; |
embeddedartists | 7:e431d9d47db6 | 207 | } |
embeddedartists | 7:e431d9d47db6 | 208 | |
embeddedartists | 7:e431d9d47db6 | 209 | if (frameId == NULL || status == NULL) { |
embeddedartists | 7:e431d9d47db6 | 210 | return ArgumentError; |
embeddedartists | 7:e431d9d47db6 | 211 | } |
embeddedartists | 7:e431d9d47db6 | 212 | |
embeddedartists | 7:e431d9d47db6 | 213 | *frameId = _frameId; |
embeddedartists | 7:e431d9d47db6 | 214 | *status = _txStatus; |
embeddedartists | 7:e431d9d47db6 | 215 | |
embeddedartists | 7:e431d9d47db6 | 216 | return Ok; |
embeddedartists | 7:e431d9d47db6 | 217 | } |
embeddedartists | 7:e431d9d47db6 | 218 | |
embeddedartists | 7:e431d9d47db6 | 219 | XBee::XBeeError XBee::getData(char** data, uint8_t* len) { |
embeddedartists | 7:e431d9d47db6 | 220 | if (!_initialized) { |
embeddedartists | 7:e431d9d47db6 | 221 | return NotInitializedError; |
embeddedartists | 7:e431d9d47db6 | 222 | } |
embeddedartists | 7:e431d9d47db6 | 223 | |
embeddedartists | 7:e431d9d47db6 | 224 | if (data == NULL || len == NULL) { |
embeddedartists | 7:e431d9d47db6 | 225 | return ArgumentError; |
embeddedartists | 7:e431d9d47db6 | 226 | } |
embeddedartists | 7:e431d9d47db6 | 227 | |
embeddedartists | 7:e431d9d47db6 | 228 | *data = _recvData; |
embeddedartists | 7:e431d9d47db6 | 229 | *len = _recvLen; |
embeddedartists | 7:e431d9d47db6 | 230 | |
embeddedartists | 7:e431d9d47db6 | 231 | return Ok; |
embeddedartists | 7:e431d9d47db6 | 232 | } |
embeddedartists | 7:e431d9d47db6 | 233 | |
embeddedartists | 7:e431d9d47db6 | 234 | XBee::XBeeError XBee::send(uint32_t addrHi, uint32_t addrLo, char* data, |
embeddedartists | 7:e431d9d47db6 | 235 | uint8_t len, uint8_t* frameId) |
embeddedartists | 7:e431d9d47db6 | 236 | { |
embeddedartists | 7:e431d9d47db6 | 237 | if (!_initialized) { |
embeddedartists | 7:e431d9d47db6 | 238 | return NotInitializedError; |
embeddedartists | 7:e431d9d47db6 | 239 | } |
embeddedartists | 7:e431d9d47db6 | 240 | |
embeddedartists | 7:e431d9d47db6 | 241 | return apiTx64(addrHi, addrLo, data, len, frameId); |
embeddedartists | 7:e431d9d47db6 | 242 | } |
embeddedartists | 7:e431d9d47db6 | 243 | |
embeddedartists | 7:e431d9d47db6 | 244 | XBee::XBeeError XBee::discoverNodes() { |
embeddedartists | 7:e431d9d47db6 | 245 | if (!_initialized) { |
embeddedartists | 7:e431d9d47db6 | 246 | return NotInitializedError; |
embeddedartists | 7:e431d9d47db6 | 247 | } |
embeddedartists | 7:e431d9d47db6 | 248 | |
embeddedartists | 7:e431d9d47db6 | 249 | return apiAtCmd("ND", 0, false); |
embeddedartists | 7:e431d9d47db6 | 250 | } |
embeddedartists | 7:e431d9d47db6 | 251 | |
embeddedartists | 7:e431d9d47db6 | 252 | |
embeddedartists | 7:e431d9d47db6 | 253 | XBee::XBeeError XBee::enterSleep() { |
embeddedartists | 7:e431d9d47db6 | 254 | _sleep = 1; |
embeddedartists | 7:e431d9d47db6 | 255 | |
embeddedartists | 7:e431d9d47db6 | 256 | return Ok; |
embeddedartists | 7:e431d9d47db6 | 257 | } |
embeddedartists | 7:e431d9d47db6 | 258 | |
embeddedartists | 7:e431d9d47db6 | 259 | XBee::XBeeError XBee::exitSleep() { |
embeddedartists | 7:e431d9d47db6 | 260 | _sleep = 0; |
embeddedartists | 7:e431d9d47db6 | 261 | |
embeddedartists | 7:e431d9d47db6 | 262 | return Ok; |
embeddedartists | 7:e431d9d47db6 | 263 | } |
embeddedartists | 7:e431d9d47db6 | 264 | |
embeddedartists | 7:e431d9d47db6 | 265 | |
embeddedartists | 7:e431d9d47db6 | 266 | void XBee::uartRxIrq() { |
embeddedartists | 7:e431d9d47db6 | 267 | while(_serial.readable()) { |
embeddedartists | 7:e431d9d47db6 | 268 | uartRxQPut(_serial.getc()); |
embeddedartists | 7:e431d9d47db6 | 269 | } |
embeddedartists | 7:e431d9d47db6 | 270 | } |
embeddedartists | 7:e431d9d47db6 | 271 | |
embeddedartists | 7:e431d9d47db6 | 272 | void XBee::uartRxQPut(uint8_t data) |
embeddedartists | 7:e431d9d47db6 | 273 | { |
embeddedartists | 7:e431d9d47db6 | 274 | // full |
embeddedartists | 7:e431d9d47db6 | 275 | if (rxqOut == (rxqIn + 1) % RX_BUF_SIZE) { |
embeddedartists | 7:e431d9d47db6 | 276 | return; |
embeddedartists | 7:e431d9d47db6 | 277 | } |
embeddedartists | 7:e431d9d47db6 | 278 | |
embeddedartists | 7:e431d9d47db6 | 279 | rxq[rxqIn] = data; |
embeddedartists | 7:e431d9d47db6 | 280 | rxqIn = (rxqIn + 1) % RX_BUF_SIZE; |
embeddedartists | 7:e431d9d47db6 | 281 | } |
embeddedartists | 7:e431d9d47db6 | 282 | |
embeddedartists | 7:e431d9d47db6 | 283 | uint8_t XBee::uartRxQGet() |
embeddedartists | 7:e431d9d47db6 | 284 | { |
embeddedartists | 7:e431d9d47db6 | 285 | uint8_t d = 0; |
embeddedartists | 7:e431d9d47db6 | 286 | // empty |
embeddedartists | 7:e431d9d47db6 | 287 | if (rxqIn == rxqOut) { |
embeddedartists | 7:e431d9d47db6 | 288 | return 0; |
embeddedartists | 7:e431d9d47db6 | 289 | } |
embeddedartists | 7:e431d9d47db6 | 290 | |
embeddedartists | 7:e431d9d47db6 | 291 | d = rxq[rxqOut]; |
embeddedartists | 7:e431d9d47db6 | 292 | rxqOut = (rxqOut + 1) % RX_BUF_SIZE; |
embeddedartists | 7:e431d9d47db6 | 293 | |
embeddedartists | 7:e431d9d47db6 | 294 | return d; |
embeddedartists | 7:e431d9d47db6 | 295 | } |
embeddedartists | 7:e431d9d47db6 | 296 | |
embeddedartists | 7:e431d9d47db6 | 297 | bool XBee::uartRxQIsEmpty() |
embeddedartists | 7:e431d9d47db6 | 298 | { |
embeddedartists | 7:e431d9d47db6 | 299 | return (rxqIn == rxqOut); |
embeddedartists | 7:e431d9d47db6 | 300 | } |
embeddedartists | 7:e431d9d47db6 | 301 | |
embeddedartists | 7:e431d9d47db6 | 302 | uint32_t XBee::uartReceive(char *buf, uint32_t buflen) |
embeddedartists | 7:e431d9d47db6 | 303 | { |
embeddedartists | 7:e431d9d47db6 | 304 | |
embeddedartists | 7:e431d9d47db6 | 305 | uint32_t pos = 0; |
embeddedartists | 7:e431d9d47db6 | 306 | |
embeddedartists | 7:e431d9d47db6 | 307 | while(buflen > 0 && !uartRxQIsEmpty()) { |
embeddedartists | 7:e431d9d47db6 | 308 | buf[pos] = uartRxQGet(); |
embeddedartists | 7:e431d9d47db6 | 309 | pos++; |
embeddedartists | 7:e431d9d47db6 | 310 | buflen--; |
embeddedartists | 7:e431d9d47db6 | 311 | } |
embeddedartists | 7:e431d9d47db6 | 312 | |
embeddedartists | 7:e431d9d47db6 | 313 | return pos; |
embeddedartists | 7:e431d9d47db6 | 314 | } |
embeddedartists | 7:e431d9d47db6 | 315 | |
embeddedartists | 7:e431d9d47db6 | 316 | int32_t XBee::uartReadLine(char* buf, uint32_t bufLen, uint32_t timeout) |
embeddedartists | 7:e431d9d47db6 | 317 | { |
embeddedartists | 7:e431d9d47db6 | 318 | uint32_t pos = 0; |
embeddedartists | 7:e431d9d47db6 | 319 | uint32_t len = 0; |
embeddedartists | 7:e431d9d47db6 | 320 | Timer tim; |
embeddedartists | 7:e431d9d47db6 | 321 | |
embeddedartists | 7:e431d9d47db6 | 322 | tim.reset(); |
embeddedartists | 7:e431d9d47db6 | 323 | tim.start(); |
embeddedartists | 7:e431d9d47db6 | 324 | |
embeddedartists | 7:e431d9d47db6 | 325 | while(pos < bufLen && tim.read_ms() < (int)timeout) { |
embeddedartists | 7:e431d9d47db6 | 326 | |
embeddedartists | 7:e431d9d47db6 | 327 | len = uartReceive(&buf[pos], 1); |
embeddedartists | 7:e431d9d47db6 | 328 | if (len > 0 && buf[pos] == CR) { |
embeddedartists | 7:e431d9d47db6 | 329 | buf[pos] = '\0'; |
embeddedartists | 7:e431d9d47db6 | 330 | break; |
embeddedartists | 7:e431d9d47db6 | 331 | } |
embeddedartists | 7:e431d9d47db6 | 332 | |
embeddedartists | 7:e431d9d47db6 | 333 | pos += len; |
embeddedartists | 7:e431d9d47db6 | 334 | } |
embeddedartists | 7:e431d9d47db6 | 335 | |
embeddedartists | 7:e431d9d47db6 | 336 | if (pos >= bufLen) { |
embeddedartists | 7:e431d9d47db6 | 337 | return BufTooSmallError; |
embeddedartists | 7:e431d9d47db6 | 338 | } |
embeddedartists | 7:e431d9d47db6 | 339 | |
embeddedartists | 7:e431d9d47db6 | 340 | if (tim.read_ms() > (int)timeout) { |
embeddedartists | 7:e431d9d47db6 | 341 | return TimeOutError; |
embeddedartists | 7:e431d9d47db6 | 342 | } |
embeddedartists | 7:e431d9d47db6 | 343 | |
embeddedartists | 7:e431d9d47db6 | 344 | return pos; |
embeddedartists | 7:e431d9d47db6 | 345 | } |
embeddedartists | 7:e431d9d47db6 | 346 | |
embeddedartists | 7:e431d9d47db6 | 347 | void XBee::resetModule() { |
embeddedartists | 7:e431d9d47db6 | 348 | // reset pulse must be at least 200 ns. Using 1 ms. |
embeddedartists | 7:e431d9d47db6 | 349 | _reset = 0; |
embeddedartists | 7:e431d9d47db6 | 350 | wait_ms(1); |
embeddedartists | 7:e431d9d47db6 | 351 | _reset = 1; |
embeddedartists | 7:e431d9d47db6 | 352 | |
embeddedartists | 7:e431d9d47db6 | 353 | // wait to make sure the module has started |
embeddedartists | 7:e431d9d47db6 | 354 | wait_ms(500); |
embeddedartists | 7:e431d9d47db6 | 355 | rxqIn = 0; |
embeddedartists | 7:e431d9d47db6 | 356 | rxqOut = 0; |
embeddedartists | 7:e431d9d47db6 | 357 | } |
embeddedartists | 7:e431d9d47db6 | 358 | |
embeddedartists | 7:e431d9d47db6 | 359 | XBee::XBeeError XBee::commandMode() { |
embeddedartists | 7:e431d9d47db6 | 360 | XBeeError err = Ok; |
embeddedartists | 7:e431d9d47db6 | 361 | int32_t lineLen = 0; |
embeddedartists | 7:e431d9d47db6 | 362 | char ebuf[10]; |
embeddedartists | 7:e431d9d47db6 | 363 | |
embeddedartists | 7:e431d9d47db6 | 364 | _serial.printf("+++"); |
embeddedartists | 7:e431d9d47db6 | 365 | |
embeddedartists | 7:e431d9d47db6 | 366 | lineLen = uartReadLine(ebuf, 10, 1200); |
embeddedartists | 7:e431d9d47db6 | 367 | |
embeddedartists | 7:e431d9d47db6 | 368 | do { |
embeddedartists | 7:e431d9d47db6 | 369 | if (lineLen < 0) { |
embeddedartists | 7:e431d9d47db6 | 370 | // error while reading |
embeddedartists | 7:e431d9d47db6 | 371 | err = ReadError; |
embeddedartists | 7:e431d9d47db6 | 372 | break; |
embeddedartists | 7:e431d9d47db6 | 373 | } |
embeddedartists | 7:e431d9d47db6 | 374 | |
embeddedartists | 7:e431d9d47db6 | 375 | if (strcmp(RESP_OK, (char*)ebuf) != 0) { |
embeddedartists | 7:e431d9d47db6 | 376 | // didn't receive OK |
embeddedartists | 7:e431d9d47db6 | 377 | err = CmdError; |
embeddedartists | 7:e431d9d47db6 | 378 | break; |
embeddedartists | 7:e431d9d47db6 | 379 | } |
embeddedartists | 7:e431d9d47db6 | 380 | } while(0); |
embeddedartists | 7:e431d9d47db6 | 381 | |
embeddedartists | 7:e431d9d47db6 | 382 | return err; |
embeddedartists | 7:e431d9d47db6 | 383 | } |
embeddedartists | 7:e431d9d47db6 | 384 | |
embeddedartists | 7:e431d9d47db6 | 385 | XBee::XBeeError XBee::atGet(const char* atCmd, char* resp, uint32_t respLen) |
embeddedartists | 7:e431d9d47db6 | 386 | { |
embeddedartists | 7:e431d9d47db6 | 387 | |
embeddedartists | 7:e431d9d47db6 | 388 | int32_t lineLen = 0; |
embeddedartists | 7:e431d9d47db6 | 389 | XBeeError err = Ok; |
embeddedartists | 7:e431d9d47db6 | 390 | |
embeddedartists | 7:e431d9d47db6 | 391 | _serial.printf("%s%s", atCmd, XBEE_END_CMD); |
embeddedartists | 7:e431d9d47db6 | 392 | |
embeddedartists | 7:e431d9d47db6 | 393 | do { |
embeddedartists | 7:e431d9d47db6 | 394 | |
embeddedartists | 7:e431d9d47db6 | 395 | // a response is expected |
embeddedartists | 7:e431d9d47db6 | 396 | if (resp != NULL && respLen > 0) { |
embeddedartists | 7:e431d9d47db6 | 397 | lineLen = uartReadLine(resp, respLen, 1000); |
embeddedartists | 7:e431d9d47db6 | 398 | |
embeddedartists | 7:e431d9d47db6 | 399 | if (lineLen < 0) { |
embeddedartists | 7:e431d9d47db6 | 400 | // error while reading |
embeddedartists | 7:e431d9d47db6 | 401 | err = ReadError; |
embeddedartists | 7:e431d9d47db6 | 402 | break; |
embeddedartists | 7:e431d9d47db6 | 403 | } |
embeddedartists | 7:e431d9d47db6 | 404 | |
embeddedartists | 7:e431d9d47db6 | 405 | } |
embeddedartists | 7:e431d9d47db6 | 406 | |
embeddedartists | 7:e431d9d47db6 | 407 | } while(0); |
embeddedartists | 7:e431d9d47db6 | 408 | |
embeddedartists | 7:e431d9d47db6 | 409 | return err; |
embeddedartists | 7:e431d9d47db6 | 410 | } |
embeddedartists | 7:e431d9d47db6 | 411 | |
embeddedartists | 7:e431d9d47db6 | 412 | XBee::XBeeError XBee::atSet(const char* atCmd) |
embeddedartists | 7:e431d9d47db6 | 413 | { |
embeddedartists | 7:e431d9d47db6 | 414 | char b[10]; |
embeddedartists | 7:e431d9d47db6 | 415 | XBeeError err = Ok; |
embeddedartists | 7:e431d9d47db6 | 416 | |
embeddedartists | 7:e431d9d47db6 | 417 | err = atGet(atCmd, b, 10); |
embeddedartists | 7:e431d9d47db6 | 418 | if (err == Ok) { |
embeddedartists | 7:e431d9d47db6 | 419 | |
embeddedartists | 7:e431d9d47db6 | 420 | if (strcmp(RESP_OK, (char*)b) != 0) { |
embeddedartists | 7:e431d9d47db6 | 421 | // didn't receive OK |
embeddedartists | 7:e431d9d47db6 | 422 | err = CmdError; |
embeddedartists | 7:e431d9d47db6 | 423 | } |
embeddedartists | 7:e431d9d47db6 | 424 | } |
embeddedartists | 7:e431d9d47db6 | 425 | |
embeddedartists | 7:e431d9d47db6 | 426 | return err; |
embeddedartists | 7:e431d9d47db6 | 427 | } |
embeddedartists | 7:e431d9d47db6 | 428 | |
embeddedartists | 7:e431d9d47db6 | 429 | void XBee::processByte(char data) |
embeddedartists | 7:e431d9d47db6 | 430 | { |
embeddedartists | 7:e431d9d47db6 | 431 | switch(_rfState) { |
embeddedartists | 7:e431d9d47db6 | 432 | case RfStateFrame: |
embeddedartists | 7:e431d9d47db6 | 433 | if (data == XBEE_START_DEL) { |
embeddedartists | 7:e431d9d47db6 | 434 | _rfPos = 0; |
embeddedartists | 7:e431d9d47db6 | 435 | _rfFrameLen = 0; |
embeddedartists | 7:e431d9d47db6 | 436 | _rfState = RfStateLength; |
embeddedartists | 7:e431d9d47db6 | 437 | |
embeddedartists | 7:e431d9d47db6 | 438 | // start timer to make sure an entire frame is received |
embeddedartists | 7:e431d9d47db6 | 439 | // within a specific time |
embeddedartists | 7:e431d9d47db6 | 440 | _rfFrameTimeout = XBEE_RECV_FRAME_TO; |
embeddedartists | 7:e431d9d47db6 | 441 | _rfFrameTimer.reset(); |
embeddedartists | 7:e431d9d47db6 | 442 | _rfFrameTimer.start(); |
embeddedartists | 7:e431d9d47db6 | 443 | } |
embeddedartists | 7:e431d9d47db6 | 444 | |
embeddedartists | 7:e431d9d47db6 | 445 | break; |
embeddedartists | 7:e431d9d47db6 | 446 | case RfStateLength: |
embeddedartists | 7:e431d9d47db6 | 447 | _rfFrameLen |= (data << (8*(1-_rfPos))); |
embeddedartists | 7:e431d9d47db6 | 448 | _rfPos++; |
embeddedartists | 7:e431d9d47db6 | 449 | if (_rfPos == 2) { |
embeddedartists | 7:e431d9d47db6 | 450 | _rfPos = 0; |
embeddedartists | 7:e431d9d47db6 | 451 | _rfState = RfStateData; |
embeddedartists | 7:e431d9d47db6 | 452 | |
embeddedartists | 7:e431d9d47db6 | 453 | if (_rfFrameLen > XBEE_BUF_SZ) { |
embeddedartists | 7:e431d9d47db6 | 454 | debug("Xbee: Frame len %d > max buffer len %d\r\n", |
embeddedartists | 7:e431d9d47db6 | 455 | (int)_rfFrameLen, (int)XBEE_BUF_SZ); |
embeddedartists | 7:e431d9d47db6 | 456 | _rfFrameLen = XBEE_BUF_SZ; |
embeddedartists | 7:e431d9d47db6 | 457 | } |
embeddedartists | 7:e431d9d47db6 | 458 | |
embeddedartists | 7:e431d9d47db6 | 459 | } |
embeddedartists | 7:e431d9d47db6 | 460 | break; |
embeddedartists | 7:e431d9d47db6 | 461 | case RfStateData: |
embeddedartists | 7:e431d9d47db6 | 462 | _rfBuf[_rfPos++] = data; |
embeddedartists | 7:e431d9d47db6 | 463 | // read up until checksum (1 byte) |
embeddedartists | 7:e431d9d47db6 | 464 | if (_rfPos == _rfFrameLen+1) { |
embeddedartists | 7:e431d9d47db6 | 465 | _rfState = RfStateFrame; |
embeddedartists | 7:e431d9d47db6 | 466 | |
embeddedartists | 7:e431d9d47db6 | 467 | // cancel timer |
embeddedartists | 7:e431d9d47db6 | 468 | _rfFrameTimeout = 0; |
embeddedartists | 7:e431d9d47db6 | 469 | _rfFrameTimer.stop(); |
embeddedartists | 7:e431d9d47db6 | 470 | |
embeddedartists | 7:e431d9d47db6 | 471 | processFrame(_rfBuf, _rfPos); |
embeddedartists | 7:e431d9d47db6 | 472 | } |
embeddedartists | 7:e431d9d47db6 | 473 | break; |
embeddedartists | 7:e431d9d47db6 | 474 | |
embeddedartists | 7:e431d9d47db6 | 475 | } |
embeddedartists | 7:e431d9d47db6 | 476 | } |
embeddedartists | 7:e431d9d47db6 | 477 | |
embeddedartists | 7:e431d9d47db6 | 478 | void XBee::processFrame(char* buf, uint32_t len) |
embeddedartists | 7:e431d9d47db6 | 479 | { |
embeddedartists | 7:e431d9d47db6 | 480 | |
embeddedartists | 7:e431d9d47db6 | 481 | uint32_t addrLo = 0; |
embeddedartists | 7:e431d9d47db6 | 482 | uint32_t addrHi = 0; |
embeddedartists | 7:e431d9d47db6 | 483 | char* b = NULL; |
embeddedartists | 7:e431d9d47db6 | 484 | uint32_t bLen = 0; |
embeddedartists | 7:e431d9d47db6 | 485 | |
embeddedartists | 7:e431d9d47db6 | 486 | if (len < 2) { |
embeddedartists | 7:e431d9d47db6 | 487 | debug("Xbee: Invalid frame length (%d)\r\n", (int)len); |
embeddedartists | 7:e431d9d47db6 | 488 | return; |
embeddedartists | 7:e431d9d47db6 | 489 | } |
embeddedartists | 7:e431d9d47db6 | 490 | |
embeddedartists | 7:e431d9d47db6 | 491 | // verify checksum |
embeddedartists | 7:e431d9d47db6 | 492 | if (checksum(buf, len) != 0) { |
embeddedartists | 7:e431d9d47db6 | 493 | debug("Xbee: Invalid checksum\r\n"); |
embeddedartists | 7:e431d9d47db6 | 494 | return; |
embeddedartists | 7:e431d9d47db6 | 495 | } |
embeddedartists | 7:e431d9d47db6 | 496 | |
embeddedartists | 7:e431d9d47db6 | 497 | switch(buf[0]) { |
embeddedartists | 7:e431d9d47db6 | 498 | case XBEE_API_ID_AT_RESP: |
embeddedartists | 7:e431d9d47db6 | 499 | if (len < 5) { |
embeddedartists | 7:e431d9d47db6 | 500 | debug("Xbee: AT resp data too small: %d\r\n ", (int)len); |
embeddedartists | 7:e431d9d47db6 | 501 | return; |
embeddedartists | 7:e431d9d47db6 | 502 | } |
embeddedartists | 7:e431d9d47db6 | 503 | |
embeddedartists | 7:e431d9d47db6 | 504 | // there is a value |
embeddedartists | 7:e431d9d47db6 | 505 | if (len > 6) { |
embeddedartists | 7:e431d9d47db6 | 506 | b = &buf[5]; |
embeddedartists | 7:e431d9d47db6 | 507 | bLen = len-5-1; |
embeddedartists | 7:e431d9d47db6 | 508 | } |
embeddedartists | 7:e431d9d47db6 | 509 | |
embeddedartists | 7:e431d9d47db6 | 510 | handleAtResponse(buf[1], &buf[2], buf[4], b, bLen); |
embeddedartists | 7:e431d9d47db6 | 511 | break; |
embeddedartists | 7:e431d9d47db6 | 512 | case XBEE_API_ID_TX_STAT: |
embeddedartists | 7:e431d9d47db6 | 513 | handleTxStatus(buf[1], buf[2]); |
embeddedartists | 7:e431d9d47db6 | 514 | break; |
embeddedartists | 7:e431d9d47db6 | 515 | case XBEE_API_ID_RX_64: |
embeddedartists | 7:e431d9d47db6 | 516 | if (len < 12) { |
embeddedartists | 7:e431d9d47db6 | 517 | debug("Xbee: RX data too small: %d\r\n ", (int)len); |
embeddedartists | 7:e431d9d47db6 | 518 | return; |
embeddedartists | 7:e431d9d47db6 | 519 | } |
embeddedartists | 7:e431d9d47db6 | 520 | addrHi = bufTo32bitInt(&buf[1]); |
embeddedartists | 7:e431d9d47db6 | 521 | addrLo = bufTo32bitInt(&buf[5]); |
embeddedartists | 7:e431d9d47db6 | 522 | |
embeddedartists | 7:e431d9d47db6 | 523 | processData(addrHi, addrLo, buf[9], buf[10], &buf[11], len-11-1); |
embeddedartists | 7:e431d9d47db6 | 524 | break; |
embeddedartists | 7:e431d9d47db6 | 525 | case XBEE_API_ID_RX_16: |
embeddedartists | 7:e431d9d47db6 | 526 | debug("Xbee: RX 16 bit (unhandled)\r\n"); |
embeddedartists | 7:e431d9d47db6 | 527 | break; |
embeddedartists | 7:e431d9d47db6 | 528 | case XBEE_API_ID_MOD_STAT: |
embeddedartists | 7:e431d9d47db6 | 529 | handleModemStatus(buf[1]); |
embeddedartists | 7:e431d9d47db6 | 530 | break; |
embeddedartists | 7:e431d9d47db6 | 531 | default: |
embeddedartists | 7:e431d9d47db6 | 532 | debug("Xbee: Unhandled API ID: %x\r\n ", buf[0]); |
embeddedartists | 7:e431d9d47db6 | 533 | |
embeddedartists | 7:e431d9d47db6 | 534 | break; |
embeddedartists | 7:e431d9d47db6 | 535 | } |
embeddedartists | 7:e431d9d47db6 | 536 | |
embeddedartists | 7:e431d9d47db6 | 537 | } |
embeddedartists | 7:e431d9d47db6 | 538 | |
embeddedartists | 7:e431d9d47db6 | 539 | void XBee::handleAtResponse(uint8_t frameId, char* atBuf, uint8_t status, |
embeddedartists | 7:e431d9d47db6 | 540 | char* valueBuf, uint32_t valueLen) |
embeddedartists | 7:e431d9d47db6 | 541 | { |
embeddedartists | 7:e431d9d47db6 | 542 | |
embeddedartists | 7:e431d9d47db6 | 543 | if (strncmp("ND", (char*)atBuf, 2) == 0) { |
embeddedartists | 7:e431d9d47db6 | 544 | handleDiscovery(status, valueBuf, valueLen); |
embeddedartists | 7:e431d9d47db6 | 545 | } |
embeddedartists | 7:e431d9d47db6 | 546 | |
embeddedartists | 7:e431d9d47db6 | 547 | } |
embeddedartists | 7:e431d9d47db6 | 548 | |
embeddedartists | 7:e431d9d47db6 | 549 | void XBee::handleDiscovery(uint8_t status, char* buf, uint32_t len) |
embeddedartists | 7:e431d9d47db6 | 550 | { |
embeddedartists | 7:e431d9d47db6 | 551 | |
embeddedartists | 7:e431d9d47db6 | 552 | if (status == 0 && len >= 11) { |
embeddedartists | 7:e431d9d47db6 | 553 | _addrHi = bufTo32bitInt(&buf[2]); |
embeddedartists | 7:e431d9d47db6 | 554 | _addrLo = bufTo32bitInt(&buf[6]); |
embeddedartists | 7:e431d9d47db6 | 555 | _rssi = buf[10]; |
embeddedartists | 7:e431d9d47db6 | 556 | |
embeddedartists | 7:e431d9d47db6 | 557 | _callbacks[CbNodeFound].call(); |
embeddedartists | 7:e431d9d47db6 | 558 | |
embeddedartists | 7:e431d9d47db6 | 559 | } |
embeddedartists | 7:e431d9d47db6 | 560 | } |
embeddedartists | 7:e431d9d47db6 | 561 | |
embeddedartists | 7:e431d9d47db6 | 562 | void XBee::handleTxStatus(uint8_t frameId, uint8_t status) |
embeddedartists | 7:e431d9d47db6 | 563 | { |
embeddedartists | 7:e431d9d47db6 | 564 | _frameId = frameId; |
embeddedartists | 7:e431d9d47db6 | 565 | switch(status) { |
embeddedartists | 7:e431d9d47db6 | 566 | case XBEE_TX_STAT_SUCCESS: |
embeddedartists | 7:e431d9d47db6 | 567 | _txStatus = TxStatusOk; |
embeddedartists | 7:e431d9d47db6 | 568 | break; |
embeddedartists | 7:e431d9d47db6 | 569 | case XBEE_TX_STAT_NOACK: |
embeddedartists | 7:e431d9d47db6 | 570 | _txStatus = TxStatusNoAck; |
embeddedartists | 7:e431d9d47db6 | 571 | break; |
embeddedartists | 7:e431d9d47db6 | 572 | case XBEE_TX_STAT_CCA_FAIL: |
embeddedartists | 7:e431d9d47db6 | 573 | _txStatus = TxStatusCCA; |
embeddedartists | 7:e431d9d47db6 | 574 | break; |
embeddedartists | 7:e431d9d47db6 | 575 | case XBEE_TX_STAT_PURGED: |
embeddedartists | 7:e431d9d47db6 | 576 | _txStatus = TxStatusPurged; |
embeddedartists | 7:e431d9d47db6 | 577 | break; |
embeddedartists | 7:e431d9d47db6 | 578 | } |
embeddedartists | 7:e431d9d47db6 | 579 | |
embeddedartists | 7:e431d9d47db6 | 580 | _callbacks[CbTxStat].call(); |
embeddedartists | 7:e431d9d47db6 | 581 | |
embeddedartists | 7:e431d9d47db6 | 582 | } |
embeddedartists | 7:e431d9d47db6 | 583 | |
embeddedartists | 7:e431d9d47db6 | 584 | void XBee::processData(uint32_t addrHi, uint32_t addrLo, uint8_t rssi, |
embeddedartists | 7:e431d9d47db6 | 585 | uint8_t opt, char* buf, uint32_t len) |
embeddedartists | 7:e431d9d47db6 | 586 | { |
embeddedartists | 7:e431d9d47db6 | 587 | _addrHi = addrHi; |
embeddedartists | 7:e431d9d47db6 | 588 | _addrLo = addrLo; |
embeddedartists | 7:e431d9d47db6 | 589 | _rssi = rssi; |
embeddedartists | 7:e431d9d47db6 | 590 | _recvData = buf; |
embeddedartists | 7:e431d9d47db6 | 591 | _recvLen = len; |
embeddedartists | 7:e431d9d47db6 | 592 | |
embeddedartists | 7:e431d9d47db6 | 593 | _callbacks[CbDataAvailable].call(); |
embeddedartists | 7:e431d9d47db6 | 594 | } |
embeddedartists | 7:e431d9d47db6 | 595 | |
embeddedartists | 7:e431d9d47db6 | 596 | void XBee::handleModemStatus(uint8_t status) { |
embeddedartists | 7:e431d9d47db6 | 597 | |
embeddedartists | 7:e431d9d47db6 | 598 | if (_type == Coordinator && status == XBEE_MOD_STAT_COORD_START) { |
embeddedartists | 7:e431d9d47db6 | 599 | _initialized = true; |
embeddedartists | 7:e431d9d47db6 | 600 | _callbacks[CbDeviceUp].call(); |
embeddedartists | 7:e431d9d47db6 | 601 | } |
embeddedartists | 7:e431d9d47db6 | 602 | else if (_type == EndDevice && status == XBEE_MOD_STAT_ASSOC) { |
embeddedartists | 7:e431d9d47db6 | 603 | _initialized = 1; |
embeddedartists | 7:e431d9d47db6 | 604 | _callbacks[CbDeviceUp].call(); |
embeddedartists | 7:e431d9d47db6 | 605 | } |
embeddedartists | 7:e431d9d47db6 | 606 | else if (_type == EndDevice && status == XBEE_MOD_STAT_DIASSOC) { |
embeddedartists | 7:e431d9d47db6 | 607 | _initialized = false; |
embeddedartists | 7:e431d9d47db6 | 608 | _callbacks[CbDeviceDown].call(); |
embeddedartists | 7:e431d9d47db6 | 609 | } |
embeddedartists | 7:e431d9d47db6 | 610 | |
embeddedartists | 7:e431d9d47db6 | 611 | } |
embeddedartists | 7:e431d9d47db6 | 612 | |
embeddedartists | 7:e431d9d47db6 | 613 | char XBee::checksum(char* buf, uint32_t len) |
embeddedartists | 7:e431d9d47db6 | 614 | { |
embeddedartists | 7:e431d9d47db6 | 615 | int i = 0; |
embeddedartists | 7:e431d9d47db6 | 616 | char cs = 0; |
embeddedartists | 7:e431d9d47db6 | 617 | |
embeddedartists | 7:e431d9d47db6 | 618 | for (i = 0; i < (int)len; i++) { |
embeddedartists | 7:e431d9d47db6 | 619 | cs += buf[i]; |
embeddedartists | 7:e431d9d47db6 | 620 | } |
embeddedartists | 7:e431d9d47db6 | 621 | |
embeddedartists | 7:e431d9d47db6 | 622 | return (0xFF - cs); |
embeddedartists | 7:e431d9d47db6 | 623 | } |
embeddedartists | 7:e431d9d47db6 | 624 | |
embeddedartists | 7:e431d9d47db6 | 625 | uint32_t XBee::bufTo32bitInt(const char* buf) |
embeddedartists | 7:e431d9d47db6 | 626 | { |
embeddedartists | 7:e431d9d47db6 | 627 | uint32_t v = 0; |
embeddedartists | 7:e431d9d47db6 | 628 | |
embeddedartists | 7:e431d9d47db6 | 629 | v |= (buf[0] << 24); |
embeddedartists | 7:e431d9d47db6 | 630 | v |= (buf[1] << 16); |
embeddedartists | 7:e431d9d47db6 | 631 | v |= (buf[2] << 8); |
embeddedartists | 7:e431d9d47db6 | 632 | v |= (buf[3]); |
embeddedartists | 7:e431d9d47db6 | 633 | |
embeddedartists | 7:e431d9d47db6 | 634 | return v; |
embeddedartists | 7:e431d9d47db6 | 635 | } |
embeddedartists | 7:e431d9d47db6 | 636 | |
embeddedartists | 7:e431d9d47db6 | 637 | void XBee::int32bitToBuf(uint32_t v, char* buf) |
embeddedartists | 7:e431d9d47db6 | 638 | { |
embeddedartists | 7:e431d9d47db6 | 639 | |
embeddedartists | 7:e431d9d47db6 | 640 | buf[0] = ((v >> 24) & 0xff); |
embeddedartists | 7:e431d9d47db6 | 641 | buf[1] = ((v >> 16) & 0xff); |
embeddedartists | 7:e431d9d47db6 | 642 | buf[2] = ((v >> 8) & 0xff); |
embeddedartists | 7:e431d9d47db6 | 643 | buf[3] = ((v >> 0) & 0xff); |
embeddedartists | 7:e431d9d47db6 | 644 | |
embeddedartists | 7:e431d9d47db6 | 645 | } |
embeddedartists | 7:e431d9d47db6 | 646 | |
embeddedartists | 7:e431d9d47db6 | 647 | |
embeddedartists | 7:e431d9d47db6 | 648 | XBee::XBeeError XBee::apiTx64(uint32_t addrHi, uint32_t addrLo, char* data, |
embeddedartists | 7:e431d9d47db6 | 649 | uint32_t len, uint8_t* frameId) |
embeddedartists | 7:e431d9d47db6 | 650 | { |
embeddedartists | 7:e431d9d47db6 | 651 | char buf[100]; |
embeddedartists | 7:e431d9d47db6 | 652 | |
embeddedartists | 7:e431d9d47db6 | 653 | |
embeddedartists | 7:e431d9d47db6 | 654 | // limiting to 85 bytes data. Remaining 15 bytes belong to the |
embeddedartists | 7:e431d9d47db6 | 655 | // frame |
embeddedartists | 7:e431d9d47db6 | 656 | if (len > 85) { |
embeddedartists | 7:e431d9d47db6 | 657 | return ArgumentError; |
embeddedartists | 7:e431d9d47db6 | 658 | } |
embeddedartists | 7:e431d9d47db6 | 659 | |
embeddedartists | 7:e431d9d47db6 | 660 | buf[0] = XBEE_START_DEL; |
embeddedartists | 7:e431d9d47db6 | 661 | |
embeddedartists | 7:e431d9d47db6 | 662 | // length |
embeddedartists | 7:e431d9d47db6 | 663 | buf[1] = 0; |
embeddedartists | 7:e431d9d47db6 | 664 | buf[2] = 11+len; |
embeddedartists | 7:e431d9d47db6 | 665 | |
embeddedartists | 7:e431d9d47db6 | 666 | // AP ID |
embeddedartists | 7:e431d9d47db6 | 667 | buf[3] = XBEE_API_ID_TX_64; |
embeddedartists | 7:e431d9d47db6 | 668 | |
embeddedartists | 7:e431d9d47db6 | 669 | // frame ID |
embeddedartists | 7:e431d9d47db6 | 670 | buf[4] = getFrameId(); |
embeddedartists | 7:e431d9d47db6 | 671 | |
embeddedartists | 7:e431d9d47db6 | 672 | |
embeddedartists | 7:e431d9d47db6 | 673 | // address |
embeddedartists | 7:e431d9d47db6 | 674 | int32bitToBuf(addrHi, &buf[5]); |
embeddedartists | 7:e431d9d47db6 | 675 | int32bitToBuf(addrLo, &buf[9]); |
embeddedartists | 7:e431d9d47db6 | 676 | |
embeddedartists | 7:e431d9d47db6 | 677 | // options |
embeddedartists | 7:e431d9d47db6 | 678 | buf[13] = 0; |
embeddedartists | 7:e431d9d47db6 | 679 | |
embeddedartists | 7:e431d9d47db6 | 680 | // data |
embeddedartists | 7:e431d9d47db6 | 681 | memcpy(&buf[14], data, len); |
embeddedartists | 7:e431d9d47db6 | 682 | |
embeddedartists | 7:e431d9d47db6 | 683 | // checksum |
embeddedartists | 7:e431d9d47db6 | 684 | buf[14+len] = checksum(&buf[3], buf[2]); |
embeddedartists | 7:e431d9d47db6 | 685 | |
embeddedartists | 7:e431d9d47db6 | 686 | if (frameId != NULL) { |
embeddedartists | 7:e431d9d47db6 | 687 | *frameId = buf[4]; |
embeddedartists | 7:e431d9d47db6 | 688 | } |
embeddedartists | 7:e431d9d47db6 | 689 | |
embeddedartists | 7:e431d9d47db6 | 690 | |
embeddedartists | 7:e431d9d47db6 | 691 | for (int i = 0; i < (15+len); i++) { |
embeddedartists | 7:e431d9d47db6 | 692 | _serial.putc(buf[i]); |
embeddedartists | 7:e431d9d47db6 | 693 | } |
embeddedartists | 7:e431d9d47db6 | 694 | |
embeddedartists | 7:e431d9d47db6 | 695 | |
embeddedartists | 7:e431d9d47db6 | 696 | return Ok; |
embeddedartists | 7:e431d9d47db6 | 697 | } |
embeddedartists | 7:e431d9d47db6 | 698 | |
embeddedartists | 7:e431d9d47db6 | 699 | XBee::XBeeError XBee::apiAtCmd(const char* atCmd, uint32_t param, bool useParameter) |
embeddedartists | 7:e431d9d47db6 | 700 | { |
embeddedartists | 7:e431d9d47db6 | 701 | char buf[12]; |
embeddedartists | 7:e431d9d47db6 | 702 | int pos = 0; |
embeddedartists | 7:e431d9d47db6 | 703 | |
embeddedartists | 7:e431d9d47db6 | 704 | buf[0] = XBEE_START_DEL; |
embeddedartists | 7:e431d9d47db6 | 705 | |
embeddedartists | 7:e431d9d47db6 | 706 | // length |
embeddedartists | 7:e431d9d47db6 | 707 | buf[1] = 0; |
embeddedartists | 7:e431d9d47db6 | 708 | buf[2] = 4; |
embeddedartists | 7:e431d9d47db6 | 709 | if (useParameter) { |
embeddedartists | 7:e431d9d47db6 | 710 | buf[2] += 4; |
embeddedartists | 7:e431d9d47db6 | 711 | } |
embeddedartists | 7:e431d9d47db6 | 712 | |
embeddedartists | 7:e431d9d47db6 | 713 | // AP ID |
embeddedartists | 7:e431d9d47db6 | 714 | buf[3] = XBEE_API_ID_AT_CMD; |
embeddedartists | 7:e431d9d47db6 | 715 | |
embeddedartists | 7:e431d9d47db6 | 716 | // frame ID |
embeddedartists | 7:e431d9d47db6 | 717 | buf[4] = getFrameId(); |
embeddedartists | 7:e431d9d47db6 | 718 | |
embeddedartists | 7:e431d9d47db6 | 719 | // AT cmd |
embeddedartists | 7:e431d9d47db6 | 720 | buf[5] = atCmd[0]; |
embeddedartists | 7:e431d9d47db6 | 721 | buf[6] = atCmd[1]; |
embeddedartists | 7:e431d9d47db6 | 722 | pos = 7; |
embeddedartists | 7:e431d9d47db6 | 723 | |
embeddedartists | 7:e431d9d47db6 | 724 | // AT parameter |
embeddedartists | 7:e431d9d47db6 | 725 | if (useParameter) { |
embeddedartists | 7:e431d9d47db6 | 726 | buf[pos++] = ((param >> 24) & 0xff); |
embeddedartists | 7:e431d9d47db6 | 727 | buf[pos++] = ((param >> 16) & 0xff); |
embeddedartists | 7:e431d9d47db6 | 728 | buf[pos++] = ((param >> 8) & 0xff); |
embeddedartists | 7:e431d9d47db6 | 729 | buf[pos++] = ((param >> 0) & 0xff); |
embeddedartists | 7:e431d9d47db6 | 730 | } |
embeddedartists | 7:e431d9d47db6 | 731 | |
embeddedartists | 7:e431d9d47db6 | 732 | // checksum |
embeddedartists | 7:e431d9d47db6 | 733 | buf[pos] = checksum(&buf[3], pos-3); |
embeddedartists | 7:e431d9d47db6 | 734 | pos++; |
embeddedartists | 7:e431d9d47db6 | 735 | |
embeddedartists | 7:e431d9d47db6 | 736 | for (int i = 0; i < pos; i++) { |
embeddedartists | 7:e431d9d47db6 | 737 | _serial.putc(buf[i]); |
embeddedartists | 7:e431d9d47db6 | 738 | } |
embeddedartists | 7:e431d9d47db6 | 739 | |
embeddedartists | 7:e431d9d47db6 | 740 | return Ok; |
embeddedartists | 7:e431d9d47db6 | 741 | } |
embeddedartists | 7:e431d9d47db6 | 742 | |
embeddedartists | 7:e431d9d47db6 | 743 | uint8_t XBee::getFrameId(void) |
embeddedartists | 7:e431d9d47db6 | 744 | { |
embeddedartists | 7:e431d9d47db6 | 745 | _rfFrameId++; |
embeddedartists | 7:e431d9d47db6 | 746 | if (_rfFrameId == 0) { |
embeddedartists | 7:e431d9d47db6 | 747 | _rfFrameId = 1; |
embeddedartists | 7:e431d9d47db6 | 748 | } |
embeddedartists | 7:e431d9d47db6 | 749 | |
embeddedartists | 7:e431d9d47db6 | 750 | return _rfFrameId; |
embeddedartists | 7:e431d9d47db6 | 751 | } |