Library to easily communicate with XBee modules.
Fork of XBeeLib by
XBee802/XBee802.cpp
- Committer:
- hbujanda
- Date:
- 2015-05-11
- Revision:
- 1:794d1d3e4a08
- Parent:
- 0:fcaad0dfa051
- Child:
- 2:2ee1b6d51df2
File content as of revision 1:794d1d3e4a08:
/** * Copyright (c) 2015 Digi International Inc., * All rights not expressly granted are reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343 * ======================================================================= */ #include "XBee802.h" #include "IO/IOSample802.h" #include "Frames/802_Frames.h" #include "FrameHandlers/FH_ModemStatus.h" using namespace XBeeLib; /* Class constructor */ XBee802::XBee802(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) : XBee(tx, rx, reset, rts, cts, baud), _sync_lost_cnt(0), _nd_handler(NULL), _rx_64b_handler(NULL), _rx_16b_handler(NULL), _io_data_64b_handler(NULL), _io_data_16b_handler(NULL) { _reset_timeout = RESET_TIMEOUT_MS; } /* Class destructor */ XBee802::~XBee802() { unregister_node_discovery_cb(); unregister_receive_cb(); unregister_io_sample_cb(); } RadioStatus XBee802::init() { RadioStatus retval = XBee::init(); const RadioProtocol radioProtocol = get_radio_protocol(); if (radioProtocol != Raw_802_15_4) { digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", Raw_802_15_4, radioProtocol); retval = Failure; } assert(radioProtocol == Raw_802_15_4); return retval; } RadioStatus XBee802::set_channel(uint8_t channel) { AtCmdFrame::AtCmdResp cmdresp; if (is_PRO()) { if (channel < 0x0C || channel > 0x17) { return Failure; } } else { if (channel < 0x0B || channel > 0x1A) { return Failure; } } cmdresp = set_param("CH", channel); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } return Success; } RadioStatus XBee802::get_channel(uint8_t * const channel) { if (channel == NULL) { return Failure; } AtCmdFrame::AtCmdResp cmdresp; uint32_t var32; cmdresp = get_param("CH", &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; *channel = var32; return Success; } RadioStatus XBee802::set_panid(uint16_t panid) { AtCmdFrame::AtCmdResp cmdresp; cmdresp = set_param("ID", panid); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } return Success; } RadioStatus XBee802::get_panid(uint16_t * const panid) { if (panid == NULL) { return Failure; } AtCmdFrame::AtCmdResp cmdresp; uint32_t var32; cmdresp = get_param("ID", &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; *panid = var32; return Success; } RadioStatus XBee802::set_network_address(uint16_t addr16) { AtCmdFrame::AtCmdResp cmdresp; cmdresp = set_param("MY", addr16); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } return Success; } void XBee802::radio_status_update(AtCmdFrame::ModemStatus modem_status) { /* Update the radio status variables */ if (modem_status == AtCmdFrame::HwReset) _hw_reset_cnt++; else if (modem_status == AtCmdFrame::WdReset) _wd_reset_cnt++; else if (modem_status == AtCmdFrame::SyncLost) _sync_lost_cnt++; _modem_status = modem_status; digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status); } TxStatus XBee802::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len) { if (remote.is_valid_addr64b()) { const uint64_t remote64 = remote.get_addr64(); digi_log(LogLevelDebug, "send_data ADDR64: %08x:%08x\r\n", UINT64_HI32(remote64), UINT64_LO32(remote64)); TxFrame802 frame = TxFrame802(remote64, _tx_options, data, len); return send_data(&frame); } if (remote.is_valid_addr16b()) { const uint16_t remote16 = remote.get_addr16(); digi_log(LogLevelDebug, "send_data ADDR16: %04x\r\n", remote16); TxFrame802 frame = TxFrame802(remote16, _tx_options, data, len); return send_data(&frame); } return TxStatusInvalidAddr; } TxStatus XBee802::send_data(uint64_t remote64, const uint8_t *const data, uint16_t len) { TxFrame802 frame = TxFrame802(remote64, _tx_options, data, len); return send_data(&frame); } TxStatus XBee802::send_data(uint16_t addr16, const uint8_t *const data, uint16_t len) { TxFrame802 frame = TxFrame802(addr16, _tx_options, data, len); return send_data(&frame); } void XBee802::register_node_discovery_cb(node_discovery_802_cb_t function) { if (_nd_handler == NULL) { _nd_handler = new FH_NodeDiscovery802(); register_frame_handler(_nd_handler); } _nd_handler->register_node_discovery_cb(function); } void XBee802::unregister_node_discovery_cb() { if (_nd_handler != NULL) { _nd_handler->unregister_node_discovery_cb(); unregister_frame_handler(_nd_handler); delete _nd_handler; _nd_handler = NULL; /* as delete does not set to NULL */ } } void XBee802::register_receive_cb(receive_802_cb_t function) { if (_rx_64b_handler == NULL) { _rx_64b_handler = new FH_RxPacket64b802(); register_frame_handler(_rx_64b_handler); } _rx_64b_handler->register_receive_cb(function); if (_rx_16b_handler == NULL) { _rx_16b_handler = new FH_RxPacket16b802(); register_frame_handler(_rx_16b_handler); } _rx_16b_handler->register_receive_cb(function); } void XBee802::unregister_receive_cb() { if (_rx_64b_handler != NULL) { _rx_64b_handler->unregister_receive_cb(); unregister_frame_handler(_rx_64b_handler); delete _rx_64b_handler; _rx_64b_handler = NULL; /* as delete does not set to NULL */ } if (_rx_16b_handler != NULL) { _rx_16b_handler->unregister_receive_cb(); unregister_frame_handler(_rx_16b_handler); delete _rx_16b_handler; _rx_16b_handler = NULL; /* as delete does not set to NULL */ } } void XBee802::register_io_sample_cb(io_data_cb_802_t function) { if (_io_data_64b_handler == NULL) { _io_data_64b_handler = new FH_IoDataSampe64b802(); register_frame_handler(_io_data_64b_handler); } _io_data_64b_handler->register_io_data_cb(function); if (_io_data_16b_handler == NULL) { _io_data_16b_handler = new FH_IoDataSampe16b802(); register_frame_handler(_io_data_16b_handler); } _io_data_16b_handler->register_io_data_cb(function); } void XBee802::unregister_io_sample_cb() { if (_io_data_64b_handler != NULL) { _io_data_64b_handler->unregister_io_data_cb(); unregister_frame_handler(_io_data_64b_handler); delete _io_data_64b_handler; _io_data_64b_handler = NULL; /* as delete does not set to NULL */ } if (_io_data_16b_handler != NULL) { _io_data_16b_handler->unregister_io_data_cb(); unregister_frame_handler(_io_data_16b_handler); delete _io_data_16b_handler; _io_data_16b_handler = NULL; /* as delete does not set to NULL */ } } AtCmdFrame::AtCmdResp XBee802::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data) { uint16_t len = sizeof *data; AtCmdFrame::AtCmdResp atCmdResponse; if (remote.is_valid_addr64b()) { const uint64_t dev_addr64 = remote.get_addr64(); AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param); atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote); } else if (remote.is_valid_addr16b()) { const uint16_t dev_addr16 = remote.get_addr16(); AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param); atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote); } else { return AtCmdFrame::AtCmdRespInvalidAddr; } if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) { atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch; } return atCmdResponse; } AtCmdFrame::AtCmdResp XBee802::set_param(const RemoteXBee& remote, const char * const param, uint32_t data) { if (remote.is_valid_addr64b()) { const uint64_t dev_addr64 = remote.get_addr64(); AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param, data); return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); } if (remote.is_valid_addr16b()) { const uint16_t dev_addr16 = remote.get_addr16(); AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param, data); return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); } return AtCmdFrame::AtCmdRespInvalidAddr; } AtCmdFrame::AtCmdResp XBee802::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len) { if (remote.is_valid_addr64b()) { const uint64_t dev_addr64 = remote.get_addr64(); AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param, data, len); return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); } if (remote.is_valid_addr16b()) { const uint16_t dev_addr16 = remote.get_addr16(); AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param, data, len); return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote); } return AtCmdFrame::AtCmdRespInvalidAddr; } AtCmdFrame::AtCmdResp XBee802::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len) { if (remote.is_valid_addr64b()) { uint64_t dev_addr64 = remote.get_addr64(); AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param); return send_at_cmd(&cmd_frame, data, len, RadioRemote, false); } if (remote.is_valid_addr16b()) { uint16_t dev_addr16 = remote.get_addr16(); AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param); return send_at_cmd(&cmd_frame, data, len, RadioRemote, false); } return AtCmdFrame::AtCmdRespInvalidAddr; } static void get_dio_cmd(XBee802::IoLine line, char * const iocmd) { if (line >= XBee802::PWM0) { iocmd[0] = 'P'; iocmd[1] = '0' + line - XBee802::PWM0; } else { iocmd[0] = 'D'; iocmd[1] = '0' + line; } iocmd[2] = '\0'; } RadioStatus XBee802::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode) { AtCmdFrame::AtCmdResp cmdresp; char iocmd[3]; get_dio_cmd(line, iocmd); cmdresp = set_param(remote, iocmd, (uint8_t)mode); if (cmdresp != AtCmdFrame::AtCmdRespOk) { digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp); return Failure; } return Success; } RadioStatus XBee802::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode) { AtCmdFrame::AtCmdResp cmdresp; char iocmd[3]; get_dio_cmd(line, iocmd); uint32_t var32; cmdresp = get_param(remote, iocmd, &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } *mode = (IoMode)var32; return Success; } RadioStatus XBee802::set_dio(const RemoteXBee& remote, IoLine line, DioVal val) { if (line > DI8) { digi_log(LogLevelError, "set_dio: Pin %d not supported as IO\r\n", line); return Failure; } if (val == Low) { return set_pin_config(remote, line, DigitalOutLow); } else { return set_pin_config(remote, line, DigitalOutHigh); } } RadioStatus XBee802::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val) { uint8_t io_sample[MAX_IO_SAMPLE_BUF_LEN]; uint16_t len; if (line > DI8) { digi_log(LogLevelError, "get_dio: Pin %d not supported as IO\r\n", line); return Failure; } RadioStatus resp = get_iosample(remote, io_sample, &len); if (resp != Success) return resp; IOSample802 ioSample = IOSample802(io_sample, len); return ioSample.get_dio(line, val); } RadioStatus XBee802::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val) { uint8_t io_sample[MAX_IO_SAMPLE_BUF_LEN]; uint16_t len; if (line > DIO5_AD5) { digi_log(LogLevelError, "get_adc: Pin %d not supported as ADC\r\n", line); return Failure; } RadioStatus resp = get_iosample(remote, io_sample, &len); if (resp != Success) { return resp; } IOSample802 ioSample = IOSample802(io_sample, len); return ioSample.get_adc(line, val); } RadioStatus XBee802::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle) { AtCmdFrame::AtCmdResp cmdresp; char iocmd[3] = { 'M', '0', '\0' }; if (line != PWM0 && line != PWM1) { return Failure; } if (line == PWM1) { iocmd[1] = '1'; } uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100); cmdresp = set_param(remote, iocmd, pwm_val); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } static uint8_t get_dio_mask(XBee802::IoLine line) { switch (line) { case XBee802::DIO4_AD4: return (1 << 0); case XBee802::DIO3_AD3: return (1 << 1); case XBee802::DIO2_AD2: return (1 << 2); case XBee802::DIO1_AD1: return (1 << 3); case XBee802::DIO0_AD0: return (1 << 4); case XBee802::DIO6: return (1 << 5); case XBee802::DI8: return (1 << 6); default: return 0; } } RadioStatus XBee802::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable) { AtCmdFrame::AtCmdResp cmdresp; uint32_t var32; uint8_t pr; cmdresp = get_param(remote, "PR", &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; pr = var32; const uint8_t dio_mask = get_dio_mask(line); if (dio_mask == 0) { digi_log(LogLevelError, "XBee802::set_pin_pull_up: invalid pin %d\r\n", line); return Failure; } if (enable) { pr |= dio_mask; } else { pr &= ~dio_mask; } cmdresp = set_param(remote, "PR", pr); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } static uint8_t get_dio_ic_mask(XBee802::IoLine line) { if (line < XBee802::DI8) { return (1 << line); } return 0; } RadioStatus XBee802::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable) { if (line > DIO7) { digi_log(LogLevelError, "XBee802::enable_dio_change_detection: pin not supported (%d)\r\n", line); return Failure; } AtCmdFrame::AtCmdResp cmdresp; uint32_t var32; uint8_t ic; cmdresp = get_param(remote, "IC", &var32); if (cmdresp != AtCmdFrame::AtCmdRespOk) { return Failure; } ic = var32; const uint8_t dio_mask = get_dio_ic_mask(line); if (dio_mask == 0) { digi_log(LogLevelError, "XBeeZB::enable_dio_change_detection: invalid pin %d\r\n", line); return Failure; } if (enable) { ic |= dio_mask; } else { ic &= ~dio_mask; } cmdresp = set_param(remote, "IC", ic); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; return Success; } #ifdef GET_PWM_AVAILABLE RadioStatus XBee802::get_pwm(const RemoteXBee& remote, IoLine line, float * const duty_cycle) { AtCmdFrame::AtCmdResp cmdresp; char iocmd[3] = { 'M', '0', '\0' }; if (line != PWM0 && line != PWM1) return Failure; if (line == PWM1) iocmd[1] = '1'; uint16_t pwm_val; cmdresp = get_param(remote, iocmd, &pwm_val); if (cmdresp != AtCmdFrame::AtCmdRespOk) return Failure; *duty_cycle = (float)(pwm_val * 100 / DR_PWM_MAX_VAL); return Success; } #endif