XBeeLib modificado para projeto do VSSS
Fork of XBeeLib by
Embed:
(wiki syntax)
Show/hide line numbers
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 19:13:35 by 1.7.2