Digi XBeeLib fixed for NonCopyable issue

Dependents:   XBeeZB_Receive_Data

Fork of XBeeLib by Digi International Inc.

This lib fixes NonCopyable<T> issues of Digi XBeeLib. Also, lib has been reworked in order to make it RTOS-aware, overcoming several others issues due to stdio Mutex operations.

Committer:
spastor
Date:
Mon May 18 13:16:55 2015 +0200
Revision:
3:8662ebe83570
Parent:
2:2ee1b6d51df2
Child:
4:629712865107
Automatic upload

Who changed what in which revision?

UserRevisionLine numberNew contents of line
spastor 0:fcaad0dfa051 1 /**
spastor 0:fcaad0dfa051 2 * Copyright (c) 2015 Digi International Inc.,
spastor 0:fcaad0dfa051 3 * All rights not expressly granted are reserved.
spastor 0:fcaad0dfa051 4 *
spastor 0:fcaad0dfa051 5 * This Source Code Form is subject to the terms of the Mozilla Public
spastor 0:fcaad0dfa051 6 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
spastor 0:fcaad0dfa051 7 * You can obtain one at http://mozilla.org/MPL/2.0/.
spastor 0:fcaad0dfa051 8 *
spastor 0:fcaad0dfa051 9 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
spastor 0:fcaad0dfa051 10 * =======================================================================
spastor 0:fcaad0dfa051 11 */
spastor 0:fcaad0dfa051 12
spastor 0:fcaad0dfa051 13 #include "XBeeLib.h"
spastor 0:fcaad0dfa051 14 #include "FrameHandlers/FH_ModemStatus.h"
spastor 0:fcaad0dfa051 15
spastor 0:fcaad0dfa051 16 /* States for the state machine that processes incoming data on the serial port */
spastor 0:fcaad0dfa051 17 #define WAITING_FOR_START_FRAME (0)
spastor 0:fcaad0dfa051 18 #define WAITING_FOR_LENGTH_MSB (1)
spastor 0:fcaad0dfa051 19 #define WAITING_FOR_LENGTH_LSB (2)
spastor 0:fcaad0dfa051 20 #define WAITING_FOR_PAYLOAD (3)
spastor 0:fcaad0dfa051 21 #define WAITING_FOR_CHECKSUM (4)
spastor 0:fcaad0dfa051 22
spastor 0:fcaad0dfa051 23 #define IS_API2() (_mode == ModeAPI2)
spastor 0:fcaad0dfa051 24 #define IS_API_MODE() (_mode == ModeAPI1 || _mode == ModeAPI2)
spastor 0:fcaad0dfa051 25
spastor 0:fcaad0dfa051 26 using namespace XBeeLib;
spastor 0:fcaad0dfa051 27
spastor 0:fcaad0dfa051 28 Timer XBee::_timer;
spastor 0:fcaad0dfa051 29 FrameBuffer XBee::_framebuf;
spastor 0:fcaad0dfa051 30
hbujanda 2:2ee1b6d51df2 31 #if defined(DEVICE_SERIAL_FC)
hbujanda 2:2ee1b6d51df2 32 bool XBee::check_radio_flow_control()
hbujanda 2:2ee1b6d51df2 33 {
hbujanda 2:2ee1b6d51df2 34 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 2:2ee1b6d51df2 35 uint32_t value;
hbujanda 2:2ee1b6d51df2 36
hbujanda 2:2ee1b6d51df2 37 if (_serial_flow_type == SerialBase::RTSCTS || _serial_flow_type == SerialBase::CTS) {
hbujanda 2:2ee1b6d51df2 38 cmdresp = get_param("D7", &value);
hbujanda 2:2ee1b6d51df2 39 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 2:2ee1b6d51df2 40 digi_log(LogLevelError, "Could not read CTS configuration. Error %d\r\n", cmdresp);
hbujanda 2:2ee1b6d51df2 41 return false;
hbujanda 2:2ee1b6d51df2 42 }
hbujanda 2:2ee1b6d51df2 43 else if (value != 1) {
hbujanda 2:2ee1b6d51df2 44 digi_log(LogLevelError, "Bad CTS configuration. Radio 'D7' param is %d and should be 1\r\n", value);
hbujanda 2:2ee1b6d51df2 45 return false;
hbujanda 2:2ee1b6d51df2 46 }
hbujanda 2:2ee1b6d51df2 47 }
hbujanda 2:2ee1b6d51df2 48
hbujanda 2:2ee1b6d51df2 49 if (_serial_flow_type == SerialBase::RTSCTS || _serial_flow_type == SerialBase::RTS) {
hbujanda 2:2ee1b6d51df2 50 cmdresp = get_param("D6", &value);
hbujanda 2:2ee1b6d51df2 51 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 2:2ee1b6d51df2 52 digi_log(LogLevelError, "Could not read RTS configuration. Error %d\r\n", cmdresp);
hbujanda 2:2ee1b6d51df2 53 return false;
hbujanda 2:2ee1b6d51df2 54 }
hbujanda 2:2ee1b6d51df2 55 else if (value != 1) {
hbujanda 2:2ee1b6d51df2 56 digi_log(LogLevelError, "Bad RTS configuration. Radio 'D6' param is %d and should be 1\r\n", value);
hbujanda 2:2ee1b6d51df2 57 return false;
hbujanda 2:2ee1b6d51df2 58 }
hbujanda 2:2ee1b6d51df2 59 }
hbujanda 2:2ee1b6d51df2 60
hbujanda 2:2ee1b6d51df2 61 return true;
hbujanda 2:2ee1b6d51df2 62 }
hbujanda 2:2ee1b6d51df2 63 #endif
hbujanda 2:2ee1b6d51df2 64
spastor 0:fcaad0dfa051 65 /* Class constructor */
spastor 0:fcaad0dfa051 66 XBee::XBee(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
hbujanda 2:2ee1b6d51df2 67 _mode(ModeUnknown), _type(Unknown), _hw_version(0), _fw_version(0), _timeout_ms(SYNC_OPS_TIMEOUT_MS), _dev_addr64(ADDR64_UNASSIGNED), _dev_addr16(ADDR16_UNKNOWN),
spastor 0:fcaad0dfa051 68 _reset(NULL), _tx_options(0), _bc_radius(0), _hw_reset_cnt(0), _wd_reset_cnt(0), _reset_timeout(0), _modem_status_handler(NULL), _modem_status(AtCmdFrame::HwReset), _initializing(true), _pm_mode(SleepDisabled)
spastor 0:fcaad0dfa051 69 {
spastor 0:fcaad0dfa051 70
spastor 0:fcaad0dfa051 71 if (reset != NC) {
hbujanda 1:794d1d3e4a08 72 _reset = new DigitalOut(reset, 1);
spastor 0:fcaad0dfa051 73 }
spastor 0:fcaad0dfa051 74 #if defined(ENABLE_PM_SUPPORT)
spastor 0:fcaad0dfa051 75 _on_sleep = NULL;
spastor 0:fcaad0dfa051 76 _sleep_req = NULL;
spastor 0:fcaad0dfa051 77 #endif /* defined(ENABLE_PM_SUPPORT) */
spastor 0:fcaad0dfa051 78
spastor 0:fcaad0dfa051 79 _uart = new RawSerial(tx, rx);
spastor 0:fcaad0dfa051 80 _uart->baud(baud);
hbujanda 1:794d1d3e4a08 81
hbujanda 1:794d1d3e4a08 82 _serial_flow_type = SerialBase::Disabled;
spastor 0:fcaad0dfa051 83 #if defined(DEVICE_SERIAL_FC)
spastor 0:fcaad0dfa051 84 if (rts != NC && cts != NC) {
hbujanda 1:794d1d3e4a08 85 _serial_flow_type = SerialBase::RTSCTS;
hbujanda 1:794d1d3e4a08 86 _uart->set_flow_control(_serial_flow_type, rts, cts);
hbujanda 1:794d1d3e4a08 87 }
hbujanda 1:794d1d3e4a08 88 else if (rts != NC && cts == NC) {
hbujanda 1:794d1d3e4a08 89 _serial_flow_type = SerialBase::RTS;
hbujanda 1:794d1d3e4a08 90 _uart->set_flow_control(_serial_flow_type, rts);
hbujanda 1:794d1d3e4a08 91 }
hbujanda 1:794d1d3e4a08 92 else if (rts == NC && cts != NC) {
hbujanda 1:794d1d3e4a08 93 _serial_flow_type = SerialBase::CTS;
hbujanda 1:794d1d3e4a08 94 _uart->set_flow_control(_serial_flow_type, cts);
spastor 0:fcaad0dfa051 95 }
spastor 0:fcaad0dfa051 96 #endif
spastor 0:fcaad0dfa051 97 /* Enable the reception of bytes on the serial interface by providing a cb */
spastor 0:fcaad0dfa051 98 _uart->attach(this, &XBee::uart_read_cb, Serial::RxIrq);
spastor 0:fcaad0dfa051 99
spastor 0:fcaad0dfa051 100 for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
spastor 0:fcaad0dfa051 101 _fhandlers[i] = NULL;
spastor 0:fcaad0dfa051 102 }
spastor 0:fcaad0dfa051 103 }
spastor 0:fcaad0dfa051 104
spastor 0:fcaad0dfa051 105 /* Class destructor */
spastor 0:fcaad0dfa051 106 XBee::~XBee()
spastor 0:fcaad0dfa051 107 {
spastor 0:fcaad0dfa051 108 unregister_modem_status_cb();
spastor 0:fcaad0dfa051 109
spastor 0:fcaad0dfa051 110 if (_uart != NULL) {
spastor 0:fcaad0dfa051 111 delete _uart;
spastor 0:fcaad0dfa051 112 }
spastor 0:fcaad0dfa051 113 if (_reset != NULL) {
spastor 0:fcaad0dfa051 114 delete _reset;
spastor 0:fcaad0dfa051 115 }
spastor 0:fcaad0dfa051 116 }
spastor 0:fcaad0dfa051 117
spastor 0:fcaad0dfa051 118 #include <inttypes.h>
spastor 0:fcaad0dfa051 119
spastor 0:fcaad0dfa051 120 RadioStatus XBee::init(void)
spastor 0:fcaad0dfa051 121 {
spastor 0:fcaad0dfa051 122 AtCmdFrame::AtCmdResp cmd_resp;
spastor 0:fcaad0dfa051 123 uint32_t var32;
spastor 0:fcaad0dfa051 124
spastor 0:fcaad0dfa051 125 /* Start the timer, used for the timeouts */
spastor 0:fcaad0dfa051 126 _timer.reset();
spastor 0:fcaad0dfa051 127 _timer.start();
spastor 0:fcaad0dfa051 128
spastor 0:fcaad0dfa051 129 _initializing = true;
spastor 0:fcaad0dfa051 130
spastor 0:fcaad0dfa051 131 device_reset();
spastor 0:fcaad0dfa051 132
spastor 0:fcaad0dfa051 133 /* Check if radio is in API1 or API2 _mode */
spastor 0:fcaad0dfa051 134 cmd_resp = get_param("AP", &var32);
spastor 0:fcaad0dfa051 135 if (cmd_resp != AtCmdFrame::AtCmdRespOk)
spastor 0:fcaad0dfa051 136 return Failure;
spastor 0:fcaad0dfa051 137
spastor 0:fcaad0dfa051 138 _mode = (RadioMode)var32;
spastor 0:fcaad0dfa051 139
spastor 0:fcaad0dfa051 140 /* Read the device unique 64b address */
spastor 0:fcaad0dfa051 141 uint32_t serialn_high, serialn_low;
spastor 0:fcaad0dfa051 142 cmd_resp = get_param("SH", &serialn_high);
spastor 0:fcaad0dfa051 143 if (cmd_resp != AtCmdFrame::AtCmdRespOk)
spastor 0:fcaad0dfa051 144 return Failure;
spastor 0:fcaad0dfa051 145 cmd_resp = get_param("SL", &serialn_low);
spastor 0:fcaad0dfa051 146 if (cmd_resp != AtCmdFrame::AtCmdRespOk)
spastor 0:fcaad0dfa051 147 return Failure;
spastor 0:fcaad0dfa051 148
spastor 0:fcaad0dfa051 149 _dev_addr64 = ((uint64_t)serialn_high << 32) | serialn_low;
spastor 0:fcaad0dfa051 150
spastor 0:fcaad0dfa051 151 /* Read some important parameters */
spastor 0:fcaad0dfa051 152 cmd_resp = get_param("HV", &var32);
spastor 0:fcaad0dfa051 153 if (cmd_resp != AtCmdFrame::AtCmdRespOk)
spastor 0:fcaad0dfa051 154 return Failure;
spastor 0:fcaad0dfa051 155 _hw_version = var32;
spastor 0:fcaad0dfa051 156
spastor 0:fcaad0dfa051 157 cmd_resp = get_param("VR", &var32);
spastor 0:fcaad0dfa051 158 if (cmd_resp != AtCmdFrame::AtCmdRespOk)
spastor 0:fcaad0dfa051 159 return Failure;
spastor 0:fcaad0dfa051 160 _fw_version = var32;
spastor 0:fcaad0dfa051 161
spastor 0:fcaad0dfa051 162 cmd_resp = get_param("MY", &var32);
spastor 0:fcaad0dfa051 163 if (cmd_resp != AtCmdFrame::AtCmdRespOk)
spastor 0:fcaad0dfa051 164 return Failure;
spastor 0:fcaad0dfa051 165 _dev_addr16 = var32;
spastor 0:fcaad0dfa051 166 _type = (RadioType)(_hw_version >> 8);
spastor 0:fcaad0dfa051 167
spastor 0:fcaad0dfa051 168 digi_log(LogLevelInfo, "mode: %02x\r\n", (uint8_t)_mode);
spastor 0:fcaad0dfa051 169 digi_log(LogLevelInfo, "HV: %04x\r\n", _hw_version);
spastor 0:fcaad0dfa051 170 digi_log(LogLevelInfo, "VR: %04x\r\n", _fw_version);
spastor 0:fcaad0dfa051 171 digi_log(LogLevelInfo, "ADDR64: %08x:%08x\r\n", UINT64_HI32(_dev_addr64), UINT64_LO32(_dev_addr64));
spastor 0:fcaad0dfa051 172 digi_log(LogLevelInfo, "ADDR16: %04x\r\n", _dev_addr16);
spastor 0:fcaad0dfa051 173
hbujanda 2:2ee1b6d51df2 174 #if defined(DEVICE_SERIAL_FC)
hbujanda 2:2ee1b6d51df2 175 bool valid_radio_fc = check_radio_flow_control();
hbujanda 2:2ee1b6d51df2 176 assert(valid_radio_fc == true);
hbujanda 2:2ee1b6d51df2 177 #endif
hbujanda 2:2ee1b6d51df2 178
spastor 0:fcaad0dfa051 179 _initializing = false;
spastor 0:fcaad0dfa051 180 if (_modem_status_handler != NULL) {
spastor 0:fcaad0dfa051 181 const ApiFrame frame = ApiFrame(ApiFrame::AtModemStatus, (uint8_t *)&_modem_status, sizeof(_modem_status));
spastor 0:fcaad0dfa051 182 _modem_status_handler->process_frame_data(&frame);
spastor 0:fcaad0dfa051 183 }
spastor 0:fcaad0dfa051 184
spastor 0:fcaad0dfa051 185 return Success;
spastor 0:fcaad0dfa051 186 }
spastor 0:fcaad0dfa051 187
spastor 0:fcaad0dfa051 188 uint64_t XBee::get_addr64() const
spastor 0:fcaad0dfa051 189 {
spastor 0:fcaad0dfa051 190 return _dev_addr64;
spastor 0:fcaad0dfa051 191 }
spastor 0:fcaad0dfa051 192
spastor 0:fcaad0dfa051 193 uint16_t XBee::get_addr16() const
spastor 0:fcaad0dfa051 194 {
spastor 0:fcaad0dfa051 195 return _dev_addr16;
spastor 0:fcaad0dfa051 196 }
spastor 0:fcaad0dfa051 197
spastor 0:fcaad0dfa051 198 RadioStatus XBee::hardware_reset()
spastor 0:fcaad0dfa051 199 {
spastor 0:fcaad0dfa051 200 if (_reset != NULL) {
spastor 0:fcaad0dfa051 201 volatile uint16_t * const rst_cnt_p = &_hw_reset_cnt;
spastor 0:fcaad0dfa051 202 const uint16_t init_rst_cnt = *rst_cnt_p;
spastor 0:fcaad0dfa051 203 *_reset = 0;
spastor 0:fcaad0dfa051 204 wait_ms(10);
spastor 0:fcaad0dfa051 205 *_reset = 1;
spastor 0:fcaad0dfa051 206 return wait_for_module_to_reset(rst_cnt_p, init_rst_cnt);
spastor 0:fcaad0dfa051 207 }
spastor 0:fcaad0dfa051 208
spastor 0:fcaad0dfa051 209 return Failure;
spastor 0:fcaad0dfa051 210 }
spastor 0:fcaad0dfa051 211
spastor 0:fcaad0dfa051 212 RadioStatus XBee::device_reset()
spastor 0:fcaad0dfa051 213 {
spastor 0:fcaad0dfa051 214 if (hardware_reset() == Success)
spastor 0:fcaad0dfa051 215 return Success;
spastor 0:fcaad0dfa051 216
spastor 0:fcaad0dfa051 217 return software_reset();
spastor 0:fcaad0dfa051 218 }
spastor 0:fcaad0dfa051 219
spastor 0:fcaad0dfa051 220 RadioStatus XBee::wait_for_module_to_reset(volatile uint16_t *rst_cnt_p, uint16_t init_rst_cnt)
spastor 0:fcaad0dfa051 221 {
spastor 0:fcaad0dfa051 222 const int rst_timeout = _timer.read_ms() + _reset_timeout;
spastor 0:fcaad0dfa051 223 while (*rst_cnt_p == init_rst_cnt && _timer.read_ms() < rst_timeout) {
spastor 0:fcaad0dfa051 224 wait_ms(100);
spastor 0:fcaad0dfa051 225 }
spastor 0:fcaad0dfa051 226
spastor 0:fcaad0dfa051 227 if (_reset_timeout && *rst_cnt_p == init_rst_cnt) {
spastor 0:fcaad0dfa051 228 digi_log(LogLevelWarning, "Reset Timeout\r\n");
spastor 0:fcaad0dfa051 229 return Failure;
spastor 0:fcaad0dfa051 230 }
spastor 0:fcaad0dfa051 231 return Success;
spastor 0:fcaad0dfa051 232 }
spastor 0:fcaad0dfa051 233
spastor 0:fcaad0dfa051 234 /** Callback function called when data is received on the serial port */
spastor 0:fcaad0dfa051 235 void XBee::uart_read_cb(void)
spastor 0:fcaad0dfa051 236 {
spastor 0:fcaad0dfa051 237 static uint8_t rxstate = WAITING_FOR_START_FRAME;
spastor 0:fcaad0dfa051 238 static uint16_t framelen = 0;
spastor 0:fcaad0dfa051 239 static uint16_t bytes_read;
spastor 0:fcaad0dfa051 240 static uint8_t chksum;
spastor 0:fcaad0dfa051 241 static ApiFrame *frame = NULL;
spastor 0:fcaad0dfa051 242 static bool last_byte_escaped = false;
spastor 0:fcaad0dfa051 243
spastor 0:fcaad0dfa051 244 while (_uart->readable()) {
spastor 0:fcaad0dfa051 245 uint8_t data = _uart->getc();
spastor 0:fcaad0dfa051 246
spastor 0:fcaad0dfa051 247 if (IS_API2() && rxstate != WAITING_FOR_START_FRAME) {
spastor 0:fcaad0dfa051 248 if (last_byte_escaped) {
spastor 0:fcaad0dfa051 249 data = data ^ DR_ESCAPE_XOR_BYTE;
spastor 0:fcaad0dfa051 250 last_byte_escaped = false;
spastor 0:fcaad0dfa051 251 } else if (data == DR_ESCAPE_BYTE) {
spastor 0:fcaad0dfa051 252 last_byte_escaped = true;
spastor 0:fcaad0dfa051 253 continue;
spastor 0:fcaad0dfa051 254 }
spastor 0:fcaad0dfa051 255 }
spastor 0:fcaad0dfa051 256
spastor 0:fcaad0dfa051 257 switch (rxstate) {
spastor 0:fcaad0dfa051 258 case WAITING_FOR_START_FRAME:
spastor 0:fcaad0dfa051 259 if (data == DR_START_OF_FRAME)
spastor 0:fcaad0dfa051 260 rxstate = WAITING_FOR_LENGTH_MSB;
spastor 0:fcaad0dfa051 261 break;
spastor 0:fcaad0dfa051 262
spastor 0:fcaad0dfa051 263 case WAITING_FOR_LENGTH_MSB:
spastor 0:fcaad0dfa051 264 framelen = data << 8;
spastor 0:fcaad0dfa051 265 rxstate = WAITING_FOR_LENGTH_LSB;
spastor 0:fcaad0dfa051 266 break;
spastor 0:fcaad0dfa051 267
spastor 0:fcaad0dfa051 268 case WAITING_FOR_LENGTH_LSB:
spastor 0:fcaad0dfa051 269 framelen |= data;
spastor 0:fcaad0dfa051 270 rxstate = WAITING_FOR_PAYLOAD; /* FIXME, if frame is NULL the status should be WAITING */
spastor 0:fcaad0dfa051 271 bytes_read = 0;
spastor 0:fcaad0dfa051 272 chksum = 0;
spastor 0:fcaad0dfa051 273 /* Sanity check that the frame is smaller than... */
spastor 0:fcaad0dfa051 274 if (framelen > MAX_FRAME_PAYLOAD_LEN) {
spastor 0:fcaad0dfa051 275 digi_log(LogLevelDebug, "framelen=%d too long\r\n", framelen);
spastor 0:fcaad0dfa051 276 digi_log(LogLevelWarning, "Frame dropped, frame too long. Increase MAX_FRAME_PAYLOAD_LEN define\r\n");
spastor 0:fcaad0dfa051 277 rxstate = WAITING_FOR_START_FRAME;
spastor 0:fcaad0dfa051 278 }
spastor 0:fcaad0dfa051 279
spastor 0:fcaad0dfa051 280 frame = _framebuf.get_next_free_frame();
spastor 0:fcaad0dfa051 281 if (frame == NULL) {
spastor 0:fcaad0dfa051 282 /* It's not possible to achive this condition as we discard older frames and only one frame can be used by syncr. commands */
spastor 0:fcaad0dfa051 283 assert(frame != NULL);
spastor 0:fcaad0dfa051 284 rxstate = WAITING_FOR_START_FRAME;
spastor 0:fcaad0dfa051 285 } else {
spastor 0:fcaad0dfa051 286 frame->set_data_len(framelen - 1);
spastor 0:fcaad0dfa051 287 }
spastor 0:fcaad0dfa051 288 break;
spastor 0:fcaad0dfa051 289
spastor 0:fcaad0dfa051 290 case WAITING_FOR_PAYLOAD:
spastor 0:fcaad0dfa051 291 if (!bytes_read)
spastor 0:fcaad0dfa051 292 frame->set_frame_type((ApiFrame::ApiFrameType)data);
spastor 0:fcaad0dfa051 293 else {
spastor 0:fcaad0dfa051 294 frame->set_data(data, bytes_read - 1);
spastor 0:fcaad0dfa051 295 }
spastor 0:fcaad0dfa051 296 chksum += data;
spastor 0:fcaad0dfa051 297 bytes_read++;
spastor 0:fcaad0dfa051 298 if (bytes_read == framelen)
spastor 0:fcaad0dfa051 299 rxstate = WAITING_FOR_CHECKSUM;
spastor 0:fcaad0dfa051 300 break;
spastor 0:fcaad0dfa051 301
spastor 0:fcaad0dfa051 302 case WAITING_FOR_CHECKSUM:
spastor 0:fcaad0dfa051 303 chksum += data;
spastor 0:fcaad0dfa051 304 if (chksum == 0xFF) {
spastor 0:fcaad0dfa051 305 /* We got a valid frame!! */
spastor 0:fcaad0dfa051 306 frame->dump();
spastor 0:fcaad0dfa051 307
spastor 0:fcaad0dfa051 308 /* If its a _modem status frame, process it to update the status info of the library.
spastor 0:fcaad0dfa051 309 * The frame is also queued to allow processing it other handlers registered.
spastor 0:fcaad0dfa051 310 * Note that radio_status_update() has to be fast to minimize the impact of processing
spastor 0:fcaad0dfa051 311 * the funcion here */
spastor 0:fcaad0dfa051 312 if (frame->get_frame_type() == ApiFrame::AtModemStatus) {
spastor 0:fcaad0dfa051 313 radio_status_update((AtCmdFrame::ModemStatus)frame->get_data_at(0));
spastor 0:fcaad0dfa051 314 if (_initializing)
spastor 0:fcaad0dfa051 315 _framebuf.free_frame(frame);
spastor 0:fcaad0dfa051 316 else
spastor 0:fcaad0dfa051 317 _framebuf.complete_frame(frame);
spastor 0:fcaad0dfa051 318 }
spastor 0:fcaad0dfa051 319 else {
spastor 0:fcaad0dfa051 320 _framebuf.complete_frame(frame);
spastor 0:fcaad0dfa051 321 /* Note, the frame will be released elsewhere, once it has been processed */
spastor 0:fcaad0dfa051 322 }
spastor 0:fcaad0dfa051 323 } else {
spastor 0:fcaad0dfa051 324 _framebuf.free_frame(frame);
spastor 0:fcaad0dfa051 325 digi_log(LogLevelWarning, "Checksum error, got %02x, %02x\r\n", data, chksum);
spastor 0:fcaad0dfa051 326 }
spastor 0:fcaad0dfa051 327 /* Intentional fall-through */
spastor 0:fcaad0dfa051 328 default:
spastor 0:fcaad0dfa051 329 rxstate = WAITING_FOR_START_FRAME;
spastor 0:fcaad0dfa051 330 break;
spastor 0:fcaad0dfa051 331 }
spastor 0:fcaad0dfa051 332 }
spastor 0:fcaad0dfa051 333 /* TODO, signal the thread processing incoming frames */
spastor 0:fcaad0dfa051 334 }
spastor 0:fcaad0dfa051 335
spastor 0:fcaad0dfa051 336 /* This is a pure virtual function, but exists here because its called from this class to
spastor 0:fcaad0dfa051 337 * to update the status of the object, and can be called before the construction of the
spastor 0:fcaad0dfa051 338 * object has been completed and the virtual functions filled */
spastor 0:fcaad0dfa051 339 void XBee::radio_status_update(AtCmdFrame::ModemStatus modem_status)
spastor 0:fcaad0dfa051 340 {
hbujanda 2:2ee1b6d51df2 341 UNUSED_PARAMETER(modem_status);
spastor 0:fcaad0dfa051 342 }
spastor 0:fcaad0dfa051 343
spastor 0:fcaad0dfa051 344 void XBee::set_timeout(uint16_t timeout_ms)
spastor 0:fcaad0dfa051 345 {
spastor 0:fcaad0dfa051 346 this->_timeout_ms = timeout_ms;
spastor 0:fcaad0dfa051 347 }
spastor 0:fcaad0dfa051 348
spastor 0:fcaad0dfa051 349 uint16_t XBee::get_timeout(void) const
spastor 0:fcaad0dfa051 350 {
spastor 0:fcaad0dfa051 351 return _timeout_ms;
spastor 0:fcaad0dfa051 352 }
spastor 0:fcaad0dfa051 353
spastor 0:fcaad0dfa051 354 RadioType XBee::get_radio_type() const
spastor 0:fcaad0dfa051 355 {
spastor 0:fcaad0dfa051 356 return _type;
spastor 0:fcaad0dfa051 357 }
spastor 0:fcaad0dfa051 358
spastor 0:fcaad0dfa051 359
spastor 0:fcaad0dfa051 360
spastor 0:fcaad0dfa051 361 /* */
spastor 0:fcaad0dfa051 362 ApiFrame * XBee::get_this_api_frame(uint8_t id, ApiFrame::ApiFrameType type,
spastor 0:fcaad0dfa051 363 ApiFrame::ApiFrameType type2)
spastor 0:fcaad0dfa051 364 {
spastor 0:fcaad0dfa051 365 int const timeout = _timer.read_ms() + _timeout_ms;
spastor 0:fcaad0dfa051 366
spastor 0:fcaad0dfa051 367 while (_timer.read_ms() < timeout) {
spastor 0:fcaad0dfa051 368 ApiFrame * frame = _framebuf.get_next_complete_frame_syncr();
spastor 0:fcaad0dfa051 369 if (frame == NULL) {
spastor 0:fcaad0dfa051 370 wait_ms(10);
spastor 0:fcaad0dfa051 371 continue;
spastor 0:fcaad0dfa051 372 }
spastor 0:fcaad0dfa051 373
spastor 0:fcaad0dfa051 374 if ((frame->get_frame_type() != type) &&
spastor 0:fcaad0dfa051 375 (frame->get_frame_type() != type2)) {
spastor 0:fcaad0dfa051 376 _framebuf.complete_frame(frame);
spastor 0:fcaad0dfa051 377 wait_ms(1);
spastor 0:fcaad0dfa051 378 continue;
spastor 0:fcaad0dfa051 379 }
spastor 0:fcaad0dfa051 380
spastor 0:fcaad0dfa051 381 if (frame->get_data_at(ATCMD_RESP_FRAME_ID_OFFSET) != id) {
spastor 0:fcaad0dfa051 382 _framebuf.complete_frame(frame);
spastor 0:fcaad0dfa051 383 wait_ms(1);
spastor 0:fcaad0dfa051 384 continue;
spastor 0:fcaad0dfa051 385 }
spastor 0:fcaad0dfa051 386
spastor 0:fcaad0dfa051 387 /* frame found */
spastor 0:fcaad0dfa051 388 return frame;
spastor 0:fcaad0dfa051 389 }
spastor 0:fcaad0dfa051 390
spastor 0:fcaad0dfa051 391 digi_log(LogLevelWarning, "Frame type: %02x, id: %02x, timeout\r\n", (uint8_t)type, id);
spastor 0:fcaad0dfa051 392
spastor 0:fcaad0dfa051 393 return NULL;
spastor 0:fcaad0dfa051 394 }
spastor 0:fcaad0dfa051 395
spastor 0:fcaad0dfa051 396 void XBee::send_byte_escaping_if(uint8_t data)
spastor 0:fcaad0dfa051 397 {
spastor 0:fcaad0dfa051 398 if (IS_API2()) {
spastor 0:fcaad0dfa051 399 switch (data) {
spastor 0:fcaad0dfa051 400 case DR_START_OF_FRAME:
spastor 0:fcaad0dfa051 401 case DR_ESCAPE_BYTE:
spastor 0:fcaad0dfa051 402 case DR_XON_BYTE:
spastor 0:fcaad0dfa051 403 case DR_XOFF_BYTE:
spastor 0:fcaad0dfa051 404 _uart->putc(DR_ESCAPE_BYTE);
spastor 0:fcaad0dfa051 405 _uart->putc(data ^ DR_ESCAPE_XOR_BYTE);
spastor 0:fcaad0dfa051 406 break;
spastor 0:fcaad0dfa051 407 default:
spastor 0:fcaad0dfa051 408 _uart->putc(data);
spastor 0:fcaad0dfa051 409 }
spastor 0:fcaad0dfa051 410 } else {
spastor 0:fcaad0dfa051 411 _uart->putc(data);
spastor 0:fcaad0dfa051 412 }
spastor 0:fcaad0dfa051 413 }
spastor 0:fcaad0dfa051 414
spastor 0:fcaad0dfa051 415 void XBee::send_api_frame(ApiFrame *frame)
spastor 0:fcaad0dfa051 416 {
spastor 0:fcaad0dfa051 417 uint8_t chksum;
spastor 0:fcaad0dfa051 418 const uint8_t *data;
spastor 0:fcaad0dfa051 419 uint16_t bytes_sent = 0, frame_len;
spastor 0:fcaad0dfa051 420
spastor 0:fcaad0dfa051 421 frame->dump();
spastor 0:fcaad0dfa051 422
spastor 0:fcaad0dfa051 423 frame_len = 1 + frame->get_data_len(); /* frame type + frame payload */
spastor 0:fcaad0dfa051 424 data = frame->get_data();
spastor 0:fcaad0dfa051 425
spastor 0:fcaad0dfa051 426 /* Send the start of frame delimiter */
spastor 0:fcaad0dfa051 427 _uart->putc(DR_START_OF_FRAME);
spastor 0:fcaad0dfa051 428
spastor 0:fcaad0dfa051 429 /* Now the length */
spastor 0:fcaad0dfa051 430 send_byte_escaping_if((uint8_t)(frame_len >> 8));
spastor 0:fcaad0dfa051 431 send_byte_escaping_if((uint8_t)frame_len);
spastor 0:fcaad0dfa051 432
spastor 0:fcaad0dfa051 433 /* Send the Frame type and then the payload */
spastor 0:fcaad0dfa051 434 chksum = (uint8_t)frame->get_frame_type();
spastor 0:fcaad0dfa051 435 send_byte_escaping_if(chksum);
spastor 0:fcaad0dfa051 436 bytes_sent++;
spastor 0:fcaad0dfa051 437
spastor 0:fcaad0dfa051 438 /* And now, send the packet payload */
spastor 0:fcaad0dfa051 439 while (bytes_sent++ < frame_len) {
spastor 0:fcaad0dfa051 440 chksum += *data;
spastor 0:fcaad0dfa051 441 send_byte_escaping_if(*data++);
spastor 0:fcaad0dfa051 442 }
spastor 0:fcaad0dfa051 443
spastor 0:fcaad0dfa051 444 /* And finally send the checksum */
spastor 0:fcaad0dfa051 445 send_byte_escaping_if(~chksum);
spastor 0:fcaad0dfa051 446 }
spastor 0:fcaad0dfa051 447
spastor 0:fcaad0dfa051 448 /** */
spastor 0:fcaad0dfa051 449 RadioStatus XBee::register_frame_handler(FrameHandler *const handler)
spastor 0:fcaad0dfa051 450 {
spastor 0:fcaad0dfa051 451 if (handler != NULL) {
spastor 0:fcaad0dfa051 452 for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
spastor 0:fcaad0dfa051 453 if (_fhandlers[i] != NULL)
spastor 0:fcaad0dfa051 454 continue;
spastor 0:fcaad0dfa051 455 _fhandlers[i] = handler;
spastor 0:fcaad0dfa051 456 return Success;
spastor 0:fcaad0dfa051 457 }
spastor 0:fcaad0dfa051 458 }
spastor 0:fcaad0dfa051 459
spastor 0:fcaad0dfa051 460 digi_log(LogLevelError, "No more Frame Handlers available. Increase MAX_FRAME_HANDLERS define\r\n");
spastor 0:fcaad0dfa051 461
spastor 0:fcaad0dfa051 462 return Failure;
spastor 0:fcaad0dfa051 463 }
spastor 0:fcaad0dfa051 464
spastor 0:fcaad0dfa051 465 /** */
spastor 0:fcaad0dfa051 466 RadioStatus XBee::unregister_frame_handler(FrameHandler *const handler)
spastor 0:fcaad0dfa051 467 {
spastor 0:fcaad0dfa051 468 int i;
spastor 0:fcaad0dfa051 469
spastor 0:fcaad0dfa051 470 if (handler != NULL) {
spastor 0:fcaad0dfa051 471 for (i = 0; i < MAX_FRAME_HANDLERS; i++) {
spastor 0:fcaad0dfa051 472 if (_fhandlers[i] == handler)
spastor 0:fcaad0dfa051 473 break;
spastor 0:fcaad0dfa051 474 }
spastor 0:fcaad0dfa051 475
spastor 0:fcaad0dfa051 476 if (i == MAX_FRAME_HANDLERS)
spastor 0:fcaad0dfa051 477 return Failure;
spastor 0:fcaad0dfa051 478
spastor 0:fcaad0dfa051 479 do {
spastor 0:fcaad0dfa051 480 if (i == MAX_FRAME_HANDLERS - 1)
spastor 0:fcaad0dfa051 481 _fhandlers[i] = NULL;
spastor 0:fcaad0dfa051 482 else
spastor 0:fcaad0dfa051 483 _fhandlers[i] = _fhandlers[i + 1];
spastor 0:fcaad0dfa051 484 } while (++i < MAX_FRAME_HANDLERS);
spastor 0:fcaad0dfa051 485 }
spastor 0:fcaad0dfa051 486
spastor 0:fcaad0dfa051 487 return Success;
spastor 0:fcaad0dfa051 488 }
spastor 0:fcaad0dfa051 489
spastor 0:fcaad0dfa051 490 XBee::RadioProtocol XBee::get_radio_protocol(void) const
spastor 0:fcaad0dfa051 491 {
spastor 0:fcaad0dfa051 492 enum HardwareVersion {
spastor 0:fcaad0dfa051 493 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 494 X09_009 = 0x01,
spastor 0:fcaad0dfa051 495 X09_019 = 0x02,
spastor 0:fcaad0dfa051 496 XH9_009 = 0x03,
spastor 0:fcaad0dfa051 497 XH9_019 = 0x04,
spastor 0:fcaad0dfa051 498 X24_009 = 0x05,
spastor 0:fcaad0dfa051 499 X24_019 = 0x06,
spastor 0:fcaad0dfa051 500 X09_001 = 0x07,
spastor 0:fcaad0dfa051 501 XH9_001 = 0x08,
spastor 0:fcaad0dfa051 502 X08_004 = 0x09,
spastor 0:fcaad0dfa051 503 XC09_009 = 0x0A,
spastor 0:fcaad0dfa051 504 XC09_038 = 0x0B,
spastor 0:fcaad0dfa051 505 X24_038 = 0x0C,
spastor 0:fcaad0dfa051 506 X09_009_TX = 0x0D,
spastor 0:fcaad0dfa051 507 X09_019_TX = 0x0E,
spastor 0:fcaad0dfa051 508 XH9_009_TX = 0x0F,
spastor 0:fcaad0dfa051 509 XH9_019_TX = 0x10,
spastor 0:fcaad0dfa051 510 X09_001_TX = 0x11,
spastor 0:fcaad0dfa051 511 XH9_001_TX = 0x12,
spastor 0:fcaad0dfa051 512 XT09B_XXX = 0x13,
spastor 0:fcaad0dfa051 513 XT09_XXX = 0x14,
spastor 0:fcaad0dfa051 514 XC08_009 = 0x15,
spastor 0:fcaad0dfa051 515 XC08_038 = 0x16,
spastor 0:fcaad0dfa051 516 #endif
spastor 0:fcaad0dfa051 517 XB24_AXX_XX = 0x17,
spastor 0:fcaad0dfa051 518 XBP24_AXX_XX = 0x18,
spastor 0:fcaad0dfa051 519 XB24_BXIX_XXX = 0x19,
spastor 0:fcaad0dfa051 520 XBP24_BXIX_XXX = 0x1A,
spastor 0:fcaad0dfa051 521 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 522 XBP09_DXIX_XXX = 0x1B,
spastor 0:fcaad0dfa051 523 XBP09_XCXX_XXX = 0x1C,
spastor 0:fcaad0dfa051 524 XBP08_DXXX_XXX = 0x1D,
spastor 0:fcaad0dfa051 525 #endif
spastor 0:fcaad0dfa051 526 XBP24B = 0x1E,
spastor 0:fcaad0dfa051 527 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 528 XB24_WF = 0x1F,
spastor 0:fcaad0dfa051 529 AMBER_MBUS = 0x20,
spastor 0:fcaad0dfa051 530 #endif
spastor 0:fcaad0dfa051 531 XBP24C = 0x21,
spastor 0:fcaad0dfa051 532 XB24C = 0x22,
spastor 0:fcaad0dfa051 533 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 534 XSC_GEN3 = 0x23,
spastor 0:fcaad0dfa051 535 SRD_868_GEN3 = 0x24,
spastor 0:fcaad0dfa051 536 ABANDONATED = 0x25,
spastor 0:fcaad0dfa051 537 SMT_900LP = 0x26,
spastor 0:fcaad0dfa051 538 WIFI_ATHEROS = 0x27,
spastor 0:fcaad0dfa051 539 SMT_WIFI_ATHEROS = 0x28,
spastor 0:fcaad0dfa051 540 SMT_475LP = 0x29,
spastor 0:fcaad0dfa051 541 XBEE_CELL_TH = 0x2A,
spastor 0:fcaad0dfa051 542 XLR_MODULE = 0x2B,
spastor 0:fcaad0dfa051 543 XB900HP_NZ = 0x2C,
spastor 0:fcaad0dfa051 544 XBP24C_TH_DIP = 0x2D,
spastor 0:fcaad0dfa051 545 XB24C_TH_DIP = 0x2E,
spastor 0:fcaad0dfa051 546 XLR_BASEBOARD = 0x2F
spastor 0:fcaad0dfa051 547 #endif
spastor 0:fcaad0dfa051 548 };
spastor 0:fcaad0dfa051 549 const bool fw_4_bytes_len = _fw_version > 0x0FFF && _fw_version < 0xFFFF;
spastor 0:fcaad0dfa051 550 const uint8_t fw_nibble_3 = (_fw_version >> (4 * 3)) & 0x000F;
spastor 0:fcaad0dfa051 551 const uint8_t fw_nibble_1 = (_fw_version >> (4 * 1)) & 0x000F;
spastor 0:fcaad0dfa051 552 const uint8_t fw_nibble_0 = (_fw_version >> (4 * 0)) & 0x000F;
spastor 0:fcaad0dfa051 553 const uint8_t hw_version_msb = _hw_version >> 8;
spastor 0:fcaad0dfa051 554
spastor 0:fcaad0dfa051 555 if (hw_version_msb == XB24_AXX_XX || hw_version_msb == XBP24_AXX_XX) {
spastor 0:fcaad0dfa051 556 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 557 if (fw_4_bytes_len && fw_nibble_3 == 8) {
spastor 0:fcaad0dfa051 558 return DigiMesh;
spastor 0:fcaad0dfa051 559 }
spastor 0:fcaad0dfa051 560 return Raw_802_15_4;
spastor 0:fcaad0dfa051 561 #else
spastor 0:fcaad0dfa051 562 if (!(fw_4_bytes_len && fw_nibble_3 == 8)) {
spastor 0:fcaad0dfa051 563 return Raw_802_15_4;
spastor 0:fcaad0dfa051 564 }
spastor 0:fcaad0dfa051 565 #endif
spastor 0:fcaad0dfa051 566 } else if (hw_version_msb == XB24_BXIX_XXX || hw_version_msb == XBP24_BXIX_XXX) {
spastor 0:fcaad0dfa051 567 if (fw_4_bytes_len && ((fw_nibble_3 == 1 && fw_nibble_1 == 2 && fw_nibble_0 == 0) || fw_nibble_3 == 2)) {
spastor 0:fcaad0dfa051 568 return ZigBee;
spastor 0:fcaad0dfa051 569 }
spastor 0:fcaad0dfa051 570 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 571 if (fw_4_bytes_len && fw_nibble_3 == 3) {
spastor 0:fcaad0dfa051 572 return SmartEnergy;
spastor 0:fcaad0dfa051 573 }
spastor 0:fcaad0dfa051 574 return ZNet;
spastor 0:fcaad0dfa051 575 } else if (hw_version_msb == XBP09_DXIX_XXX) {
spastor 0:fcaad0dfa051 576 if (fw_4_bytes_len && (fw_nibble_3 == 8 || fw_nibble_1 == 8)) {
spastor 0:fcaad0dfa051 577 return DigiMesh;
spastor 0:fcaad0dfa051 578 }
spastor 0:fcaad0dfa051 579 return DigiPoint;
spastor 0:fcaad0dfa051 580 } else if (hw_version_msb == XBP08_DXXX_XXX) {
spastor 0:fcaad0dfa051 581 return DigiPoint;
spastor 0:fcaad0dfa051 582 #endif
spastor 0:fcaad0dfa051 583 } else if (hw_version_msb == XBP24B) {
spastor 0:fcaad0dfa051 584 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 585 if (fw_4_bytes_len && fw_nibble_3 == 3) {
spastor 0:fcaad0dfa051 586 return SmartEnergy;
spastor 0:fcaad0dfa051 587 }
spastor 0:fcaad0dfa051 588 return ZigBee;
spastor 0:fcaad0dfa051 589 #else
spastor 0:fcaad0dfa051 590 if (!(fw_4_bytes_len && fw_nibble_3 == 3)) {
spastor 0:fcaad0dfa051 591 return ZigBee;
spastor 0:fcaad0dfa051 592 }
spastor 0:fcaad0dfa051 593 #endif
spastor 0:fcaad0dfa051 594 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 595 } else if (hw_version_msb == XB24_WF || hw_version_msb == WIFI_ATHEROS || hw_version_msb == SMT_WIFI_ATHEROS) {
spastor 0:fcaad0dfa051 596 return XBeeWiFi;
spastor 0:fcaad0dfa051 597 #endif
spastor 0:fcaad0dfa051 598 } else if (hw_version_msb == XBP24C || hw_version_msb == XB24C) {
spastor 0:fcaad0dfa051 599 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 600 if (fw_4_bytes_len && fw_nibble_3 == 5) {
spastor 0:fcaad0dfa051 601 return SmartEnergy;
spastor 0:fcaad0dfa051 602 }
spastor 0:fcaad0dfa051 603 return ZigBee;
spastor 0:fcaad0dfa051 604 #else
spastor 0:fcaad0dfa051 605 if (!(fw_4_bytes_len && fw_nibble_3 == 5)) {
spastor 0:fcaad0dfa051 606 return ZigBee;
spastor 0:fcaad0dfa051 607 }
spastor 0:fcaad0dfa051 608 #endif
spastor 0:fcaad0dfa051 609 #ifdef EXTRA_XBEE_PROTOCOLS
spastor 0:fcaad0dfa051 610 } else if (hw_version_msb == XSC_GEN3 || hw_version_msb == SRD_868_GEN3) {
spastor 0:fcaad0dfa051 611 if (fw_4_bytes_len && fw_nibble_3 == 8) {
spastor 0:fcaad0dfa051 612 return DigiMesh;
spastor 0:fcaad0dfa051 613 } else if (fw_4_bytes_len && fw_nibble_3 == 1) {
spastor 0:fcaad0dfa051 614 return DigiPoint;
spastor 0:fcaad0dfa051 615 }
spastor 0:fcaad0dfa051 616 return None;
spastor 0:fcaad0dfa051 617 } else if (hw_version_msb == XBEE_CELL_TH) {
spastor 0:fcaad0dfa051 618 return None;
spastor 0:fcaad0dfa051 619 } else if (hw_version_msb == XLR_MODULE) {
spastor 0:fcaad0dfa051 620 return None;
spastor 0:fcaad0dfa051 621 } else if (hw_version_msb == XLR_BASEBOARD) {
spastor 0:fcaad0dfa051 622 return None;
spastor 0:fcaad0dfa051 623 } else if (hw_version_msb == XB900HP_NZ) {
spastor 0:fcaad0dfa051 624 return DigiPoint;
spastor 0:fcaad0dfa051 625 }
spastor 0:fcaad0dfa051 626 #else
spastor 0:fcaad0dfa051 627 }
spastor 0:fcaad0dfa051 628 #endif
spastor 0:fcaad0dfa051 629
spastor 0:fcaad0dfa051 630 return None;
spastor 0:fcaad0dfa051 631 }
spastor 0:fcaad0dfa051 632
spastor 0:fcaad0dfa051 633 #define TX_STATUS_OFFSET_ZB 4
spastor 0:fcaad0dfa051 634 #define TX_STATUS_OFFSET_802 1
spastor 0:fcaad0dfa051 635
spastor 0:fcaad0dfa051 636 TxStatus XBee::send_data(ApiFrame *frame)
spastor 0:fcaad0dfa051 637 {
spastor 0:fcaad0dfa051 638 TxStatus resp = TxStatusTimeout;
spastor 0:fcaad0dfa051 639 ApiFrame *resp_frame;
spastor 0:fcaad0dfa051 640
spastor 0:fcaad0dfa051 641 send_api_frame(frame);
spastor 0:fcaad0dfa051 642
spastor 0:fcaad0dfa051 643 /* Wait for the transmit status response packet */
spastor 0:fcaad0dfa051 644 resp_frame = get_this_api_frame(frame->get_frame_id(),
spastor 0:fcaad0dfa051 645 ApiFrame::TxStatusZB, ApiFrame::TxStatus);
spastor 0:fcaad0dfa051 646 if (resp_frame == NULL)
spastor 0:fcaad0dfa051 647 return resp;
spastor 0:fcaad0dfa051 648
spastor 0:fcaad0dfa051 649 uint8_t index = resp_frame->get_frame_type() == ApiFrame::TxStatusZB ?
spastor 0:fcaad0dfa051 650 TX_STATUS_OFFSET_ZB : TX_STATUS_OFFSET_802;
spastor 0:fcaad0dfa051 651
spastor 0:fcaad0dfa051 652 resp = (TxStatus)resp_frame->get_data_at(index);
spastor 0:fcaad0dfa051 653
spastor 0:fcaad0dfa051 654 /* Once processed, remove the frame from the buffer */
spastor 0:fcaad0dfa051 655 _framebuf.free_frame(resp_frame);
spastor 0:fcaad0dfa051 656
spastor 0:fcaad0dfa051 657 return resp;
spastor 0:fcaad0dfa051 658 }
spastor 0:fcaad0dfa051 659
spastor 3:8662ebe83570 660 TxStatus XBee::send_data_broadcast(const uint8_t *const data, uint16_t len, bool syncr)
spastor 0:fcaad0dfa051 661 {
spastor 0:fcaad0dfa051 662 const RemoteXBee remoteDevice = RemoteXBee(ADDR64_BROADCAST);
spastor 3:8662ebe83570 663 return send_data(remoteDevice, data, len, syncr);
spastor 0:fcaad0dfa051 664 }
spastor 0:fcaad0dfa051 665
spastor 0:fcaad0dfa051 666 #if defined(ENABLE_PM_SUPPORT)
spastor 0:fcaad0dfa051 667
spastor 0:fcaad0dfa051 668 RadioStatus XBee::set_pm_control(PmMode mode, PinName on_sleep, PinName sleep_rq)
spastor 0:fcaad0dfa051 669 {
spastor 0:fcaad0dfa051 670 if (on_sleep != NC) {
spastor 0:fcaad0dfa051 671 _on_sleep = new InterruptIn(on_sleep);
spastor 0:fcaad0dfa051 672 }
spastor 0:fcaad0dfa051 673 if (sleep_rq != NC) {
spastor 0:fcaad0dfa051 674 _sleep_req = new DigitalOut(sleep_rq);
spastor 0:fcaad0dfa051 675 }
spastor 0:fcaad0dfa051 676 _pm_mode = mode;
spastor 0:fcaad0dfa051 677 /* TODO, set PM mode in the radio */
spastor 0:fcaad0dfa051 678 //return 0;
spastor 0:fcaad0dfa051 679 return Success;
spastor 0:fcaad0dfa051 680 }
spastor 0:fcaad0dfa051 681
spastor 0:fcaad0dfa051 682
spastor 0:fcaad0dfa051 683 RadioStatus XBee::get_pm_mode(PmMode *mode)
spastor 0:fcaad0dfa051 684 {
spastor 0:fcaad0dfa051 685 *mode = _pm_mode;
spastor 0:fcaad0dfa051 686 return Success;
spastor 0:fcaad0dfa051 687 }
spastor 0:fcaad0dfa051 688
spastor 0:fcaad0dfa051 689 RadioStatus XBee::config_pm_timing(uint32_t before_sleep_ms, uint32_t total_sleep_period_ms)
spastor 0:fcaad0dfa051 690 {
hbujanda 2:2ee1b6d51df2 691 UNUSED_PARAMETER(before_sleep_ms);
hbujanda 2:2ee1b6d51df2 692 UNUSED_PARAMETER(total_sleep_period_ms);
spastor 0:fcaad0dfa051 693 return Success;
spastor 0:fcaad0dfa051 694 }
spastor 0:fcaad0dfa051 695
spastor 0:fcaad0dfa051 696 RadioStatus XBee::enter_sleep_mode()
spastor 0:fcaad0dfa051 697 {
spastor 0:fcaad0dfa051 698 if (_sleep_req == NULL)
spastor 0:fcaad0dfa051 699 return sleep_now();
spastor 0:fcaad0dfa051 700
spastor 0:fcaad0dfa051 701 _sleep_req->write(1);
spastor 0:fcaad0dfa051 702 return Success;
spastor 0:fcaad0dfa051 703 }
spastor 0:fcaad0dfa051 704
spastor 0:fcaad0dfa051 705 void XBee::exit_sleep_mode()
spastor 0:fcaad0dfa051 706 {
spastor 0:fcaad0dfa051 707 /* TODO, check also mode? */
spastor 0:fcaad0dfa051 708 if (_sleep_req != NULL)
spastor 0:fcaad0dfa051 709 _sleep_req->write(0);
spastor 0:fcaad0dfa051 710 }
spastor 0:fcaad0dfa051 711
spastor 0:fcaad0dfa051 712 bool XBee::is_sleeping()
spastor 0:fcaad0dfa051 713 {
spastor 0:fcaad0dfa051 714 /* TODO */
spastor 0:fcaad0dfa051 715 return true;
spastor 0:fcaad0dfa051 716 }
spastor 0:fcaad0dfa051 717
spastor 0:fcaad0dfa051 718
spastor 0:fcaad0dfa051 719
spastor 0:fcaad0dfa051 720 void XBee::register_wakeup_cb(void (*f)(void))
spastor 0:fcaad0dfa051 721 {
spastor 0:fcaad0dfa051 722 if (_on_sleep == NULL)
spastor 0:fcaad0dfa051 723 return;
spastor 0:fcaad0dfa051 724
spastor 0:fcaad0dfa051 725 _on_sleep->rise(f);
spastor 0:fcaad0dfa051 726 }
spastor 0:fcaad0dfa051 727
spastor 0:fcaad0dfa051 728 void XBee::unregister_wakeup_cb()
spastor 0:fcaad0dfa051 729 {
spastor 0:fcaad0dfa051 730 _on_sleep->disable_irq();
spastor 0:fcaad0dfa051 731 _on_sleep->rise(NULL);
spastor 0:fcaad0dfa051 732 }
spastor 0:fcaad0dfa051 733
spastor 0:fcaad0dfa051 734 #endif /* defined(ENABLE_PM_SUPPORT) */
spastor 0:fcaad0dfa051 735
spastor 0:fcaad0dfa051 736
spastor 0:fcaad0dfa051 737 uint32_t XBee::process_rx_frames(void)
spastor 0:fcaad0dfa051 738 {
spastor 0:fcaad0dfa051 739 ApiFrame *frame = NULL;
spastor 0:fcaad0dfa051 740
spastor 0:fcaad0dfa051 741 while ((frame = _framebuf.get_next_complete_frame_app()) != NULL) {
spastor 0:fcaad0dfa051 742 for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
spastor 0:fcaad0dfa051 743
spastor 0:fcaad0dfa051 744 if (_fhandlers[i] == NULL) {
spastor 0:fcaad0dfa051 745 /* No more handlers, break here */
spastor 0:fcaad0dfa051 746 break;
spastor 0:fcaad0dfa051 747 }
spastor 0:fcaad0dfa051 748
spastor 0:fcaad0dfa051 749 /* Check if frame and handler match, if not... go for the next one */
spastor 0:fcaad0dfa051 750 if (frame->get_frame_type() != _fhandlers[i]->get_type()) {
spastor 0:fcaad0dfa051 751 continue;
spastor 0:fcaad0dfa051 752 }
spastor 0:fcaad0dfa051 753
spastor 0:fcaad0dfa051 754 _fhandlers[i]->process_frame_data(frame);
spastor 0:fcaad0dfa051 755 }
spastor 0:fcaad0dfa051 756
spastor 0:fcaad0dfa051 757 /* Once processed, remove the frame from the buffer */
spastor 0:fcaad0dfa051 758 _framebuf.free_frame(frame);
spastor 0:fcaad0dfa051 759 }
spastor 0:fcaad0dfa051 760
spastor 0:fcaad0dfa051 761 return _framebuf.get_dropped_frames_count();
spastor 0:fcaad0dfa051 762 }
spastor 0:fcaad0dfa051 763
spastor 0:fcaad0dfa051 764 void XBee::register_modem_status_cb(modem_status_cb_t function)
spastor 0:fcaad0dfa051 765 {
spastor 0:fcaad0dfa051 766 if (_modem_status_handler == NULL) {
spastor 0:fcaad0dfa051 767 _modem_status_handler = new FH_ModemStatus();
spastor 0:fcaad0dfa051 768 register_frame_handler(_modem_status_handler);
spastor 0:fcaad0dfa051 769 }
spastor 0:fcaad0dfa051 770 _modem_status_handler->register_modem_status_cb(function);
spastor 0:fcaad0dfa051 771 }
spastor 0:fcaad0dfa051 772
spastor 0:fcaad0dfa051 773 void XBee::unregister_modem_status_cb()
spastor 0:fcaad0dfa051 774 {
spastor 0:fcaad0dfa051 775 if (_modem_status_handler != NULL) {
spastor 0:fcaad0dfa051 776 _modem_status_handler->unregister_modem_status_cb();
spastor 0:fcaad0dfa051 777 unregister_frame_handler(_modem_status_handler);
spastor 0:fcaad0dfa051 778 delete _modem_status_handler;
spastor 0:fcaad0dfa051 779 _modem_status_handler = NULL; /* as delete does not set to NULL */
spastor 0:fcaad0dfa051 780 }
spastor 0:fcaad0dfa051 781 }
spastor 0:fcaad0dfa051 782