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