XBee modules

Dependencies:   DigiLogger

Fork of XBeeLib by Digi International Inc.

Committer:
hbujanda
Date:
Thu Jul 28 15:36:36 2016 +0200
Revision:
7:3ac2a461ce76
Parent:
6:06522f3a6642
Child:
8:b5f4a0e92249
Automatic upload

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hbujanda 6:06522f3a6642 1 /**
hbujanda 6:06522f3a6642 2 * Copyright (c) 2015 Digi International Inc.,
hbujanda 6:06522f3a6642 3 * All rights not expressly granted are reserved.
hbujanda 6:06522f3a6642 4 *
hbujanda 6:06522f3a6642 5 * This Source Code Form is subject to the terms of the Mozilla Public
hbujanda 6:06522f3a6642 6 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
hbujanda 6:06522f3a6642 7 * You can obtain one at http://mozilla.org/MPL/2.0/.
hbujanda 6:06522f3a6642 8 *
hbujanda 6:06522f3a6642 9 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
hbujanda 6:06522f3a6642 10 * =======================================================================
hbujanda 6:06522f3a6642 11 */
hbujanda 6:06522f3a6642 12
hbujanda 6:06522f3a6642 13 #include "XBeeDM.h"
hbujanda 6:06522f3a6642 14 #include "IO/IOSampleDM.h"
hbujanda 6:06522f3a6642 15 #include "Frames/DigiMeshFrames.h"
hbujanda 6:06522f3a6642 16
hbujanda 6:06522f3a6642 17 using namespace XBeeLib;
hbujanda 6:06522f3a6642 18
hbujanda 6:06522f3a6642 19 #define BROADCAST_RADIUS_USE_NH 0x00
hbujanda 6:06522f3a6642 20
hbujanda 6:06522f3a6642 21 /* Class constructor */
hbujanda 6:06522f3a6642 22 XBeeDM::XBeeDM(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
hbujanda 6:06522f3a6642 23 XBee(tx, rx, reset, rts, cts, baud), _nd_handler(NULL), _rx_pkt_handler(NULL), _io_data_handler(NULL)
hbujanda 6:06522f3a6642 24 {
hbujanda 6:06522f3a6642 25 }
hbujanda 6:06522f3a6642 26
hbujanda 6:06522f3a6642 27 RadioStatus XBeeDM::init()
hbujanda 6:06522f3a6642 28 {
hbujanda 6:06522f3a6642 29 RadioStatus retval = XBee::init();
hbujanda 6:06522f3a6642 30
hbujanda 6:06522f3a6642 31 const RadioProtocol radioProtocol = get_radio_protocol();
hbujanda 6:06522f3a6642 32 if (radioProtocol != DigiMesh) {
hbujanda 6:06522f3a6642 33 digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", DigiMesh, radioProtocol);
hbujanda 6:06522f3a6642 34 retval = Failure;
hbujanda 6:06522f3a6642 35 }
hbujanda 6:06522f3a6642 36 assert(radioProtocol == DigiMesh);
hbujanda 6:06522f3a6642 37
hbujanda 6:06522f3a6642 38 return retval;
hbujanda 6:06522f3a6642 39 }
hbujanda 6:06522f3a6642 40
hbujanda 6:06522f3a6642 41 /* Class destructor */
hbujanda 6:06522f3a6642 42 XBeeDM::~XBeeDM()
hbujanda 6:06522f3a6642 43 {
hbujanda 6:06522f3a6642 44 unregister_node_discovery_cb();
hbujanda 6:06522f3a6642 45 unregister_receive_cb();
hbujanda 6:06522f3a6642 46 unregister_io_sample_cb();
hbujanda 6:06522f3a6642 47 }
hbujanda 6:06522f3a6642 48
hbujanda 6:06522f3a6642 49 RadioStatus XBeeDM::set_channel(uint8_t channel)
hbujanda 6:06522f3a6642 50 {
hbujanda 6:06522f3a6642 51 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 52
hbujanda 6:06522f3a6642 53 /* Pro and Non-Pro modules have different channels available. The at
hbujanda 6:06522f3a6642 54 command will return an error if the selected channel is not available */
hbujanda 6:06522f3a6642 55 cmdresp = set_param("CH", channel);
hbujanda 6:06522f3a6642 56 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 57 return Failure;
hbujanda 6:06522f3a6642 58 }
hbujanda 6:06522f3a6642 59 return Success;
hbujanda 6:06522f3a6642 60 }
hbujanda 6:06522f3a6642 61
hbujanda 6:06522f3a6642 62 RadioStatus XBeeDM::get_channel(uint8_t * const channel)
hbujanda 6:06522f3a6642 63 {
hbujanda 6:06522f3a6642 64 if (channel == NULL) {
hbujanda 6:06522f3a6642 65 return Failure;
hbujanda 6:06522f3a6642 66 }
hbujanda 6:06522f3a6642 67 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 68
hbujanda 6:06522f3a6642 69 uint32_t var32;
hbujanda 6:06522f3a6642 70 cmdresp = get_param("CH", &var32);
hbujanda 6:06522f3a6642 71 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 72 return Failure;
hbujanda 6:06522f3a6642 73 }
hbujanda 6:06522f3a6642 74 *channel = var32;
hbujanda 6:06522f3a6642 75 return Success;
hbujanda 6:06522f3a6642 76 }
hbujanda 6:06522f3a6642 77
hbujanda 6:06522f3a6642 78 RadioStatus XBeeDM::set_network_id(uint16_t network_id)
hbujanda 6:06522f3a6642 79 {
hbujanda 6:06522f3a6642 80 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 81
hbujanda 6:06522f3a6642 82 cmdresp = set_param("ID", network_id);
hbujanda 6:06522f3a6642 83 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 84 return Failure;
hbujanda 6:06522f3a6642 85 }
hbujanda 6:06522f3a6642 86 return Success;
hbujanda 6:06522f3a6642 87 }
hbujanda 6:06522f3a6642 88
hbujanda 6:06522f3a6642 89 RadioStatus XBeeDM::get_network_id(uint16_t * const network_id)
hbujanda 6:06522f3a6642 90 {
hbujanda 6:06522f3a6642 91 if (network_id == NULL) {
hbujanda 6:06522f3a6642 92 return Failure;
hbujanda 6:06522f3a6642 93 }
hbujanda 6:06522f3a6642 94 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 95
hbujanda 6:06522f3a6642 96 uint32_t var32;
hbujanda 6:06522f3a6642 97 cmdresp = get_param("ID", &var32);
hbujanda 6:06522f3a6642 98 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 99 return Failure;
hbujanda 6:06522f3a6642 100 }
hbujanda 6:06522f3a6642 101 *network_id = var32;
hbujanda 6:06522f3a6642 102 return Success;
hbujanda 6:06522f3a6642 103 }
hbujanda 6:06522f3a6642 104
hbujanda 6:06522f3a6642 105 RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms)
hbujanda 6:06522f3a6642 106 {
hbujanda 6:06522f3a6642 107 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 108 uint32_t var32;
hbujanda 6:06522f3a6642 109
hbujanda 6:06522f3a6642 110 cmdresp = get_param("N?", &var32);
hbujanda 6:06522f3a6642 111 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 112 return Failure;
hbujanda 6:06522f3a6642 113 }
hbujanda 6:06522f3a6642 114 *timeout_ms = (uint16_t)var32;
hbujanda 6:06522f3a6642 115
hbujanda 6:06522f3a6642 116 return Success;
hbujanda 6:06522f3a6642 117 }
hbujanda 6:06522f3a6642 118
hbujanda 6:06522f3a6642 119 RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
hbujanda 6:06522f3a6642 120 {
hbujanda 6:06522f3a6642 121 const RadioStatus status = get_node_discovery_timeout(timeout_ms);
hbujanda 6:06522f3a6642 122
hbujanda 6:06522f3a6642 123 *wait_for_complete_timeout = false;
hbujanda 6:06522f3a6642 124
hbujanda 6:06522f3a6642 125 return status;
hbujanda 6:06522f3a6642 126 }
hbujanda 6:06522f3a6642 127
hbujanda 6:06522f3a6642 128 RadioStatus XBeeDM::set_network_security_key(const uint8_t * const key, const uint16_t length)
hbujanda 6:06522f3a6642 129 {
hbujanda 6:06522f3a6642 130 if (key == NULL || length == 0 || length > 16) {
hbujanda 6:06522f3a6642 131 return Failure;
hbujanda 6:06522f3a6642 132 }
hbujanda 6:06522f3a6642 133 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 134
hbujanda 6:06522f3a6642 135 cmdresp = set_param("NK", key, length);
hbujanda 6:06522f3a6642 136 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
hbujanda 6:06522f3a6642 137 }
hbujanda 6:06522f3a6642 138
hbujanda 6:06522f3a6642 139 RadioStatus XBeeDM::set_encryption_options(const uint8_t options)
hbujanda 6:06522f3a6642 140 {
hbujanda 6:06522f3a6642 141 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 142
hbujanda 6:06522f3a6642 143 cmdresp = set_param("EO", options);
hbujanda 6:06522f3a6642 144 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
hbujanda 6:06522f3a6642 145 }
hbujanda 6:06522f3a6642 146
hbujanda 6:06522f3a6642 147 void XBeeDM::radio_status_update(AtCmdFrame::ModemStatus modem_status)
hbujanda 6:06522f3a6642 148 {
hbujanda 6:06522f3a6642 149 /* Update the radio status variables */
hbujanda 6:06522f3a6642 150 if (modem_status == AtCmdFrame::HwReset) {
hbujanda 6:06522f3a6642 151 _hw_reset_cnt++;
hbujanda 6:06522f3a6642 152 } else if (modem_status == AtCmdFrame::WdReset) {
hbujanda 6:06522f3a6642 153 _wd_reset_cnt++;
hbujanda 6:06522f3a6642 154 }
hbujanda 6:06522f3a6642 155
hbujanda 6:06522f3a6642 156 _modem_status = modem_status;
hbujanda 6:06522f3a6642 157
hbujanda 6:06522f3a6642 158 digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
hbujanda 6:06522f3a6642 159 }
hbujanda 6:06522f3a6642 160
hbujanda 6:06522f3a6642 161 TxStatus XBeeDM::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 162 {
hbujanda 6:06522f3a6642 163 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 164 return TxStatusInvalidAddr;
hbujanda 6:06522f3a6642 165 }
hbujanda 6:06522f3a6642 166
hbujanda 6:06522f3a6642 167 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 168 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 169
hbujanda 6:06522f3a6642 170 TxFrameDM frame = TxFrameDM(remote64, remote16, BROADCAST_RADIUS_USE_NH,
hbujanda 6:06522f3a6642 171 _tx_options, data, len);
hbujanda 6:06522f3a6642 172 if (syncr) {
hbujanda 6:06522f3a6642 173 return send_data(&frame);
hbujanda 6:06522f3a6642 174 } else {
hbujanda 6:06522f3a6642 175 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 176 send_api_frame(&frame);
hbujanda 6:06522f3a6642 177 return TxStatusSuccess;
hbujanda 6:06522f3a6642 178 }
hbujanda 6:06522f3a6642 179 }
hbujanda 6:06522f3a6642 180
hbujanda 6:06522f3a6642 181 TxStatus XBeeDM::send_data(const RemoteXBee& remote, uint8_t source_ep,
hbujanda 6:06522f3a6642 182 uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
hbujanda 6:06522f3a6642 183 const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 184 {
hbujanda 6:06522f3a6642 185 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 186 return TxStatusInvalidAddr;
hbujanda 6:06522f3a6642 187 }
hbujanda 6:06522f3a6642 188
hbujanda 6:06522f3a6642 189 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 190 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 191
hbujanda 6:06522f3a6642 192 TxFrameDM frame = TxFrameDM(remote64, remote16, source_ep, dest_ep,
hbujanda 6:06522f3a6642 193 cluster_id, profile_id, BROADCAST_RADIUS_USE_NH,
hbujanda 6:06522f3a6642 194 _tx_options, data, len);
hbujanda 6:06522f3a6642 195 if (syncr) {
hbujanda 6:06522f3a6642 196 return send_data(&frame);
hbujanda 6:06522f3a6642 197 } else {
hbujanda 6:06522f3a6642 198 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 199 send_api_frame(&frame);
hbujanda 6:06522f3a6642 200 return TxStatusSuccess;
hbujanda 6:06522f3a6642 201 }
hbujanda 6:06522f3a6642 202 }
hbujanda 6:06522f3a6642 203
hbujanda 6:06522f3a6642 204 TxStatus XBeeDM::send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 205 {
hbujanda 6:06522f3a6642 206 const uint64_t remaddr = ADDR64_COORDINATOR;
hbujanda 6:06522f3a6642 207
hbujanda 6:06522f3a6642 208 TxFrameDM frame = TxFrameDM(remaddr, ADDR16_UNKNOWN, BROADCAST_RADIUS_USE_NH, _tx_options, data, len);
hbujanda 6:06522f3a6642 209 if (syncr) {
hbujanda 6:06522f3a6642 210 return send_data(&frame);
hbujanda 6:06522f3a6642 211 } else {
hbujanda 6:06522f3a6642 212 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 213 send_api_frame(&frame);
hbujanda 6:06522f3a6642 214 return TxStatusSuccess;
hbujanda 6:06522f3a6642 215 }
hbujanda 6:06522f3a6642 216 }
hbujanda 6:06522f3a6642 217
hbujanda 6:06522f3a6642 218 RemoteXBeeDM XBeeDM::get_remote_node_by_id(const char * const node_id)
hbujanda 6:06522f3a6642 219 {
hbujanda 6:06522f3a6642 220 uint64_t addr64;
hbujanda 6:06522f3a6642 221 uint16_t addr16;
hbujanda 6:06522f3a6642 222 _get_remote_node_by_id(node_id, &addr64, &addr16);
hbujanda 6:06522f3a6642 223 return RemoteXBeeDM(addr64);
hbujanda 6:06522f3a6642 224 }
hbujanda 6:06522f3a6642 225
hbujanda 6:06522f3a6642 226 XBeeDM::AssocStatus XBeeDM::get_assoc_status(void)
hbujanda 6:06522f3a6642 227 {
hbujanda 6:06522f3a6642 228 return (AssocStatus)get_AI();
hbujanda 6:06522f3a6642 229 }
hbujanda 6:06522f3a6642 230
hbujanda 6:06522f3a6642 231 void XBeeDM::register_node_discovery_cb(node_discovery_dm_cb_t function)
hbujanda 6:06522f3a6642 232 {
hbujanda 6:06522f3a6642 233 if (_nd_handler == NULL) {
hbujanda 6:06522f3a6642 234 _nd_handler = new FH_NodeDiscoveryDM();
hbujanda 6:06522f3a6642 235 register_frame_handler(_nd_handler);
hbujanda 6:06522f3a6642 236 }
hbujanda 6:06522f3a6642 237 _nd_handler->register_node_discovery_cb(function);
hbujanda 6:06522f3a6642 238 }
hbujanda 6:06522f3a6642 239
hbujanda 6:06522f3a6642 240 void XBeeDM::unregister_node_discovery_cb()
hbujanda 6:06522f3a6642 241 {
hbujanda 6:06522f3a6642 242 if (_nd_handler != NULL) {
hbujanda 6:06522f3a6642 243 _nd_handler->unregister_node_discovery_cb();
hbujanda 6:06522f3a6642 244 unregister_frame_handler(_nd_handler);
hbujanda 6:06522f3a6642 245 delete _nd_handler;
hbujanda 6:06522f3a6642 246 _nd_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 247 }
hbujanda 6:06522f3a6642 248 }
hbujanda 6:06522f3a6642 249
hbujanda 6:06522f3a6642 250 void XBeeDM::register_receive_cb(receive_dm_cb_t function)
hbujanda 6:06522f3a6642 251 {
hbujanda 6:06522f3a6642 252 if (_rx_pkt_handler == NULL) {
hbujanda 6:06522f3a6642 253 _rx_pkt_handler = new FH_RxPacketDM();
hbujanda 6:06522f3a6642 254 register_frame_handler(_rx_pkt_handler);
hbujanda 6:06522f3a6642 255 }
hbujanda 6:06522f3a6642 256 _rx_pkt_handler->register_receive_cb(function);
hbujanda 6:06522f3a6642 257 }
hbujanda 6:06522f3a6642 258
hbujanda 6:06522f3a6642 259 void XBeeDM::unregister_receive_cb()
hbujanda 6:06522f3a6642 260 {
hbujanda 6:06522f3a6642 261 if (_rx_pkt_handler != NULL) {
hbujanda 6:06522f3a6642 262 _rx_pkt_handler->unregister_receive_cb();
hbujanda 6:06522f3a6642 263 unregister_frame_handler(_rx_pkt_handler);
hbujanda 6:06522f3a6642 264 delete _rx_pkt_handler;
hbujanda 6:06522f3a6642 265 _rx_pkt_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 266 }
hbujanda 6:06522f3a6642 267 }
hbujanda 6:06522f3a6642 268
hbujanda 6:06522f3a6642 269 void XBeeDM::register_io_sample_cb(io_data_cb_dm_t function)
hbujanda 6:06522f3a6642 270 {
hbujanda 6:06522f3a6642 271 if (_io_data_handler == NULL) {
hbujanda 6:06522f3a6642 272 _io_data_handler = new FH_IoDataSampeDM();
hbujanda 6:06522f3a6642 273 register_frame_handler(_io_data_handler);
hbujanda 6:06522f3a6642 274 }
hbujanda 6:06522f3a6642 275 _io_data_handler->register_io_data_cb(function);
hbujanda 6:06522f3a6642 276 }
hbujanda 6:06522f3a6642 277
hbujanda 6:06522f3a6642 278 void XBeeDM::unregister_io_sample_cb()
hbujanda 6:06522f3a6642 279 {
hbujanda 6:06522f3a6642 280 if (_io_data_handler != NULL) {
hbujanda 6:06522f3a6642 281 _io_data_handler->unregister_io_data_cb();
hbujanda 6:06522f3a6642 282 unregister_frame_handler(_io_data_handler);
hbujanda 6:06522f3a6642 283 delete _io_data_handler;
hbujanda 6:06522f3a6642 284 _io_data_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 285 }
hbujanda 6:06522f3a6642 286 }
hbujanda 6:06522f3a6642 287
hbujanda 6:06522f3a6642 288 AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data)
hbujanda 6:06522f3a6642 289 {
hbujanda 6:06522f3a6642 290 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 291 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 292 }
hbujanda 6:06522f3a6642 293
hbujanda 6:06522f3a6642 294 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 295 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 296 uint16_t len = sizeof *data;
hbujanda 6:06522f3a6642 297 AtCmdFrame::AtCmdResp atCmdResponse;
hbujanda 6:06522f3a6642 298
hbujanda 6:06522f3a6642 299 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
hbujanda 6:06522f3a6642 300 atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote);
hbujanda 6:06522f3a6642 301
hbujanda 6:06522f3a6642 302 if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) {
hbujanda 6:06522f3a6642 303 atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
hbujanda 6:06522f3a6642 304 }
hbujanda 6:06522f3a6642 305
hbujanda 6:06522f3a6642 306 return atCmdResponse;
hbujanda 6:06522f3a6642 307 }
hbujanda 6:06522f3a6642 308
hbujanda 6:06522f3a6642 309 AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, uint32_t data)
hbujanda 6:06522f3a6642 310 {
hbujanda 6:06522f3a6642 311 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 312 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 313 }
hbujanda 6:06522f3a6642 314
hbujanda 6:06522f3a6642 315 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 316 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 317
hbujanda 6:06522f3a6642 318 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data);
hbujanda 6:06522f3a6642 319 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
hbujanda 6:06522f3a6642 320 }
hbujanda 6:06522f3a6642 321
hbujanda 6:06522f3a6642 322 AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len)
hbujanda 6:06522f3a6642 323 {
hbujanda 6:06522f3a6642 324 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 325 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 326 }
hbujanda 6:06522f3a6642 327
hbujanda 6:06522f3a6642 328 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 329 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 330
hbujanda 6:06522f3a6642 331 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data, len);
hbujanda 6:06522f3a6642 332 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
hbujanda 6:06522f3a6642 333 }
hbujanda 6:06522f3a6642 334
hbujanda 6:06522f3a6642 335 AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len)
hbujanda 6:06522f3a6642 336 {
hbujanda 6:06522f3a6642 337
hbujanda 6:06522f3a6642 338 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 339 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 340 }
hbujanda 6:06522f3a6642 341
hbujanda 6:06522f3a6642 342 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 343 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 344
hbujanda 6:06522f3a6642 345 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
hbujanda 6:06522f3a6642 346 return send_at_cmd(&cmd_frame, data, len, RadioRemote, false);
hbujanda 6:06522f3a6642 347 }
hbujanda 6:06522f3a6642 348
hbujanda 6:06522f3a6642 349 static void get_dio_cmd(XBeeDM::IoLine line, char * const iocmd)
hbujanda 6:06522f3a6642 350 {
hbujanda 6:06522f3a6642 351 if (line >= XBeeDM::DIO10_PWM0) {
hbujanda 6:06522f3a6642 352 iocmd[0] = 'P';
hbujanda 6:06522f3a6642 353 iocmd[1] = '0' + line - XBeeDM::DIO10_PWM0;
hbujanda 6:06522f3a6642 354 } else {
hbujanda 6:06522f3a6642 355 iocmd[0] = 'D';
hbujanda 6:06522f3a6642 356 iocmd[1] = '0' + line;
hbujanda 6:06522f3a6642 357 }
hbujanda 6:06522f3a6642 358 iocmd[2] = '\0';
hbujanda 6:06522f3a6642 359 }
hbujanda 6:06522f3a6642 360
hbujanda 6:06522f3a6642 361 RadioStatus XBeeDM::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode)
hbujanda 6:06522f3a6642 362 {
hbujanda 6:06522f3a6642 363 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 364 char iocmd[3];
hbujanda 6:06522f3a6642 365
hbujanda 6:06522f3a6642 366 get_dio_cmd(line, iocmd);
hbujanda 6:06522f3a6642 367
hbujanda 6:06522f3a6642 368 cmdresp = set_param(remote, iocmd, (uint8_t)mode);
hbujanda 6:06522f3a6642 369 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 370 digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp);
hbujanda 6:06522f3a6642 371 return Failure;
hbujanda 6:06522f3a6642 372 }
hbujanda 6:06522f3a6642 373
hbujanda 6:06522f3a6642 374 return Success;
hbujanda 6:06522f3a6642 375 }
hbujanda 6:06522f3a6642 376
hbujanda 6:06522f3a6642 377 RadioStatus XBeeDM::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode)
hbujanda 6:06522f3a6642 378 {
hbujanda 6:06522f3a6642 379 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 380 char iocmd[3];
hbujanda 6:06522f3a6642 381
hbujanda 6:06522f3a6642 382 get_dio_cmd(line, iocmd);
hbujanda 6:06522f3a6642 383
hbujanda 6:06522f3a6642 384 uint32_t var32;
hbujanda 6:06522f3a6642 385 cmdresp = get_param(remote, iocmd, &var32);
hbujanda 6:06522f3a6642 386 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 387 return Failure;
hbujanda 6:06522f3a6642 388 }
hbujanda 6:06522f3a6642 389 *mode = (IoMode)var32;
hbujanda 6:06522f3a6642 390
hbujanda 6:06522f3a6642 391 return Success;
hbujanda 6:06522f3a6642 392 }
hbujanda 6:06522f3a6642 393
hbujanda 6:06522f3a6642 394 RadioStatus XBeeDM::set_dio(const RemoteXBee& remote, IoLine line, DioVal val)
hbujanda 6:06522f3a6642 395 {
hbujanda 6:06522f3a6642 396 return set_pin_config(remote, line, val == Low ? DigitalOutLow : DigitalOutHigh);
hbujanda 6:06522f3a6642 397 }
hbujanda 6:06522f3a6642 398
hbujanda 6:06522f3a6642 399 RadioStatus XBeeDM::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)
hbujanda 6:06522f3a6642 400 {
hbujanda 6:06522f3a6642 401 return get_iosample(remote).get_dio(line, val);
hbujanda 6:06522f3a6642 402 }
hbujanda 6:06522f3a6642 403
hbujanda 6:06522f3a6642 404 RadioStatus XBeeDM::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)
hbujanda 6:06522f3a6642 405 {
hbujanda 6:06522f3a6642 406 return get_iosample(remote).get_adc(line, val);
hbujanda 6:06522f3a6642 407 }
hbujanda 6:06522f3a6642 408
hbujanda 6:06522f3a6642 409 RadioStatus XBeeDM::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle)
hbujanda 6:06522f3a6642 410 {
hbujanda 6:06522f3a6642 411 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 412 char iocmd[3] = { 'M', '0', '\0' };
hbujanda 6:06522f3a6642 413
hbujanda 6:06522f3a6642 414 if (line != DIO10_PWM0 && line != DIO11_PWM1) {
hbujanda 6:06522f3a6642 415 return Failure;
hbujanda 6:06522f3a6642 416 }
hbujanda 6:06522f3a6642 417 if (line == DIO11_PWM1) {
hbujanda 6:06522f3a6642 418 iocmd[1] = '1';
hbujanda 6:06522f3a6642 419 }
hbujanda 6:06522f3a6642 420
hbujanda 6:06522f3a6642 421 uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100);
hbujanda 6:06522f3a6642 422
hbujanda 6:06522f3a6642 423 cmdresp = set_param(remote, iocmd, pwm_val);
hbujanda 6:06522f3a6642 424 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
hbujanda 6:06522f3a6642 425 }
hbujanda 6:06522f3a6642 426
hbujanda 6:06522f3a6642 427 IOSampleDM XBeeDM::get_iosample(const RemoteXBee& remote)
hbujanda 6:06522f3a6642 428 {
hbujanda 6:06522f3a6642 429 uint8_t io_sample[MAX_IO_SAMPLE_DM_LEN];
hbujanda 6:06522f3a6642 430 uint16_t len = sizeof io_sample;
hbujanda 6:06522f3a6642 431
hbujanda 6:06522f3a6642 432 RadioStatus resp = _get_iosample(remote, io_sample, &len);
hbujanda 6:06522f3a6642 433 if (resp != Success) {
hbujanda 6:06522f3a6642 434 digi_log(LogLevelError, "XBeeDM::get_iosample failed to get an IOSample\r\n");
hbujanda 6:06522f3a6642 435 len = 0;
hbujanda 6:06522f3a6642 436 }
hbujanda 6:06522f3a6642 437
hbujanda 6:06522f3a6642 438 return IOSampleDM(io_sample, len);
hbujanda 6:06522f3a6642 439 }
hbujanda 6:06522f3a6642 440
hbujanda 6:06522f3a6642 441 static uint16_t get_dio_pr_mask(XBeeDM::IoLine line)
hbujanda 6:06522f3a6642 442 {
hbujanda 6:06522f3a6642 443 switch (line) {
hbujanda 6:06522f3a6642 444 case XBeeDM::DIO4:
hbujanda 6:06522f3a6642 445 return (1 << 0);
hbujanda 6:06522f3a6642 446 case XBeeDM::DIO3_AD3:
hbujanda 6:06522f3a6642 447 return (1 << 1);
hbujanda 6:06522f3a6642 448 case XBeeDM::DIO2_AD2:
hbujanda 6:06522f3a6642 449 return (1 << 2);
hbujanda 6:06522f3a6642 450 case XBeeDM::DIO1_AD1:
hbujanda 6:06522f3a6642 451 return (1 << 3);
hbujanda 6:06522f3a6642 452 case XBeeDM::DIO0_AD0:
hbujanda 6:06522f3a6642 453 return (1 << 4);
hbujanda 6:06522f3a6642 454 case XBeeDM::DIO6:
hbujanda 6:06522f3a6642 455 return (1 << 5);
hbujanda 6:06522f3a6642 456 case XBeeDM::DIO8:
hbujanda 6:06522f3a6642 457 return (1 << 6);
hbujanda 6:06522f3a6642 458 case XBeeDM::DIO5:
hbujanda 6:06522f3a6642 459 return (1 << 8);
hbujanda 6:06522f3a6642 460 case XBeeDM::DIO9:
hbujanda 6:06522f3a6642 461 return (1 << 9);
hbujanda 6:06522f3a6642 462 case XBeeDM::DIO12:
hbujanda 6:06522f3a6642 463 return (1 << 10);
hbujanda 6:06522f3a6642 464 case XBeeDM::DIO10_PWM0:
hbujanda 6:06522f3a6642 465 return (1 << 11);
hbujanda 6:06522f3a6642 466 case XBeeDM::DIO11_PWM1:
hbujanda 6:06522f3a6642 467 return (1 << 12);
hbujanda 6:06522f3a6642 468 case XBeeDM::DIO7:
hbujanda 6:06522f3a6642 469 return (1 << 13);
hbujanda 6:06522f3a6642 470 default:
hbujanda 6:06522f3a6642 471 return 0;
hbujanda 6:06522f3a6642 472 }
hbujanda 6:06522f3a6642 473 }
hbujanda 6:06522f3a6642 474
hbujanda 6:06522f3a6642 475 RadioStatus XBeeDM::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable)
hbujanda 6:06522f3a6642 476 {
hbujanda 6:06522f3a6642 477 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 478 uint32_t var32;
hbujanda 6:06522f3a6642 479 uint16_t pr;
hbujanda 6:06522f3a6642 480
hbujanda 6:06522f3a6642 481 cmdresp = get_param(remote, "PR", &var32);
hbujanda 6:06522f3a6642 482 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 483 return Failure;
hbujanda 6:06522f3a6642 484 }
hbujanda 6:06522f3a6642 485 pr = var32;
hbujanda 6:06522f3a6642 486
hbujanda 6:06522f3a6642 487 const uint16_t dio_mask = get_dio_pr_mask(line);
hbujanda 6:06522f3a6642 488 if (dio_mask == 0) {
hbujanda 6:06522f3a6642 489 digi_log(LogLevelError, "XBeeDM::set_pin_pull_up: invalid pin %d\r\n", line);
hbujanda 6:06522f3a6642 490 return Failure;
hbujanda 6:06522f3a6642 491 }
hbujanda 6:06522f3a6642 492
hbujanda 6:06522f3a6642 493 if (enable) {
hbujanda 6:06522f3a6642 494 pr |= dio_mask;
hbujanda 6:06522f3a6642 495 } else {
hbujanda 6:06522f3a6642 496 pr &= ~dio_mask;
hbujanda 6:06522f3a6642 497 }
hbujanda 6:06522f3a6642 498
hbujanda 6:06522f3a6642 499 cmdresp = set_param(remote, "PR", pr);
hbujanda 6:06522f3a6642 500 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 501 return Failure;
hbujanda 6:06522f3a6642 502 }
hbujanda 6:06522f3a6642 503
hbujanda 6:06522f3a6642 504 return Success;
hbujanda 6:06522f3a6642 505 }
hbujanda 6:06522f3a6642 506
hbujanda 6:06522f3a6642 507 static uint16_t get_dio_ic_mask(XBeeDM::IoLine line)
hbujanda 6:06522f3a6642 508 {
hbujanda 6:06522f3a6642 509 if (line <= XBeeDM::DIO12) {
hbujanda 6:06522f3a6642 510 return (1 << line);
hbujanda 6:06522f3a6642 511 }
hbujanda 6:06522f3a6642 512 return 0;
hbujanda 6:06522f3a6642 513 }
hbujanda 6:06522f3a6642 514
hbujanda 6:06522f3a6642 515 RadioStatus XBeeDM::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable)
hbujanda 6:06522f3a6642 516 {
hbujanda 6:06522f3a6642 517 if (line > DIO12) {
hbujanda 6:06522f3a6642 518 digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: pin not supported (%d)\r\n", line);
hbujanda 6:06522f3a6642 519 return Failure;
hbujanda 6:06522f3a6642 520 }
hbujanda 6:06522f3a6642 521
hbujanda 6:06522f3a6642 522 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 523 uint32_t var32;
hbujanda 6:06522f3a6642 524 uint16_t ic;
hbujanda 6:06522f3a6642 525
hbujanda 6:06522f3a6642 526 cmdresp = get_param(remote, "IC", &var32);
hbujanda 6:06522f3a6642 527 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 528 return Failure;
hbujanda 6:06522f3a6642 529 }
hbujanda 6:06522f3a6642 530 ic = var32;
hbujanda 6:06522f3a6642 531
hbujanda 6:06522f3a6642 532 const uint16_t dio_mask = get_dio_ic_mask(line);
hbujanda 6:06522f3a6642 533 if (dio_mask == 0) {
hbujanda 6:06522f3a6642 534 digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: invalid pin %d\r\n", line);
hbujanda 6:06522f3a6642 535 return Failure;
hbujanda 6:06522f3a6642 536 }
hbujanda 6:06522f3a6642 537
hbujanda 6:06522f3a6642 538 if (enable) {
hbujanda 6:06522f3a6642 539 ic |= dio_mask;
hbujanda 6:06522f3a6642 540 } else {
hbujanda 6:06522f3a6642 541 ic &= ~dio_mask;
hbujanda 6:06522f3a6642 542 }
hbujanda 6:06522f3a6642 543
hbujanda 6:06522f3a6642 544 cmdresp = set_param(remote, "IC", ic);
hbujanda 6:06522f3a6642 545 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 546 return Failure;
hbujanda 6:06522f3a6642 547 }
hbujanda 6:06522f3a6642 548
hbujanda 6:06522f3a6642 549 return Success;
hbujanda 6:06522f3a6642 550 }
hbujanda 7:3ac2a461ce76 551
hbujanda 7:3ac2a461ce76 552 RadioStatus XBeeDM::config_poll_destination(const RemoteXBee& destination)
hbujanda 7:3ac2a461ce76 553 {
hbujanda 7:3ac2a461ce76 554 uint32_t dh;
hbujanda 7:3ac2a461ce76 555 uint32_t dl;
hbujanda 7:3ac2a461ce76 556
hbujanda 7:3ac2a461ce76 557 if (destination.is_valid_addr64b()) {
hbujanda 7:3ac2a461ce76 558 const uint64_t dest64 = destination.get_addr64();
hbujanda 7:3ac2a461ce76 559 dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF);
hbujanda 7:3ac2a461ce76 560 dl = (uint32_t)((dest64 & 0xFFFFFFFF));
hbujanda 7:3ac2a461ce76 561 } else {
hbujanda 7:3ac2a461ce76 562 digi_log(LogLevelError, "config_poll_destination: Invalid destination");
hbujanda 7:3ac2a461ce76 563 return Failure;
hbujanda 7:3ac2a461ce76 564 }
hbujanda 7:3ac2a461ce76 565
hbujanda 7:3ac2a461ce76 566 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 7:3ac2a461ce76 567
hbujanda 7:3ac2a461ce76 568 cmdresp = set_param("DH", dh);
hbujanda 7:3ac2a461ce76 569 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 7:3ac2a461ce76 570 digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp);
hbujanda 7:3ac2a461ce76 571 return Failure;
hbujanda 7:3ac2a461ce76 572 }
hbujanda 7:3ac2a461ce76 573
hbujanda 7:3ac2a461ce76 574 cmdresp = set_param("DL", dl);
hbujanda 7:3ac2a461ce76 575 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 7:3ac2a461ce76 576 digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp);
hbujanda 7:3ac2a461ce76 577 return Failure;
hbujanda 7:3ac2a461ce76 578 }
hbujanda 7:3ac2a461ce76 579
hbujanda 7:3ac2a461ce76 580 return Success;
hbujanda 7:3ac2a461ce76 581 }