test
Embed:
(wiki syntax)
Show/hide line numbers
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 Nov 1 2022 06:41:58 by 1.7.2