Xbee s2b for lpc11u24

Dependencies:   DigiLogger

Dependents:  

Fork of XBeeLib by Digi International Inc.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers XBeeDM.cpp Source File

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 }