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
XBee802.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 #include "XBee802.h" 00013 #include "IO/IOSample802.h" 00014 #include "Frames/802_Frames.h" 00015 #include "FrameHandlers/FH_ModemStatus.h" 00016 00017 using namespace XBeeLib; 00018 00019 /* Class constructor */ 00020 XBee802::XBee802(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) : 00021 XBee(tx, rx, reset, rts, cts, baud), 00022 _nd_handler(NULL), _rx_64b_handler(NULL), _rx_16b_handler(NULL), 00023 _io_data_64b_handler(NULL), _io_data_16b_handler(NULL) 00024 { 00025 00026 } 00027 00028 /* Class destructor */ 00029 XBee802::~XBee802() 00030 { 00031 unregister_node_discovery_cb(); 00032 unregister_receive_cb(); 00033 unregister_io_sample_cb(); 00034 } 00035 00036 RadioStatus XBee802::init() 00037 { 00038 RadioStatus retval = XBee::init(); 00039 uint16_t addr16; 00040 RadioStatus error = get_network_address(&addr16); 00041 if (error == Success) { 00042 digi_log(LogLevelInfo, "ADDR16: %04x\r\n", addr16); 00043 } else { 00044 digi_log(LogLevelInfo, "ADDR16: UNKNOWN\r\n"); 00045 } 00046 00047 const RadioProtocol radioProtocol = get_radio_protocol(); 00048 if (radioProtocol != Raw_802_15_4) { 00049 digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", Raw_802_15_4, radioProtocol); 00050 retval = Failure; 00051 } 00052 assert(radioProtocol == Raw_802_15_4); 00053 00054 return retval; 00055 } 00056 00057 RadioStatus XBee802::set_channel(uint8_t channel) 00058 { 00059 AtCmdFrame::AtCmdResp cmdresp; 00060 00061 /* Pro and Non-Pro modules have different channels available. The at 00062 command will return an error if the selected channel is not available */ 00063 cmdresp = set_param("CH", channel); 00064 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00065 return Failure; 00066 } 00067 return Success; 00068 } 00069 00070 RadioStatus XBee802::get_channel(uint8_t * const channel) 00071 { 00072 if (channel == NULL) { 00073 return Failure; 00074 } 00075 AtCmdFrame::AtCmdResp cmdresp; 00076 00077 uint32_t var32; 00078 cmdresp = get_param("CH", &var32); 00079 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00080 return Failure; 00081 } 00082 *channel = var32; 00083 return Success; 00084 } 00085 00086 RadioStatus XBee802::set_panid(uint16_t panid) 00087 { 00088 AtCmdFrame::AtCmdResp cmdresp; 00089 00090 cmdresp = set_param("ID", panid); 00091 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00092 return Failure; 00093 } 00094 return Success; 00095 } 00096 00097 RadioStatus XBee802::get_panid(uint16_t * const panid) 00098 { 00099 if (panid == NULL) { 00100 return Failure; 00101 } 00102 AtCmdFrame::AtCmdResp cmdresp; 00103 00104 uint32_t var32; 00105 cmdresp = get_param("ID", &var32); 00106 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00107 return Failure; 00108 } 00109 *panid = var32; 00110 return Success; 00111 } 00112 00113 RadioStatus XBee802::get_network_address(uint16_t * const addr16) 00114 { 00115 if (addr16 == NULL) { 00116 return Failure; 00117 } 00118 AtCmdFrame::AtCmdResp cmdresp; 00119 00120 uint32_t var32; 00121 cmdresp = get_param("MY", &var32); 00122 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00123 return Failure; 00124 } 00125 *addr16 = var32; 00126 return Success; 00127 } 00128 00129 RadioStatus XBee802::set_network_address(uint16_t addr16) 00130 { 00131 AtCmdFrame::AtCmdResp cmdresp; 00132 00133 cmdresp = set_param("MY", addr16); 00134 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00135 return Failure; 00136 } 00137 return Success; 00138 } 00139 00140 RadioStatus XBee802::get_node_discovery_timeout(uint16_t * const timeout_ms) 00141 { 00142 AtCmdFrame::AtCmdResp cmdresp; 00143 uint32_t var32; 00144 00145 cmdresp = get_param("NT", &var32); 00146 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00147 return Failure; 00148 } 00149 *timeout_ms = (uint16_t)var32; 00150 00151 /* No N? command available for this protocol. Add a fix 1s guard time */ 00152 *timeout_ms += 1000; 00153 00154 return Success; 00155 } 00156 00157 RadioStatus XBee802::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout) 00158 { 00159 const RadioStatus status = get_node_discovery_timeout(timeout_ms); 00160 00161 /* This protocol requires to wait for the complete timeout before attempting 00162 to execute other commands */ 00163 *wait_for_complete_timeout = true; 00164 00165 return status; 00166 } 00167 00168 void XBee802::radio_status_update(AtCmdFrame::ModemStatus modem_status) 00169 { 00170 /* Update the radio status variables */ 00171 if (modem_status == AtCmdFrame::HwReset) { 00172 _hw_reset_cnt++; 00173 } else if (modem_status == AtCmdFrame::WdReset) { 00174 _wd_reset_cnt++; 00175 } 00176 00177 _modem_status = modem_status; 00178 00179 digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status); 00180 } 00181 00182 TxStatus XBee802::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr) 00183 { 00184 if (remote.is_valid_addr64b()) { 00185 const uint64_t remote64 = remote.get_addr64(); 00186 00187 digi_log(LogLevelDebug, "send_data ADDR64: %08x:%08x\r\n", UINT64_HI32(remote64), UINT64_LO32(remote64)); 00188 00189 TxFrame802 frame = TxFrame802(remote64, _tx_options, data, len); 00190 00191 if (syncr) { 00192 return send_data(&frame); 00193 } else { 00194 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */ 00195 send_api_frame(&frame); 00196 return TxStatusSuccess; 00197 } 00198 } 00199 00200 if (remote.is_valid_addr16b()) { 00201 const uint16_t remote16 = remote.get_addr16(); 00202 00203 digi_log(LogLevelDebug, "send_data ADDR16: %04x\r\n", remote16); 00204 00205 TxFrame802 frame = TxFrame802(remote16, _tx_options, data, len); 00206 00207 if (syncr) { 00208 return send_data(&frame); 00209 } else { 00210 frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */ 00211 send_api_frame(&frame); 00212 return TxStatusSuccess; 00213 } 00214 } 00215 00216 return TxStatusInvalidAddr; 00217 } 00218 00219 XBee802::AssocStatus XBee802::get_assoc_status(void) 00220 { 00221 return (AssocStatus )get_AI(); 00222 } 00223 00224 RemoteXBee802 XBee802::get_remote_node_by_id(const char * const node_id) 00225 { 00226 uint64_t addr64; 00227 uint16_t addr16; 00228 00229 _get_remote_node_by_id(node_id, &addr64, &addr16); 00230 return RemoteXBee802(addr64, addr16); 00231 } 00232 00233 void XBee802::register_node_discovery_cb(node_discovery_802_cb_t function) 00234 { 00235 if (_nd_handler == NULL) { 00236 _nd_handler = new FH_NodeDiscovery802(); 00237 register_frame_handler(_nd_handler); 00238 } 00239 _nd_handler->register_node_discovery_cb(function); 00240 } 00241 00242 void XBee802::unregister_node_discovery_cb() 00243 { 00244 if (_nd_handler != NULL) { 00245 _nd_handler->unregister_node_discovery_cb(); 00246 unregister_frame_handler(_nd_handler); 00247 delete _nd_handler; 00248 _nd_handler = NULL; /* as delete does not set to NULL */ 00249 } 00250 } 00251 00252 void XBee802::register_receive_cb(receive_802_cb_t function) 00253 { 00254 if (_rx_64b_handler == NULL) { 00255 _rx_64b_handler = new FH_RxPacket64b802(); 00256 register_frame_handler(_rx_64b_handler); 00257 } 00258 _rx_64b_handler->register_receive_cb(function); 00259 00260 if (_rx_16b_handler == NULL) { 00261 _rx_16b_handler = new FH_RxPacket16b802(); 00262 register_frame_handler(_rx_16b_handler); 00263 } 00264 _rx_16b_handler->register_receive_cb(function); 00265 } 00266 00267 void XBee802::unregister_receive_cb() 00268 { 00269 if (_rx_64b_handler != NULL) { 00270 _rx_64b_handler->unregister_receive_cb(); 00271 unregister_frame_handler(_rx_64b_handler); 00272 delete _rx_64b_handler; 00273 _rx_64b_handler = NULL; /* as delete does not set to NULL */ 00274 } 00275 00276 if (_rx_16b_handler != NULL) { 00277 _rx_16b_handler->unregister_receive_cb(); 00278 unregister_frame_handler(_rx_16b_handler); 00279 delete _rx_16b_handler; 00280 _rx_16b_handler = NULL; /* as delete does not set to NULL */ 00281 } 00282 } 00283 00284 void XBee802::register_io_sample_cb(io_data_cb_802_t function) 00285 { 00286 if (_io_data_64b_handler == NULL) { 00287 _io_data_64b_handler = new FH_IoDataSampe64b802(); 00288 register_frame_handler(_io_data_64b_handler); 00289 } 00290 _io_data_64b_handler->register_io_data_cb(function); 00291 00292 if (_io_data_16b_handler == NULL) { 00293 _io_data_16b_handler = new FH_IoDataSampe16b802(); 00294 register_frame_handler(_io_data_16b_handler); 00295 } 00296 _io_data_16b_handler->register_io_data_cb(function); 00297 } 00298 00299 void XBee802::unregister_io_sample_cb() 00300 { 00301 if (_io_data_64b_handler != NULL) { 00302 _io_data_64b_handler->unregister_io_data_cb(); 00303 unregister_frame_handler(_io_data_64b_handler); 00304 delete _io_data_64b_handler; 00305 _io_data_64b_handler = NULL; /* as delete does not set to NULL */ 00306 } 00307 00308 if (_io_data_16b_handler != NULL) { 00309 _io_data_16b_handler->unregister_io_data_cb(); 00310 unregister_frame_handler(_io_data_16b_handler); 00311 delete _io_data_16b_handler; 00312 _io_data_16b_handler = NULL; /* as delete does not set to NULL */ 00313 } 00314 } 00315 00316 AtCmdFrame::AtCmdResp XBee802::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data) 00317 { 00318 uint16_t len = sizeof *data; 00319 AtCmdFrame::AtCmdResp atCmdResponse; 00320 00321 if (remote.is_valid_addr64b()) { 00322 const uint64_t dev_addr64 = remote.get_addr64(); 00323 00324 AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param); 00325 atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote); 00326 } else if (remote.is_valid_addr16b()) { 00327 const uint16_t dev_addr16 = remote.get_addr16(); 00328 00329 AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param); 00330 atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote); 00331 } else { 00332 return AtCmdFrame::AtCmdRespInvalidAddr; 00333 } 00334 00335 if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) { 00336 atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch; 00337 } 00338 00339 return atCmdResponse; 00340 } 00341 00342 AtCmdFrame::AtCmdResp XBee802::set_param(const RemoteXBee& remote, const char * const param, uint32_t data) 00343 { 00344 if (remote.is_valid_addr64b()) { 00345 const uint64_t dev_addr64 = remote.get_addr64(); 00346 00347 AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param, data); 00348 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); 00349 } 00350 00351 if (remote.is_valid_addr16b()) { 00352 const uint16_t dev_addr16 = remote.get_addr16(); 00353 00354 AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param, data); 00355 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); 00356 } 00357 00358 return AtCmdFrame::AtCmdRespInvalidAddr; 00359 } 00360 00361 AtCmdFrame::AtCmdResp XBee802::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len) 00362 { 00363 if (remote.is_valid_addr64b()) { 00364 const uint64_t dev_addr64 = remote.get_addr64(); 00365 00366 AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param, data, len); 00367 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); 00368 } 00369 00370 if (remote.is_valid_addr16b()) { 00371 const uint16_t dev_addr16 = remote.get_addr16(); 00372 00373 AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param, data, len); 00374 return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); 00375 } 00376 00377 return AtCmdFrame::AtCmdRespInvalidAddr; 00378 } 00379 00380 AtCmdFrame::AtCmdResp XBee802::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len) 00381 { 00382 if (remote.is_valid_addr64b()) { 00383 uint64_t dev_addr64 = remote.get_addr64(); 00384 00385 AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param); 00386 return send_at_cmd(&cmd_frame, data, len, RadioRemote, false); 00387 } 00388 00389 if (remote.is_valid_addr16b()) { 00390 uint16_t dev_addr16 = remote.get_addr16(); 00391 00392 AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param); 00393 return send_at_cmd(&cmd_frame, data, len, RadioRemote, false); 00394 } 00395 00396 return AtCmdFrame::AtCmdRespInvalidAddr; 00397 } 00398 00399 static void get_dio_cmd(XBee802::IoLine line, char * const iocmd) 00400 { 00401 if (line >= XBee802::PWM0) { 00402 iocmd[0] = 'P'; 00403 iocmd[1] = '0' + line - XBee802::PWM0; 00404 } else { 00405 iocmd[0] = 'D'; 00406 iocmd[1] = '0' + line; 00407 } 00408 iocmd[2] = '\0'; 00409 } 00410 00411 RadioStatus XBee802::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode) 00412 { 00413 AtCmdFrame::AtCmdResp cmdresp; 00414 char iocmd[3]; 00415 00416 get_dio_cmd(line, iocmd); 00417 00418 cmdresp = set_param(remote, iocmd, (uint8_t)mode); 00419 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00420 digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp); 00421 return Failure; 00422 } 00423 00424 return Success; 00425 } 00426 00427 RadioStatus XBee802::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode) 00428 { 00429 AtCmdFrame::AtCmdResp cmdresp; 00430 char iocmd[3]; 00431 00432 get_dio_cmd(line, iocmd); 00433 00434 uint32_t var32; 00435 cmdresp = get_param(remote, iocmd, &var32); 00436 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00437 return Failure; 00438 } 00439 *mode = (IoMode)var32; 00440 00441 return Success; 00442 } 00443 00444 RadioStatus XBee802::set_dio(const RemoteXBee& remote, IoLine line, DioVal val) 00445 { 00446 if (line > DI8) { 00447 digi_log(LogLevelError, "set_dio: Pin %d not supported as IO\r\n", line); 00448 return Failure; 00449 } 00450 00451 if (val == Low) { 00452 return set_pin_config(remote, line, DigitalOutLow); 00453 } else { 00454 return set_pin_config(remote, line, DigitalOutHigh); 00455 } 00456 } 00457 00458 RadioStatus XBee802::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val) 00459 { 00460 return get_iosample(remote).get_dio(line, val); 00461 } 00462 00463 RadioStatus XBee802::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val) 00464 { 00465 return get_iosample(remote).get_adc(line, val); 00466 } 00467 00468 RadioStatus XBee802::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle) 00469 { 00470 AtCmdFrame::AtCmdResp cmdresp; 00471 char iocmd[3] = { 'M', '0', '\0' }; 00472 00473 if (line != PWM0 && line != PWM1) { 00474 return Failure; 00475 } 00476 if (line == PWM1) { 00477 iocmd[1] = '1'; 00478 } 00479 00480 uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100); 00481 00482 cmdresp = set_param(remote, iocmd, pwm_val); 00483 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure; 00484 } 00485 00486 IOSample802 XBee802::get_iosample(const RemoteXBee& remote) 00487 { 00488 uint8_t io_sample[MAX_IO_SAMPLE_802_LEN]; 00489 uint16_t len = sizeof io_sample; 00490 00491 RadioStatus resp = _get_iosample(remote, io_sample, &len); 00492 if (resp != Success) { 00493 digi_log(LogLevelError, "XBee802::get_iosample failed to get an IOSample\r\n"); 00494 len = 0; 00495 } 00496 return IOSample802(io_sample, len); 00497 } 00498 00499 static uint8_t get_dio_mask(XBee802::IoLine line) 00500 { 00501 switch (line) { 00502 case XBee802::DIO4_AD4: 00503 return (1 << 0); 00504 case XBee802::DIO3_AD3: 00505 return (1 << 1); 00506 case XBee802::DIO2_AD2: 00507 return (1 << 2); 00508 case XBee802::DIO1_AD1: 00509 return (1 << 3); 00510 case XBee802::DIO0_AD0: 00511 return (1 << 4); 00512 case XBee802::DIO6: 00513 return (1 << 5); 00514 case XBee802::DI8: 00515 return (1 << 6); 00516 default: 00517 return 0; 00518 } 00519 } 00520 00521 RadioStatus XBee802::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable) 00522 { 00523 AtCmdFrame::AtCmdResp cmdresp; 00524 uint32_t var32; 00525 uint8_t pr; 00526 00527 cmdresp = get_param(remote, "PR", &var32); 00528 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00529 return Failure; 00530 } 00531 pr = var32; 00532 00533 const uint8_t dio_mask = get_dio_mask(line); 00534 if (dio_mask == 0) { 00535 digi_log(LogLevelError, "XBee802::set_pin_pull_up: invalid pin %d\r\n", line); 00536 return Failure; 00537 } 00538 00539 if (enable) { 00540 pr |= dio_mask; 00541 } else { 00542 pr &= ~dio_mask; 00543 } 00544 00545 cmdresp = set_param(remote, "PR", pr); 00546 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure; 00547 } 00548 00549 static uint8_t get_dio_ic_mask(XBee802::IoLine line) 00550 { 00551 if (line < XBee802::DI8) { 00552 return (1 << line); 00553 } 00554 return 0; 00555 } 00556 00557 RadioStatus XBee802::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable) 00558 { 00559 if (line > DIO7) { 00560 digi_log(LogLevelError, "XBee802::enable_dio_change_detection: pin not supported (%d)\r\n", line); 00561 return Failure; 00562 } 00563 00564 AtCmdFrame::AtCmdResp cmdresp; 00565 uint32_t var32; 00566 uint8_t ic; 00567 00568 cmdresp = get_param(remote, "IC", &var32); 00569 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00570 return Failure; 00571 } 00572 ic = var32; 00573 00574 const uint8_t dio_mask = get_dio_ic_mask(line); 00575 if (dio_mask == 0) { 00576 digi_log(LogLevelError, "XBeeZB::enable_dio_change_detection: invalid pin %d\r\n", line); 00577 return Failure; 00578 } 00579 00580 if (enable) { 00581 ic |= dio_mask; 00582 } else { 00583 ic &= ~dio_mask; 00584 } 00585 00586 cmdresp = set_param(remote, "IC", ic); 00587 return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure; 00588 } 00589 00590 #ifdef GET_PWM_AVAILABLE 00591 RadioStatus XBee802::get_pwm(const RemoteXBee& remote, IoLine line, float * const duty_cycle) 00592 { 00593 AtCmdFrame::AtCmdResp cmdresp; 00594 char iocmd[3] = { 'M', '0', '\0' }; 00595 00596 if (line != PWM0 && line != PWM1) { 00597 return Failure; 00598 } 00599 00600 if (line == PWM1) { 00601 iocmd[1] = '1'; 00602 } 00603 00604 uint16_t pwm_val; 00605 00606 cmdresp = get_param(remote, iocmd, &pwm_val); 00607 if (cmdresp != AtCmdFrame::AtCmdRespOk) { 00608 return Failure; 00609 } 00610 00611 *duty_cycle = (float)(pwm_val * 100 / DR_PWM_MAX_VAL); 00612 00613 return Success; 00614 } 00615 #endif
Generated on Tue Jul 12 2022 20:40:23 by
