Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of XBeeLib by
XBeeDM.cpp
00001 /** 00002 * Copyright (c) 2015 Digi International Inc., 00003 * All rights not expressly granted are reserved. 00004 * 00005 * This Source Code Form is subject to the terms of the Mozilla Public 00006 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 00007 * You can obtain one at http://mozilla.org/MPL/2.0/. 00008 * 00009 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343 00010 * ======================================================================= 00011 */ 00012 00013 #include "XBeeDM.h" 00014 #include "IO/IOSampleDM.h" 00015 #include "Frames/DigiMeshFrames.h" 00016 00017 using namespace XBeeLib; 00018 00019 #define BROADCAST_RADIUS_USE_NH 0x00 00020 00021 /* Class constructor */ 00022 XBeeDM::XBeeDM(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) : 00023 XBee(tx, rx, reset, rts, cts, baud), _nd_handler(NULL), _rx_pkt_handler(NULL), _io_data_handler(NULL) 00024 { 00025 } 00026 00027 RadioStatus XBeeDM::init() 00028 { 00029 RadioStatus retval = XBee::init(); 00030 00031 const RadioProtocol radioProtocol = get_radio_protocol(); 00032 if (radioProtocol != DigiMesh) { 00033 digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", DigiMesh, radioProtocol); 00034 retval = Failure; 00035 } 00036 assert(radioProtocol == DigiMesh); 00037 00038 return retval; 00039 } 00040 00041 /* Class destructor */ 00042 XBeeDM::~XBeeDM() 00043 { 00044 unregister_node_discovery_cb(); 00045 unregister_receive_cb(); 00046 unregister_io_sample_cb(); 00047 } 00048 00049 RadioStatus XBeeDM::set_channel(uint8_t channel) 00050 { 00051 AtCmdFrame::AtCmdResp cmdresp; 00052 00053 /* Pro and Non-Pro modules have different channels available. The at 00054 command will return an error if the selected channel is not available */ 00055 cmdresp = set_param("CH", channel); 00056 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00057 return Failure; 00058 } 00059 return Success; 00060 } 00061 00062 RadioStatus XBeeDM::get_channel(uint8_t * const channel) 00063 { 00064 if (channel == NULL) { 00065 return Failure; 00066 } 00067 AtCmdFrame::AtCmdResp cmdresp; 00068 00069 uint32_t var32; 00070 cmdresp = get_param("CH", &var32); 00071 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00072 return Failure; 00073 } 00074 *channel = var32; 00075 return Success; 00076 } 00077 00078 RadioStatus XBeeDM::set_network_id(uint16_t network_id) 00079 { 00080 AtCmdFrame::AtCmdResp cmdresp; 00081 00082 cmdresp = set_param("ID", network_id); 00083 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00084 return Failure; 00085 } 00086 return Success; 00087 } 00088 00089 RadioStatus XBeeDM::get_network_id(uint16_t * const network_id) 00090 { 00091 if (network_id == NULL) { 00092 return Failure; 00093 } 00094 AtCmdFrame::AtCmdResp cmdresp; 00095 00096 uint32_t var32; 00097 cmdresp = get_param("ID", &var32); 00098 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00099 return Failure; 00100 } 00101 *network_id = var32; 00102 return Success; 00103 } 00104 00105 RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms) 00106 { 00107 AtCmdFrame::AtCmdResp cmdresp; 00108 uint32_t var32; 00109 00110 cmdresp = get_param("N?", &var32); 00111 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00112 return Failure; 00113 } 00114 *timeout_ms = (uint16_t)var32; 00115 00116 return Success; 00117 } 00118 00119 RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout) 00120 { 00121 const RadioStatus status = get_node_discovery_timeout(timeout_ms); 00122 00123 *wait_for_complete_timeout = false; 00124 00125 return status; 00126 } 00127 00128 void XBeeDM::radio_status_update(AtCmdFrame::ModemStatus modem_status) 00129 { 00130 /* Update the radio status variables */ 00131 if (modem_status == AtCmdFrame::HwReset) { 00132 _hw_reset_cnt++; 00133 } else if (modem_status == AtCmdFrame::WdReset) { 00134 _wd_reset_cnt++; 00135 } 00136 00137 _modem_status = modem_status; 00138 00139 digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status); 00140 } 00141 00142 TxStatus XBeeDM::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr) 00143 { 00144 if (!remote.is_valid_addr64b()) { 00145 return TxStatusInvalidAddr; 00146 } 00147 00148 const uint64_t remote64 = remote.get_addr64(); 00149 const uint16_t remote16 = remote.get_addr16(); 00150 00151 TxFrameDM frame = TxFrameDM(remote64, remote16, BROADCAST_RADIUS_USE_NH, 00152 _tx_options, data, len); 00153 if (syncr) { 00154 return send_data(&frame); 00155 } else { 00156 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */ 00157 send_api_frame(&frame); 00158 return TxStatusSuccess; 00159 } 00160 } 00161 00162 TxStatus XBeeDM::send_data(const RemoteXBee& remote, uint8_t source_ep, 00163 uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id, 00164 const uint8_t *const data, uint16_t len, bool syncr) 00165 { 00166 if (!remote.is_valid_addr64b()) { 00167 return TxStatusInvalidAddr; 00168 } 00169 00170 const uint64_t remote64 = remote.get_addr64(); 00171 const uint16_t remote16 = remote.get_addr16(); 00172 00173 TxFrameDM frame = TxFrameDM(remote64, remote16, source_ep, dest_ep, 00174 cluster_id, profile_id, BROADCAST_RADIUS_USE_NH, 00175 _tx_options, data, len); 00176 if (syncr) { 00177 return send_data(&frame); 00178 } else { 00179 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */ 00180 send_api_frame(&frame); 00181 return TxStatusSuccess; 00182 } 00183 } 00184 00185 TxStatus XBeeDM::send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr) 00186 { 00187 const uint64_t remaddr = ADDR64_COORDINATOR; 00188 00189 TxFrameDM frame = TxFrameDM(remaddr, ADDR16_UNKNOWN, BROADCAST_RADIUS_USE_NH, _tx_options, data, len); 00190 if (syncr) { 00191 return send_data(&frame); 00192 } else { 00193 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */ 00194 send_api_frame(&frame); 00195 return TxStatusSuccess; 00196 } 00197 } 00198 00199 RemoteXBeeDM XBeeDM::get_remote_node_by_id(const char * const node_id) 00200 { 00201 uint64_t addr64; 00202 uint16_t addr16; 00203 _get_remote_node_by_id(node_id, &addr64, &addr16); 00204 return RemoteXBeeDM(addr64); 00205 } 00206 00207 void XBeeDM::register_node_discovery_cb(node_discovery_dm_cb_t function) 00208 { 00209 if (_nd_handler == NULL) { 00210 _nd_handler = new FH_NodeDiscoveryDM(); 00211 register_frame_handler(_nd_handler); 00212 } 00213 _nd_handler->register_node_discovery_cb(function); 00214 } 00215 00216 void XBeeDM::unregister_node_discovery_cb() 00217 { 00218 if (_nd_handler != NULL) { 00219 _nd_handler->unregister_node_discovery_cb(); 00220 unregister_frame_handler(_nd_handler); 00221 delete _nd_handler; 00222 _nd_handler = NULL; /* as delete does not set to NULL */ 00223 } 00224 } 00225 00226 void XBeeDM::register_receive_cb(receive_dm_cb_t function) 00227 { 00228 if (_rx_pkt_handler == NULL) { 00229 _rx_pkt_handler = new FH_RxPacketDM(); 00230 register_frame_handler(_rx_pkt_handler); 00231 } 00232 _rx_pkt_handler->register_receive_cb(function); 00233 } 00234 00235 void XBeeDM::unregister_receive_cb() 00236 { 00237 if (_rx_pkt_handler != NULL) { 00238 _rx_pkt_handler->unregister_receive_cb(); 00239 unregister_frame_handler(_rx_pkt_handler); 00240 delete _rx_pkt_handler; 00241 _rx_pkt_handler = NULL; /* as delete does not set to NULL */ 00242 } 00243 } 00244 00245 void XBeeDM::register_io_sample_cb(io_data_cb_dm_t function) 00246 { 00247 if (_io_data_handler == NULL) { 00248 _io_data_handler = new FH_IoDataSampeDM(); 00249 register_frame_handler(_io_data_handler); 00250 } 00251 _io_data_handler->register_io_data_cb(function); 00252 } 00253 00254 void XBeeDM::unregister_io_sample_cb() 00255 { 00256 if (_io_data_handler != NULL) { 00257 _io_data_handler->unregister_io_data_cb(); 00258 unregister_frame_handler(_io_data_handler); 00259 delete _io_data_handler; 00260 _io_data_handler = NULL; /* as delete does not set to NULL */ 00261 } 00262 } 00263 00264 AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data) 00265 { 00266 if (!remote.is_valid_addr64b()) { 00267 return AtCmdFrame::AtCmdRespInvalidAddr; 00268 } 00269 00270 const uint64_t remote64 = remote.get_addr64(); 00271 const uint16_t remote16 = remote.get_addr16(); 00272 uint16_t len = sizeof *data; 00273 AtCmdFrame::AtCmdResp atCmdResponse; 00274 00275 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param); 00276 atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote); 00277 00278 if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) { 00279 atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch; 00280 } 00281 00282 return atCmdResponse; 00283 } 00284 00285 AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, uint32_t data) 00286 { 00287 if (!remote.is_valid_addr64b()) { 00288 return AtCmdFrame::AtCmdRespInvalidAddr; 00289 } 00290 00291 const uint64_t remote64 = remote.get_addr64(); 00292 const uint16_t remote16 = remote.get_addr16(); 00293 00294 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data); 00295 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); 00296 } 00297 00298 AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len) 00299 { 00300 if (!remote.is_valid_addr64b()) { 00301 return AtCmdFrame::AtCmdRespInvalidAddr; 00302 } 00303 00304 const uint64_t remote64 = remote.get_addr64(); 00305 const uint16_t remote16 = remote.get_addr16(); 00306 00307 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data, len); 00308 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); 00309 } 00310 00311 AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len) 00312 { 00313 00314 if (!remote.is_valid_addr64b()) { 00315 return AtCmdFrame::AtCmdRespInvalidAddr; 00316 } 00317 00318 const uint64_t remote64 = remote.get_addr64(); 00319 const uint16_t remote16 = remote.get_addr16(); 00320 00321 AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param); 00322 return send_at_cmd(&cmd_frame, data, len, RadioRemote, false); 00323 } 00324 00325 static void get_dio_cmd(XBeeDM::IoLine line, char * const iocmd) 00326 { 00327 if (line >= XBeeDM::DIO10_PWM0) { 00328 iocmd[0] = 'P'; 00329 iocmd[1] = '0' + line - XBeeDM::DIO10_PWM0; 00330 } else { 00331 iocmd[0] = 'D'; 00332 iocmd[1] = '0' + line; 00333 } 00334 iocmd[2] = '\0'; 00335 } 00336 00337 RadioStatus XBeeDM::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode) 00338 { 00339 AtCmdFrame::AtCmdResp cmdresp; 00340 char iocmd[3]; 00341 00342 get_dio_cmd(line, iocmd); 00343 00344 cmdresp = set_param(remote, iocmd, (uint8_t)mode); 00345 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00346 digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp); 00347 return Failure; 00348 } 00349 00350 return Success; 00351 } 00352 00353 RadioStatus XBeeDM::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode) 00354 { 00355 AtCmdFrame::AtCmdResp cmdresp; 00356 char iocmd[3]; 00357 00358 get_dio_cmd(line, iocmd); 00359 00360 uint32_t var32; 00361 cmdresp = get_param(remote, iocmd, &var32); 00362 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00363 return Failure; 00364 } 00365 *mode = (IoMode)var32; 00366 00367 return Success; 00368 } 00369 00370 RadioStatus XBeeDM::set_dio(const RemoteXBee& remote, IoLine line, DioVal val) 00371 { 00372 return set_pin_config(remote, line, val == Low ? DigitalOutLow : DigitalOutHigh); 00373 } 00374 00375 RadioStatus XBeeDM::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val) 00376 { 00377 return get_iosample(remote).get_dio(line, val); 00378 } 00379 00380 RadioStatus XBeeDM::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val) 00381 { 00382 return get_iosample(remote).get_adc(line, val); 00383 } 00384 00385 RadioStatus XBeeDM::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle) 00386 { 00387 AtCmdFrame::AtCmdResp cmdresp; 00388 char iocmd[3] = { 'M', '0', '\0' }; 00389 00390 if (line != DIO10_PWM0 && line != DIO11_PWM1) { 00391 return Failure; 00392 } 00393 if (line == DIO11_PWM1) { 00394 iocmd[1] = '1'; 00395 } 00396 00397 uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100); 00398 00399 cmdresp = set_param(remote, iocmd, pwm_val); 00400 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure; 00401 } 00402 00403 IOSampleDM XBeeDM::get_iosample(const RemoteXBee& remote) 00404 { 00405 uint8_t io_sample[MAX_IO_SAMPLE_DM_LEN]; 00406 uint16_t len = sizeof io_sample; 00407 00408 RadioStatus resp = _get_iosample(remote, io_sample, &len); 00409 if (resp != Success) { 00410 digi_log(LogLevelError, "XBeeDM::get_iosample failed to get an IOSample\r\n"); 00411 len = 0; 00412 } 00413 00414 return IOSampleDM(io_sample, len); 00415 } 00416 00417 static uint16_t get_dio_pr_mask(XBeeDM::IoLine line) 00418 { 00419 switch (line) { 00420 case XBeeDM::DIO4: 00421 return (1 << 0); 00422 case XBeeDM::DIO3_AD3: 00423 return (1 << 1); 00424 case XBeeDM::DIO2_AD2: 00425 return (1 << 2); 00426 case XBeeDM::DIO1_AD1: 00427 return (1 << 3); 00428 case XBeeDM::DIO0_AD0: 00429 return (1 << 4); 00430 case XBeeDM::DIO6: 00431 return (1 << 5); 00432 case XBeeDM::DIO8: 00433 return (1 << 6); 00434 case XBeeDM::DIO5: 00435 return (1 << 8); 00436 case XBeeDM::DIO9: 00437 return (1 << 9); 00438 case XBeeDM::DIO12: 00439 return (1 << 10); 00440 case XBeeDM::DIO10_PWM0: 00441 return (1 << 11); 00442 case XBeeDM::DIO11_PWM1: 00443 return (1 << 12); 00444 case XBeeDM::DIO7: 00445 return (1 << 13); 00446 default: 00447 return 0; 00448 } 00449 } 00450 00451 RadioStatus XBeeDM::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable) 00452 { 00453 AtCmdFrame::AtCmdResp cmdresp; 00454 uint32_t var32; 00455 uint16_t pr; 00456 00457 cmdresp = get_param(remote, "PR", &var32); 00458 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00459 return Failure; 00460 } 00461 pr = var32; 00462 00463 const uint16_t dio_mask = get_dio_pr_mask(line); 00464 if (dio_mask == 0) { 00465 digi_log(LogLevelError, "XBeeDM::set_pin_pull_up: invalid pin %d\r\n", line); 00466 return Failure; 00467 } 00468 00469 if (enable) { 00470 pr |= dio_mask; 00471 } else { 00472 pr &= ~dio_mask; 00473 } 00474 00475 cmdresp = set_param(remote, "PR", pr); 00476 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00477 return Failure; 00478 } 00479 00480 return Success; 00481 } 00482 00483 static uint16_t get_dio_ic_mask(XBeeDM::IoLine line) 00484 { 00485 if (line <= XBeeDM::DIO12) { 00486 return (1 << line); 00487 } 00488 return 0; 00489 } 00490 00491 RadioStatus XBeeDM::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable) 00492 { 00493 if (line > DIO12) { 00494 digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: pin not supported (%d)\r\n", line); 00495 return Failure; 00496 } 00497 00498 AtCmdFrame::AtCmdResp cmdresp; 00499 uint32_t var32; 00500 uint16_t ic; 00501 00502 cmdresp = get_param(remote, "IC", &var32); 00503 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00504 return Failure; 00505 } 00506 ic = var32; 00507 00508 const uint16_t dio_mask = get_dio_ic_mask(line); 00509 if (dio_mask == 0) { 00510 digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: invalid pin %d\r\n", line); 00511 return Failure; 00512 } 00513 00514 if (enable) { 00515 ic |= dio_mask; 00516 } else { 00517 ic &= ~dio_mask; 00518 } 00519 00520 cmdresp = set_param(remote, "IC", ic); 00521 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00522 return Failure; 00523 } 00524 00525 return Success; 00526 } 00527 00528 RadioStatus XBeeDM::config_poll_destination(const RemoteXBee& destination) 00529 { 00530 uint32_t dh; 00531 uint32_t dl; 00532 00533 if (destination.is_valid_addr64b()) { 00534 const uint64_t dest64 = destination.get_addr64(); 00535 dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF); 00536 dl = (uint32_t)((dest64 & 0xFFFFFFFF)); 00537 } else { 00538 digi_log(LogLevelError, "config_poll_destination: Invalid destination"); 00539 return Failure; 00540 } 00541 00542 AtCmdFrame::AtCmdResp cmdresp; 00543 00544 cmdresp = set_param("DH", dh); 00545 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00546 digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp); 00547 return Failure; 00548 } 00549 00550 cmdresp = set_param("DL", dl); 00551 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00552 digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp); 00553 return Failure; 00554 } 00555 00556 return Success; 00557 }
Generated on Tue Jul 12 2022 20:40:23 by
