Library to easily communicate with XBee modules.

Dependencies:   DigiLogger

Dependents:   WaterLogger XbeeGateway XBee_Cooker ProjetReceiver ... more

Use XBee radio modules to easily improve your project with wireless connectivity. You can enable entire networks of connected devices. XBees can exchange data with other modules in the network and configure remote modules as well as trigger actions or collect sensor data on XBee nodes without needing additional external microcontrollers. Using this documentation and configuration tools with XBee modules, it is easy to develop these types of applications and more.

/media/uploads/spastor/xbee-xbeepro-series1.jpg

The XBee mbed Library is a ready-to-import mbed extension that dramatically reduces development time for XBee projects on the mbed platforms. There are many modular examples, making it an easy and smooth process to add wireless networking to a whole range of useful applications.

Info

Currently 802.15.4 (Series 1 and 2), ZigBee (Series 2) and DigiMesh (Series 1 and 2) modules are supported. The libraries can be extended to support other protocols like DigiMesh point-to-point, WiFi, etc.

User manual

The user manual can be found at this project's Wiki pages:

  1. Configuring the library
  2. Debugging the library
  3. Initializing modules
  4. Resetting the local module
  5. Receiving Data from other module
  6. Sending data to another module
  7. Discovering nodes in the network
  8. Configuring local and remote modules
  9. Handling modem status changes
  10. Handling remote modules DIOs, ADCs and PWMs
  11. Handling IO Data Samples from other module
  12. Radio Power Management

Ready to use examples

There are a lot of ready to use examples to get started quickly.
Make sure you have a valid example setup before running the examples:

Examples for ZigBee modules

Import programXBeeZB_Receive_Data

ZigBee Receive Data example for mbed XBeeLib By Digi

Import programXBeeZB_Send_Data

ZigBee Send Data example for mbed XBeeLib By Digi

Import programXBeeZB_module_config

ZigBee network configuration example for mbed XBeeLib By Digi

Import programXBeeZB_AT_Commands

ZigBee AT Commands example for mbed XBeeLib By Digi

Import programXBeeZB_dio_adc

ZigBee DIOs and ADCs example for mbed XBeeLib By Digi

Import programXBeeZB_IO_Sample_Callback

ZigBee IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBeeZB_modem_status

ZigBee Modem Status example for mbed XBeeLib By Digi

Import programXBeeZB_node_discovery

ZigBee Node Discovery example for mbed XBeeLib By Digi

Import programXBeeZB_power_mngmnt_cyclic_sleep

ZigBee Power Management using Cyclic Sleep example for mbed XBeeLib By Digi

Import programXBeeZB_power_mngmnt_pin_sleep

ZigBee Power Management using Pin Sleep example for mbed XBeeLib By Digi

Examples for 802.15.4 modules

Import programXBee802_Receive_Data

802.15.4 Receive Data example for mbed XBeeLib By Digi

Import programXBee802_Send_Data

802.15.4 Send Data example for mbed XBeeLib By Digi

Import programXBee802_module_config

802.15.4 network configuration example for mbed XBeeLib By Digi

Import programXBee802_AT_Commands

802.15.4 AT Commands example for mbed XBeeLib By Digi

Import programXBee802_dio_adc_pwm

802.15.4 DIOs, ADCs and PWM example for mbed XBeeLib By Digi

Import programXBee802_IO_Sample_Callback

802.15.4 IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBee802_node_discovery

802.15.4 Node Discovery example for mbed XBeeLib By Digi

Import programXBee802_power_mngmnt_cyclic_sleep

802.15.4 Power Management using Cyclic Sleep example for mbed XBeeLib By Digi

Import programXBee802_power_mngmnt_pin_sleep

802.15.4 Power Management using Pin Sleep example for mbed XBeeLib By Digi

Examples for DigiMesh modules

Import programXBeeDM_Receive_Data

DigiMesh Receive Data example for mbed XBeeLib By Digi

Import programXBeeDM_Send_Data

DigiMesh Send Data example for mbed XBeeLib By Digi

Import programXBeeDM_module_config

DigiMesh network configuration example for mbed XBeeLib By Digi

