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