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