Import programXBeeDM_AT_Commands

DigiMesh AT Commands example for mbed XBeeLib By Digi

Import programXBeeDM_dio_adc_pwm

DigiMEsh DIOs, ADCs and PWMs example for mbed XBeeLib By Digi

Import programXBeeDM_IO_Sample_Callback

DigiMesh IO Sampling Callback example for mbed XBeeLib By Digi

Import programXBeeDM_modem_status

DigiMesh Modem Status example for mbed XBeeLib By Digi

Import programXBeeDM_node_discovery

DigiMesh Node Discovery example for mbed XBeeLib By Digi

Import programXBeeDM_power_mngmnt_asyncr_cyclic_sleep

DigiMesh Power Management using Asynchronous Cyclic Sleep example for mbed XBeeLib By Digi

Import programXBeeDM_power_mngmnt_pin_sleep

DigiMesh Power Management using Pin Sleep example for mbed XBeeLib By Digi

Committer:
hbujanda
Date:
Fri Jul 29 13:10:07 2016 +0200
Revision:
9:780db84ce891
Parent:
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 void XBeeDM::radio_status_update(AtCmdFrame::ModemStatus modem_status)
hbujanda 6:06522f3a6642 129 {
hbujanda 6:06522f3a6642 130 /* Update the radio status variables */
hbujanda 6:06522f3a6642 131 if (modem_status == AtCmdFrame::HwReset) {
hbujanda 6:06522f3a6642 132 _hw_reset_cnt++;
hbujanda 6:06522f3a6642 133 } else if (modem_status == AtCmdFrame::WdReset) {
hbujanda 6:06522f3a6642 134 _wd_reset_cnt++;
hbujanda 6:06522f3a6642 135 }
hbujanda 6:06522f3a6642 136
hbujanda 6:06522f3a6642 137 _modem_status = modem_status;
hbujanda 6:06522f3a6642 138
hbujanda 6:06522f3a6642 139 digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
hbujanda 6:06522f3a6642 140 }
hbujanda 6:06522f3a6642 141
hbujanda 6:06522f3a6642 142 TxStatus XBeeDM::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 143 {
hbujanda 6:06522f3a6642 144 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 145 return TxStatusInvalidAddr;
hbujanda 6:06522f3a6642 146 }
hbujanda 6:06522f3a6642 147
hbujanda 6:06522f3a6642 148 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 149 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 150
hbujanda 6:06522f3a6642 151 TxFrameDM frame = TxFrameDM(remote64, remote16, BROADCAST_RADIUS_USE_NH,
hbujanda 6:06522f3a6642 152 _tx_options, data, len);
hbujanda 6:06522f3a6642 153 if (syncr) {
hbujanda 6:06522f3a6642 154 return send_data(&frame);
hbujanda 6:06522f3a6642 155 } else {
hbujanda 6:06522f3a6642 156 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 157 send_api_frame(&frame);
hbujanda 6:06522f3a6642 158 return TxStatusSuccess;
hbujanda 6:06522f3a6642 159 }
hbujanda 6:06522f3a6642 160 }
hbujanda 6:06522f3a6642 161
hbujanda 6:06522f3a6642 162 TxStatus XBeeDM::send_data(const RemoteXBee& remote, uint8_t source_ep,
hbujanda 6:06522f3a6642 163 uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
hbujanda 6:06522f3a6642 164 const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 165 {
hbujanda 6:06522f3a6642 166 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 167 return TxStatusInvalidAddr;
hbujanda 6:06522f3a6642 168 }
hbujanda 6:06522f3a6642 169
hbujanda 6:06522f3a6642 170 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 171 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 172
hbujanda 6:06522f3a6642 173 TxFrameDM frame = TxFrameDM(remote64, remote16, source_ep, dest_ep,
hbujanda 6:06522f3a6642 174 cluster_id, profile_id, BROADCAST_RADIUS_USE_NH,
hbujanda 6:06522f3a6642 175 _tx_options, data, len);
hbujanda 6:06522f3a6642 176 if (syncr) {
hbujanda 6:06522f3a6642 177 return send_data(&frame);
hbujanda 6:06522f3a6642 178 } else {
hbujanda 6:06522f3a6642 179 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 180 send_api_frame(&frame);
hbujanda 6:06522f3a6642 181 return TxStatusSuccess;
hbujanda 6:06522f3a6642 182 }
hbujanda 6:06522f3a6642 183 }
hbujanda 6:06522f3a6642 184
hbujanda 6:06522f3a6642 185 TxStatus XBeeDM::send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr)
hbujanda 6:06522f3a6642 186 {
hbujanda 6:06522f3a6642 187 const uint64_t remaddr = ADDR64_COORDINATOR;
hbujanda 6:06522f3a6642 188
hbujanda 6:06522f3a6642 189 TxFrameDM frame = TxFrameDM(remaddr, ADDR16_UNKNOWN, BROADCAST_RADIUS_USE_NH, _tx_options, data, len);
hbujanda 6:06522f3a6642 190 if (syncr) {
hbujanda 6:06522f3a6642 191 return send_data(&frame);
hbujanda 6:06522f3a6642 192 } else {
hbujanda 6:06522f3a6642 193 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
hbujanda 6:06522f3a6642 194 send_api_frame(&frame);
hbujanda 6:06522f3a6642 195 return TxStatusSuccess;
hbujanda 6:06522f3a6642 196 }
hbujanda 6:06522f3a6642 197 }
hbujanda 6:06522f3a6642 198
hbujanda 6:06522f3a6642 199 RemoteXBeeDM XBeeDM::get_remote_node_by_id(const char * const node_id)
hbujanda 6:06522f3a6642 200 {
hbujanda 6:06522f3a6642 201 uint64_t addr64;
hbujanda 6:06522f3a6642 202 uint16_t addr16;
hbujanda 6:06522f3a6642 203 _get_remote_node_by_id(node_id, &addr64, &addr16);
hbujanda 6:06522f3a6642 204 return RemoteXBeeDM(addr64);
hbujanda 6:06522f3a6642 205 }
hbujanda 6:06522f3a6642 206
hbujanda 6:06522f3a6642 207 void XBeeDM::register_node_discovery_cb(node_discovery_dm_cb_t function)
hbujanda 6:06522f3a6642 208 {
hbujanda 6:06522f3a6642 209 if (_nd_handler == NULL) {
hbujanda 6:06522f3a6642 210 _nd_handler = new FH_NodeDiscoveryDM();
hbujanda 6:06522f3a6642 211 register_frame_handler(_nd_handler);
hbujanda 6:06522f3a6642 212 }
hbujanda 6:06522f3a6642 213 _nd_handler->register_node_discovery_cb(function);
hbujanda 6:06522f3a6642 214 }
hbujanda 6:06522f3a6642 215
hbujanda 6:06522f3a6642 216 void XBeeDM::unregister_node_discovery_cb()
hbujanda 6:06522f3a6642 217 {
hbujanda 6:06522f3a6642 218 if (_nd_handler != NULL) {
hbujanda 6:06522f3a6642 219 _nd_handler->unregister_node_discovery_cb();
hbujanda 6:06522f3a6642 220 unregister_frame_handler(_nd_handler);
hbujanda 6:06522f3a6642 221 delete _nd_handler;
hbujanda 6:06522f3a6642 222 _nd_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 223 }
hbujanda 6:06522f3a6642 224 }
hbujanda 6:06522f3a6642 225
hbujanda 6:06522f3a6642 226 void XBeeDM::register_receive_cb(receive_dm_cb_t function)
hbujanda 6:06522f3a6642 227 {
hbujanda 6:06522f3a6642 228 if (_rx_pkt_handler == NULL) {
hbujanda 6:06522f3a6642 229 _rx_pkt_handler = new FH_RxPacketDM();
hbujanda 6:06522f3a6642 230 register_frame_handler(_rx_pkt_handler);
hbujanda 6:06522f3a6642 231 }
hbujanda 6:06522f3a6642 232 _rx_pkt_handler->register_receive_cb(function);
hbujanda 6:06522f3a6642 233 }
hbujanda 6:06522f3a6642 234
hbujanda 6:06522f3a6642 235 void XBeeDM::unregister_receive_cb()
hbujanda 6:06522f3a6642 236 {
hbujanda 6:06522f3a6642 237 if (_rx_pkt_handler != NULL) {
hbujanda 6:06522f3a6642 238 _rx_pkt_handler->unregister_receive_cb();
hbujanda 6:06522f3a6642 239 unregister_frame_handler(_rx_pkt_handler);
hbujanda 6:06522f3a6642 240 delete _rx_pkt_handler;
hbujanda 6:06522f3a6642 241 _rx_pkt_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 242 }
hbujanda 6:06522f3a6642 243 }
hbujanda 6:06522f3a6642 244
hbujanda 6:06522f3a6642 245 void XBeeDM::register_io_sample_cb(io_data_cb_dm_t function)
hbujanda 6:06522f3a6642 246 {
hbujanda 6:06522f3a6642 247 if (_io_data_handler == NULL) {
hbujanda 6:06522f3a6642 248 _io_data_handler = new FH_IoDataSampeDM();
hbujanda 6:06522f3a6642 249 register_frame_handler(_io_data_handler);
hbujanda 6:06522f3a6642 250 }
hbujanda 6:06522f3a6642 251 _io_data_handler->register_io_data_cb(function);
hbujanda 6:06522f3a6642 252 }
hbujanda 6:06522f3a6642 253
hbujanda 6:06522f3a6642 254 void XBeeDM::unregister_io_sample_cb()
hbujanda 6:06522f3a6642 255 {
hbujanda 6:06522f3a6642 256 if (_io_data_handler != NULL) {
hbujanda 6:06522f3a6642 257 _io_data_handler->unregister_io_data_cb();
hbujanda 6:06522f3a6642 258 unregister_frame_handler(_io_data_handler);
hbujanda 6:06522f3a6642 259 delete _io_data_handler;
hbujanda 6:06522f3a6642 260 _io_data_handler = NULL; /* as delete does not set to NULL */
hbujanda 6:06522f3a6642 261 }
hbujanda 6:06522f3a6642 262 }
hbujanda 6:06522f3a6642 263
hbujanda 6:06522f3a6642 264 AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data)
hbujanda 6:06522f3a6642 265 {
hbujanda 6:06522f3a6642 266 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 267 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 268 }
hbujanda 6:06522f3a6642 269
hbujanda 6:06522f3a6642 270 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 271 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 272 uint16_t len = sizeof *data;
hbujanda 6:06522f3a6642 273 AtCmdFrame::AtCmdResp atCmdResponse;
hbujanda 6:06522f3a6642 274
hbujanda 6:06522f3a6642 275 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
hbujanda 6:06522f3a6642 276 atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote);
hbujanda 6:06522f3a6642 277
hbujanda 6:06522f3a6642 278 if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) {
hbujanda 6:06522f3a6642 279 atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
hbujanda 6:06522f3a6642 280 }
hbujanda 6:06522f3a6642 281
hbujanda 6:06522f3a6642 282 return atCmdResponse;
hbujanda 6:06522f3a6642 283 }
hbujanda 6:06522f3a6642 284
hbujanda 6:06522f3a6642 285 AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, uint32_t data)
hbujanda 6:06522f3a6642 286 {
hbujanda 6:06522f3a6642 287 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 288 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 289 }
hbujanda 6:06522f3a6642 290
hbujanda 6:06522f3a6642 291 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 292 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 293
hbujanda 6:06522f3a6642 294 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data);
hbujanda 6:06522f3a6642 295 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
hbujanda 6:06522f3a6642 296 }
hbujanda 6:06522f3a6642 297
hbujanda 6:06522f3a6642 298 AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len)
hbujanda 6:06522f3a6642 299 {
hbujanda 6:06522f3a6642 300 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 301 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 302 }
hbujanda 6:06522f3a6642 303
hbujanda 6:06522f3a6642 304 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 305 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 306
hbujanda 6:06522f3a6642 307 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data, len);
hbujanda 6:06522f3a6642 308 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
hbujanda 6:06522f3a6642 309 }
hbujanda 6:06522f3a6642 310
hbujanda 6:06522f3a6642 311 AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len)
hbujanda 6:06522f3a6642 312 {
hbujanda 6:06522f3a6642 313
hbujanda 6:06522f3a6642 314 if (!remote.is_valid_addr64b()) {
hbujanda 6:06522f3a6642 315 return AtCmdFrame::AtCmdRespInvalidAddr;
hbujanda 6:06522f3a6642 316 }
hbujanda 6:06522f3a6642 317
hbujanda 6:06522f3a6642 318 const uint64_t remote64 = remote.get_addr64();
hbujanda 6:06522f3a6642 319 const uint16_t remote16 = remote.get_addr16();
hbujanda 6:06522f3a6642 320
hbujanda 6:06522f3a6642 321 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
hbujanda 6:06522f3a6642 322 return send_at_cmd(&cmd_frame, data, len, RadioRemote, false);
hbujanda 6:06522f3a6642 323 }
hbujanda 6:06522f3a6642 324
hbujanda 6:06522f3a6642 325 static void get_dio_cmd(XBeeDM::IoLine line, char * const iocmd)
hbujanda 6:06522f3a6642 326 {
hbujanda 6:06522f3a6642 327 if (line >= XBeeDM::DIO10_PWM0) {
hbujanda 6:06522f3a6642 328 iocmd[0] = 'P';
hbujanda 6:06522f3a6642 329 iocmd[1] = '0' + line - XBeeDM::DIO10_PWM0;
hbujanda 6:06522f3a6642 330 } else {
hbujanda 6:06522f3a6642 331 iocmd[0] = 'D';
hbujanda 6:06522f3a6642 332 iocmd[1] = '0' + line;
hbujanda 6:06522f3a6642 333 }
hbujanda 6:06522f3a6642 334 iocmd[2] = '\0';
hbujanda 6:06522f3a6642 335 }
hbujanda 6:06522f3a6642 336
hbujanda 6:06522f3a6642 337 RadioStatus XBeeDM::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode)
hbujanda 6:06522f3a6642 338 {
hbujanda 6:06522f3a6642 339 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 340 char iocmd[3];
hbujanda 6:06522f3a6642 341
hbujanda 6:06522f3a6642 342 get_dio_cmd(line, iocmd);
hbujanda 6:06522f3a6642 343
hbujanda 6:06522f3a6642 344 cmdresp = set_param(remote, iocmd, (uint8_t)mode);
hbujanda 6:06522f3a6642 345 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 346 digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp);
hbujanda 6:06522f3a6642 347 return Failure;
hbujanda 6:06522f3a6642 348 }
hbujanda 6:06522f3a6642 349
hbujanda 6:06522f3a6642 350 return Success;
hbujanda 6:06522f3a6642 351 }
hbujanda 6:06522f3a6642 352
hbujanda 6:06522f3a6642 353 RadioStatus XBeeDM::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode)
hbujanda 6:06522f3a6642 354 {
hbujanda 6:06522f3a6642 355 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 356 char iocmd[3];
hbujanda 6:06522f3a6642 357
hbujanda 6:06522f3a6642 358 get_dio_cmd(line, iocmd);
hbujanda 6:06522f3a6642 359
hbujanda 6:06522f3a6642 360 uint32_t var32;
hbujanda 6:06522f3a6642 361 cmdresp = get_param(remote, iocmd, &var32);
hbujanda 6:06522f3a6642 362 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 363 return Failure;
hbujanda 6:06522f3a6642 364 }
hbujanda 6:06522f3a6642 365 *mode = (IoMode)var32;
hbujanda 6:06522f3a6642 366
hbujanda 6:06522f3a6642 367 return Success;
hbujanda 6:06522f3a6642 368 }
hbujanda 6:06522f3a6642 369
hbujanda 6:06522f3a6642 370 RadioStatus XBeeDM::set_dio(const RemoteXBee& remote, IoLine line, DioVal val)
hbujanda 6:06522f3a6642 371 {
hbujanda 6:06522f3a6642 372 return set_pin_config(remote, line, val == Low ? DigitalOutLow : DigitalOutHigh);
hbujanda 6:06522f3a6642 373 }
hbujanda 6:06522f3a6642 374
hbujanda 6:06522f3a6642 375 RadioStatus XBeeDM::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)
hbujanda 6:06522f3a6642 376 {
hbujanda 6:06522f3a6642 377 return get_iosample(remote).get_dio(line, val);
hbujanda 6:06522f3a6642 378 }
hbujanda 6:06522f3a6642 379
hbujanda 6:06522f3a6642 380 RadioStatus XBeeDM::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)
hbujanda 6:06522f3a6642 381 {
hbujanda 6:06522f3a6642 382 return get_iosample(remote).get_adc(line, val);
hbujanda 6:06522f3a6642 383 }
hbujanda 6:06522f3a6642 384
hbujanda 6:06522f3a6642 385 RadioStatus XBeeDM::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle)
hbujanda 6:06522f3a6642 386 {
hbujanda 6:06522f3a6642 387 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 388 char iocmd[3] = { 'M', '0', '\0' };
hbujanda 6:06522f3a6642 389
hbujanda 6:06522f3a6642 390 if (line != DIO10_PWM0 && line != DIO11_PWM1) {
hbujanda 6:06522f3a6642 391 return Failure;
hbujanda 6:06522f3a6642 392 }
hbujanda 6:06522f3a6642 393 if (line == DIO11_PWM1) {
hbujanda 6:06522f3a6642 394 iocmd[1] = '1';
hbujanda 6:06522f3a6642 395 }
hbujanda 6:06522f3a6642 396
hbujanda 6:06522f3a6642 397 uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100);
hbujanda 6:06522f3a6642 398
hbujanda 6:06522f3a6642 399 cmdresp = set_param(remote, iocmd, pwm_val);
hbujanda 6:06522f3a6642 400 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
hbujanda 6:06522f3a6642 401 }
hbujanda 6:06522f3a6642 402
hbujanda 6:06522f3a6642 403 IOSampleDM XBeeDM::get_iosample(const RemoteXBee& remote)
hbujanda 6:06522f3a6642 404 {
hbujanda 6:06522f3a6642 405 uint8_t io_sample[MAX_IO_SAMPLE_DM_LEN];
hbujanda 6:06522f3a6642 406 uint16_t len = sizeof io_sample;
hbujanda 6:06522f3a6642 407
hbujanda 6:06522f3a6642 408 RadioStatus resp = _get_iosample(remote, io_sample, &len);
hbujanda 6:06522f3a6642 409 if (resp != Success) {
hbujanda 6:06522f3a6642 410 digi_log(LogLevelError, "XBeeDM::get_iosample failed to get an IOSample\r\n");
hbujanda 6:06522f3a6642 411 len = 0;
hbujanda 6:06522f3a6642 412 }
hbujanda 6:06522f3a6642 413
hbujanda 6:06522f3a6642 414 return IOSampleDM(io_sample, len);
hbujanda 6:06522f3a6642 415 }
hbujanda 6:06522f3a6642 416
hbujanda 6:06522f3a6642 417 static uint16_t get_dio_pr_mask(XBeeDM::IoLine line)
hbujanda 6:06522f3a6642 418 {
hbujanda 6:06522f3a6642 419 switch (line) {
hbujanda 6:06522f3a6642 420 case XBeeDM::DIO4:
hbujanda 6:06522f3a6642 421 return (1 << 0);
hbujanda 6:06522f3a6642 422 case XBeeDM::DIO3_AD3:
hbujanda 6:06522f3a6642 423 return (1 << 1);
hbujanda 6:06522f3a6642 424 case XBeeDM::DIO2_AD2:
hbujanda 6:06522f3a6642 425 return (1 << 2);
hbujanda 6:06522f3a6642 426 case XBeeDM::DIO1_AD1:
hbujanda 6:06522f3a6642 427 return (1 << 3);
hbujanda 6:06522f3a6642 428 case XBeeDM::DIO0_AD0:
hbujanda 6:06522f3a6642 429 return (1 << 4);
hbujanda 6:06522f3a6642 430 case XBeeDM::DIO6:
hbujanda 6:06522f3a6642 431 return (1 << 5);
hbujanda 6:06522f3a6642 432 case XBeeDM::DIO8:
hbujanda 6:06522f3a6642 433 return (1 << 6);
hbujanda 6:06522f3a6642 434 case XBeeDM::DIO5:
hbujanda 6:06522f3a6642 435 return (1 << 8);
hbujanda 6:06522f3a6642 436 case XBeeDM::DIO9:
hbujanda 6:06522f3a6642 437 return (1 << 9);
hbujanda 6:06522f3a6642 438 case XBeeDM::DIO12:
hbujanda 6:06522f3a6642 439 return (1 << 10);
hbujanda 6:06522f3a6642 440 case XBeeDM::DIO10_PWM0:
hbujanda 6:06522f3a6642 441 return (1 << 11);
hbujanda 6:06522f3a6642 442 case XBeeDM::DIO11_PWM1:
hbujanda 6:06522f3a6642 443 return (1 << 12);
hbujanda 6:06522f3a6642 444 case XBeeDM::DIO7:
hbujanda 6:06522f3a6642 445 return (1 << 13);
hbujanda 6:06522f3a6642 446 default:
hbujanda 6:06522f3a6642 447 return 0;
hbujanda 6:06522f3a6642 448 }
hbujanda 6:06522f3a6642 449 }
hbujanda 6:06522f3a6642 450
hbujanda 6:06522f3a6642 451 RadioStatus XBeeDM::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable)
hbujanda 6:06522f3a6642 452 {
hbujanda 6:06522f3a6642 453 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 454 uint32_t var32;
hbujanda 6:06522f3a6642 455 uint16_t pr;
hbujanda 6:06522f3a6642 456
hbujanda 6:06522f3a6642 457 cmdresp = get_param(remote, "PR", &var32);
hbujanda 6:06522f3a6642 458 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 459 return Failure;
hbujanda 6:06522f3a6642 460 }
hbujanda 6:06522f3a6642 461 pr = var32;
hbujanda 6:06522f3a6642 462
hbujanda 6:06522f3a6642 463 const uint16_t dio_mask = get_dio_pr_mask(line);
hbujanda 6:06522f3a6642 464 if (dio_mask == 0) {
hbujanda 6:06522f3a6642 465 digi_log(LogLevelError, "XBeeDM::set_pin_pull_up: invalid pin %d\r\n", line);
hbujanda 6:06522f3a6642 466 return Failure;
hbujanda 6:06522f3a6642 467 }
hbujanda 6:06522f3a6642 468
hbujanda 6:06522f3a6642 469 if (enable) {
hbujanda 6:06522f3a6642 470 pr |= dio_mask;
hbujanda 6:06522f3a6642 471 } else {
hbujanda 6:06522f3a6642 472 pr &= ~dio_mask;
hbujanda 6:06522f3a6642 473 }
hbujanda 6:06522f3a6642 474
hbujanda 6:06522f3a6642 475 cmdresp = set_param(remote, "PR", pr);
hbujanda 6:06522f3a6642 476 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 477 return Failure;
hbujanda 6:06522f3a6642 478 }
hbujanda 6:06522f3a6642 479
hbujanda 6:06522f3a6642 480 return Success;
hbujanda 6:06522f3a6642 481 }
hbujanda 6:06522f3a6642 482
hbujanda 6:06522f3a6642 483 static uint16_t get_dio_ic_mask(XBeeDM::IoLine line)
hbujanda 6:06522f3a6642 484 {
hbujanda 6:06522f3a6642 485 if (line <= XBeeDM::DIO12) {
hbujanda 6:06522f3a6642 486 return (1 << line);
hbujanda 6:06522f3a6642 487 }
hbujanda 6:06522f3a6642 488 return 0;
hbujanda 6:06522f3a6642 489 }
hbujanda 6:06522f3a6642 490
hbujanda 6:06522f3a6642 491 RadioStatus XBeeDM::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable)
hbujanda 6:06522f3a6642 492 {
hbujanda 6:06522f3a6642 493 if (line > DIO12) {
hbujanda 6:06522f3a6642 494 digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: pin not supported (%d)\r\n", line);
hbujanda 6:06522f3a6642 495 return Failure;
hbujanda 6:06522f3a6642 496 }
hbujanda 6:06522f3a6642 497
hbujanda 6:06522f3a6642 498 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 6:06522f3a6642 499 uint32_t var32;
hbujanda 6:06522f3a6642 500 uint16_t ic;
hbujanda 6:06522f3a6642 501
hbujanda 6:06522f3a6642 502 cmdresp = get_param(remote, "IC", &var32);
hbujanda 6:06522f3a6642 503 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 504 return Failure;
hbujanda 6:06522f3a6642 505 }
hbujanda 6:06522f3a6642 506 ic = var32;
hbujanda 6:06522f3a6642 507
hbujanda 6:06522f3a6642 508 const uint16_t dio_mask = get_dio_ic_mask(line);
hbujanda 6:06522f3a6642 509 if (dio_mask == 0) {
hbujanda 6:06522f3a6642 510 digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: invalid pin %d\r\n", line);
hbujanda 6:06522f3a6642 511 return Failure;
hbujanda 6:06522f3a6642 512 }
hbujanda 6:06522f3a6642 513
hbujanda 6:06522f3a6642 514 if (enable) {
hbujanda 6:06522f3a6642 515 ic |= dio_mask;
hbujanda 6:06522f3a6642 516 } else {
hbujanda 6:06522f3a6642 517 ic &= ~dio_mask;
hbujanda 6:06522f3a6642 518 }
hbujanda 6:06522f3a6642 519
hbujanda 6:06522f3a6642 520 cmdresp = set_param(remote, "IC", ic);
hbujanda 6:06522f3a6642 521 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 6:06522f3a6642 522 return Failure;
hbujanda 6:06522f3a6642 523 }
hbujanda 6:06522f3a6642 524
hbujanda 6:06522f3a6642 525 return Success;
hbujanda 6:06522f3a6642 526 }
hbujanda 7:3ac2a461ce76 527
hbujanda 7:3ac2a461ce76 528 RadioStatus XBeeDM::config_poll_destination(const RemoteXBee& destination)
hbujanda 7:3ac2a461ce76 529 {
hbujanda 7:3ac2a461ce76 530 uint32_t dh;
hbujanda 7:3ac2a461ce76 531 uint32_t dl;
hbujanda 7:3ac2a461ce76 532
hbujanda 7:3ac2a461ce76 533 if (destination.is_valid_addr64b()) {
hbujanda 7:3ac2a461ce76 534 const uint64_t dest64 = destination.get_addr64();
hbujanda 7:3ac2a461ce76 535 dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF);
hbujanda 7:3ac2a461ce76 536 dl = (uint32_t)((dest64 & 0xFFFFFFFF));
hbujanda 7:3ac2a461ce76 537 } else {
hbujanda 7:3ac2a461ce76 538 digi_log(LogLevelError, "config_poll_destination: Invalid destination");
hbujanda 7:3ac2a461ce76 539 return Failure;
hbujanda 7:3ac2a461ce76 540 }
hbujanda 7:3ac2a461ce76 541
hbujanda 7:3ac2a461ce76 542 AtCmdFrame::AtCmdResp cmdresp;
hbujanda 7:3ac2a461ce76 543
hbujanda 7:3ac2a461ce76 544 cmdresp = set_param("DH", dh);
hbujanda 7:3ac2a461ce76 545 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 7:3ac2a461ce76 546 digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp);
hbujanda 7:3ac2a461ce76 547 return Failure;
hbujanda 7:3ac2a461ce76 548 }
hbujanda 7:3ac2a461ce76 549
hbujanda 7:3ac2a461ce76 550 cmdresp = set_param("DL", dl);
hbujanda 7:3ac2a461ce76 551 if (cmdresp != AtCmdFrame::AtCmdRespOk) {
hbujanda 7:3ac2a461ce76 552 digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp);
hbujanda 7:3ac2a461ce76 553 return Failure;
hbujanda 7:3ac2a461ce76 554 }
hbujanda 7:3ac2a461ce76 555
hbujanda 7:3ac2a461ce76 556 return Success;
hbujanda 7:3ac2a461ce76 557 }