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.
Dependents: XBeeZB_Receive_Data
Fork of XBeeLib by
Revision 0:fcaad0dfa051, committed 2015-05-08
- Comitter:
- spastor
- Date:
- Fri May 08 11:50:56 2015 +0200
- Child:
- 1:794d1d3e4a08
- Commit message:
- Automatic upload
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DigiLogger.lib Fri May 08 11:50:56 2015 +0200 @@ -0,0 +1,1 @@ +http://developer.mbed.org/teams/Digi-International-Inc/code/DigiLogger/#79cea2b2eea6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameBuffer/FrameBuffer.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,131 @@
+/**
+ * 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 "FrameBuffer.h"
+
+#if !(defined AVOID_DISABLE_IRQS)
+#define disable_irq() __disable_irq()
+#define enable_irq() __enable_irq()
+#else
+#define disable_irq()
+#define enable_irq()
+#endif
+
+FrameBuffer::FrameBuffer() : _head(0), _tail_app(0), _tail_syncr(0), _dropped_frames(0)
+{
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++) {
+ _frm_buf[i].frame = new ApiFrame(MAX_FRAME_PAYLOAD_LEN - 1);
+ _frm_buf[i].status = FrameStatusFree;
+ }
+}
+
+FrameBuffer::~FrameBuffer()
+{
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++) {
+ delete _frm_buf[i].frame;
+ }
+}
+
+ApiFrame *FrameBuffer::get_next_free_frame(void)
+{
+ uint8_t i = _head;
+ ApiFrame *ret = NULL;
+
+ do {
+ if (_frm_buf[i].status == FrameStatusFree || _frm_buf[i].status == FrameStatusComplete) {
+ if (_frm_buf[i].status == FrameStatusComplete)
+ _dropped_frames++;
+ _frm_buf[i].status = FrameStatusAssigned;
+ ret = _frm_buf[i].frame;
+ _head = ++i % FRAME_BUFFER_SIZE;
+ break;
+ }
+ i++;
+ i = i % FRAME_BUFFER_SIZE;
+ } while (i != _head);
+
+ return ret;
+}
+
+bool FrameBuffer::complete_frame(ApiFrame *frame)
+{
+ bool ret = false;
+
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++) {
+ if (_frm_buf[i].frame == frame) {
+ _frm_buf[i].status = FrameStatusComplete;
+ ret = true;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+ApiFrame *FrameBuffer::get_next_complete_frame(uint8_t* tail)
+{
+ uint8_t i = *tail;
+ ApiFrame *ret = NULL;
+
+ do {
+ disable_irq();
+ if (_frm_buf[i].status == FrameStatusComplete) {
+ _frm_buf[i].status = FrameStatusAssigned;
+ enable_irq();
+ ret = _frm_buf[i].frame;
+ *tail = ++i % FRAME_BUFFER_SIZE;
+ break;
+ }
+ enable_irq();
+ i++;
+ i = i % FRAME_BUFFER_SIZE;
+ } while (i != *tail);
+
+ return ret;
+}
+
+ApiFrame *FrameBuffer::get_next_complete_frame_syncr(void)
+{
+ return get_next_complete_frame(&_tail_syncr);
+}
+
+ApiFrame *FrameBuffer::get_next_complete_frame_app(void)
+{
+ return get_next_complete_frame(&_tail_app);
+}
+
+bool FrameBuffer::free_frame(ApiFrame *frame)
+{
+ bool ret = false;
+
+ for (int i = 0; i < FRAME_BUFFER_SIZE; i++) {
+ if (_frm_buf[i].frame == frame) {
+ _frm_buf[i].status = FrameStatusFree;
+ ret = true;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+uint32_t FrameBuffer::get_dropped_frames_count(void)
+{
+ const uint32_t dropped_frames = _dropped_frames;
+
+ _dropped_frames = 0;
+
+ return dropped_frames;
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameBuffer/FrameBuffer.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,114 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FRAME_BUFFER_H_)
+#define __FRAME_BUFFER_H_
+
+#include "config.h"
+#include "mbed.h"
+#include "Frames/ApiFrame.h"
+
+#if FRAME_BUFFER_SIZE > 255
+# error "FRAME_BUFFER_SIZE must be lower than 256"
+#endif
+
+typedef struct element {
+ ApiFrame *frame;
+ uint8_t status;
+} buf_element_t;
+
+/**
+ * @class FrameBuffer
+ * @brief storage class for incoming frames
+ */
+class FrameBuffer
+{
+ public:
+ /** Constructor */
+ FrameBuffer();
+
+ FrameBuffer(const FrameBuffer& other); /* Intentionally not implemented */
+ /** Destructor */
+ ~FrameBuffer();
+
+ /** get_next_free_frame returns the next free frame
+ *
+ * @returns a pointer to the next free frame */
+ ApiFrame *get_next_free_frame();
+
+ /** complete_frame sets the status of the frame to complete once the
+ * data has been set in the buffer.
+ *
+ * @param pointer to the buffer we want to set as complete
+ * @returns true on success, false otherwise
+ */
+ bool complete_frame(ApiFrame *frame);
+
+ /** free_frame makes the frame available to be reused in future
+ *
+ * @param frame to release */
+ bool free_frame(ApiFrame *frame);
+
+ /** get_next_complete_frame_app returns the pointer to the next complete frame using _tail_app
+ *
+ * @returns the pointer to the selected buffer
+ */
+ ApiFrame *get_next_complete_frame_app();
+
+ /** get_next_complete_frame_syncr returns the pointer to the next complete frame using _tail_syncr
+ *
+ * @returns the pointer to the selected buffer
+ */
+ ApiFrame *get_next_complete_frame_syncr();
+
+ /** get_dropped_frames_count returns the number of dropped frames since latest call to this method
+ *
+ * @returns the number of dropped frames since latest call to this method
+ */
+ uint32_t get_dropped_frames_count();
+
+
+protected:
+
+ /** frame status */
+ enum FrameStatus {
+ FrameStatusFree = 0, /**< Free */
+ FrameStatusAssigned, /**< Assigned */
+ FrameStatusComplete /**< Complete */
+ };
+
+ /** buffer array */
+ buf_element_t _frm_buf[FRAME_BUFFER_SIZE];
+
+ /** head frame index */
+ uint8_t _head;
+
+ /** tail frame index for application */
+ uint8_t _tail_app;
+
+ /** tail frame index for syncronous operations */
+ uint8_t _tail_syncr;
+
+ /** dropped frames */
+ uint32_t _dropped_frames;
+
+ /** get_next_complete_frame returns the pointer to the next complete frame
+ *
+ * @param tail tail index to use (either _tail_app or _tail_syncr)
+ * @returns the pointer to the selected buffer
+ */
+ ApiFrame *get_next_complete_frame(uint8_t* tail);
+};
+
+#endif /* __FRAME_BUFFER_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_AtCmdResp.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,174 @@
+/**
+ * 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 "FrameHandlers/FH_AtCmdResp.h"
+#include "Frames/ApiFrame.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_AtCmdResp::FH_AtCmdResp() :
+ FrameHandler(ApiFrame::AtCmdResp), at_cmd_resp_cb(NULL)
+{
+}
+
+FH_AtCmdResp::FH_AtCmdResp(ApiFrame::ApiFrameType type) :
+ FrameHandler(type), at_cmd_resp_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_AtCmdResp::~FH_AtCmdResp()
+{
+}
+
+/** */
+void FH_AtCmdResp::register_at_cmd_resp_cb(at_cmd_resp_cb_t function)
+{
+ at_cmd_resp_cb = function;
+}
+
+/** */
+void FH_AtCmdResp::unregister_at_cmd_resp_cb()
+{
+ at_cmd_resp_cb = NULL;
+}
+
+void FH_AtCmdResp::process_frame_data(const ApiFrame * const frame)
+{
+ /* The caller checks that the type matches, so no need to check it here again */
+
+ if (at_cmd_resp_cb == NULL)
+ return;
+
+ at_cmd_resp_cb(frame->get_data(), frame->get_data_len());
+}
+
+
+/** Class constructor */
+FH_NodeDiscoveryZB::FH_NodeDiscoveryZB() :
+ FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscoveryZB::~FH_NodeDiscoveryZB()
+{
+}
+
+/** */
+void FH_NodeDiscoveryZB::register_node_discovery_cb(node_discovery_zb_cb_t function)
+{
+ node_discovery_cb = function;
+}
+
+/** */
+void FH_NodeDiscoveryZB::unregister_node_discovery_cb()
+{
+ node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscoveryZB::process_frame_data(const ApiFrame *const frame)
+{
+ /* The caller checks that the type matches, so no need to check it here again */
+
+ if (node_discovery_cb == NULL) {
+ return;
+ }
+
+ if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+ frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+ return;
+ }
+
+ if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+ return;
+ }
+
+ const uint8_t * const data = frame->get_data(); /* The data payload we get here is the full AT command response payload, excluding the frameid. Keep that in mind for the offsets */
+ const uint16_t addr16 = UINT16(data[ATCMD_RESP_NW_ADDR_H_OFFSET], data[ATCMD_RESP_NW_ADDR_L_OFFSET]);
+ const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+ const char * const node_id = (const char *)&data[ATCMD_RESP_NI_OFFSET];
+#if 0
+ const unsigned int node_id_len = strlen(node_id);
+ const unsigned int parent_addr16_offset = ATCMD_RESP_NI_OFFSET + node_id_len + sizeof "";
+ const uint16_t parent_addr16 = UINT16(data[parent_addr16_offset], data[parent_addr16_offset + 1]);
+ const NetworkRole network_role = (NetworkRole)(data[parent_addr16_offset + 2]);
+ const uint16_t profile_id = UINT16(data[parent_addr16_offset + 4], data[parent_addr16_offset + 5]);
+ const uint16_t manuf_id = UINT16(data[parent_addr16_offset + 6], data[parent_addr16_offset + 7]);
+#endif
+ RemoteXBeeZB remote = RemoteXBeeZB(addr64, addr16);
+
+ node_discovery_cb(remote, node_id);
+}
+
+
+
+/** Class constructor */
+FH_NodeDiscovery802::FH_NodeDiscovery802() :
+ FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscovery802::~FH_NodeDiscovery802()
+{
+}
+
+/** */
+void FH_NodeDiscovery802::register_node_discovery_cb(node_discovery_802_cb_t function)
+{
+ node_discovery_cb = function;
+}
+
+/** */
+void FH_NodeDiscovery802::unregister_node_discovery_cb()
+{
+ node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscovery802::process_frame_data(const ApiFrame *const frame)
+{
+ /* The caller checks that the type matches, so no need to check it here again */
+
+ if (node_discovery_cb == NULL) {
+ return;
+ }
+
+ if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+ frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+ return;
+ }
+
+ if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+ return;
+ }
+
+ const uint16_t min_atnd_response_with_data = 2 + 8 + 1;
+ if (frame->get_data_len() < min_atnd_response_with_data) {
+ /* Do not process the ATND "OK" response */
+ return;
+ }
+
+ const uint8_t * const data = frame->get_data();
+ const uint16_t addr16 = UINT16(data[ATCMD_RESP_NW_ADDR_H_OFFSET], data[ATCMD_RESP_NW_ADDR_L_OFFSET]);
+ const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+#if 0
+ const uint8_t signal_strength = data[ATCMD_802_RESP_SIGN_STR_OFFSET];
+#endif
+ const RemoteXBee802 remote = RemoteXBee802(addr64, addr16);
+ const char * const nodeid = (const char *)(&data[ATCMD_802_RESP_NI_OFFSET]);
+
+ node_discovery_cb(remote, nodeid);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_AtCmdResp.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,125 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FH_AT_CMD_RESP_H_)
+#define __FH_AT_CMD_RESP_H_
+
+#include "FrameHandler.h"
+#include "XBee/XBee.h"
+
+namespace XBeeLib {
+typedef void (*at_cmd_resp_cb_t)(const uint8_t * data, uint16_t len);
+
+class FH_AtCmdResp : public FrameHandler
+{
+ private:
+ /** Callback function, invoked (if registered) when an at command response packet is received */
+ at_cmd_resp_cb_t at_cmd_resp_cb;
+
+ public:
+
+ /** Class constructor */
+ FH_AtCmdResp();
+
+ /** Class constructor */
+ FH_AtCmdResp(ApiFrame::ApiFrameType type);
+
+
+ /** Class destructor */
+ virtual ~FH_AtCmdResp();
+
+ virtual void process_frame_data(const ApiFrame *const frame);
+
+ /** */
+ virtual void register_at_cmd_resp_cb(at_cmd_resp_cb_t function);
+
+ /** */
+ virtual void unregister_at_cmd_resp_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** Node Discovery Response callback type declaration for ZigBee
+ * @param remote discovered remote node.
+ * @param node_id Node Identifier (NI parameter) of remote.
+ */
+typedef void (*node_discovery_zb_cb_t)(const RemoteXBeeZB& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscoveryZB : public FH_AtCmdResp
+{
+ private:
+ /** Callback function, invoked (if registered) when an at command response packet is received */
+ node_discovery_zb_cb_t node_discovery_cb;
+
+ public:
+
+ /** Class constructor */
+ FH_NodeDiscoveryZB();
+
+ /** Class destructor */
+ virtual ~FH_NodeDiscoveryZB();
+
+ virtual void process_frame_data(const ApiFrame *const frame);
+
+ /** */
+ virtual void register_node_discovery_cb(node_discovery_zb_cb_t function);
+
+ /** */
+ virtual void unregister_node_discovery_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** Node Discovery Response callback type declaration for 802.15.4
+ * @param remote discovered remote node.
+ * @param node_id Node Identifier (NI parameter) of remote.
+ */
+typedef void (*node_discovery_802_cb_t)(const RemoteXBee802& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscovery802 : public FH_AtCmdResp
+{
+ private:
+ /** Callback function, invoked (if registered) when an at command response packet is received */
+ node_discovery_802_cb_t node_discovery_cb;
+
+ public:
+
+ /** Class constructor */
+ FH_NodeDiscovery802();
+
+ /** Class destructor */
+ virtual ~FH_NodeDiscovery802();
+
+ virtual void process_frame_data(const ApiFrame *const frame);
+
+ /** */
+ virtual void register_node_discovery_cb(node_discovery_802_cb_t function);
+
+ /** */
+ virtual void unregister_node_discovery_cb();
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __FH_AT_CMD_RESP_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_IoDataSample802.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,106 @@
+/**
+ * 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 "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampe64b802::FH_IoDataSampe64b802() : FrameHandler(ApiFrame::Io64Bit),
+ io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampe64b802::~FH_IoDataSampe64b802()
+{
+}
+
+/** */
+void FH_IoDataSampe64b802::register_io_data_cb(io_data_cb_802_t function)
+{
+ io_data_cb = function;
+}
+
+/** */
+void FH_IoDataSampe64b802::unregister_io_data_cb()
+{
+ io_data_cb = NULL;
+}
+
+#define IO_SAMPLE_64_802_DATA_OFFSET 10
+
+/** */
+void FH_IoDataSampe64b802::process_frame_data(const ApiFrame *const frame)
+{
+ const uint8_t * const datap = frame->get_data();
+
+ /* The caller checks that the type matches, so no need to check it here again */
+ if (io_data_cb == NULL) {
+ return;
+ }
+
+ /* We got an IO packet, decode it... */
+ const uint64_t sender64 = addr64_from_uint8_t(datap);
+ const RemoteXBee802 sender = RemoteXBee802(sender64);
+ const IOSample802 ioSample = IOSample802(&datap[IO_SAMPLE_64_802_DATA_OFFSET], frame->get_data_len() - IO_SAMPLE_64_802_DATA_OFFSET);
+
+ io_data_cb(sender, ioSample);
+}
+
+/** Class constructor */
+FH_IoDataSampe16b802::FH_IoDataSampe16b802() : FrameHandler(ApiFrame::Io16Bit),
+ io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampe16b802::~FH_IoDataSampe16b802()
+{
+}
+
+/** */
+void FH_IoDataSampe16b802::register_io_data_cb(io_data_cb_802_t function)
+{
+ io_data_cb = function;
+}
+
+/** */
+void FH_IoDataSampe16b802::unregister_io_data_cb()
+{
+ io_data_cb = NULL;
+}
+
+#define IO_SAMPLE_16_802_ADDR16_MSB_OFFSET 0
+#define IO_SAMPLE_16_802_ADDR16_LSB_OFFSET 1
+#define IO_SAMPLE_16_802_DATA_OFFSET 4
+
+/** */
+void FH_IoDataSampe16b802::process_frame_data(const ApiFrame *const frame)
+{
+ const uint8_t * const datap = frame->get_data();;
+
+ /* The caller checks that the type matches, so no need to check it here again */
+ if (io_data_cb == NULL) {
+ return;
+ }
+
+ /* We got an IO packet, decode it... */
+ const uint16_t sender16 = ADDR16(datap[IO_SAMPLE_16_802_ADDR16_MSB_OFFSET], datap[IO_SAMPLE_16_802_ADDR16_LSB_OFFSET]);
+ const RemoteXBee802 sender = RemoteXBee802(sender16);
+
+ const IOSample802 ioSample = IOSample802(&datap[IO_SAMPLE_16_802_DATA_OFFSET], frame->get_data_len() - IO_SAMPLE_16_802_DATA_OFFSET);
+
+ io_data_cb(sender, ioSample);
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_IoDataSample802.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,79 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_802_H_)
+#define __FH_IO_DATA_SAMPLE_802_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSample802;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (802.15.4 modules) callback type declaration
+ * @param remote the remote module that sent the data
+ * @param sample_data a referece to an @ref IOSample802 that can be queried for the IoLines' values
+ */
+typedef void (*io_data_cb_802_t)(const RemoteXBee802& remote, const IOSample802& sample_data);
+/**
+ * @}
+ */
+
+
+class FH_IoDataSampe64b802 : public FrameHandler
+{
+ public:
+ /** Class constructor */
+ FH_IoDataSampe64b802();
+
+ /** Class destructor */
+ virtual ~FH_IoDataSampe64b802();
+
+ /** */
+ virtual void process_frame_data(const ApiFrame *const frame);
+
+ void register_io_data_cb(io_data_cb_802_t function);
+ void unregister_io_data_cb();
+
+ private:
+ /** Callback function, invoked if registered */
+ io_data_cb_802_t io_data_cb;
+
+};
+
+class FH_IoDataSampe16b802 : public FrameHandler
+{
+ public:
+ /** Class constructor */
+ FH_IoDataSampe16b802();
+
+ /** Class destructor */
+ virtual ~FH_IoDataSampe16b802();
+
+ /** */
+ virtual void process_frame_data(const ApiFrame *const frame);
+
+ void register_io_data_cb(io_data_cb_802_t function);
+ void unregister_io_data_cb();
+ private:
+ /** Callback function, invoked if registered */
+ io_data_cb_802_t io_data_cb;
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_802_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_IoDataSampleZB.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,61 @@
+/**
+ * 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 "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampeZB::FH_IoDataSampeZB() : FrameHandler(ApiFrame::IoSampleRxZB),
+ io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampeZB::~FH_IoDataSampeZB()
+{
+}
+
+/** */
+void FH_IoDataSampeZB::register_io_data_cb(io_data_cb_zb_t function)
+{
+ io_data_cb = function;
+}
+
+/** */
+void FH_IoDataSampeZB::unregister_io_data_cb()
+{
+ io_data_cb = NULL;
+}
+
+/* ZB RX packet offsets */
+#define ZB_IO_SAMPLE_ADDR16_MSB_OFFSET 8
+#define ZB_IO_SAMPLE_ADDR16_LSB_OFFSET 9
+#define ZB_IO_SAMPLE_DATA_OFFSET 11
+
+/** */
+void FH_IoDataSampeZB::process_frame_data(const ApiFrame *const frame)
+{
+ const uint8_t * const datap = frame->get_data();;
+
+ /* The caller checks that the type matches, so no need to check it here again */
+ if (io_data_cb == NULL)
+ return;
+
+ /* We got an IO packet, decode it... */
+ const uint64_t sender64 = addr64_from_uint8_t(datap);
+ const uint16_t sender16 = ADDR16(datap[ZB_IO_SAMPLE_ADDR16_MSB_OFFSET], datap[ZB_IO_SAMPLE_ADDR16_LSB_OFFSET]);
+ const RemoteXBeeZB sender = RemoteXBeeZB(sender64, sender16);
+ const IOSampleZB ioSample = IOSampleZB(&datap[ZB_IO_SAMPLE_DATA_OFFSET], frame->get_data_len() - ZB_IO_SAMPLE_DATA_OFFSET);
+
+ io_data_cb(sender, ioSample);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_IoDataSampleZB.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,57 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_ZB_H_)
+#define __FH_IO_DATA_SAMPLE_ZB_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSampleZB;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (ZigBee modules) callback type declaration
+ * @param remote the remote module that sent the data
+ * @param sample_data a referece to an @ref IOSampleZB that can be queried for the IoLines' values
+ */
+typedef void (*io_data_cb_zb_t)(const RemoteXBeeZB& remote, const IOSampleZB& sample_data);
+/**
+ * @}
+ */
+
+class FH_IoDataSampeZB : public FrameHandler
+{
+ public:
+ /** Class constructor */
+ FH_IoDataSampeZB();
+
+ /** Class destructor */
+ virtual ~FH_IoDataSampeZB();
+ /** */
+ virtual void process_frame_data(const ApiFrame *const frame);
+
+ void register_io_data_cb(io_data_cb_zb_t function);
+ void unregister_io_data_cb();
+
+ private:
+ /** Callback function, invoked if registered */
+ io_data_cb_zb_t io_data_cb;
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_ZB_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_ModemStatus.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,47 @@
+/**
+ * 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 "FH_ModemStatus.h"
+
+/** Class constructor */
+FH_ModemStatus::FH_ModemStatus() : FrameHandler(ApiFrame::AtModemStatus), modem_status_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_ModemStatus::~FH_ModemStatus()
+{
+}
+
+/** */
+void FH_ModemStatus::register_modem_status_cb(modem_status_cb_t function)
+{
+ modem_status_cb = function;
+}
+
+/** */
+void FH_ModemStatus::unregister_modem_status_cb(void)
+{
+ modem_status_cb = NULL;
+}
+
+void FH_ModemStatus::process_frame_data(const ApiFrame *const frame)
+{
+ /* The caller checks that the type matches, so no need to check it here again */
+
+ if (modem_status_cb == NULL)
+ return;
+
+ modem_status_cb((AtCmdFrame::ModemStatus)frame->get_data_at(0));
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_ModemStatus.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,48 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FH_MODEM_STATUS_H_)
+#define __FH_MODEM_STATUS_H_
+
+#include "Frames/AtCmdFrame.h"
+#include "FrameHandler.h"
+
+typedef void (*modem_status_cb_t)(AtCmdFrame::ModemStatus status);
+
+class FH_ModemStatus : public FrameHandler
+{
+ private:
+ /** Callback function, invoked (if registered) when a modem status packet is received */
+ modem_status_cb_t modem_status_cb;
+
+ public:
+ /** Class constructor */
+ FH_ModemStatus();
+
+ /** Class destructor */
+ virtual ~FH_ModemStatus();
+
+ /** Method called by the stack to process the modem status frame data
+
+ \param frame pointer pointing to api frame that must be processed */
+ virtual void process_frame_data(const ApiFrame *const frame);
+
+ /** */
+ virtual void register_modem_status_cb(modem_status_cb_t function);
+
+ /** */
+ virtual void unregister_modem_status_cb(void);
+};
+
+#endif /* __FH_MODEM_STATUS_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_RxPacket802.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,114 @@
+/**
+ * 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 "FH_RxPacket802.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacket64b802::FH_RxPacket64b802() : FrameHandler(ApiFrame::RxPacket64Bit),
+ receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacket64b802::~FH_RxPacket64b802()
+{
+}
+
+/** */
+void FH_RxPacket64b802::register_receive_cb(receive_802_cb_t function)
+{
+ receive_cb = function;
+}
+
+/** */
+void FH_RxPacket64b802::unregister_receive_cb(void)
+{
+ receive_cb = NULL;
+}
+
+/* 802.15.4 RX packet offsets */
+#define RX_802_RSSI_OFFSET 8
+#define RX_802_OPTIONS_OFFSET 9
+#define RX_802_DATA_OFFSET 10
+#define RX_802_OVERHEAD (8+1+1)
+
+#define BROADCAST_PACKET 0x02
+
+/** */
+void FH_RxPacket64b802::process_frame_data(const ApiFrame *const frame)
+{
+ /* The caller checks that the type matches, so no need to check it here again */
+
+ if (receive_cb == NULL)
+ return;
+
+ /* We got a rx packet, decode it... */
+ const uint8_t *datap = frame->get_data();
+ const uint64_t sender64 = addr64_from_uint8_t(datap);
+// uint8_t rssi = datap[RX_802_RSSI_OFFSET];
+ const uint8_t rx_options = datap[RX_802_OPTIONS_OFFSET];
+ const RemoteXBee802 sender = RemoteXBee802(sender64);
+
+ receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[RX_802_DATA_OFFSET], frame->get_data_len() - RX_802_OVERHEAD);
+}
+
+
+/** Class constructor */
+FH_RxPacket16b802::FH_RxPacket16b802() : FrameHandler(ApiFrame::RxPacket16Bit),
+ receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacket16b802::~FH_RxPacket16b802()
+{
+}
+
+/** */
+void FH_RxPacket16b802::register_receive_cb(receive_802_cb_t function)
+{
+ receive_cb = function;
+}
+
+/** */
+void FH_RxPacket16b802::unregister_receive_cb(void)
+{
+ receive_cb = NULL;
+}
+
+/* 802.15.4 RX packet offsets */
+#define RX_802_ADDR16_MSB_OFFSET 0
+#define RX_802_ADDR16_LSB_OFFSET 1
+#define RX_802_RSSI_OFFSET2 2
+#define RX_802_OPTIONS_OFFSET2 3
+#define RX_802_DATA_OFFSET2 4
+#define RX_802_OVERHEAD2 (2+1+1)
+
+/** */
+void FH_RxPacket16b802::process_frame_data(const ApiFrame *const frame)
+{
+ /* The caller checks that the type matches, so no need to check it here again */
+
+ if (receive_cb == NULL)
+ return;
+
+ /* We got a rx packet, decode it... */
+ const uint8_t *datap = frame->get_data();
+ const uint16_t sender16 = ADDR16(datap[RX_802_ADDR16_MSB_OFFSET], datap[RX_802_ADDR16_LSB_OFFSET]);
+ //uint8_t rssi = datap[RX_802_RSSI_OFFSET2];
+ const uint8_t rx_options = datap[RX_802_OPTIONS_OFFSET2];
+ const RemoteXBee802 sender = RemoteXBee802(sender16);
+
+ receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[RX_802_DATA_OFFSET2], frame->get_data_len() - RX_802_OVERHEAD2);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_RxPacket802.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,86 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_802_H_)
+#define __FH_RX_PACKET_802_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+ * @param remote the remote module that sent the data
+ * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+ * @param data a pointer to data sent by @b remote.
+ * @param len length (in bytes) of @b data buffer
+ */
+typedef void (*receive_802_cb_t)(const RemoteXBee802& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacket64b802 : public FrameHandler
+{
+ private:
+ /** Callback function, invoked if registered */
+ receive_802_cb_t receive_cb;
+
+ public:
+ /** Class constructor */
+ FH_RxPacket64b802();
+
+ /** Class destructor */
+ virtual ~FH_RxPacket64b802();
+
+ /** */
+ virtual void process_frame_data(const ApiFrame* const frame);
+
+ /** */
+ virtual void register_receive_cb(receive_802_cb_t function);
+
+ /** */
+ virtual void unregister_receive_cb();
+};
+
+class FH_RxPacket16b802 : public FrameHandler
+{
+ private:
+ /** Callback function, invoked if registered */
+ receive_802_cb_t receive_cb;
+
+ public:
+ /** Class constructor */
+ FH_RxPacket16b802();
+
+ /** Class destructor */
+ virtual ~FH_RxPacket16b802();
+
+ /** */
+ virtual void process_frame_data(const ApiFrame *const frame);
+
+ /** */
+ virtual void register_receive_cb(receive_802_cb_t function);
+
+ /** */
+ virtual void unregister_receive_cb();
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_802_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_RxPacketZB.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,64 @@
+/**
+ * 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 "FH_RxPacketZB.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacketZB::FH_RxPacketZB() : FrameHandler(ApiFrame::RxPacketAO0), receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacketZB::~FH_RxPacketZB()
+{
+}
+
+/** */
+void FH_RxPacketZB::register_receive_cb(receive_zb_cb_t function)
+{
+ receive_cb = function;
+}
+
+/** */
+void FH_RxPacketZB::unregister_receive_cb(void)
+{
+ receive_cb = NULL;
+}
+
+/* ZB RX packet offsets */
+#define ZB_RX_ADDR16_MSB_OFFSET 8
+#define ZB_RX_ADDR16_LSB_OFFSET 9
+#define ZB_RX_OPTIONS_OFFSET 10
+#define ZB_RX_DATA_OFFSET 11
+#define ZB_RX_OVERHEAD (8+2+1)
+
+#define BROADCAST_PACKET 0x02
+
+/** */
+void FH_RxPacketZB::process_frame_data(const ApiFrame *const frame)
+{
+ /* The caller checks that the type matches, so no need to check it here again */
+
+ if (receive_cb == NULL)
+ return;
+
+ /* We got a rx packet, decode it... */
+ const uint8_t *datap = frame->get_data();
+ const uint64_t sender64 = addr64_from_uint8_t(datap);
+ const uint16_t sender16 = ADDR16(datap[ZB_RX_ADDR16_MSB_OFFSET], datap[ZB_RX_ADDR16_LSB_OFFSET]);
+ const uint8_t rx_options = datap[ZB_RX_OPTIONS_OFFSET];
+ const RemoteXBeeZB sender = RemoteXBeeZB(sender64, sender16);
+
+ receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[ZB_RX_DATA_OFFSET], frame->get_data_len() - ZB_RX_OVERHEAD);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FH_RxPacketZB.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,65 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_ZB_H_)
+#define __FH_RX_PACKET_ZB_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+ * @param remote the remote module that sent the data
+ * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+ * @param data a pointer to data sent by @b remote.
+ * @param len length (in bytes) of @b data buffer
+ */
+typedef void (*receive_zb_cb_t)(const RemoteXBeeZB& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacketZB : public FrameHandler
+{
+ private:
+ /** Callback function, invoked if registered */
+ receive_zb_cb_t receive_cb;
+
+ public:
+ /** Class constructor */
+ FH_RxPacketZB();
+
+ /** Class destructor */
+ virtual ~FH_RxPacketZB();
+
+ /** Method called by the stack to process the modem status frame data
+
+ \param frame pointer pointing to api frame that must be processed */
+ virtual void process_frame_data(const ApiFrame* const frame);
+
+ /** */
+ void register_receive_cb(receive_zb_cb_t function);
+
+ /** */
+ void unregister_receive_cb();
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_ZB_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FrameHandler.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,29 @@
+/**
+ * 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 "FrameHandler.h"
+
+FrameHandler::FrameHandler(ApiFrame::ApiFrameType t) : _type(t)
+{
+}
+
+FrameHandler::~FrameHandler()
+{
+}
+
+ApiFrame::ApiFrameType FrameHandler::get_type() const
+{
+ return _type;
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FrameHandlers/FrameHandler.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,54 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__FRAME_HANDLER_H_)
+#define __FRAME_HANDLER_H_
+
+#include "Frames/ApiFrame.h"
+
+/** Class for the frame handlers */
+class FrameHandler
+{
+ friend class ApiFrame;
+
+ public:
+ /** Class constructor
+ *
+ * @param type frame type handled by this frame handler
+ */
+ FrameHandler(ApiFrame::ApiFrameType type);
+
+ FrameHandler(const FrameHandler& other); /* Intentionally not implemented */
+ /** Class destructor */
+ virtual ~FrameHandler();
+
+ /** get_type returns the type of frames handled by this handler
+ *
+ * @returns the frame type handled by the handler
+ */
+ ApiFrame::ApiFrameType get_type() const;
+
+ /** process_frame_data method called by the library to process the
+ * the incoming frames if the type matches.
+ *
+ * @param frame pointer pointing to the api frame that must be processed
+ */
+ virtual void process_frame_data(const ApiFrame *const frame) = 0;
+
+ protected:
+ /** frame type handled by this handler */
+ ApiFrame::ApiFrameType _type;
+};
+
+#endif /* defined(__FRAME_HANDLER_H_) */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/802_Frames.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,64 @@
+/**
+ * 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 "802_Frames.h"
+
+#define FRAME_ID_LEN 1
+#define ADDR64_LEN 8
+#define ADDR16_LEN 2
+#define OPTIONS_LEN 1
+#define TX_REQUEST_OVERHEAD (FRAME_ID_LEN + ADDR64_LEN + OPTIONS_LEN)
+#define TX_REQUEST_OVERHEAD2 (FRAME_ID_LEN + ADDR16_LEN + OPTIONS_LEN)
+
+/** Class constructor */
+TxFrame802::TxFrame802(uint64_t addr, uint8_t tx_options,
+ const uint8_t *const data, uint16_t len)
+{
+ uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+ _frame_id = get_next_frame_id();
+
+ /* copy the frame id, the 64bit remote address, the tx options byte
+ * and the frame data */
+
+ frame_data[0] = _frame_id;
+ rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+ frame_data[9] = tx_options;
+
+ if (len)
+ memcpy(&frame_data[10], data, len);
+
+ set_api_frame(TxReq64Bit, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrame802::TxFrame802(uint16_t addr16, uint8_t tx_options,
+ const uint8_t *const data, uint16_t len)
+{
+ uint8_t frame_data[TX_REQUEST_OVERHEAD2 + len];
+
+ _frame_id = get_next_frame_id();
+
+ /* copy the frame id, the 16bit remote address, the tx options byte
+ * and the frame data */
+
+ frame_data[0] = _frame_id;
+ frame_data[1] = (uint8_t)(addr16 >> 8);
+ frame_data[2] = (uint8_t)addr16;
+ frame_data[3] = tx_options;
+
+ if (len)
+ memcpy(&frame_data[4], data, len);
+
+ set_api_frame(TxReq16Bit, frame_data, TX_REQUEST_OVERHEAD2 + len);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/802_Frames.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,30 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__802_FRAMES_H_)
+#define __802_FRAMES_H_
+
+#include "ApiFrame.h"
+
+class TxFrame802 : public ApiFrame
+{
+ public:
+ /** Class constructor */
+ TxFrame802(uint64_t addr, uint8_t tx_options, const uint8_t *const data, uint16_t len);
+ TxFrame802(uint16_t addr16, uint8_t tx_options, const uint8_t *const data, uint16_t len);
+
+ protected:
+};
+
+#endif /* __802_FRAMES_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/ApiFrame.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,132 @@
+/**
+ * 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 "mbed.h"
+#include "XBee/XBee.h"
+#include "ApiFrame.h"
+
+using namespace XBeeLib;
+
+uint8_t ApiFrame::last_frame_id = 0;
+
+ApiFrame::ApiFrame(void)
+{
+ this->_type = Invalid;
+ this->_data = NULL;
+ this->_data_frame_len = 0;
+ this->_alloc_data = false;
+ _frame_id = get_next_frame_id();
+}
+
+ApiFrame::ApiFrame(uint16_t len)
+{
+ this->_type = Invalid;
+ this->_data = new uint8_t[len];
+ this->_alloc_data = true;
+ this->_data_frame_len = len;
+ this->_frame_id = get_next_frame_id();
+}
+
+uint8_t ApiFrame::get_next_frame_id(void)
+{
+ last_frame_id++;
+ if (last_frame_id == 0)
+ last_frame_id++;
+
+ return last_frame_id;
+}
+
+ApiFrame::ApiFrame(ApiFrameType type, const uint8_t *data, uint16_t len)
+{
+ this->_data = NULL;
+ set_api_frame(type, data, len);
+}
+
+void ApiFrame::set_api_frame(ApiFrameType type, const uint8_t *data, uint16_t len)
+{
+ this->_type = type;
+ this->_data_frame_len = len;
+ if (this->_data)
+ delete _data;
+ this->_data = new uint8_t[len];
+ this->_alloc_data = true;
+ assert(this->_data != NULL);
+ memcpy((void *)this->_data, data, len);
+}
+
+ApiFrame::~ApiFrame()
+{
+ if (this->_data != NULL && this->_alloc_data) {
+ delete[] this->_data;
+ }
+}
+
+void ApiFrame::dump(void) const
+{
+#if defined(ENABLE_LOGGING)
+ digi_log(LogLevelFrameData, "API frame: type %02x, len %d\r\n", this->_type, this->_data_frame_len);
+ for (int i = 0; i < this->_data_frame_len; i++)
+ digi_log(LogLevelFrameData, "%02x ", this->_data[i]);
+ digi_log(LogLevelFrameData, "\r\n");
+#endif
+}
+
+void ApiFrame::dump_if(ApiFrameType type)
+{
+ if (_type != type)
+ return;
+ dump();
+}
+
+ApiFrame::ApiFrameType ApiFrame::get_frame_type() const
+{
+ return _type;
+}
+
+void ApiFrame::set_frame_type(ApiFrameType type)
+{
+ _type = type;
+}
+
+uint16_t ApiFrame::get_data_len() const
+{
+ return _data_frame_len;
+}
+
+void ApiFrame::set_data_len(uint16_t len)
+{
+ _data_frame_len = len;
+}
+
+const uint8_t *ApiFrame::get_data() const
+{
+ return _data;
+}
+
+uint8_t ApiFrame::get_data_at(uint16_t index) const
+{
+ return *(_data + index);
+}
+
+void ApiFrame::set_data(uint8_t d, uint16_t index)
+{
+ *(_data + index) = d;
+}
+
+/* Returns the frame_id of this frame */
+uint8_t ApiFrame::get_frame_id() const
+{
+ return _frame_id;
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/ApiFrame.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,177 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__API_FRAME_H_)
+#define __API_FRAME_H_
+
+#include "XBee/Addresses.h"
+
+/** Class for XBee API frames */
+class ApiFrame
+{
+ /** Static variable that contains the last frame ID value assigned */
+ static uint8_t last_frame_id;
+
+ public:
+ /** List of API frames. Note that not all frames are supported by all radios */
+ enum ApiFrameType {
+
+ TxReq64Bit = 0x00, /**< TxReq64Bit: Only for 802.15.4 modules */
+ TxReq16Bit = 0x01, /**< TxReq16Bit: Only for 802.15.4 modules */
+ AtCmd = 0x08, /**< AtCmd */
+ AtCmdQueuePV = 0x09, /**< AtCmdQueuePV */
+ TxReqZB = 0x10, /**< TxReqZB: Only for ZigBee modules */
+ ExpAddrCmd = 0x11, /**< ExpAddrCmd: Only for ZigBee modules */
+ RemoteCmdReq = 0x17, /**< RemoteCmdReq */
+ CreateSrcRoute = 0x21, /**< CreateSrcRoute */
+ RxPacket64Bit = 0x80, /**< RxPacket64Bit: Only for 802.15.4 modules */
+ RxPacket16Bit = 0x81, /**< RxPacket16Bit: Only for 802.15.4 modules */
+ Io64Bit = 0x82, /**< Io64Bit: Only for 802.15.4 modules */
+ Io16Bit = 0x83, /**< Io16Bit */
+ AtCmdResp = 0x88, /**< AtCmdResp */
+ TxStatus = 0x89, /**< TxStatus */
+ AtModemStatus = 0x8A, /**< AtModemStatus */
+ TxStatusZB = 0x8B, /**< TxStatusZB: Only for ZigBee modules */
+ RxPacketAO0 = 0x90, /**< RxPacketAO0: Only for ZigBee modules */
+ RxPacketAO1 = 0x91, /**< RxPacketAO1: Only for ZigBee modules */
+ IoSampleRxZB = 0x92, /**< IoSampleRxZB: Only for ZigBee modules */
+ SensorRxIndAO0 = 0x94, /**< SensorRxIndAO0: Only for ZigBee modules */
+ NodeIdentIndAO0 = 0x95, /**< NodeIdentIndAO0: Only for ZigBee modules */
+ RemoteCmdResp = 0x97, /**< RemoteCmdResp */
+ OtaFwUpStatus = 0xA0, /**< OtaFwUpStatus */
+ RouteRecInd = 0xA1, /**< RouteRecInd */
+ Many2OneRRInd = 0xA3, /**< Many2OneRRInd */
+ Invalid = ~0, /**< Invalid */
+ };
+
+ /** Default constructor */
+ ApiFrame();
+
+ /** Constructor
+ *
+ * @param len length of the API frame (will allocate len bytes).
+ */
+ ApiFrame(uint16_t len);
+
+ /** Constructor
+ *
+ * @param type frame type of this api frame.
+ * @param data pointer to frame data payload.
+ * @param len length of the payload.
+ */
+ ApiFrame(ApiFrameType type, const uint8_t *data, uint16_t len);
+
+ /** Destructor */
+ ~ApiFrame();
+
+ ApiFrame(const ApiFrame& other); /* Intentionally not implemented */
+
+ /** get_frame_type gets the type of the frame
+ *
+ * @returns the type of this frame.
+ */
+ ApiFrameType get_frame_type() const;
+
+ /** dump dumps the information of this frame */
+ void dump() const;
+
+ /** dump_if dumps the information of the frame if the frame type matches
+ * with the parameter.
+ *
+ * @param type dump the frame info/data if the frame type matches with type.
+ */
+ void dump_if(ApiFrameType type);
+
+
+ /** set_frame_type sets the type of the frame to type.
+ *
+ * @param type the type we want to set on the frame.
+ */
+ void set_frame_type(ApiFrameType type);
+
+ /** get_data_len gets the length of the frame data payload.
+ *
+ * @returns the length of the data payload.
+ */
+ uint16_t get_data_len() const;
+
+ /** set_data_len sets the length of the frame data payload.
+ *
+ * @param len the length of the data payload will be set on this frame.
+ */
+ void set_data_len(uint16_t len);
+
+ /** get_data returns a pointer to the frame data payload.
+ *
+ * @returns a pointer to the frame data payload.
+ */
+ const uint8_t *get_data() const;
+
+ /** get_data_at returns the byte at index offset.
+ *
+ * @param index offset of the byte we want to get.
+ * @returns the byte at index offset.
+ */
+ uint8_t get_data_at(uint16_t index) const;
+
+ /** set_data sets data byte at the specified index or offset.
+ *
+ * @param data byte that will be set at index position.
+ * @param index offset of the byte we want to set.
+ */
+ void set_data(uint8_t data, uint16_t index);
+
+ /** get_frame_id returns the frame id of this frame.
+ *
+ * @returns the frame id of this frame.
+ */
+ uint8_t get_frame_id() const;
+
+ static uint8_t get_current_frame_id()
+ {
+ return last_frame_id;
+ }
+
+ protected:
+ /** Type of this frame */
+ ApiFrameType _type;
+
+ /** length of the payload, excluding the frame type */
+ uint16_t _data_frame_len;
+
+ /** pointer to the frame data */
+ uint8_t *_data;
+
+ /** True if the constructor allocates the data. Needed to delete it on the destructor */
+ bool _alloc_data;
+
+ /** Frame ID of this frame */
+ uint8_t _frame_id;
+
+ /** get_next_frame_id - returns the next frame ID secuentially, skipping the value 0
+ *
+ * @returns the next frame ID that should be assigned to a frame
+ */
+ uint8_t get_next_frame_id();
+
+ /** set_api_frame sets several members
+ *
+ * @param type frame type of this api frame.
+ * @param data pointer to frame data payload.
+ * @param len length of the payload.
+ */
+ void set_api_frame(ApiFrameType type, const uint8_t *data, uint16_t len);
+};
+
+#endif /* __API_FRAME_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/AtCmdFrame.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,147 @@
+/**
+ * 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 "mbed.h"
+#include "Utils/Debug.h"
+#include "AtCmdFrame.h"
+
+#define AT_CMD_LEN 2
+#define AT_CMD_ID_LEN 1
+
+void AtCmdFrame::build_at_cmd_frame(const char *cmd, const uint8_t *cmd_params, uint8_t payload_len, bool reverse)
+{
+ uint8_t frame_data[AT_CMD_LEN + AT_CMD_ID_LEN + payload_len];
+
+ frame_data[0] = _frame_id;
+ frame_data[1] = cmd[0];
+ frame_data[2] = cmd[1];
+ if (payload_len) {
+ if (reverse) {
+ rmemcpy(&frame_data[3], cmd_params, payload_len);
+ } else {
+ memcpy(&frame_data[3], cmd_params, payload_len);
+ }
+ }
+
+ set_api_frame(AtCmd, frame_data, AT_CMD_LEN + AT_CMD_ID_LEN + payload_len);
+}
+
+AtCmdFrame::AtCmdFrame(const char * const cmd, uint32_t cmd_param)
+{
+ assert(cmd != NULL);
+ assert(strlen(cmd) == AT_CMD_LEN);
+
+ uint8_t len;
+ if (cmd_param <= 0xFF) {
+ len = 1;
+ } else if (cmd_param <= 0xFFFF) {
+ len = 2;
+ } else if (cmd_param <= 0xFFFFFF) {
+ len = 3;
+ } else {
+ len = 4;
+ }
+ build_at_cmd_frame(cmd, (uint8_t *)&cmd_param, len);
+}
+
+AtCmdFrame::AtCmdFrame(const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+ assert(cmd != NULL);
+ assert(strlen(cmd) == AT_CMD_LEN);
+
+ build_at_cmd_frame(cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote, const char * const cmd, uint32_t cmd_param)
+{
+ assert(cmd != NULL);
+ assert(strlen(cmd) == AT_CMD_LEN);
+
+ build_at_cmd_remote_frame(remote, ADDR16_UNKNOWN, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote, const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+ assert(cmd != NULL);
+ assert(strlen(cmd) == AT_CMD_LEN);
+
+ build_at_cmd_remote_frame(remote, ADDR16_UNKNOWN, cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint16_t remote, const char * const cmd, uint32_t cmd_param)
+{
+ assert(cmd != NULL);
+ assert(strlen(cmd) == AT_CMD_LEN);
+
+ build_at_cmd_remote_frame(ADDR64_UNASSIGNED, remote, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint16_t remote, const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+ assert(cmd != NULL);
+ assert(strlen(cmd) == AT_CMD_LEN);
+
+ build_at_cmd_remote_frame(ADDR64_UNASSIGNED, remote, cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, uint32_t cmd_param)
+{
+ assert(cmd != NULL);
+ assert(strlen(cmd) == AT_CMD_LEN);
+
+ build_at_cmd_remote_frame(remote64, remote16, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd,
+ const uint8_t * cmd_param, uint16_t param_len)
+{
+ assert(cmd != NULL);
+ assert(strlen(cmd) == AT_CMD_LEN);
+
+ build_at_cmd_remote_frame(remote64, remote16, cmd, cmd_param, param_len, false);
+}
+
+#define FRAME_ID_LEN 1
+#define ADDR64_LEN 8
+#define ADDR16_LEN 2
+#define OPTIONS_LEN 1
+#define AT_CMD_LEN 2
+#define REM_AT_CMD_OVERHEAD (FRAME_ID_LEN + ADDR64_LEN + \
+ ADDR16_LEN + OPTIONS_LEN + \
+ AT_CMD_LEN)
+
+void AtCmdFrame::build_at_cmd_remote_frame(uint64_t remote64, uint16_t remote16,
+ const char *const cmd, const uint8_t *const cmd_params, uint8_t params_len, bool reverse)
+{
+ uint8_t frame_data[REM_AT_CMD_OVERHEAD + params_len];
+
+ /* copy the frame id, the 64bit remote address, the 16bit network address,
+ * the options byte, the command and the command params */
+
+ frame_data[0] = _frame_id;
+ rmemcpy(&frame_data[1], (const uint8_t *)&remote64, sizeof remote64);
+ frame_data[9] = (uint8_t)(remote16 >> 8);
+ frame_data[10] = (uint8_t)remote16;
+ frame_data[11] = 0x02; /* TODO Options */
+ frame_data[12] = cmd[0];
+ frame_data[13] = cmd[1];
+
+ if (params_len) {
+ if (reverse) {
+ rmemcpy(&frame_data[14], cmd_params, params_len);
+ } else {
+ memcpy(&frame_data[14], cmd_params, params_len);
+ }
+ }
+
+ set_api_frame(RemoteCmdReq, frame_data, REM_AT_CMD_OVERHEAD + params_len);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/AtCmdFrame.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,168 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__AT_CMD_FRAME_H_)
+#define __AT_CMD_FRAME_H_
+
+#include "ApiFrame.h"
+
+#define REM_AT_CMD_RESP_FRM_ID_OFFSET 0
+#define REM_AT_CMD_RESP_STATUS_OFFSET 13
+#define REM_AT_CMD_RESP_CMD_DATA_OFFSET 14
+#define REM_AT_CMD_RESP_OVERHEAD 14 /* ID + ADDR64 + ADDR16 + CMD + status */
+
+#define ATCMD_RESP_FRAME_ID_OFFSET 0
+#define ATCMD_RESP_CMD_LOW_OFFSET 1
+#define ATCMD_RESP_CMD_HIGH_OFFSET 2
+#define ATCMD_RESP_STATUS_OFFSET 3
+#define ATCMD_RESP_DATA_OFFSET 4
+#define ATCMD_RESP_NW_ADDR_H_OFFSET 4
+#define ATCMD_RESP_NW_ADDR_L_OFFSET 5
+#define ATCMD_RESP_SH_ADDR_L_OFFSET 6
+#define ATCMD_RESP_SH_ADDR_H_OFFSET 10
+#define ATCMD_RESP_NI_OFFSET 14
+
+#define ATCMD_RESP_OVERHEAD 4 /* ID + CMD + status */
+
+#define ATCMD_802_RESP_SIGN_STR_OFFSET 14
+#define ATCMD_802_RESP_NI_OFFSET 15
+
+#define MAX_NI_PARAM_LEN 20
+
+/** Class for the AT command api frames. Derived from ApiFrame */
+class AtCmdFrame : public ApiFrame
+{
+ public:
+
+ /**
+ * AtCmdResp
+ */
+ enum AtCmdResp {
+ AtCmdRespOk = 0, /**< Ok */
+ AtCmdRespError = 1, /**< Error */
+ AtCmdRespInvalidCmd = 2, /**< Invalid Command */
+ AtCmdRespInvalidParam = 3, /**< Invalid Parameter */
+ AtCmdRespTxFailure = 4, /**< Tx Failure */
+ AtCmdRespLenMismatch = 0xfd, /**< Length Mismatch (Error generated by the library) */
+ AtCmdRespInvalidAddr = 0xfe, /**< Invalid Address (Error generated by the library) */
+ AtCmdRespTimeout = 0xff, /**< Timeout (Error generated by the library) */
+ };
+
+ /**
+ * ModemStatus
+ */
+ enum ModemStatus {
+ HwReset = 0, /**< Hardware reset */
+ WdReset = 1, /**< Watchdog timer reset */
+ JoinedNW = 2, /**< Joined network (routers and end devices) */
+ Disassociated = 3, /**< Disassociated */
+ SyncLost = 4, /**< Synchronization Lost */
+ CoordRealign = 5, /**< Coordinator realignment */
+ CoordStarted = 6, /**< Coordinator started */
+ NwSecKeyUpdated = 7, /**< Network security key was updated */
+ NwWokeUp = 0x0B, /**< NwWokeUp */
+ NwToSleep = 0x0C, /**< NwToSleep */
+ VccExceeded = 0x0D, /**< VccExceeded: PRO S2B only? */
+ ModConfChangeJoinInProg = 0x11, /**< Modem configuration changed while join in progress */
+ };
+
+ /** Class constructor
+ *
+ * @param cmd at command of the frame
+ * @param cmd_param command parameter
+ * @param param_len length of the command param
+ */
+ AtCmdFrame(const char * const cmd, const uint32_t cmd_param);
+
+ /** Class constructor
+ *
+ * @param cmd at command of the frame
+ * @param cmd_param pointer to command parameter
+ * @param param_len length of the command param
+ */
+ AtCmdFrame(const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+ /** Class constructor
+ *
+ * @param remote 64 bit address of the remote device where we want to run the command
+ * @param cmd at command of the frame
+ * @param cmd_param command parameter
+ */
+ AtCmdFrame(uint64_t remote, const char * const cmd, uint32_t cmd_param);
+
+ /** Class constructor
+ *
+ * @param remote 64 bit address of the remote device where we want to run the command
+ * @param cmd at command of the frame
+ * @param cmd_param pointer to command parameter
+ * @param param_len length of the command param
+ */
+ AtCmdFrame(uint64_t remote, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+ /** Class constructor
+ *
+ * @param remote 16 bit address of the remote device where we want to run the command
+ * @param cmd at command of the frame
+ * @param cmd_param command parameter
+ */
+ AtCmdFrame(uint16_t remote, const char * const cmd, uint32_t cmd_param);
+
+ /** Class constructor
+ *
+ * @param remote 16 bit address of the remote device where we want to run the command
+ * @param cmd at command of the frame
+ * @param cmd_param pointer to command parameter
+ * @param param_len length of the command param
+ */
+ AtCmdFrame(uint16_t remote, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+ /** Class constructor
+ *
+ * @param remote 64 bit address of the remote device where we want to run the command
+ * @param remote 16 bit address of the remote device where we want to run the command
+ * @param cmd at command of the frame
+ * @param cmd_param command parameter
+ */
+ AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, uint32_t cmd_param);
+
+ /** Class constructor
+ *
+ * @param remote 64 bit address of the remote device where we want to run the command
+ * @param remote 16 bit address of the remote device where we want to run the command
+ * @param cmd at command of the frame
+ * @param cmd_param pointer to command parameter
+ * @param param_len length of the command param
+ */
+ AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+ protected:
+ /** build_at_cmd_frame method used by the constructors to create the at command frame
+ *
+ * @param cmd at command of the frame
+ * @param cmd_params pointer to command parameter
+ * @param param_len length of the command param
+ */
+ void build_at_cmd_frame(const char *cmd, const uint8_t *cmd_params, uint8_t payload_len, bool reverse = true);
+
+ /** build_at_cmd_remote_frame method used by the constructors to create the at command frame
+ *
+ * @param remote64 64 bit address of the remote device where we want to run the command
+ * @param remote16 16 bit address of the remote device where we want to run the command
+ * @param cmd at command of the frame
+ * @param cmd_params pointer to command parameter
+ * @param param_len length of the command param
+ */
+ void build_at_cmd_remote_frame(uint64_t remote64, uint16_t remote16,
+ const char *const cmd, const uint8_t *const cmd_params, uint8_t payload_len, bool reverse = true);
+};
+
+#endif /* __AT_CMD_FRAME_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/ZigbeeFrames.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,87 @@
+/**
+ * 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 "ZigbeeFrames.h"
+
+#define FRAME_ID_LEN 1
+#define ADDR64_LEN 8
+#define ADDR16_LEN 2
+#define BROADCAST_RADIOUS_LEN 1
+#define OPTIONS_LEN 1
+#define TX_REQUEST_OVERHEAD (FRAME_ID_LEN + ADDR64_LEN + \
+ ADDR16_LEN + BROADCAST_RADIOUS_LEN + \
+ OPTIONS_LEN)
+#define SOURCE_EP_LEN 1
+#define DEST_EP_LEN 1
+#define CLUSTER_ID_LEN 2
+#define PROFILE_ID_LEN 2
+
+#define EXP_ADDR_OVERHEAD (TX_REQUEST_OVERHEAD + SOURCE_EP_LEN + \
+ DEST_EP_LEN + CLUSTER_ID_LEN + \
+ PROFILE_ID_LEN)
+
+/** Class constructor */
+TxFrameZB::TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad, uint8_t tx_opt,
+ const uint8_t *const data, uint16_t len)
+{
+ uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+ _frame_id = get_next_frame_id();
+
+ /* copy the frame id, the 64bit remote address, the 16bit network address,
+ * the broad cast radious, the options byte and the frame data */
+
+ frame_data[0] = _frame_id;
+ rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+ frame_data[9] = (uint8_t)(addr16 >> 8);
+ frame_data[10] = (uint8_t)addr16;
+ frame_data[11] = broadcast_rad;
+ frame_data[12] = tx_opt;
+
+ if (len)
+ memcpy(&frame_data[13], data, len);
+
+ set_api_frame(TxReqZB, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrameZB::TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+ uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+ uint8_t tx_opt, const uint8_t *const data, uint16_t len)
+{
+ uint8_t frame_data[EXP_ADDR_OVERHEAD + len];
+
+ _frame_id = get_next_frame_id();
+
+ /* copy the frame id, the 64bit remote address, the 16bit network address,
+ * the end point source and destination addresses, the cluster and profile IDs,
+ * the broad cast radious, the options byte and the frame data */
+
+ frame_data[0] = _frame_id;
+ rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+ frame_data[9] = (uint8_t)(addr16 >> 8);
+ frame_data[10] = (uint8_t)addr16;
+ frame_data[11] = source_ep;
+ frame_data[12] = dest_ep;
+ frame_data[13] = (uint8_t)(cluster_id >> 8);
+ frame_data[14] = (uint8_t)cluster_id;
+ frame_data[15] = (uint8_t)(profile_id >> 8);
+ frame_data[16] = (uint8_t)profile_id;
+ frame_data[17] = broadcast_rad;
+ frame_data[18] = tx_opt;
+
+ if (len)
+ memcpy(&frame_data[19], data, len);
+
+ set_api_frame(ExpAddrCmd, frame_data, EXP_ADDR_OVERHEAD + len);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Frames/ZigbeeFrames.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,33 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__ZIGBEE_FRAME_H_)
+#define __ZIGBEE_FRAME_H_
+
+#include "ApiFrame.h"
+
+class TxFrameZB : public ApiFrame
+{
+ public:
+ /** Class constructor */
+ TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad,
+ uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+
+ /** Class constructor */
+ TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+ uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+ uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+};
+
+#endif /* __ZIGBEE_FRAME_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IO/IO.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,62 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__IO_H_)
+#define __IO_H_
+
+#define DR_PWM_MAX_VAL 0x3FF
+
+#define MAX_IO_SAMPLE_BUF_LEN 22 /* 1 + 2 + 1 + 2 + 16 */
+
+namespace XBeeLib {
+
+/**
+ * @defgroup IoMode
+ * @{
+ */
+/**
+ * IoMode
+ */
+enum IoMode {
+ Disabled = 0, /**< Disabled */
+ SpecialFunc = 1, /**< Special Function */
+ Adc = 2, /**< Adc */
+ Pwm = 2, /**< Pwm */
+ DigitalInput = 3, /**< Digital Input */
+ DigitalOutLow = 4, /**< Digital Out Low */
+ DigitalOutHigh = 5, /**< Digital Out High */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup DioVal
+ * @{
+ */
+/**
+ * DioVal
+ */
+enum DioVal {
+ Low = 0, /**< Low Value */
+ High = 1, /**< High Value */
+};
+/**
+ * @}
+ */
+
+} /* namespace XBeeLib */
+
+
+#endif /* __IO_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IO/IOSample802.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,87 @@
+#include "XBeeLib.h"
+#include "IO/IOSample802.h"
+#include "Utils/Debug.h"
+
+#define IO_SAMPLE_802_DIGITAL_INPUTS_MASK 0x01FF
+#define IO_SAMPLE_802_DIGITAL_INPUTS_COUNT 9
+#define IO_SAMPLE_802_MIN_SIZE (2 + 2)
+
+using namespace XBeeLib;
+
+IOSample802::IOSample802(const uint8_t* const raw_data, size_t size)
+{
+ assert(size >= IO_SAMPLE_802_MIN_SIZE);
+ assert(size <= sizeof _sampled_data);
+
+ _channel_mask = UINT16(raw_data[1], raw_data[2]);
+ _sampled_data_size = size - 3;
+ memcpy(&_sampled_data[0], &raw_data[3], _sampled_data_size);
+}
+
+IOSample802::~IOSample802()
+{
+
+}
+
+RadioStatus IOSample802::get_dio(XBee802::IoLine line, DioVal* const dio_value) const
+{
+ if (line > XBee802::DI8) {
+ digi_log(LogLevelError, "get_dio: Pin %d not supported as IO\r\n", line);
+ return Failure;
+ }
+
+ const uint16_t mask = 1 << line;
+ if (mask & _channel_mask) {
+ const uint8_t digital_channels = get_dio_channels();
+
+ *dio_value = digital_channels & mask ? High : Low;
+ return Success;
+ }
+ return Failure;
+}
+
+RadioStatus IOSample802::get_adc(XBee802::IoLine line, uint16_t* const val) const
+{
+ if (line > XBee802::DIO5_AD5) {
+ digi_log(LogLevelError, "get_adc: Pin %d not supported as ADC\r\n", line);
+ return Failure;
+ }
+ const uint8_t analog_mask = _channel_mask >> IO_SAMPLE_802_DIGITAL_INPUTS_COUNT;
+ const uint8_t line_mask = 1 << line;
+ const bool adc_present = line_mask & analog_mask;
+ if (!adc_present) {
+ return Failure;
+ }
+
+ uint8_t analog_data_idx = dio_channels_present() == 0 ? 0 : 2;
+ uint8_t line_sample = 0;
+
+ while (analog_data_idx < _sampled_data_size) {
+ if (analog_mask & (1 << line_sample)) {
+ if (line_sample == line) {
+ /* Write the analog value */
+ *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+ break;
+ }
+ analog_data_idx += 2;
+ }
+ line_sample++;
+ }
+
+ return Success;
+}
+
+inline bool IOSample802::dio_channels_present(void) const
+{
+ return _channel_mask & IO_SAMPLE_802_DIGITAL_INPUTS_MASK;
+}
+
+inline uint8_t IOSample802::get_dio_channels(void) const
+{
+ if (dio_channels_present()) {
+ return UINT16(_sampled_data[0], _sampled_data[1]);
+ }
+ else {
+ return 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IO/IOSample802.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,64 @@
+/**
+ * Digi XBee library for mbed. This is the only header you have to include from your application to use the library.
+ *
+ * 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.
+ */
+
+#ifndef _IO_IOSAMPLE802_H_
+#define _IO_IOSAMPLE802_H_
+
+#define MAX_IO_SAMPLE_802_LEN (2 + 2 * 6)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in 802.15.4 modules */
+class IOSample802 {
+ public:
+ /** Class constructor
+ * @param raw_data The IO Sample data, as returned by an "IS" command response or in the Io16Bit (0x83) or Io64Bit (0x82) frames
+ * @param size size (in bytes) of raw_data
+ */
+ IOSample802(const uint8_t* const raw_data, size_t size);
+
+ /** Class destructor */
+ ~IOSample802();
+
+ /** get_dio - read the value of a DIO configured as digital input
+ *
+ * @param line DIO line being read
+ * @param val pointer where the DIO value read will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_dio(XBee802::IoLine line, DioVal* const dio_value) const;
+
+ /** get_adc - read the value of the espcified ADC line
+ *
+ * @param line ADC line being read
+ * @param val pointer where the value read from the ADC will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_adc(XBee802::IoLine line, uint16_t* const val) const;
+
+ protected:
+ uint16_t _channel_mask;
+ uint8_t _sampled_data[MAX_IO_SAMPLE_802_LEN];
+ uint8_t _sampled_data_size;
+
+ inline bool dio_channels_present(void) const;
+ inline uint8_t get_dio_channels(void) const;
+};
+
+} /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLE802_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IO/IOSampleZB.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,69 @@
+#include "XBeeLib.h"
+#include "IO/IOSampleZB.h"
+
+#define IO_SAMPLE_ZB_MIN_SIZE (2 + 1 + 2)
+
+using namespace XBeeLib;
+
+IOSampleZB::IOSampleZB(const uint8_t* const raw_data, size_t size)
+{
+ assert(size >= IO_SAMPLE_ZB_MIN_SIZE);
+ assert(size <= sizeof _sampled_data);
+
+ _digital_mask = UINT16(raw_data[1], raw_data[2]);
+ _analog_mask = raw_data[3];
+ _sampled_data_size = size - 4;
+ memcpy(&_sampled_data[0], &raw_data[4], _sampled_data_size);
+}
+
+IOSampleZB::~IOSampleZB()
+{
+
+}
+
+RadioStatus IOSampleZB::get_dio(XBeeZB::IoLine line, DioVal* const dio_value) const
+{
+ const uint16_t mask = 1 << line;
+ if (mask & _digital_mask) {
+ const uint16_t digital_channels = get_digital_channels();
+
+ *dio_value = digital_channels & mask ? High : Low;
+ return Success;
+ }
+ return Failure;
+}
+
+RadioStatus IOSampleZB::get_adc(XBeeZB::IoLine line, uint16_t* const val) const
+{
+ const uint8_t line_mask = 1 << line;
+ const bool adc_present = line_mask & _analog_mask;
+ if (!adc_present) {
+ return Failure;
+ }
+
+ uint8_t analog_data_idx = _digital_mask == 0 ? 0 : 2;
+ uint8_t line_sample = 0;
+
+ while (analog_data_idx < _sampled_data_size) {
+ if (_analog_mask & (1 << line_sample)) {
+ if (line_sample == line) {
+ /* Write the analog value */
+ *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+ break;
+ }
+ analog_data_idx += 2;
+ }
+ line_sample++;
+ }
+
+ return Success;
+}
+
+inline uint16_t IOSampleZB::get_digital_channels(void) const
+{
+ if (_digital_mask == 0) {
+ return 0;
+ }
+ return UINT16(_sampled_data[0], _sampled_data[1]);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IO/IOSampleZB.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,64 @@
+/**
+ * Digi XBee library for mbed. This is the only header you have to include from your application to use the library.
+ *
+ * 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.
+ */
+
+#ifndef _IO_IOSAMPLEZB_H_
+#define _IO_IOSAMPLEZB_H_
+
+#define MAX_IO_SAMPLE_ZB_LEN (2 + 2 * 5)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in ZigBee modules */
+class IOSampleZB {
+ public:
+ /** Class constructor
+ * @param raw_data The IO Sample data, as returned by an "IS" command response or in the IoSampleRxZB (0x92) frames
+ * @param size size (in bytes) of raw_data.
+ */
+ IOSampleZB(const uint8_t* const raw_data, size_t size);
+
+ /** Class destructor */
+ ~IOSampleZB();
+
+ /** get_dio - read the value of a DIO configured as digital input
+ *
+ * @param line DIO line being read
+ * @param val pointer where the DIO value read will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_dio(XBeeZB::IoLine line, DioVal* const dio_value) const;
+
+ /** get_adc - read the value of the espcified ADC line
+ *
+ * @param line ADC line being read
+ * @param val pointer where the value read from the ADC will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_adc(XBeeZB::IoLine line, uint16_t* const val) const;
+
+ protected:
+ uint16_t _digital_mask;
+ uint8_t _analog_mask;
+ uint8_t _sampled_data[MAX_IO_SAMPLE_ZB_LEN];
+ uint8_t _sampled_data_size;
+
+ inline uint16_t get_digital_channels(void) const;
+};
+
+} /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLEZB_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/RemoteXBee/RemoteXBee.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,79 @@
+/**
+ * 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 "RemoteXBee.h"
+
+using namespace XBeeLib;
+
+RemoteXBee::RemoteXBee()
+{
+ _dev_addr64 = ADDR64_UNASSIGNED;
+ _dev_addr16 = ADDR16_UNKNOWN;
+}
+
+RemoteXBee::RemoteXBee(uint64_t remote64) : _dev_addr64(remote64)
+{
+ _dev_addr16 = ADDR16_UNKNOWN;
+}
+
+RemoteXBee::~RemoteXBee()
+{
+}
+
+uint64_t RemoteXBee::get_addr64() const
+{
+ return _dev_addr64;
+}
+
+uint16_t RemoteXBee::get_addr16() const
+{
+ return _dev_addr16;
+}
+
+RemoteXBee802::RemoteXBee802() : RemoteXBee()
+{
+}
+
+RemoteXBee802::RemoteXBee802(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBee802::RemoteXBee802(uint16_t remote16) : RemoteXBee()
+{
+ _dev_addr16 = remote16;
+}
+
+RemoteXBee802::RemoteXBee802(uint64_t remote64, uint16_t remote16) : RemoteXBee(remote64)
+{
+ _dev_addr16 = remote16;
+}
+
+RemoteXBee802::~RemoteXBee802()
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB() : RemoteXBee()
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB(uint64_t remote64, uint16_t remote16) : RemoteXBee(remote64)
+{
+ _dev_addr16 = remote16;
+}
+
+RemoteXBeeZB::~RemoteXBeeZB()
+{
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/RemoteXBee/RemoteXBee.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,162 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_REMOTE_H_)
+#define __XBEE_REMOTE_H_
+
+#include "XBee/Addresses.h"
+
+namespace XBeeLib {
+
+/** Class for Remote XBee modules. Not to be used directly. */
+class RemoteXBee
+{
+ public:
+
+ /** Default Class constructor for a remote device (connected wirelessly). No address set.
+ */
+ RemoteXBee();
+
+ /** Class constructor for a remote device (connected wirelessly) using 64bit addressing
+ * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+ */
+ RemoteXBee(uint64_t remote64);
+
+ /** Class destructor */
+ ~RemoteXBee();
+
+ /** get_addr64 - returns the 64bit address of the remote device
+ *
+ * @returns the 64bit address of the remote device
+ */
+ uint64_t get_addr64() const;
+
+ /** get_addr16 - returns the 16bit address of the remote device
+ *
+ * @returns the 16bit address of the remote device
+ */
+ uint16_t get_addr16() const;
+
+ /** operator == overload so the object can be compared to equal */
+ inline bool operator == (const RemoteXBee &b) const
+ {
+ return ((b._dev_addr16 == _dev_addr16) &&
+ (b._dev_addr64 == _dev_addr64));
+ }
+
+ /** operator != overload so the object can be compared to not equal */
+ inline bool operator != (const RemoteXBee &b) const
+ {
+ return !(this == &b);
+ }
+
+ /** is_valid_addr16b - checks if the RemoteXBee object has a valid 16b address
+ * @returns true if valid, false otherwise
+ */
+ inline bool is_valid_addr16b() const
+ {
+ return (_dev_addr16 != ADDR16_UNKNOWN);
+ }
+
+ /** is_valid_addr64b - checks if the RemoteXBee object has a valid 64b address
+ * @returns true if valid, false otherwise
+ */
+ inline bool is_valid_addr64b() const
+ {
+ return !(_dev_addr64 == ADDR64_UNASSIGNED);
+ }
+
+
+ protected:
+ /** Remote Device 64 bit address */
+ uint64_t _dev_addr64;
+
+ /** Remote Device 16 bit address */
+ uint16_t _dev_addr16;
+};
+
+class FH_NodeDiscovery802;
+/** Class for 802.15.4 Remote XBee modules */
+class RemoteXBee802 : public RemoteXBee
+{
+ public:
+
+ /** Default Class constructor for a 802.15.4 remote device (connected wirelessly). No address set.
+ */
+ RemoteXBee802();
+
+ /** Class constructor for a 802.15.4 remote device (connected wirelessly) using 64bit addressing
+ * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+ */
+ RemoteXBee802(uint64_t remote64);
+
+ /** Class constructor for a 802.15.4 remote device (connected wirelessly) using 16bit addressing
+ * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+ */
+ RemoteXBee802(uint16_t remote16);
+
+ /** Class destructor */
+ ~RemoteXBee802();
+
+ inline bool is_valid(void)
+ {
+ return is_valid_addr64b() || is_valid_addr16b();
+ }
+
+ protected:
+
+ friend FH_NodeDiscovery802;
+ friend class XBee802;
+
+ /** Class constructor for a 802.15.4 remote device (connected wirelessly) for which both the 64-bit and 16-bit addresses are known.
+ * This constructor is only used by FH_NodeDiscovery802 class.
+ * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+ * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+ */
+ RemoteXBee802(uint64_t remote64, uint16_t remote16);
+};
+
+/** Class for ZigBee Remote XBee modules */
+class RemoteXBeeZB : public RemoteXBee
+{
+ public:
+
+ /** Default Class constructor for a ZigBee remote device (connected wirelessly). No address set.
+ */
+ RemoteXBeeZB();
+
+ /** Class constructor for a ZigBee remote device (connected wirelessly) using 64bit addressing
+ * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+ */
+ RemoteXBeeZB(uint64_t remote64);
+
+ /** Class constructor for a ZigBee remote device (connected wirelessly) using 64bit and 16b addressing
+ * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+ * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+ */
+ RemoteXBeeZB(uint64_t remote64, uint16_t remote16);
+
+ /** Class destructor */
+ ~RemoteXBeeZB();
+
+ inline bool is_valid(void)
+ {
+ return is_valid_addr64b();
+ }
+};
+
+} /* namespace XBeeLib */
+
+#endif /* defined(__XBEE_REMOTE_H_) */
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Utils/Debug.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,38 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__DEBUG_H_)
+#define __DEBUG_H_
+
+#include "config.h"
+
+#if defined(ENABLE_LOGGING)
+
+#include "DigiLogger.h"
+
+#define digi_log(...) DigiLog::DigiLogger::log_format(__VA_ARGS__);
+#else
+#define digi_log(...) do {} while(0)
+#endif
+
+#if defined(ENABLE_ASSERTIONS)
+#include "mbed.h"
+#define assert(expr) if (!(expr)) { \
+ digi_log(LogLevelNone, "Assertion failed: %s, file %s, line %d\n", \
+ #expr, __FILE__, __LINE__); \
+ mbed_die(); \
+ }
+#else
+#define assert(expr)
+#endif
+
+#endif /* __DEBUG_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Utils/Utils.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,34 @@
+/**
+ * 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 "Utils.h"
+#include <cstring>
+
+void rmemcpy(uint8_t * const dest, const uint8_t * const src, uint16_t bytes)
+{
+ uint8_t *destp = dest + bytes - 1;
+ uint8_t *srcp = (uint8_t *)src;
+
+ while (destp >= dest)
+ *destp-- = *srcp++;
+}
+
+uint64_t addr64_from_uint8_t(const uint8_t * const data, bool big_endian = true)
+{
+ int64_t addr64;
+ if (big_endian) {
+ rmemcpy((uint8_t *)&addr64, data, 8);
+ } else {
+ memcpy((uint8_t *)&addr64, data, 8);
+ }
+ return addr64;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Utils/Utils.h Fri May 08 11:50:56 2015 +0200 @@ -0,0 +1,38 @@ +/** + * 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 + * ======================================================================= + */ + +#if !defined(__XB_UTILS_H_) +#define __XB_UTILS_H_ + +#include <stdint.h> + +/** Buils an uint16_t out of 2 single bytes */ +#define UINT16(msb,lsb) (uint16_t)(((msb) << 8) | (lsb)) +/** Buils an uint64_t out of 2 uint32_t */ +#define UINT64(msb,lsb) (uint64_t)(((uint64_t)(msb) << 32) | (lsb)) + +#define UINT64_HI32(u64) (uint32_t)((u64) >> 32) +#define UINT64_LO32(u64) (uint32_t)((u64) & 0xFFFFFFFF) + +#define UNUSED_PARAMETER(a) ((void)(a)) + +/** rmemcpy - like memcpy but copies the bytes in reverse order + * + * @param dest pointer with the destination address + * @param src pointer with the source address + * @param bytes number of bytes that will be copied + */ +void rmemcpy(uint8_t * const dest, const uint8_t * const src, uint16_t bytes); + +#endif /* __XB_UTILS_H_ */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XBee/Addresses.h Fri May 08 11:50:56 2015 +0200 @@ -0,0 +1,34 @@ +/** + * 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 + * ======================================================================= + */ + +#if !defined(__ADDRESSES_H_) +#define __ADDRESSES_H_ + +#include <stdint.h> +#include <string.h> + +#include "Utils/Utils.h" + +/* Some commonly used addresses */ +#define ADDR64_BROADCAST ((uint64_t)0x000000000000FFFF) +#define ADDR64_COORDINATOR ((uint64_t)0x0000000000000000) +#define ADDR64_UNASSIGNED ((uint64_t)0xFFFFFFFFFFFFFFFF) + +#define ADDR16_UNKNOWN ((uint16_t)0xFFFE) +#define ADDR16_BROADCAST ((uint16_t)0xFFFF) + +/** Macro used to create a 16bit data type from 2 bytes */ +#define ADDR16(msb,lsb) UINT16(msb,lsb) + +uint64_t addr64_from_uint8_t(const uint8_t * const data, bool big_endian = true); + +#endif /* __ADDRESSES_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee/AtCommands.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,139 @@
+/**
+ * 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 "XBeeLib.h"
+
+#define GET_CMD_RESP(fr, radio_location) (radio_location == RadioRemote ? fr->get_data_at(REM_AT_CMD_RESP_STATUS_OFFSET) \
+ : fr->get_data_at(ATCMD_RESP_STATUS_OFFSET))
+
+#define GET_DATA_LEN(fr, radio_location) (radio_location == RadioRemote ? (fr->get_data_len() - REM_AT_CMD_RESP_OVERHEAD) \
+ : (fr->get_data_len() - ATCMD_RESP_OVERHEAD))
+
+#define GET_DATA_OFF(radio_location) (radio_location == RadioRemote ? REM_AT_CMD_RESP_CMD_DATA_OFFSET \
+ : ATCMD_RESP_DATA_OFFSET)
+
+using namespace XBeeLib;
+
+/** Method that sends an AT command to the module and waits for the command response.
+ * @returns the AT command response */
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame,
+ uint8_t *const buf, uint16_t *const len, RadioLocation radio_location, bool reverse)
+{
+ AtCmdFrame::AtCmdResp resp = AtCmdFrame::AtCmdRespTimeout;
+ ApiFrame *resp_frame;
+ ApiFrame::ApiFrameType expected_type =
+ (frame->get_frame_type() == ApiFrame::AtCmd) ?
+ ApiFrame::AtCmdResp : ApiFrame::RemoteCmdResp;
+
+ send_api_frame(frame);
+
+ /* Wait for the AT command response packet */
+ resp_frame = get_this_api_frame(frame->get_frame_id(), expected_type);
+ if (resp_frame == NULL)
+ return resp;
+
+ resp = (AtCmdFrame::AtCmdResp)GET_CMD_RESP(resp_frame, radio_location);
+ if (resp == AtCmdFrame::AtCmdRespOk) {
+ if (buf != NULL && len != NULL) {
+
+ /* Copy the command response data */
+ uint16_t new_len = GET_DATA_LEN(resp_frame, radio_location);
+
+ *len = (*len < new_len) ? *len : new_len;
+
+ /* rmemcpy makes the endian change */
+ if (reverse) {
+ rmemcpy(buf, resp_frame->get_data() + GET_DATA_OFF(radio_location), *len);
+ } else {
+ memcpy(buf, resp_frame->get_data() + GET_DATA_OFF(radio_location), *len);
+ }
+ }
+ } else {
+ digi_log(LogLevelWarning, "send_at_cmd bad response: 0x%x\r\n", resp);
+ }
+
+ /* Once processed, remove the frame from the buffer */
+ _framebuf.free_frame(resp_frame);
+ return resp;
+}
+
+/** Method that sends an AT command to the module and waits for the command response.
+ * @returns the AT command response */
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame)
+{
+ return send_at_cmd(frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint8_t *data)
+{
+ uint16_t len = sizeof *data;
+ AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, data, &len);
+
+ if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data)
+ atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+
+ return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint16_t *data)
+{
+ uint16_t len = sizeof *data;
+ AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, (uint8_t *)data, &len);
+
+ if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data)
+ atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+
+ return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint32_t *data)
+{
+ uint16_t len = sizeof *data;
+ AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, (uint8_t *)data, &len);
+
+ if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data)
+ atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+
+ return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::get_param(const char * const param, uint32_t * const data)
+{
+ uint16_t len = sizeof *data;
+ AtCmdFrame cmd_frame = AtCmdFrame(param);
+
+ *data = 0; /* Set to zero, send_at_cmd() only writes the necessary bytes, so if only 1 is written all the remaining 3 should be 0. */
+ AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len);
+
+ if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data)
+ atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+
+ return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::set_param(const char * const param, uint32_t data)
+{
+ AtCmdFrame cmd_frame = AtCmdFrame(param, data);
+ return send_at_cmd(&cmd_frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::set_param(const char * const param, const uint8_t * data, uint16_t len)
+{
+ AtCmdFrame cmd_frame = AtCmdFrame(param, data, len);
+ return send_at_cmd(&cmd_frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::get_param(const char * const param, uint8_t * const data, uint16_t * const len)
+{
+ AtCmdFrame cmd_frame = AtCmdFrame(param);
+ return send_at_cmd(&cmd_frame, data, len, RadioLocal, false);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee/RadioConfig.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,346 @@
+/**
+ * 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 "XBeeLib.h"
+#include "Frames/ApiFrame.h"
+
+using namespace XBeeLib;
+
+RadioStatus XBee::write_config(void)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("WR");
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ return Success;
+}
+
+RadioStatus XBee::sleep_now(void)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("SI");
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ return Success;
+}
+
+RadioStatus XBee::set_power_level(uint8_t level)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ if (level > 4) {
+ return Failure;
+ }
+
+ cmdresp = set_param("PL", level);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+
+ return Success;
+}
+
+RadioStatus XBee::get_power_level(uint8_t * const level)
+{
+ if (level == NULL) {
+ return Failure;
+ }
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ uint32_t var32;
+ cmdresp = get_param("PL", &var32);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ *level = var32;
+ return Success;
+}
+
+RadioStatus XBee::get_network_address(uint16_t * const addr16)
+{
+ if (addr16 == NULL) {
+ return Failure;
+ }
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ uint32_t var32;
+ cmdresp = get_param("MY", &var32);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ *addr16 = var32;
+ return Success;
+}
+
+RadioStatus XBee::software_reset(void)
+{
+ volatile uint16_t * const rst_cnt_p = &_wd_reset_cnt;
+ const uint16_t init_rst_cnt = *rst_cnt_p;
+
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("FR");
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+
+ return wait_for_module_to_reset(rst_cnt_p, init_rst_cnt);
+}
+
+RadioStatus XBee::set_node_identifier(const char * const node_id)
+{
+ if (node_id == NULL) {
+ return Failure;
+ }
+
+ AtCmdFrame::AtCmdResp cmdresp;
+ const size_t str_len = strlen(node_id);
+
+ if(str_len > 20 || str_len < 1) {
+ return Failure;
+ }
+
+ cmdresp = set_param("NI", (const uint8_t *)node_id, str_len);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ return Success;
+}
+
+RadioStatus XBee::get_node_identifier(char * const node_id)
+{
+ if (node_id == NULL) {
+ return Failure;
+ }
+
+ uint16_t max_ni_length = 20;
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = get_param("NI", (uint8_t *)node_id, &max_ni_length);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ node_id[max_ni_length] = '\0';
+ return Success;
+}
+
+uint16_t XBee::get_hw_version() const
+{
+ return _hw_version;
+}
+
+uint16_t XBee::get_fw_version() const
+{
+ return _fw_version;
+}
+
+void XBee::set_tx_options(uint8_t options)
+{
+ _tx_options = options;
+}
+
+uint8_t XBee::get_tx_options() const
+{
+ return _tx_options;
+}
+
+void XBee::set_broadcast_radius(uint8_t bc_radius)
+{
+ _bc_radius = bc_radius;
+}
+
+uint8_t XBee::get_bc_radius() const
+{
+ return _bc_radius;
+}
+
+RadioStatus XBee::start_node_discovery()
+{
+ AtCmdFrame cmd_frame = AtCmdFrame("ND");
+ send_api_frame(&cmd_frame);
+
+ return Success;
+}
+
+void XBee::_get_remote_node_by_id(const char * const node_id, uint64_t * const addr64, uint16_t * const addr16)
+{
+ *addr64 = ADDR64_UNASSIGNED;
+ *addr16 = ADDR16_UNKNOWN;
+ if (node_id == NULL) {
+ return;
+ }
+ const size_t node_id_len = strlen(node_id);
+ if (node_id_len == 0 || node_id_len > MAX_NI_PARAM_LEN) {
+ return;
+ }
+
+ const uint16_t old_timeout = _timeout_ms;
+
+ uint32_t nd_timeout_100msec;
+ const AtCmdFrame::AtCmdResp nt_resp = get_param("NT", &nd_timeout_100msec);
+ if (nt_resp != AtCmdFrame::AtCmdRespOk) {
+ _timeout_ms = 10000;
+ } else {
+ _timeout_ms = (uint16_t)nd_timeout_100msec * 100 + 1000;
+ }
+
+ const AtCmdFrame::AtCmdResp cmdresp = set_param("ND", (const uint8_t *)node_id, strlen(node_id));
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ _timeout_ms = old_timeout;
+ return;
+ }
+
+ const int nd_start_time = _timer.read_ms();
+ const int nd_end_time = nd_start_time + _timeout_ms;
+
+ AtCmdFrame atnd_frame = AtCmdFrame("ND", (const uint8_t *)node_id, strlen(node_id));
+ send_api_frame(&atnd_frame);
+
+ ApiFrame * const resp_frame = get_this_api_frame(atnd_frame.get_frame_id(), ApiFrame::AtCmdResp);
+ _timeout_ms = old_timeout;
+
+ while (_timer.read_ms() < nd_end_time) {
+ wait_ms(10);
+ }
+
+ if (resp_frame == NULL) {
+ digi_log(LogLevelWarning, "XBeeZB::get_remote_node_by_id timeout when waiting for ATND response");
+ return;
+ }
+
+ const AtCmdFrame::AtCmdResp resp = (AtCmdFrame::AtCmdResp)resp_frame->get_data_at(ATCMD_RESP_STATUS_OFFSET);
+ if (resp != AtCmdFrame::AtCmdRespOk) {
+ digi_log(LogLevelWarning, "send_at_cmd bad response: 0x%x\r\n", resp);
+ _framebuf.free_frame(resp_frame);
+ return;
+ }
+
+ rmemcpy((uint8_t *)addr16, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET, sizeof *addr16);
+ rmemcpy((uint8_t *)addr64, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET + sizeof *addr16, sizeof *addr64);
+ _framebuf.free_frame(resp_frame);
+ return;
+}
+
+RadioStatus XBee::config_node_discovery(uint16_t timeout_ms, uint8_t options)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("NT", (uint8_t)(timeout_ms / 100));
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+
+ cmdresp = set_param("NO", (uint8_t)options);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ cmdresp = set_param("AC");
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+
+ return Success;
+}
+
+RadioStatus XBee::get_config_node_discovery(uint16_t * const timeout_ms, uint8_t * const options)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+ uint32_t var32;
+
+ cmdresp = get_param("NT", &var32);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ *timeout_ms = var32;
+
+ cmdresp = get_param("NO", &var32);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ *options = var32;
+ return Success;
+}
+
+RadioStatus XBee::get_iosample(const RemoteXBee& remote, uint8_t * const io_sample, uint16_t * const len)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+ *len = MAX_IO_SAMPLE_BUF_LEN;
+
+ /* Force a sample read */
+ cmdresp = get_param(remote, "IS", io_sample, len);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ digi_log(LogLevelError, "get_iosample error %d:\r\n", cmdresp);
+ return Failure;
+ }
+
+ return Success;
+}
+
+RadioStatus XBee::config_io_sample_destination(const RemoteXBee& remote, const RemoteXBee& destination)
+{
+ uint32_t dh;
+ uint32_t dl;
+
+ if (destination.is_valid_addr64b()) {
+ const uint64_t dest64 = destination.get_addr64();
+ dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF);
+ dl = (uint32_t)((dest64 & 0xFFFFFFFF));
+ } else if (destination.is_valid_addr16b()) {
+ const uint16_t destAddr16 = destination.get_addr16();
+ dh = 0;
+ dl = destAddr16;
+ } else {
+ digi_log(LogLevelError, "send_io_sample_to: Invalid destination");
+ return Failure;
+ }
+
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param(remote, "DH", dh);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ digi_log(LogLevelError, "send_io_sample_to error %d:\r\n", cmdresp);
+ return Failure;
+ }
+
+ cmdresp = set_param(remote, "DL", dl);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ digi_log(LogLevelError, "send_io_sample_to error %d:\r\n", cmdresp);
+ return Failure;
+ }
+
+ return Success;
+}
+
+RadioStatus XBee::set_io_sample_rate(const RemoteXBee& remote, const float seconds)
+{
+ const float max_seconds = 65.535;
+
+ if (seconds > max_seconds) {
+ digi_log(LogLevelError, "XBee::set_io_sample_rate error seconds rate exceeds maximum %d:\r\n", max_seconds);
+ return Failure;
+ }
+
+ AtCmdFrame::AtCmdResp cmdresp;
+ const uint16_t milliseconds = seconds * 1000;
+
+ cmdresp = set_param(remote, "IR", milliseconds);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ digi_log(LogLevelError, "XBee::set_io_sample_rate error %d:\r\n", cmdresp);
+ return Failure;
+ }
+
+ return Success;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee/XBee.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,732 @@
+/**
+ * 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 "XBeeLib.h"
+#include "FrameHandlers/FH_ModemStatus.h"
+
+/* States for the state machine that processes incoming data on the serial port */
+#define WAITING_FOR_START_FRAME (0)
+#define WAITING_FOR_LENGTH_MSB (1)
+#define WAITING_FOR_LENGTH_LSB (2)
+#define WAITING_FOR_PAYLOAD (3)
+#define WAITING_FOR_CHECKSUM (4)
+
+#define IS_API2() (_mode == ModeAPI2)
+#define IS_API_MODE() (_mode == ModeAPI1 || _mode == ModeAPI2)
+
+using namespace XBeeLib;
+
+Timer XBee::_timer;
+FrameBuffer XBee::_framebuf;
+
+/* Class constructor */
+XBee::XBee(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+ _mode(ModeUnknown), _type(Unknown), _hw_version(0), _fw_version(0), _timeout_ms(SYNC_OPS_TIMEOUT_MS), _dev_addr64(ADDR64_UNASSIGNED), _dev_addr16(ADDR16_UNKNOWN),
+ _reset(NULL), _tx_options(0), _bc_radius(0), _hw_reset_cnt(0), _wd_reset_cnt(0), _reset_timeout(0), _modem_status_handler(NULL), _modem_status(AtCmdFrame::HwReset), _initializing(true), _pm_mode(SleepDisabled)
+{
+
+ if (reset != NC) {
+ _reset = new DigitalOut(reset);
+ }
+#if defined(ENABLE_PM_SUPPORT)
+ _on_sleep = NULL;
+ _sleep_req = NULL;
+#endif /* defined(ENABLE_PM_SUPPORT) */
+
+ _uart = new RawSerial(tx, rx);
+ _uart->baud(baud);
+#if defined(DEVICE_SERIAL_FC)
+ if (rts != NC && cts != NC) {
+ _uart->set_flow_control(SerialBase::RTSCTS, rts, cts);
+ }
+#endif
+ /* Enable the reception of bytes on the serial interface by providing a cb */
+ _uart->attach(this, &XBee::uart_read_cb, Serial::RxIrq);
+
+ for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+ _fhandlers[i] = NULL;
+ }
+}
+
+/* Class destructor */
+XBee::~XBee()
+{
+ unregister_modem_status_cb();
+
+ if (_uart != NULL) {
+ delete _uart;
+ }
+ if (_reset != NULL) {
+ delete _reset;
+ }
+}
+
+#include <inttypes.h>
+
+RadioStatus XBee::init(void)
+{
+ AtCmdFrame::AtCmdResp cmd_resp;
+ uint32_t var32;
+
+ /* Start the timer, used for the timeouts */
+ _timer.reset();
+ _timer.start();
+
+ _initializing = true;
+
+ device_reset();
+
+ /* Check if radio is in API1 or API2 _mode */
+ cmd_resp = get_param("AP", &var32);
+ if (cmd_resp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+
+ _mode = (RadioMode)var32;
+
+ /* Read the device unique 64b address */
+ uint32_t serialn_high, serialn_low;
+ cmd_resp = get_param("SH", &serialn_high);
+ if (cmd_resp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ cmd_resp = get_param("SL", &serialn_low);
+ if (cmd_resp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+
+ _dev_addr64 = ((uint64_t)serialn_high << 32) | serialn_low;
+
+ /* Read some important parameters */
+ cmd_resp = get_param("HV", &var32);
+ if (cmd_resp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ _hw_version = var32;
+
+ cmd_resp = get_param("VR", &var32);
+ if (cmd_resp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ _fw_version = var32;
+
+ cmd_resp = get_param("MY", &var32);
+ if (cmd_resp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ _dev_addr16 = var32;
+ _type = (RadioType)(_hw_version >> 8);
+
+ digi_log(LogLevelInfo, "mode: %02x\r\n", (uint8_t)_mode);
+ digi_log(LogLevelInfo, "HV: %04x\r\n", _hw_version);
+ digi_log(LogLevelInfo, "VR: %04x\r\n", _fw_version);
+ digi_log(LogLevelInfo, "ADDR64: %08x:%08x\r\n", UINT64_HI32(_dev_addr64), UINT64_LO32(_dev_addr64));
+ digi_log(LogLevelInfo, "ADDR16: %04x\r\n", _dev_addr16);
+
+ _initializing = false;
+ if (_modem_status_handler != NULL) {
+ const ApiFrame frame = ApiFrame(ApiFrame::AtModemStatus, (uint8_t *)&_modem_status, sizeof(_modem_status));
+ _modem_status_handler->process_frame_data(&frame);
+ }
+
+ return Success;
+}
+
+uint64_t XBee::get_addr64() const
+{
+ return _dev_addr64;
+}
+
+uint16_t XBee::get_addr16() const
+{
+ return _dev_addr16;
+}
+
+RadioStatus XBee::hardware_reset()
+{
+ if (_reset != NULL) {
+ volatile uint16_t * const rst_cnt_p = &_hw_reset_cnt;
+ const uint16_t init_rst_cnt = *rst_cnt_p;
+ *_reset = 0;
+ wait_ms(10);
+ *_reset = 1;
+ return wait_for_module_to_reset(rst_cnt_p, init_rst_cnt);
+ }
+
+ return Failure;
+}
+
+RadioStatus XBee::device_reset()
+{
+ if (hardware_reset() == Success)
+ return Success;
+
+ return software_reset();
+}
+
+RadioStatus XBee::wait_for_module_to_reset(volatile uint16_t *rst_cnt_p, uint16_t init_rst_cnt)
+{
+ const int rst_timeout = _timer.read_ms() + _reset_timeout;
+ while (*rst_cnt_p == init_rst_cnt && _timer.read_ms() < rst_timeout) {
+ wait_ms(100);
+ }
+
+ if (_reset_timeout && *rst_cnt_p == init_rst_cnt) {
+ digi_log(LogLevelWarning, "Reset Timeout\r\n");
+ return Failure;
+ }
+ return Success;
+}
+
+/** Callback function called when data is received on the serial port */
+void XBee::uart_read_cb(void)
+{
+ static uint8_t rxstate = WAITING_FOR_START_FRAME;
+ static uint16_t framelen = 0;
+ static uint16_t bytes_read;
+ static uint8_t chksum;
+ static ApiFrame *frame = NULL;
+ static bool last_byte_escaped = false;
+
+ while (_uart->readable()) {
+ uint8_t data = _uart->getc();
+
+ if (IS_API2() && rxstate != WAITING_FOR_START_FRAME) {
+ if (last_byte_escaped) {
+ data = data ^ DR_ESCAPE_XOR_BYTE;
+ last_byte_escaped = false;
+ } else if (data == DR_ESCAPE_BYTE) {
+ last_byte_escaped = true;
+ continue;
+ }
+ }
+
+ switch (rxstate) {
+ case WAITING_FOR_START_FRAME:
+ if (data == DR_START_OF_FRAME)
+ rxstate = WAITING_FOR_LENGTH_MSB;
+ break;
+
+ case WAITING_FOR_LENGTH_MSB:
+ framelen = data << 8;
+ rxstate = WAITING_FOR_LENGTH_LSB;
+ break;
+
+ case WAITING_FOR_LENGTH_LSB:
+ framelen |= data;
+ rxstate = WAITING_FOR_PAYLOAD; /* FIXME, if frame is NULL the status should be WAITING */
+ bytes_read = 0;
+ chksum = 0;
+ /* Sanity check that the frame is smaller than... */
+ if (framelen > MAX_FRAME_PAYLOAD_LEN) {
+ digi_log(LogLevelDebug, "framelen=%d too long\r\n", framelen);
+ digi_log(LogLevelWarning, "Frame dropped, frame too long. Increase MAX_FRAME_PAYLOAD_LEN define\r\n");
+ rxstate = WAITING_FOR_START_FRAME;
+ }
+
+ frame = _framebuf.get_next_free_frame();
+ if (frame == NULL) {
+ /* It's not possible to achive this condition as we discard older frames and only one frame can be used by syncr. commands */
+ assert(frame != NULL);
+ rxstate = WAITING_FOR_START_FRAME;
+ } else {
+ frame->set_data_len(framelen - 1);
+ }
+ break;
+
+ case WAITING_FOR_PAYLOAD:
+ if (!bytes_read)
+ frame->set_frame_type((ApiFrame::ApiFrameType)data);
+ else {
+ frame->set_data(data, bytes_read - 1);
+ }
+ chksum += data;
+ bytes_read++;
+ if (bytes_read == framelen)
+ rxstate = WAITING_FOR_CHECKSUM;
+ break;
+
+ case WAITING_FOR_CHECKSUM:
+ chksum += data;
+ if (chksum == 0xFF) {
+ /* We got a valid frame!! */
+ frame->dump();
+
+ /* If its a _modem status frame, process it to update the status info of the library.
+ * The frame is also queued to allow processing it other handlers registered.
+ * Note that radio_status_update() has to be fast to minimize the impact of processing
+ * the funcion here */
+ if (frame->get_frame_type() == ApiFrame::AtModemStatus) {
+ radio_status_update((AtCmdFrame::ModemStatus)frame->get_data_at(0));
+ if (_initializing)
+ _framebuf.free_frame(frame);
+ else
+ _framebuf.complete_frame(frame);
+ }
+ else {
+ _framebuf.complete_frame(frame);
+ /* Note, the frame will be released elsewhere, once it has been processed */
+ }
+ } else {
+ _framebuf.free_frame(frame);
+ digi_log(LogLevelWarning, "Checksum error, got %02x, %02x\r\n", data, chksum);
+ }
+ /* Intentional fall-through */
+ default:
+ rxstate = WAITING_FOR_START_FRAME;
+ break;
+ }
+ }
+ /* TODO, signal the thread processing incoming frames */
+}
+
+/* This is a pure virtual function, but exists here because its called from this class to
+ * to update the status of the object, and can be called before the construction of the
+ * object has been completed and the virtual functions filled */
+void XBee::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+ UNUSED_PARAMETER(modem_status);
+}
+
+void XBee::set_timeout(uint16_t timeout_ms)
+{
+ this->_timeout_ms = timeout_ms;
+}
+
+uint16_t XBee::get_timeout(void) const
+{
+ return _timeout_ms;
+}
+
+RadioType XBee::get_radio_type() const
+{
+ return _type;
+}
+
+
+
+/* */
+ApiFrame * XBee::get_this_api_frame(uint8_t id, ApiFrame::ApiFrameType type,
+ ApiFrame::ApiFrameType type2)
+{
+ int const timeout = _timer.read_ms() + _timeout_ms;
+
+ while (_timer.read_ms() < timeout) {
+ ApiFrame * frame = _framebuf.get_next_complete_frame_syncr();
+ if (frame == NULL) {
+ wait_ms(10);
+ continue;
+ }
+
+ if ((frame->get_frame_type() != type) &&
+ (frame->get_frame_type() != type2)) {
+ _framebuf.complete_frame(frame);
+ wait_ms(1);
+ continue;
+ }
+
+ if (frame->get_data_at(ATCMD_RESP_FRAME_ID_OFFSET) != id) {
+ _framebuf.complete_frame(frame);
+ wait_ms(1);
+ continue;
+ }
+
+ /* frame found */
+ return frame;
+ }
+
+ digi_log(LogLevelWarning, "Frame type: %02x, id: %02x, timeout\r\n", (uint8_t)type, id);
+
+ return NULL;
+}
+
+void XBee::send_byte_escaping_if(uint8_t data)
+{
+ if (IS_API2()) {
+ switch (data) {
+ case DR_START_OF_FRAME:
+ case DR_ESCAPE_BYTE:
+ case DR_XON_BYTE:
+ case DR_XOFF_BYTE:
+ _uart->putc(DR_ESCAPE_BYTE);
+ _uart->putc(data ^ DR_ESCAPE_XOR_BYTE);
+ break;
+ default:
+ _uart->putc(data);
+ }
+ } else {
+ _uart->putc(data);
+ }
+}
+
+void XBee::send_api_frame(ApiFrame *frame)
+{
+ uint8_t chksum;
+ const uint8_t *data;
+ uint16_t bytes_sent = 0, frame_len;
+
+ frame->dump();
+
+ frame_len = 1 + frame->get_data_len(); /* frame type + frame payload */
+ data = frame->get_data();
+
+ /* Send the start of frame delimiter */
+ _uart->putc(DR_START_OF_FRAME);
+
+ /* Now the length */
+ send_byte_escaping_if((uint8_t)(frame_len >> 8));
+ send_byte_escaping_if((uint8_t)frame_len);
+
+ /* Send the Frame type and then the payload */
+ chksum = (uint8_t)frame->get_frame_type();
+ send_byte_escaping_if(chksum);
+ bytes_sent++;
+
+ /* And now, send the packet payload */
+ while (bytes_sent++ < frame_len) {
+ chksum += *data;
+ send_byte_escaping_if(*data++);
+ }
+
+ /* And finally send the checksum */
+ send_byte_escaping_if(~chksum);
+}
+
+/** */
+RadioStatus XBee::register_frame_handler(FrameHandler *const handler)
+{
+ if (handler != NULL) {
+ for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+ if (_fhandlers[i] != NULL)
+ continue;
+ _fhandlers[i] = handler;
+ return Success;
+ }
+ }
+
+ digi_log(LogLevelError, "No more Frame Handlers available. Increase MAX_FRAME_HANDLERS define\r\n");
+
+ return Failure;
+}
+
+/** */
+RadioStatus XBee::unregister_frame_handler(FrameHandler *const handler)
+{
+ int i;
+
+ if (handler != NULL) {
+ for (i = 0; i < MAX_FRAME_HANDLERS; i++) {
+ if (_fhandlers[i] == handler)
+ break;
+ }
+
+ if (i == MAX_FRAME_HANDLERS)
+ return Failure;
+
+ do {
+ if (i == MAX_FRAME_HANDLERS - 1)
+ _fhandlers[i] = NULL;
+ else
+ _fhandlers[i] = _fhandlers[i + 1];
+ } while (++i < MAX_FRAME_HANDLERS);
+ }
+
+ return Success;
+}
+
+XBee::RadioProtocol XBee::get_radio_protocol(void) const
+{
+ enum HardwareVersion {
+#ifdef EXTRA_XBEE_PROTOCOLS
+ X09_009 = 0x01,
+ X09_019 = 0x02,
+ XH9_009 = 0x03,
+ XH9_019 = 0x04,
+ X24_009 = 0x05,
+ X24_019 = 0x06,
+ X09_001 = 0x07,
+ XH9_001 = 0x08,
+ X08_004 = 0x09,
+ XC09_009 = 0x0A,
+ XC09_038 = 0x0B,
+ X24_038 = 0x0C,
+ X09_009_TX = 0x0D,
+ X09_019_TX = 0x0E,
+ XH9_009_TX = 0x0F,
+ XH9_019_TX = 0x10,
+ X09_001_TX = 0x11,
+ XH9_001_TX = 0x12,
+ XT09B_XXX = 0x13,
+ XT09_XXX = 0x14,
+ XC08_009 = 0x15,
+ XC08_038 = 0x16,
+#endif
+ XB24_AXX_XX = 0x17,
+ XBP24_AXX_XX = 0x18,
+ XB24_BXIX_XXX = 0x19,
+ XBP24_BXIX_XXX = 0x1A,
+#ifdef EXTRA_XBEE_PROTOCOLS
+ XBP09_DXIX_XXX = 0x1B,
+ XBP09_XCXX_XXX = 0x1C,
+ XBP08_DXXX_XXX = 0x1D,
+#endif
+ XBP24B = 0x1E,
+#ifdef EXTRA_XBEE_PROTOCOLS
+ XB24_WF = 0x1F,
+ AMBER_MBUS = 0x20,
+#endif
+ XBP24C = 0x21,
+ XB24C = 0x22,
+#ifdef EXTRA_XBEE_PROTOCOLS
+ XSC_GEN3 = 0x23,
+ SRD_868_GEN3 = 0x24,
+ ABANDONATED = 0x25,
+ SMT_900LP = 0x26,
+ WIFI_ATHEROS = 0x27,
+ SMT_WIFI_ATHEROS = 0x28,
+ SMT_475LP = 0x29,
+ XBEE_CELL_TH = 0x2A,
+ XLR_MODULE = 0x2B,
+ XB900HP_NZ = 0x2C,
+ XBP24C_TH_DIP = 0x2D,
+ XB24C_TH_DIP = 0x2E,
+ XLR_BASEBOARD = 0x2F
+#endif
+ };
+ const bool fw_4_bytes_len = _fw_version > 0x0FFF && _fw_version < 0xFFFF;
+ const uint8_t fw_nibble_3 = (_fw_version >> (4 * 3)) & 0x000F;
+ const uint8_t fw_nibble_1 = (_fw_version >> (4 * 1)) & 0x000F;
+ const uint8_t fw_nibble_0 = (_fw_version >> (4 * 0)) & 0x000F;
+ const uint8_t hw_version_msb = _hw_version >> 8;
+
+ if (hw_version_msb == XB24_AXX_XX || hw_version_msb == XBP24_AXX_XX) {
+#ifdef EXTRA_XBEE_PROTOCOLS
+ if (fw_4_bytes_len && fw_nibble_3 == 8) {
+ return DigiMesh;
+ }
+ return Raw_802_15_4;
+#else
+ if (!(fw_4_bytes_len && fw_nibble_3 == 8)) {
+ return Raw_802_15_4;
+ }
+#endif
+ } else if (hw_version_msb == XB24_BXIX_XXX || hw_version_msb == XBP24_BXIX_XXX) {
+ if (fw_4_bytes_len && ((fw_nibble_3 == 1 && fw_nibble_1 == 2 && fw_nibble_0 == 0) || fw_nibble_3 == 2)) {
+ return ZigBee;
+ }
+#ifdef EXTRA_XBEE_PROTOCOLS
+ if (fw_4_bytes_len && fw_nibble_3 == 3) {
+ return SmartEnergy;
+ }
+ return ZNet;
+ } else if (hw_version_msb == XBP09_DXIX_XXX) {
+ if (fw_4_bytes_len && (fw_nibble_3 == 8 || fw_nibble_1 == 8)) {
+ return DigiMesh;
+ }
+ return DigiPoint;
+ } else if (hw_version_msb == XBP08_DXXX_XXX) {
+ return DigiPoint;
+#endif
+ } else if (hw_version_msb == XBP24B) {
+#ifdef EXTRA_XBEE_PROTOCOLS
+ if (fw_4_bytes_len && fw_nibble_3 == 3) {
+ return SmartEnergy;
+ }
+ return ZigBee;
+#else
+ if (!(fw_4_bytes_len && fw_nibble_3 == 3)) {
+ return ZigBee;
+ }
+#endif
+#ifdef EXTRA_XBEE_PROTOCOLS
+ } else if (hw_version_msb == XB24_WF || hw_version_msb == WIFI_ATHEROS || hw_version_msb == SMT_WIFI_ATHEROS) {
+ return XBeeWiFi;
+#endif
+ } else if (hw_version_msb == XBP24C || hw_version_msb == XB24C) {
+#ifdef EXTRA_XBEE_PROTOCOLS
+ if (fw_4_bytes_len && fw_nibble_3 == 5) {
+ return SmartEnergy;
+ }
+ return ZigBee;
+#else
+ if (!(fw_4_bytes_len && fw_nibble_3 == 5)) {
+ return ZigBee;
+ }
+#endif
+#ifdef EXTRA_XBEE_PROTOCOLS
+ } else if (hw_version_msb == XSC_GEN3 || hw_version_msb == SRD_868_GEN3) {
+ if (fw_4_bytes_len && fw_nibble_3 == 8) {
+ return DigiMesh;
+ } else if (fw_4_bytes_len && fw_nibble_3 == 1) {
+ return DigiPoint;
+ }
+ return None;
+ } else if (hw_version_msb == XBEE_CELL_TH) {
+ return None;
+ } else if (hw_version_msb == XLR_MODULE) {
+ return None;
+ } else if (hw_version_msb == XLR_BASEBOARD) {
+ return None;
+ } else if (hw_version_msb == XB900HP_NZ) {
+ return DigiPoint;
+ }
+#else
+ }
+#endif
+
+ return None;
+}
+
+#define TX_STATUS_OFFSET_ZB 4
+#define TX_STATUS_OFFSET_802 1
+
+TxStatus XBee::send_data(ApiFrame *frame)
+{
+ TxStatus resp = TxStatusTimeout;
+ ApiFrame *resp_frame;
+
+ send_api_frame(frame);
+
+ /* Wait for the transmit status response packet */
+ resp_frame = get_this_api_frame(frame->get_frame_id(),
+ ApiFrame::TxStatusZB, ApiFrame::TxStatus);
+ if (resp_frame == NULL)
+ return resp;
+
+ uint8_t index = resp_frame->get_frame_type() == ApiFrame::TxStatusZB ?
+ TX_STATUS_OFFSET_ZB : TX_STATUS_OFFSET_802;
+
+ resp = (TxStatus)resp_frame->get_data_at(index);
+
+ /* Once processed, remove the frame from the buffer */
+ _framebuf.free_frame(resp_frame);
+
+ return resp;
+}
+
+TxStatus XBee::send_data_broadcast(const uint8_t *const data, uint16_t len)
+{
+ const RemoteXBee remoteDevice = RemoteXBee(ADDR64_BROADCAST);
+ return send_data(remoteDevice, data, len);
+}
+
+#if defined(ENABLE_PM_SUPPORT)
+
+RadioStatus XBee::set_pm_control(PmMode mode, PinName on_sleep, PinName sleep_rq)
+{
+ if (on_sleep != NC) {
+ _on_sleep = new InterruptIn(on_sleep);
+ }
+ if (sleep_rq != NC) {
+ _sleep_req = new DigitalOut(sleep_rq);
+ }
+ _pm_mode = mode;
+ /* TODO, set PM mode in the radio */
+ //return 0;
+ return Success;
+}
+
+
+RadioStatus XBee::get_pm_mode(PmMode *mode)
+{
+ *mode = _pm_mode;
+ return Success;
+}
+
+RadioStatus XBee::config_pm_timing(uint32_t before_sleep_ms, uint32_t total_sleep_period_ms)
+{
+ UNUSED_PARAMETER(before_sleep_ms);
+ UNUSED_PARAMETER(total_sleep_period_ms);
+ return Success;
+}
+
+RadioStatus XBee::enter_sleep_mode()
+{
+ if (_sleep_req == NULL)
+ return sleep_now();
+
+ _sleep_req->write(1);
+ return Success;
+}
+
+void XBee::exit_sleep_mode()
+{
+ /* TODO, check also mode? */
+ if (_sleep_req != NULL)
+ _sleep_req->write(0);
+}
+
+bool XBee::is_sleeping()
+{
+ /* TODO */
+ return true;
+}
+
+
+
+void XBee::register_wakeup_cb(void (*f)(void))
+{
+ if (_on_sleep == NULL)
+ return;
+
+ _on_sleep->rise(f);
+}
+
+void XBee::unregister_wakeup_cb()
+{
+ _on_sleep->disable_irq();
+ _on_sleep->rise(NULL);
+}
+
+#endif /* defined(ENABLE_PM_SUPPORT) */
+
+
+uint32_t XBee::process_rx_frames(void)
+{
+ ApiFrame *frame = NULL;
+
+ while ((frame = _framebuf.get_next_complete_frame_app()) != NULL) {
+ for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+
+ if (_fhandlers[i] == NULL) {
+ /* No more handlers, break here */
+ break;
+ }
+
+ /* Check if frame and handler match, if not... go for the next one */
+ if (frame->get_frame_type() != _fhandlers[i]->get_type()) {
+ continue;
+ }
+
+ _fhandlers[i]->process_frame_data(frame);
+ }
+
+ /* Once processed, remove the frame from the buffer */
+ _framebuf.free_frame(frame);
+ }
+
+ return _framebuf.get_dropped_frames_count();
+}
+
+void XBee::register_modem_status_cb(modem_status_cb_t function)
+{
+ if (_modem_status_handler == NULL) {
+ _modem_status_handler = new FH_ModemStatus();
+ register_frame_handler(_modem_status_handler);
+ }
+ _modem_status_handler->register_modem_status_cb(function);
+}
+
+void XBee::unregister_modem_status_cb()
+{
+ if (_modem_status_handler != NULL) {
+ _modem_status_handler->unregister_modem_status_cb();
+ unregister_frame_handler(_modem_status_handler);
+ delete _modem_status_handler;
+ _modem_status_handler = NULL; /* as delete does not set to NULL */
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee/XBee.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,845 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__DIGI_RADIO_H_)
+#define __DIGI_RADIO_H_
+
+#include <stdint.h>
+#include "config.h"
+#include "Utils/Debug.h"
+#include "Frames/AtCmdFrame.h"
+#include "FrameHandlers/FrameHandler.h"
+#include "FrameHandlers/FH_ModemStatus.h"
+#include "FrameBuffer/FrameBuffer.h"
+#include "Addresses.h"
+#include "RemoteXBee/RemoteXBee.h"
+#include "IO/IO.h"
+
+#define MAX_FRAME_HANDLERS 4
+#define RESET_TIMEOUT_MS 5000
+
+#define DR_API_FRAME_OVERHEAD 4 /* Start of frame + frame len + checksum */
+#define DR_MIN_API_FRAME_LEN 4
+#define DR_START_OF_FRAME 0x7E
+#define DR_ESCAPE_BYTE 0x7D
+#define DR_XON_BYTE 0x11
+#define DR_XOFF_BYTE 0x13
+#define DR_ESCAPE_XOR_BYTE 0x20
+
+/* TODO, verify these flags work in all modules */
+#define DISABLE_RETRIES_AND_ROUTE_REPAIR 0x01
+#define ENABLE_APS_ENCRYPTION 0x20
+#define USE_EXTENDED_TX_TIMEOUT 0x40
+
+namespace XBeeLib {
+
+/**
+ * @defgroup RadioStatus
+ * @{
+ */
+/**
+ * RadioStatus
+ */
+enum RadioStatus {
+ Success = 0, /**< Success */
+ Failure = -1, /**< Failure */
+ OpNotSupported = -2, /**< Option Not Supported */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup RadioType
+ * @{
+ */
+/**
+ * RadioType
+ */
+enum RadioType {
+ Unknown = 0, /**< Not detected yet */
+ XB24_A_S1 = 0x17, /**< S1 */
+ XBP24_A_S1 = 0x18, /**< S1 */
+ XB24_B_S2 = 0x19, /**< S2 */
+ XBP24_B_S2 = 0x1A, /**< S2 */
+ XBP09_D = 0x1B, /**< S4 */
+ XBP09_XC = 0x1C, /**< S3 */
+ XBP08_D = 0x1D, /**< 868MHz S5 */
+ XBP24_B_S2B = 0x1E, /**< S2B */
+ XB24_WF = 0x1F, /**< S6 */
+ XBP24_C_SMT = 0x21, /**< XBee PRO SMT S2C */
+ XB24_C_SMT = 0x22, /**< XBee SMT S2C */
+ XBP09_XC_B = 0x23, /**< S3B */
+ XBP09_B = 0x23, /**< S3B */
+ XB8 = 0x24, /**< S8 */
+ XB2B_WF_TH = 0x27, /**< S6B TH */
+ XB2B_WF_SMT = 0x28, /**< S6B SMT */
+ XBP24_C_TH = 0x2D, /**< S2C TH */
+ XB24_C_TH = 0x2E, /**< S2C TH */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup TxStatus
+ * @{
+ */
+/**
+ * TxStatus
+ */
+enum TxStatus {
+ TxStatusSuccess = 0, /**< Success */
+ TxStatusAckFail = 1, /**< MAC ACK Failure */
+ TxStatusCCAFail = 2, /**< CCA Failure */
+ TxStatusInvDestEP = 0x15, /**< Invalid destination endpoint */
+ TxStatusNwAckFail = 0x21, /**< Network ACK Failure */
+ TxStatusNotJoinNw = 0x22, /**< Not Joined to Network */
+ TxStatusSelfAddr = 0x23, /**< Self-addressed */
+ TxStatusAddrNotFound = 0x24, /**< Address Not Found */
+ TxStatusRouteNotFound = 0x25, /**< Route Not Found */
+ TxStatusBroadSrcFail2Heard = 0x26, /**< Broadcast source failed to hear a neighbor relay the message */
+ TxStatusInvBindTableIdx = 0x2B, /**< Invalid binding table index */
+ TxStatusResourceError = 0x2C, /**< Resource error lack of free buffers, timers, etc. */
+ TxStatusAttBroadcWithAPS = 0x2D, /**< Attempted broadcast with APS transmission */
+ TxStatusAttUnicWithAPSEE0 = 0x2E, /**< Attempted unicast with APS transmission, but EE=0 */
+ TxStatusResourceError2 = 0x31, /**< TxStatusResourceError2 */
+ TxStatusInternalError = 0x32, /**< Resource error lack of free buffers, timers, etc. */
+ TxStatusPayloadTooLarge = 0x74, /**< Data payload too large */
+ TxStatusIndirectMsgUnReq = 0x75, /**< Indirect message unrequested */
+ TxStatusInvalidAddr = 0xfe, /**< Invalid Address (Error generated by the library) */
+ TxStatusTimeout = 0xff, /**< Timeout (Error generated by the library) */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup PmMode
+ * @{
+ */
+/**
+ * PmMode
+ */
+enum PmMode {
+ SleepDisabled = 0, /**< SleepDisabled */
+ PinSleep = 1, /**< PinSleep */
+ PinDoze = 2, /**< PinDoze */
+ CyclicSeleep = 4, /**< CyclicSeleep */
+ CyclicSeleepPinW = 5, /**< CyclicSeleepPinW */
+};
+/**
+ * @}
+ */
+
+ /**
+ * @defgroup NetworkRole
+ * @{
+ */
+/**
+ * NetworkRole
+ */
+enum NetworkRole {
+ UnknownRole, /**< Unknown Role */
+ Coordinator, /**< Coordinator */
+ Router, /**< Router */
+ EndDevice, /**< EndDevice */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup RadioLocation
+ * @{
+ */
+/**
+ * RadioLocation
+ */
+enum RadioLocation {
+ RadioLocal = 0, /**< Local Radio */
+ RadioRemote = 1, /**< Remote Radio */
+};
+/**
+ * @}
+ */
+
+/** Parent Class for XBee modules, not to be directly used */
+class XBee
+{
+ private:
+ /** wait_for_module_to_reset - waits until a Modem Status packet with a reset status
+ * is received, or the timeout expires.
+ *
+ * @returns
+ * Success if a Modem Status was received,
+ * Failure otherwise
+ */
+ RadioStatus wait_for_module_to_reset(volatile uint16_t *rst_cnt_p, uint16_t init_rst_cnt);
+
+ protected:
+ /** timer used by local and remote objects */
+ static Timer _timer;
+
+ /** buffer to store the received frames */
+ static FrameBuffer _framebuf;
+
+ public:
+
+ /**
+ * RadioMode
+ */
+ enum RadioMode {
+ ModeUnknown = 0, /**< Unknown */
+ ModeAPI1 = 1, /**< API1 */
+ ModeAPI2 = 2, /**< API2 */
+ ModeTransparent = 3, /**< Transparent */
+ ModeBootloader = 4, /**< Bootloader */
+ };
+
+ /** Class constructor
+ * @param tx the TX pin of the UART that will interface the XBee module
+ * @param rx the RX pin of the UART that will interface the XBee module
+ * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+ * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+ * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+ * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+ * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+ * */
+ XBee(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+ XBee(const XBee& other); /* Intentionally not implemented */
+ /** Class destructor */
+ virtual ~XBee();
+
+ /** init- initializes object
+ * This function must be called just after creating the object so it initializes internal data.
+ * @returns
+ * Success if the module has been properly initialized and is ready to process data.
+ * Failure otherwise.
+ */
+ RadioStatus init();
+
+ /** get_addr64 - returns the 64bit address of the local device
+ *
+ * @returns the 64bit address of the local device
+ */
+ uint64_t get_addr64() const;
+
+ /** get_addr16 - returns the 16bit address of the local device
+ *
+ * @returns the 16-bit address of the local device.
+ */
+ uint16_t get_addr16() const;
+
+ /** get_network_address - gets the 16bit network address of the device
+ *
+ * @param addr pointer where the device 16bit network address will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_network_address(uint16_t * const addr);
+
+ /** hardware_reset - performs a hardware reset. The reset GPIO must have
+ * been provided to the constructor
+ *
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus hardware_reset();
+
+ /** software_reset - performs a firmware reset
+ *
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus software_reset();
+
+ /** device_reset - performs a hardware reset if there is a GPIO connected to the
+ * reset line of the device. Otherwise, performs a firmware reset.
+ *
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+#if defined(UNIT_TEST)
+ virtual
+#endif
+ RadioStatus device_reset();
+
+ /** get_radio_type - returns the type of radio, in most cases the hardware version
+ *
+ * @returns the radio type
+ */
+ RadioType get_radio_type() const;
+
+ /** set_tx_options - sets the transmit options byte, used with the transmit frames.
+ * Valid flags are:
+ * - DISABLE_RETRIES_AND_ROUTE_REPAIR
+ * - ENABLE_APS_ENCRYPTION
+ * - USE_EXTENDED_TX_TIMEOUT
+ *
+ * @param options variable with the option flags
+ */
+ void set_tx_options(uint8_t options);
+
+ /** set_broadcast_radius - sets the max number of hops for a broadcast msg.
+ * When set to 0 uses the maximum possible.
+ *
+ * @param bc_radius variable with the broadcast radious
+ */
+ void set_broadcast_radius(uint8_t bc_radius);
+
+ /** get_tx_options - returns the tx options byte configured in the library.
+ *
+ * @returns the tx options byte configured in the library.
+ */
+ uint8_t get_tx_options() const;
+
+ /** get_bc_radius - returns the broadcast radius configured in the library.
+ *
+ * @returns the broadcast radius configured in the library.
+ */
+ uint8_t get_bc_radius() const;
+
+ /************************ Configuration member methods *************************/
+ /** write_config - write settings to non volatile memory
+ *
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus write_config();
+
+ /** config_io_sample_destination - configures to which node a remote module will send its IO Samples to.
+ * @Note: this will modify 'remote' DH and DL parameters, if the remote node is configured in transparent mode this could lead to unwanted behavior.
+ * Consult the module's reference manual for more information.
+ *
+ * @param remote remote device that will be sending the IO Samples
+ * @param destination remote device that will be receiving the IO Samples sent by 'remote'
+ * @returns the result of the data transfer
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus config_io_sample_destination(const RemoteXBee& remote, const RemoteXBee& destination);
+
+ /** set_io_sample_rate - configures how often the IO Samples should be sent to the destination (see @ref send_io_sample_to).
+ *
+ * @param remote remote device that will be sending the IO Samples
+ * @param seconds the IO Sample sending rate in seconds (granularity is of 1 millisecond). Maximum is 65.535 seconds.
+ * @returns the result of the data transfer
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_io_sample_rate(const RemoteXBee& remote, float seconds);
+
+ /** set_power_level - sets the power level at which the radio will transmit
+ *
+ * @param level power level at which the radio will transmit
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_power_level(uint8_t level);
+
+ /** get_power_level - reads the power level configured in the radio
+ *
+ * @param level pointer where the read power level will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_power_level(uint8_t * const level);
+
+ /** get_hw_version - gets the hardware version of the radio
+ *
+ * @returns the hardware version of the radio
+ */
+ uint16_t get_hw_version() const;
+
+ /** get_fw_version - gets the firmware version of the radio
+ *
+ * @returns the firmware version of the radio
+ */
+ uint16_t get_fw_version() const;
+
+ /** set_node_identifier - configures the Node Identifier string
+ *
+ * @param node_id NULL-terminated string with the Node Identifier that will be set on the module. Up to 20 characters length (21 with NULL-terminator).
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_node_identifier(const char * const node_id);
+
+ /** get_node_identifier - reads the configured Node Identifier string
+ *
+ * @param node_id Pointer to where to store the read Node Identifier, it must point to a buffer with at least 21-bytes length.
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_node_identifier(char * const node_id);
+
+ /** start_node_discovery - starts a node discovery operation. The responses
+ * have to be processes on the callback function that have to be registered
+ * for that purpose
+ *
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus start_node_discovery();
+
+#define XBEEZB_ND_OPTION_APPEND_DD (1 << 0)
+#define XBEEZB_ND_OPTION_SELF_RESPONSE (1 << 1)
+#define XBEE802_ND_OPTION_SELF_RESPONSE (1 << 0)
+
+ /** config_node_discovery - configures the node discovery operation
+ *
+ * @param timeout_ms max allowed time for devices in the network to answer
+ * to the Node Discovery request
+ * @param options node discovery options (flags)
+ * XBEE802_ND_OPTION_SELF_RESPONSE - to allow the module self responding (802.15.4 only)
+ * XBEEZB_ND_OPTION_SELF_RESPONSE - to allow the module self responding (ZigBee only)
+ * XBEEZB_ND_OPTION_APPEND_DD - to append the DD value to the response (ZigBee only)
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus config_node_discovery(uint16_t timeout_ms, uint8_t options = 0);
+
+ /** get_config_node_discovery - reads the configuration of the node discovery
+ * settings
+ *
+ * @param timeout_ms pointer where the node discovery time out value will be stored
+ * @param options pointer whre the node discovery options (flags) will be saved
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_config_node_discovery(uint16_t * const timeout_ms, uint8_t * const options);
+
+ /** set_timeout - sets the timeout in ms, used by sync methods
+ *
+ * @param timeout_ms new timeout in ms
+ */
+ void set_timeout(uint16_t timeout_ms);
+
+ /** get_timeout - gets the timeout in ms configured in the library. This value
+ * is used in sync commands
+ *
+ * @returns the configured timeout value in ms
+ */
+ uint16_t get_timeout() const;
+
+ /* ... */
+
+ /*********************** send_data member methods ************************/
+ /** send_data - sends data to a remote device waiting for the packet
+ * answer with the result of the operation
+ *
+ * @param remote remote device
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len) = 0;
+
+ /** send_data_broadcast - sends data to all devices in the network, using the
+ * broadcast address. The method waits for the packet
+ * answer with the result of the operation
+ *
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ TxStatus send_data_broadcast(const uint8_t *const data, uint16_t len);
+
+ /** set_param - sets a parameter in the local radio by sending an AT command and waiting for the response.
+ *
+ * @param param parameter to be set.
+ * @param data the parameter value (4 bytes) to be set.
+ * @returns the command response status.
+ */
+ AtCmdFrame::AtCmdResp set_param(const char * const param, uint32_t data);
+
+ /** set_param - sets a parameter in the local radio by sending an AT command and waiting for the response.
+ *
+ * @param param parameter to be set.
+ * @param data the parameter value byte array (len bytes) to be set.
+ * @param len number of bytes of the parameter value.
+ * @returns the command response status.
+ */
+ AtCmdFrame::AtCmdResp set_param(const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+ /** get_param - gets a parameter from the local radio by sending an AT command and waiting for the response.
+ *
+ * @param param parameter to be get.
+ * @param data pointer where the param value (4 bytes) will be stored.
+ * @returns the command response status.
+ */
+ AtCmdFrame::AtCmdResp get_param(const char * const param, uint32_t * const data);
+
+ /** get_param - gets a parameter from the local radio by sending an AT command and waiting for the response.
+ *
+ * @param param parameter to be get.
+ * @param data pointer where the param value (n bytes) will be stored.
+ * @param len pointer where the number of bytes of the param value will be stored.
+ * @returns the command response status.
+ */
+ AtCmdFrame::AtCmdResp get_param(const char * const param, uint8_t * const data, uint16_t * const len);
+
+ /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be set.
+ * @param data the parameter value (4 bytes) to be set.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data) = 0;
+
+ /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be set.
+ * @param data the parameter value byte array (len bytes) to be set.
+ * @param len number of bytes of the parameter value.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0) = 0;
+
+ /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be get.
+ * @param data pointer where the param value (4 bytes) will be stored.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data) = 0;
+
+ /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be get.
+ * @param data pointer where the param value (n bytes) will be stored.
+ * @param len pointer where the number of bytes of the param value will be stored.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len) = 0;
+
+#if defined(ENABLE_PM_SUPPORT)
+ /** set_pm_control - sets the operational mode of the Power Management on
+ * the radio and registers the GPIOs used to handle the
+ * Power Management
+ *
+ * @param mode operational mode of the power management
+ * @param on_sleep pin used to detect the on/sleep status of the module
+ * @param sleep_rq pin used to request the module to go to sleep (when pin
+ * sleep mode is used
+ * @returns the result of the configuration operation
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_pm_control(PmMode mode, PinName on_sleep = NC, PinName sleep_rq = NC);
+
+ /** get_pm_mode - gets the power management mode programmed in the radio.
+ *
+ * @param mode pointer where the read mode will be stored.
+ * @returns the result of the configuration operation
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_pm_mode(PmMode *mode);
+
+ /** config_pm_timing - configures the power management timing parameters.
+ *
+ * @param before_sleep_ms number of miliseconds of inactivity before the radio will
+ * automatically go to sleep again (when using cyclic sleep).
+ * @param total_sleep_period_ms time interval in ms the radio will be sleeping. Once
+ * this time passes, the radio will wakeup, will check for
+ * packets and will wait before_sleep_ms of inactivity
+ * before entering again in sleep mode.
+ * @returns the result of the configuration operation
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus config_pm_timing(uint32_t before_sleep_ms, uint32_t total_sleep_period_ms);
+
+ /** enter_sleep_mode - sets the radio into low power mode. If the pm working mode
+ * is pin-sleep, then it will use the GPIO, otherwise, it will
+ * use the serial interface.
+ *
+ * @note the method does not wait until the radio enters in sleep mode, it returns
+ * without making any verification.
+ * @returns the result of the operation
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus enter_sleep_mode();
+
+ /** exit_sleep_mode - for the pm mode called pin-sleep, sets the radio into active power
+ * using the corresponding GPIO.
+ *
+ */
+ void exit_sleep_mode();
+
+ /** is_sleeping - checks if the radio is sleeping or if its active.
+ *
+ * @returns true if the radio is sleeping, false otherwisw
+ */
+ bool is_sleeping();
+
+ /** register_wakeup_cb - registers the callback function that will be called
+ * when the radio wakes up from sleep mode.
+ *
+ * @param f function pointer with the callback function
+ */
+ void register_wakeup_cb(void (*f)(void));
+
+ /** unregister_wakeup_cb - removes the wakeup callback */
+ void unregister_wakeup_cb();
+#endif /* defined(ENABLE_PM_SUPPORT) */
+
+ /** process_rx_frames - method that process the frames queued in the reception
+ * buffer. Calls the process_frame_data method of the frame
+ * handlers registered
+ *
+ * @returns Number of dropped frames since latest call to this method.
+ */
+ uint32_t process_rx_frames();
+
+ /** register_modem_status_cb - registers the callback function that will be called
+ * when a Modem Status packet is received
+ *
+ * @param function function pointer with the callback function
+ */
+ void register_modem_status_cb(modem_status_cb_t function);
+
+ /** unregister_modem_status_cb - removes the Modem Status reception callback */
+ void unregister_modem_status_cb();
+
+ protected:
+
+ enum RadioProtocol {
+ None,
+ ZigBee,
+ Raw_802_15_4,
+#ifdef EXTRA_XBEE_PROTOCOLS
+ XBeeWiFi,
+ DigiMesh,
+ SmartEnergy,
+ DigiPoint,
+ ZNet,
+#endif
+ };
+ /** send_byte_escaping_if - sends a byte, through the serial interface, to
+ * the radio, escaping the byte if the working mode of the radio is API2.
+ *
+ * @param line PWM line being set
+ * @param data the byte that will be send to radio
+ */
+ void send_byte_escaping_if(uint8_t data);
+
+ /** uart_read_cb - serial interface callback, called when data is received on
+ * the serial port. The function parses the incoming data and, when a good
+ * frame is detected, saves it in the frame list
+ */
+ void uart_read_cb();
+
+ /** get_this_api_frame - searches in the FrameBuffer for an incoming frame
+ * with frameid equal to id and frame type equal to type
+ * or type2. If after timeout the frame hast not been found,
+ * returns.
+ *
+ * @param id id of the frame we are looking for.
+ * @param type tye type we expect the frame to be.
+ * @param type2 alternative valid type, if provided.
+ * @returns a pointer to the frame found in the FrameBuffer or a null pointer if
+ * the frame has not been found and the timeout expired.
+ */
+ ApiFrame * get_this_api_frame(uint8_t id, ApiFrame::ApiFrameType type,
+ ApiFrame::ApiFrameType type2 = ApiFrame::Invalid);
+
+ /** send_api_frame - method to send, over the serial port, an API frame
+ *
+ * @param frame pointer to the frame that will be sent.
+ */
+#if defined(UNIT_TEST)
+ virtual
+#endif
+ void send_api_frame(ApiFrame *frame);
+
+ /** update_radio_status - method called when a modem status frame is received
+ * to update the internal status variables of the library.
+ * @note This is not a pure virtual function because it can be called while
+ * the object is being constructed and we need the implementation of the
+ * base class.
+ *
+ * @param status byte with the status received in the modem status frame
+ */
+ virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+ /** Method used internaly by the derived classes to transmit data to
+ * remote nodes, waiting for the answer from the device
+ *
+ * @param frame frame that will be sent to the radio (have to be a
+ * proper transmit frame
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ TxStatus send_data(ApiFrame *frame);
+
+ /** send_at_cmd - sends an AT command to the radio and waits for the response.
+ *
+ * @param frame api frame with the command and command params.
+ * @param buf pointer where the param response (n bytes) will be stored.
+ * @param len pointer where the number of bytes of the param response will be stored.
+ * @param radio_location radio location, either RadioLocal or RadioRemote.
+ * @param reverse reverse the byte ordering of the response saved in buf.
+ * @returns the command response status.
+ */
+ AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame,
+ uint8_t *const buf, uint16_t *const len, RadioLocation radio_location = RadioLocal, bool reverse = true);
+
+ /* send_at_cmd - methods used internally by other methods */
+ AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame);
+ AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint8_t *data);
+ AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint16_t *data);
+ AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint32_t *data);
+
+#if defined(ENABLE_PM_SUPPORT)
+ /** Sets the radio into low power mode. This method is used by enter_sleep_mode() */
+ RadioStatus sleep_now();
+#endif /* defined(ENABLE_PM_SUPPORT) */
+
+ /** register_frame_handler - registers an object to handle incoming frames from
+ * the radio.
+ * @note For any type of frame more than one handler can be registered and all
+ * of them are called, sequentially, when a frame of that type arrives.
+ *
+ * @param handler pointer to the frame handler object
+ * @returns the result of the registration
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus register_frame_handler(FrameHandler *const handler);
+
+ /** unregister_frame_handler - removes a previously registered frame handler
+ *
+ * @param handler pointer to the frame handler object
+ * @returns the result of the unregister operation
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus unregister_frame_handler(FrameHandler *const handler);
+
+ /** get_radio_protocol - returns the RF protocol that the connected module uses
+ * based on its firmware and hardware versions
+ *
+ * @returns a RadioProtocol enum.
+ */
+ RadioProtocol get_radio_protocol(void) const;
+
+ /** get_iosample - forces an io_sample read (reads all digital and analog inputs)
+ *
+ * @param remote remote device
+ * @param io_sample buffer where the io_sample response is copied
+ * @param len pointer where the length of the io_sample response is stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_iosample(const RemoteXBee& remote, uint8_t * const io_sample, uint16_t * const len);
+
+ void _get_remote_node_by_id(const char * const node_id, uint64_t * addr64, uint16_t * addr16);
+
+ /** Operating mode of the module (API1, API2,...) */
+ RadioMode _mode;
+
+ /** Type of radio, mainly the hardware version, but may differ in some cases */
+ RadioType _type;
+
+ /** Hardware version value of the radio */
+ uint16_t _hw_version;
+
+ /** Firmware version value of the radio */
+ uint16_t _fw_version;
+
+ /** Timeout in ms for sync operations (when we wait for a response) */
+ uint16_t _timeout_ms;
+
+ /** Device 64 bit address (SH, SL) */
+ uint64_t _dev_addr64;
+
+ /** Device 16 bit address (MY) */
+ uint16_t _dev_addr16;
+
+ /** Serial Interface, use RawSerial as we dont use the streams */
+ RawSerial *_uart;
+
+ /** IO connected to the radio reset line */
+ DigitalOut *_reset;
+
+ /** Transmit options byte */
+ uint8_t _tx_options;
+
+ /** Broadcast radius, number of hops a broadcast transmission can occur.
+ * When set to 0 it will use the maximum */
+ uint8_t _bc_radius;
+ /** Array of frame handler pointers. We use an array instead of a vector or other
+ * data structure to save memory and avoid dynamic memory allocation, to avoid
+ * memory fragmentation */
+ FrameHandler *_fhandlers[MAX_FRAME_HANDLERS];
+
+ /** Hardware reset counter, automatically updated by the library */
+ volatile uint16_t _hw_reset_cnt;
+
+ /** Watchdog reset counter, automatically updated by the library */
+ volatile uint16_t _wd_reset_cnt;
+
+ uint16_t _reset_timeout;
+
+ /** Frame handler used for the Modem Status packets. Automatically registered when a callback
+ * function is registered */
+ FH_ModemStatus *_modem_status_handler;
+
+ /** Latest modem status received */
+ AtCmdFrame::ModemStatus _modem_status;
+
+ /** Library is initializing */
+ bool _initializing;
+
+#if defined(ENABLE_PM_SUPPORT)
+ /* Power Management mode used by the radio */
+ PmMode _pm_mode;
+ /** IO connected to the radio on_sleep line */
+ InterruptIn *_on_sleep;
+ /** IO connected to the radio sleep_req line */
+ DigitalOut *_sleep_req;
+#endif
+};
+
+} /* namespace XBeeLib */
+
+#endif /* defined(__DIGI_RADIO_H_) */
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee802/XBee802.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,572 @@
+/**
+ * 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;
+}
+
+RemoteXBee802 XBee802::get_remote_node_by_id(const char * const node_id)
+{
+ uint64_t addr64;
+ uint16_t addr16;
+ _get_remote_node_by_id(node_id, &addr64, &addr16);
+ return RemoteXBee802(addr64, addr16);
+}
+
+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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee802/XBee802.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,357 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_802_H_)
+#define __XBEE_802_H_
+
+#include "FrameHandlers/FH_AtCmdResp.h"
+#include "FrameHandlers/FH_RxPacket802.h"
+#include "FrameHandlers/FH_IoDataSample802.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/** Class for XBee ZigBee modules, derived from XBee */
+class XBee802 : public XBee
+{
+ public:
+
+ /**
+ * IoLine for XBee802 Modules
+ */
+ enum IoLine {
+ DIO0_AD0 = 0, /**< DIO0_AD0 pin */
+ DIO1_AD1 = 1, /**< DIO1_AD1 pin */
+ DIO2_AD2 = 2, /**< DIO2_AD2 pin */
+ DIO3_AD3 = 3, /**< DIO3_AD3 pin */
+ DIO4_AD4 = 4, /**< DIO4_AD4 pin */
+ DIO5_AD5 = 5, /**< DIO5_AD5 pin */
+ DIO6 = 6, /**< DIO6 pin */
+ DIO7 = 7, /**< DIO7 pin */
+ DI8 = 8, /**< DI8 pin */
+ PWM0, /**< PWM0 pin */
+ PWM1 /**< PWM1 pin */
+ };
+
+ /** Class constructor
+ * @param tx the TX pin of the UART that will interface the XBee module
+ * @param rx the RX pin of the UART that will interface the XBee module
+ * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+ * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+ * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+ * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+ * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+ */
+ XBee802(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+ /** Class destructor */
+ virtual ~XBee802();
+
+ /** init - initializes object
+ * This function must be called just after creating the object so it initializes internal data.
+ * @returns
+ * Success if the module has been properly initialized and is ready to process data.
+ * Failure otherwise.
+ */
+ RadioStatus init();
+
+ /** set_panid - sets the 16 bit PAN ID.
+ *
+ * @param panid the PAN ID value that will be set on the radio
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_panid(uint16_t panid);
+
+ /** get_panid - gets the configured 16 bit PAN ID
+ *
+ * @param panid pointer where the read PAN ID value will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_panid(uint16_t * const panid);
+
+ /** set_channel - sets the network channel number
+ *
+ * @param channel the channel in which the radio operates. Range is 0x0B - 0x1A for XBee and 0x0C - 0x17 for XBee-PRO.
+ * The Center Frequency = 2.405 + (CH - 11) * 5 MHz
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_channel(uint8_t channel);
+
+ /** get_panid - gets the network channel number
+ *
+ * @param channel pointer where the channel value will be stored.
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_channel(uint8_t * const channel);
+
+ /** set_network_address - sets the 16 bit network address of the device
+ *
+ * @param addr the device 16bit network address (0x0 - 0xFFFF)
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_network_address(uint16_t addr);
+
+ /** register_node_discovery_cb - registers the callback function that will be called
+ * when the responses to the node discovery command arrive
+ *
+ * @param function function pointer with the callback function
+ */
+ void register_node_discovery_cb(node_discovery_802_cb_t function);
+
+ /** unregister_node_discovery_cb - removes the node discovery callback */
+ void unregister_node_discovery_cb();
+
+ /** register_receive_cb - registers the callback function that will be called
+ * when a rx packet is received
+ *
+ * @param function function pointer with the callback function
+ */
+ void register_receive_cb(receive_802_cb_t function);
+
+ /** unregister_receive_cb - removes the rx packet callback */
+ void unregister_receive_cb();
+
+ /** register_io_sample_cb - registers the callback function that will be called
+ * when a IO Sample Data packet is received
+ *
+ * @param function function pointer with the callback function
+ */
+ void register_io_sample_cb(io_data_cb_802_t function);
+
+ /** unregister_io_sample_cb - removes the IO Sample Data reception callback */
+ void unregister_io_sample_cb();
+
+ /*********************** send_data member methods ************************/
+ /** send_data - sends data to a remote device waiting for the packet
+ * answer with the result of the operation
+ *
+ * @param remote remote device
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len);
+
+ /** get_remote_node_by_id - searches for a device in the network with the specified Node Identifier.
+ *
+ * @param node_id node id of the device we are looking for
+ * @returns a RemoteXBee802 with the 16-bit and 64-bit address of the remote device whose node id matches with the parameter.
+ * If node is not found, the returned object will have invalid addresses (RemoteXBee802::is_valid() will return false).
+ */
+ RemoteXBee802 get_remote_node_by_id(const char * const node_id);
+
+ /* Allow using XBee::set_param() methods for local radio from this class */
+ using XBee::set_param;
+
+ /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be set.
+ * @param data the parameter value (4 bytes) to be set.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data);
+
+ /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be set.
+ * @param the parameter value byte array (len bytes) to be set.
+ * @param len number of bytes of the parameter value.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+ /* Allow using XBee::get_param() methods for local radio from this class */
+ using XBee::get_param;
+
+ /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be get.
+ * @param data pointer where the param value (4 bytes) will be stored.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data);
+
+ /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be get.
+ * @param data pointer where the param value (n bytes) will be stored.
+ * @param len pointer where the number of bytes of the param value will be stored.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len);
+
+ /************************* IO member methods **************************/
+ /** set_pin_config - configures a radio IO line
+ *
+ * @param remote remote device
+ * @param line IO line being configured
+ * @param mode configuration mode for the selected line
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode);
+
+ /** get_pin_config - gets the configuration of a radio IO line
+ *
+ * @param remote remote device
+ * @param line IO line being read to get its configuration
+ * @param mode pointer where the configuration will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode);
+
+ /** set_dio - sets to low/high a DIO line
+ *
+ * @param remote remote device
+ * @param line DIO line being set
+ * @param val value that will be set in the DIO line
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_dio(const RemoteXBee& remote, IoLine line, DioVal val);
+
+ /** get_dio - read the value of a DIO configured as digital input
+ *
+ * @param remote remote device
+ * @param line DIO line being read
+ * @param val pointer where the DIO value read will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val);
+
+ /** get_adc - read the value of the espcified ADC line
+ *
+ * @param remote remote device
+ * @param line ADC line being read
+ * @param val pointer where the value read from the ADC will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val);
+
+ /** set_pwm - sets the duty cycle of a PWM line
+ *
+ * @param remote remote device
+ * @param line PWM line being set
+ * @param duty_cycle duty cycle that will be set in the PWM line
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle);
+
+ /** set_pin_pull_up - enables or disables the internal pull-up resistor of a line
+ *
+ * @param remote remote device
+ * @param line line being configured for pull-up
+ * @param enable whether to enable the internal pull-up resistor.
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable);
+
+ /** enable_dio_change_detection - enables or disables the notification when a change is detected in a digital input line.
+ * In other words, it will force an IO Sample transmission when the DIO state changes. Only for DIO0 to DIO7.
+ *
+ * @param remote remote device
+ * @param line line being configured for pull-up
+ * @param enable whether to enable the internal pull-up resistor.
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable);
+
+/* TODO: With current firmware ATM0 fails: Returns just OK and sets pwm to 0 */
+#ifdef GET_PWM_AVAILABLE
+ /** get_pwm - gets the duty cycle of a PWM line
+ *
+ * @param remote remote device
+ * @param line PWM line being read
+ * @param duty_cycle pointer where the value of the duty cycle read from
+ * the PWM line will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_pwm(const RemoteXBee& remote, IoLine line, float * const duty_cycle);
+#endif
+
+ protected:
+ inline bool is_PRO()
+ {
+ return (_hw_version & 0xFF00U) == 0x1800U;
+ }
+
+ /** Synchronization lost counter, automatically updated by the library */
+ volatile uint16_t _sync_lost_cnt;
+
+ /** Frame handler used for the node discovery. Registered when a callback function
+ * is registered */
+ FH_NodeDiscovery802 *_nd_handler;
+
+ /** Frame handler used for the rx 64 bit packets. Automatically registered when a callback
+ * function is registered */
+ FH_RxPacket64b802 *_rx_64b_handler;
+
+ /** Frame handler used for the rx 16 bit packets. Automatically registered when a callback
+ * function is registered */
+ FH_RxPacket16b802 *_rx_16b_handler;
+
+ /** Frame handler used for the 64 bit IO Data Samples packets. Automatically registered when a callback
+ * function is registered */
+ FH_IoDataSampe64b802 *_io_data_64b_handler;
+
+ /** Frame handler used for the 16 bit IO Data Samples packets. Automatically registered when a callback
+ * function is registered */
+ FH_IoDataSampe16b802 *_io_data_16b_handler;
+
+ /** Method called directly by the library when a modem status frame is received to
+ * update the internal status variables */
+ virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+ /* Allow using XBee::send_data() methods from this class */
+ using XBee::send_data;
+
+ private:
+
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __XBEE_802_H_ */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XBeeLib.h Fri May 08 11:50:56 2015 +0200 @@ -0,0 +1,39 @@ +/** + * Digi XBee library for mbed. This is the only header you have to include from your application to use the library. + * + * 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. + */ + +/** @file + */ + +#if !defined(__XBEE_H_) +#define __XBEE_H_ + +#define XB_LIBRARY_VERSION 0x00010500U +#define XB_MAJOR_VERSION ((XB_LIBRARY_VERSION >> 24) & 0xFFU) +#define XB_MINOR_VERSION ((XB_LIBRARY_VERSION >> 16) & 0xFFU) +#define XB_PATCH_LEVEL ((XB_LIBRARY_VERSION >> 8) & 0xFFU) +#define XB_BUILD_ID (XB_LIBRARY_VERSION & 0xFFU) + +/**/ +#define XB_LIB_BANNER "\r\n\r\nmbed Digi Radio library v%d.%d.%d\r\n", \ + XB_MAJOR_VERSION, XB_MINOR_VERSION, XB_PATCH_LEVEL + +#include "XBeeZB/XBeeZB.h" +#include "IO/IOSampleZB.h" +#include "XBee802/XBee802.h" +#include "IO/IOSample802.h" +#include "XBee/Addresses.h" +#include "RemoteXBee/RemoteXBee.h" + +#endif /* __XBEE_H_ */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBeeZB/XBeeZB.cpp Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,662 @@
+/**
+ * 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 "XBeeZB.h"
+#include "IO/IOSampleZB.h"
+#include "Frames/ZigbeeFrames.h"
+
+using namespace XBeeLib;
+
+/* Class constructor */
+XBeeZB::XBeeZB(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+ XBee(tx, rx, reset, rts, cts, baud), _nw_role(UnknownRole), _joined_network(false),
+ _vcc_exceeded_cnt(0), _broadcast_radious(0), _nd_handler(NULL),
+ _rx_pkt_handler(NULL), _io_data_handler(NULL)
+{
+ _reset_timeout = RESET_TIMEOUT_MS;
+}
+
+RadioStatus XBeeZB::init()
+{
+ RadioStatus retval = XBee::init();
+ /* Determine the role of this device in the network */
+ switch(_fw_version & 0xFF00) {
+ case 0x2100: _nw_role = Coordinator; break;
+ case 0x2300: _nw_role = Router; break;
+ case 0x2900: _nw_role = EndDevice; break;
+ default: _nw_role = UnknownRole; break;
+ }
+
+ const RadioProtocol radioProtocol = get_radio_protocol();
+ if (radioProtocol != ZigBee) {
+ digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", ZigBee, radioProtocol);
+ retval = Failure;
+ }
+ assert(radioProtocol == ZigBee);
+
+ return retval;
+}
+
+/* Class destructor */
+XBeeZB::~XBeeZB()
+{
+ unregister_node_discovery_cb();
+ unregister_receive_cb();
+ unregister_io_sample_cb();
+}
+
+RadioStatus XBeeZB::set_channel_mask(uint16_t chmask)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("SC", chmask);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ return Success;
+}
+
+RadioStatus XBeeZB::get_channel_mask(uint16_t * const chmask)
+{
+ if (chmask == NULL) {
+ return Failure;
+ }
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ uint32_t var32;
+ cmdresp = get_param("SC", &var32);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ *chmask = var32;
+ return Success;
+}
+
+RadioStatus XBeeZB::set_panid(uint64_t panid)
+{
+ uint8_t panid_u8[8];
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ rmemcpy(panid_u8, (const uint8_t *) &panid, sizeof panid_u8);
+
+ cmdresp = set_param("ID", panid_u8, sizeof panid_u8);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ return Success;
+}
+
+RadioStatus XBeeZB::get_operating_panid(uint64_t * const opanid)
+{
+ if (opanid == NULL) {
+ return Failure;
+ }
+ uint8_t opanid_u8[8];
+ uint16_t len = sizeof opanid_u8;
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = get_param("OP", opanid_u8, &len);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ if (len != sizeof opanid_u8) {
+ digi_log(LogLevelError, "XBeeZB::get_operating_panid: Read %d bytes instead of %d for OP", len, sizeof opanid_u8);
+ return Failure;
+ }
+ rmemcpy((uint8_t *)opanid, opanid_u8, len);
+ return Success;
+}
+
+RadioStatus XBeeZB::get_configured_panid(uint64_t * const panid)
+{
+ if (panid == NULL) {
+ return Failure;
+ }
+ uint8_t panid_u8[8];
+ uint16_t len = sizeof panid_u8;
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = get_param("ID", panid_u8, &len);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ if (len != sizeof panid_u8) {
+ digi_log(LogLevelError, "XBeeZB::get_configured_panid: Read %d bytes instead of %d for ID", len, sizeof panid_u8);
+ return Failure;
+ }
+ rmemcpy((uint8_t *)panid, panid_u8, len);
+ return Success;
+}
+
+RadioStatus XBeeZB::set_panid(const RemoteXBee& remote, uint64_t panid)
+{
+ uint8_t panid_u8[8];
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ rmemcpy(panid_u8, (const uint8_t *) &panid, sizeof panid_u8);
+
+ cmdresp = set_param(remote, "ID", panid_u8, sizeof panid_u8);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ return Success;
+}
+
+RadioStatus XBeeZB::get_operating_panid(const RemoteXBee& remote, uint64_t * const opanid)
+{
+ if (opanid == NULL) {
+ return Failure;
+ }
+ uint8_t opanid_u8[8];
+ uint16_t len = sizeof opanid_u8;
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = get_param(remote, "OP", opanid_u8, &len);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ if (len != sizeof opanid_u8) {
+ digi_log(LogLevelError, "XBeeZB::get_operating_panid: Read %d bytes instead of %d for OP", len, sizeof opanid_u8);
+ return Failure;
+ }
+ rmemcpy((uint8_t *)opanid, opanid_u8, len);
+ return Success;
+}
+
+RadioStatus XBeeZB::get_configured_panid(const RemoteXBee& remote, uint64_t * const panid)
+{
+ if (panid == NULL) {
+ return Failure;
+ }
+ uint8_t panid_u8[8];
+ uint16_t len = sizeof panid_u8;
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = get_param(remote, "ID", panid_u8, &len);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ if (len != sizeof panid_u8) {
+ digi_log(LogLevelError, "XBeeZB::get_configured_panid: Read %d bytes instead of %d for ID", len, sizeof panid_u8);
+ return Failure;
+ }
+ rmemcpy((uint8_t *)panid, panid_u8, len);
+ return Success;
+}
+
+RadioStatus XBeeZB::check_for_coordinator_at_start(bool enable)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("JV", (uint8_t)enable);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ return Success;
+}
+
+RadioStatus XBeeZB::enable_network_encryption(bool enable)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("EE", enable);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ return Success;
+}
+
+RadioStatus XBeeZB::set_encryption_key(const uint8_t * const key, const uint16_t length)
+{
+ if (key == NULL || length == 0) {
+ return Failure;
+ }
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("NK", key, length);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ return Success;
+}
+
+RadioStatus XBeeZB::set_tc_link_key(const uint8_t * const key, const uint16_t length)
+{
+ if (key == NULL || length == 0) {
+ return Failure;
+ }
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("KY", key, length);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ return Success;
+}
+
+RadioStatus XBeeZB::set_encryption_options(const uint8_t options)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+
+ cmdresp = set_param("EO", options);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk)
+ return Failure;
+ return Success;
+}
+
+void XBeeZB::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+ /* Update the radio status variables */
+ if (modem_status == AtCmdFrame::HwReset) {
+ _hw_reset_cnt++;
+ _joined_network = false;
+ }
+ else if (modem_status == AtCmdFrame::WdReset) {
+ _wd_reset_cnt++;
+ _joined_network = false;
+ }
+ else if (modem_status == AtCmdFrame::JoinedNW)
+ _joined_network = true;
+ else if (modem_status == AtCmdFrame::Disassociated)
+ _joined_network = false;
+ else if (modem_status == AtCmdFrame::VccExceeded)
+ _vcc_exceeded_cnt++;
+
+ _modem_status = modem_status;
+
+ digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
+}
+
+TxStatus XBeeZB::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len)
+{
+ if (!remote.is_valid_addr64b())
+ return TxStatusInvalidAddr;
+
+ const uint64_t remote64 = remote.get_addr64();
+ const uint16_t remote16 = remote.get_addr16();
+
+ TxFrameZB frame = TxFrameZB(remote64, remote16, _broadcast_radious,
+ _tx_options, data, len);
+ return send_data(&frame);
+}
+
+TxStatus XBeeZB::send_data(uint64_t remote64, const uint8_t *const data, uint16_t len)
+{
+ TxFrameZB frame = TxFrameZB(remote64, ADDR16_UNKNOWN, _broadcast_radious,
+ _tx_options, data, len);
+ return send_data(&frame);
+}
+
+TxStatus XBeeZB::send_data(uint64_t remote64, uint16_t remote16,
+ const uint8_t *const data, uint16_t len)
+{
+ TxFrameZB frame = TxFrameZB(remote64, remote16, _broadcast_radious,
+ _tx_options, data, len);
+ return send_data(&frame);
+}
+
+TxStatus XBeeZB::send_data(const RemoteXBee& remote, uint8_t source_ep,
+ uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
+ const uint8_t *const data, uint16_t len)
+{
+ if (!remote.is_valid_addr64b())
+ return TxStatusInvalidAddr;
+
+ const uint64_t remote64 = remote.get_addr64();
+ const uint16_t remote16 = remote.get_addr16();
+
+ TxFrameZB frame = TxFrameZB(remote64, remote16, source_ep, dest_ep,
+ cluster_id, profile_id, _broadcast_radious,
+ _tx_options, data, len);
+ return send_data(&frame);
+}
+
+TxStatus XBeeZB::send_data(uint64_t remote64, uint16_t remote16, uint8_t source_ep,
+ uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
+ const uint8_t *const data, uint16_t len)
+{
+ TxFrameZB frame = TxFrameZB(remote64, remote16, source_ep, dest_ep,
+ cluster_id, profile_id, _broadcast_radious,
+ _tx_options, data, len);
+ return send_data(&frame);
+}
+
+TxStatus XBeeZB::send_data_to_coordinator(const uint8_t *const data, uint16_t len)
+{
+ const uint64_t remaddr = ADDR64_COORDINATOR;
+
+ TxFrameZB frame = TxFrameZB(remaddr, ADDR16_UNKNOWN, _broadcast_radious,
+ _tx_options, data, len);
+ return send_data(&frame);
+}
+
+RemoteXBeeZB XBeeZB::get_remote_node_by_id(const char * const node_id)
+{
+ uint64_t addr64;
+ uint16_t addr16;
+ _get_remote_node_by_id(node_id, &addr64, &addr16);
+ return RemoteXBeeZB(addr64, addr16);
+}
+
+NetworkRole XBeeZB::get_network_role()
+{
+ return _nw_role;
+}
+
+bool XBeeZB::is_joined()
+{
+ return _joined_network;
+}
+
+void XBeeZB::register_node_discovery_cb(node_discovery_zb_cb_t function)
+{
+ if (_nd_handler == NULL) {
+ _nd_handler = new FH_NodeDiscoveryZB();
+ register_frame_handler(_nd_handler);
+ }
+ _nd_handler->register_node_discovery_cb(function);
+}
+
+void XBeeZB::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 XBeeZB::register_receive_cb(receive_zb_cb_t function)
+{
+ if (_rx_pkt_handler == NULL) {
+ _rx_pkt_handler = new FH_RxPacketZB();
+ register_frame_handler(_rx_pkt_handler);
+ }
+ _rx_pkt_handler->register_receive_cb(function);
+}
+
+void XBeeZB::unregister_receive_cb()
+{
+ if (_rx_pkt_handler != NULL) {
+ _rx_pkt_handler->unregister_receive_cb();
+ unregister_frame_handler(_rx_pkt_handler);
+ delete _rx_pkt_handler;
+ _rx_pkt_handler = NULL; /* as delete does not set to NULL */
+ }
+}
+
+void XBeeZB::register_io_sample_cb(io_data_cb_zb_t function)
+{
+ if (_io_data_handler == NULL) {
+ _io_data_handler = new FH_IoDataSampeZB();
+ register_frame_handler(_io_data_handler);
+ }
+ _io_data_handler->register_io_data_cb(function);
+}
+
+void XBeeZB::unregister_io_sample_cb()
+{
+ if (_io_data_handler != NULL) {
+ _io_data_handler->unregister_io_data_cb();
+ unregister_frame_handler(_io_data_handler);
+ delete _io_data_handler;
+ _io_data_handler = NULL; /* as delete does not set to NULL */
+ }
+}
+
+AtCmdFrame::AtCmdResp XBeeZB::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data)
+{
+ if (!remote.is_valid_addr64b())
+ return AtCmdFrame::AtCmdRespInvalidAddr;
+
+ const uint64_t remote64 = remote.get_addr64();
+ const uint16_t remote16 = remote.get_addr16();
+ uint16_t len = sizeof *data;
+ AtCmdFrame::AtCmdResp atCmdResponse;
+
+ AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
+ atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote);
+
+ if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data)
+ atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+
+ return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBeeZB::set_param(const RemoteXBee& remote, const char * const param, uint32_t data)
+{
+ if (!remote.is_valid_addr64b())
+ return AtCmdFrame::AtCmdRespInvalidAddr;
+
+ const uint64_t remote64 = remote.get_addr64();
+ const uint16_t remote16 = remote.get_addr16();
+
+ AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data);
+ return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+}
+
+AtCmdFrame::AtCmdResp XBeeZB::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len)
+{
+ if (!remote.is_valid_addr64b())
+ return AtCmdFrame::AtCmdRespInvalidAddr;
+
+ const uint64_t remote64 = remote.get_addr64();
+ const uint16_t remote16 = remote.get_addr16();
+
+ AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data, len);
+ return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+}
+
+AtCmdFrame::AtCmdResp XBeeZB::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len)
+{
+
+ if (!remote.is_valid_addr64b())
+ return AtCmdFrame::AtCmdRespInvalidAddr;
+
+ const uint64_t remote64 = remote.get_addr64();
+ const uint16_t remote16 = remote.get_addr16();
+
+ AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
+ return send_at_cmd(&cmd_frame, data, len, RadioRemote, false);
+}
+
+static void get_dio_cmd(XBeeZB::IoLine line, char * const iocmd)
+{
+ if (line >= XBeeZB::DIO10) {
+ iocmd[0] = 'P';
+ iocmd[1] = '0' + line - XBeeZB::DIO10;
+ } else {
+ iocmd[0] = 'D';
+ iocmd[1] = '0' + line;
+ }
+ iocmd[2] = '\0';
+}
+
+RadioStatus XBeeZB::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 XBeeZB::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 XBeeZB::set_dio(const RemoteXBee& remote, IoLine line, DioVal val)
+{
+ if (val == Low)
+ return set_pin_config(remote, line, DigitalOutLow);
+ else
+ return set_pin_config(remote, line, DigitalOutHigh);
+}
+
+RadioStatus XBeeZB::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)
+{
+ uint8_t io_sample[MAX_IO_SAMPLE_BUF_LEN];
+ uint16_t len;
+
+ RadioStatus resp = get_iosample(remote, io_sample, &len);
+ if (resp != Success)
+ return resp;
+
+ IOSampleZB ioSample = IOSampleZB(io_sample, len);
+ return ioSample.get_dio(line, val);
+}
+
+RadioStatus XBeeZB::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)
+{
+ uint8_t io_sample[MAX_IO_SAMPLE_BUF_LEN];
+ uint16_t len;
+
+ switch (line) {
+ case SUPPLY_VOLTAGE:
+ case DIO3_AD3:
+ case DIO2_AD2:
+ case DIO1_AD1:
+ case DIO0_AD0:
+ break;
+ default:
+ 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;
+
+ IOSampleZB ioSample = IOSampleZB(io_sample, len);
+ return ioSample.get_adc(line, val);
+}
+
+static uint16_t get_dio_pr_mask(XBeeZB::IoLine line)
+{
+ switch (line) {
+ case XBeeZB::DIO4:
+ return (1 << 0);
+ case XBeeZB::DIO3_AD3:
+ return (1 << 1);
+ case XBeeZB::DIO2_AD2:
+ return (1 << 2);
+ case XBeeZB::DIO1_AD1:
+ return (1 << 3);
+ case XBeeZB::DIO0_AD0:
+ return (1 << 4);
+ case XBeeZB::DIO6:
+ return (1 << 5);
+ case XBeeZB::DIO5:
+ return (1 << 8);
+ case XBeeZB::DIO12:
+ return (1 << 10);
+ case XBeeZB::DIO10:
+ return (1 << 11);
+ case XBeeZB::DIO11:
+ return (1 << 12);
+ case XBeeZB::DIO7:
+ return (1 << 13);
+ default:
+ return 0;
+ }
+}
+
+RadioStatus XBeeZB::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable)
+{
+ AtCmdFrame::AtCmdResp cmdresp;
+ uint32_t var32;
+ uint16_t pr;
+
+ cmdresp = get_param(remote, "PR", &var32);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ pr = var32;
+
+ const uint16_t dio_mask = get_dio_pr_mask(line);
+ if (dio_mask == 0) {
+ digi_log(LogLevelError, "XBeeZB::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 uint16_t get_dio_ic_mask(XBeeZB::IoLine line)
+{
+ if (line < XBeeZB::DIO12) {
+ return (1 << line);
+ }
+ return 0;
+}
+
+RadioStatus XBeeZB::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable)
+{
+ if (line > DIO11) {
+ digi_log(LogLevelError, "XBeeZB::enable_dio_change_detection: pin not supported (%d)\r\n", line);
+ return Failure;
+ }
+
+ AtCmdFrame::AtCmdResp cmdresp;
+ uint32_t var32;
+ uint16_t ic;
+
+ cmdresp = get_param(remote, "IC", &var32);
+ if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+ return Failure;
+ }
+ ic = var32;
+
+ const uint16_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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/XBeeZB/XBeeZB.h Fri May 08 11:50:56 2015 +0200
@@ -0,0 +1,509 @@
+/**
+ * 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
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_ZB_H_)
+#define __XBEE_ZB_H_
+
+#include "XBee/XBee.h"
+#include "FrameHandlers/FH_AtCmdResp.h"
+#include "FrameHandlers/FH_RxPacketZB.h"
+#include "FrameHandlers/FH_IoDataSampleZB.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/** Class for XBee ZigBee modules, derived from XBee */
+class XBeeZB : public XBee
+{
+ public:
+
+ /**
+ * IoLine for XBeeZB Modules
+ */
+ enum IoLine {
+ DIO0_AD0 = 0, /**< DIO0_AD0 pin */
+ DIO1_AD1 = 1, /**< DIO1_AD1 pin */
+ DIO2_AD2 = 2, /**< DIO2_AD2 pin */
+ DIO3_AD3 = 3, /**< DIO3_AD3 pin */
+ DIO4 = 4, /**< DIO4 pin */
+ DIO5 = 5, /**< DIO5 pin */
+ DIO6 = 6, /**< DIO6 pin */
+ DIO7 = 7, /**< DIO7 pin */
+ DIO10 = 10, /**< DIO10 pin */
+ DIO11 = 11, /**< DIO11 pin */
+ DIO12 = 12, /**< DIO12 pin */
+ SUPPLY_VOLTAGE = 7, /**< SUPPLY_VOLTAGE is not a real pin */
+ };
+
+ /** Class constructor
+ * @param tx the TX pin of the UART that will interface the XBee module
+ * @param rx the RX pin of the UART that will interface the XBee module
+ * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+ * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+ * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+ * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+ * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+ */
+ XBeeZB(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+ /** Class destructor */
+ virtual ~XBeeZB();
+
+ /** init- initializes object
+ * This function must be called just after creating the object so it initializes internal data.
+ * @returns
+ * Success if the module has been properly initialized and is ready to process data.
+ * Failure otherwise.
+ */
+ RadioStatus init();
+
+ /** set_panid - sets the 64bit extended PAN ID.
+ *
+ * @note on ZigBee devices, if set to 0, the coordinator will select a random PAN ID
+ * and the routers will join any extended PAN ID
+ * @param panid the PAN ID value that will be set on the radio
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_panid(uint64_t panid);
+
+ /** get_configured_panid - gets the configured PAN ID, as it was set by @ref set_panid().
+ *
+ * @note on ZigBee devices, if set to 0, the coordinator will select a random PAN ID
+ * and the routers will join any extended PAN ID
+ * @param panid pointer where the configured PAN ID will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_configured_panid(uint64_t * const panid);
+
+ /** get_operating_panid - gets the operating 64bit extended PAN ID the module is running on. This is useful to determine the PAN ID when the ID parameter (@ref set_panid) is set to 0x00.
+ *
+ * @param panid pointer where the operating PAN ID will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_operating_panid(uint64_t * const panid);
+
+ /** set_panid - sets the 64bit extended PAN ID.
+ *
+ * @note on ZigBee devices, if set to 0, the coordinator will select a random PAN ID
+ * and the routers will join any extended PAN ID
+ * @param remote remote device
+ * @param panid the PAN ID value that will be set on the radio
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_panid(const RemoteXBee& remote, uint64_t panid);
+
+ /** get_configured_panid - gets the configured PAN ID in a remote node, as it was set by @ref set_panid()
+ *
+ * @note on ZigBee devices, if set to 0, the coordinator will select a random PAN ID
+ * and the routers will join any extended PAN ID
+ *
+ * @param remote remote device
+ * @param panid pointer where the configured PAN ID will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_configured_panid(const RemoteXBee& remote, uint64_t * const panid);
+
+ /** get_operating_panid - gets the operating 64bit extended PAN ID in which a remote node is running on. This is useful to determine the PAN ID when the ID parameter (@ref set_panid) is set to 0x00.
+ *
+ * @param remote remote device
+ * @param panid pointer where the operating PAN ID will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_operating_panid(const RemoteXBee& remote, uint64_t * const panid);
+
+ /** set_channel_mask - sets the channel mask in which the module will scan for the PAN ID (if it is a router or end-device) or start the network (if it is a coordinator).
+ * It should be set to the minimum available set of channels of all nodes in the network. Refer to "SC" parameter in the product manual for more information.
+ *
+ * @param chmask bit field list of channels to scan (router/end-devices) or to choose when starting a network (coordinator). Bit 0 is for channel 0x0B and bit 15 for channel 0x1A.
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_channel_mask(uint16_t const chmask);
+
+ /** get_channel_mask - gets the channel mask in which the module will scan for the PAN ID (if it is a router or end-device) or start the network (if it is a coordinator).
+ *
+ * @param chmask pointer to where the configured channel mask will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_channel_mask(uint16_t * const chmask);
+
+ /** check_for_coordinator_at_start - (Routers only) If enabled, a router will verify the coordinator is on its operating channel when joining or coming up from a power cycle.
+ * If a coordinator is not detected, the router will leave its current channel and attempt to join a new PAN. If JV=0, the router will continue operating on its current channel even if a coordinator is not detected.
+ *
+ * @param enable whether to enable this feature or not
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus check_for_coordinator_at_start(bool enable);
+
+ /** enable_network_encryption - Enable network encryption.
+ *
+ * @param enable whether to enable this feature or not
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus enable_network_encryption(bool enable);
+
+ /** set_encryption_key - Set the 128-bit AES network encryption key. If set to 0 (default), the module will select a random network key.
+ * It is not recommended to set the key programmatically, because it could be read through the raw serial port bits.
+ * @param key pointer to the 128-bit AES key
+ * @param length size of the buffer pointed by 'key'
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_encryption_key(const uint8_t * const key, const uint16_t length);
+
+ /** set_tc_link_key - Set the Trust Center 128-bit AES link key. Setting it to 0 will cause the coordinator to transmit the network key in the clear to joining devices, and will cause joining devices to acquire the network key in the clear when joining.
+ * It is not recommended to set the key programmatically, because it could be read through the raw serial port bits.
+ * @param key pointer to the 128-bit AES key
+ * @param length size of the buffer pointed by 'key'
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_tc_link_key(const uint8_t * const key, const uint16_t length);
+
+#define XBEE_ZB_ENC_OPT_SEND_KEY_ON_JOIN 0x01
+#define XBEE_ZB_ENC_OPT_USE_TRUST_CENTER 0x02
+ /** set_encryption_options - Configure options for encryption. Unused option bits should be set to 0. Options include:
+ * - XBEE_ZB_ENC_OPT_SEND_KEY_ON_JOIN - Send the security key unsecured over-the-air during joins
+ * - XBEE_ZB_ENC_OPT_USE_TRUST_CENTER - Use trust center (coordinator only)
+ * @param options bit mask with the encryption options
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_encryption_options(const uint8_t options);
+
+ /** register_node_discovery_cb - registers the callback function that will be called
+ * when the responses to the node discovery command arrive
+ *
+ * @param function function pointer with the callback function
+ */
+ void register_node_discovery_cb(node_discovery_zb_cb_t function);
+
+ /** unregister_node_discovery_cb - removes the node discovery callback */
+ void unregister_node_discovery_cb();
+
+ /** register_receive_cb - registers the callback function that will be called
+ * when a data packet is received
+ *
+ * @param function function pointer with the callback function
+ */
+ void register_receive_cb(receive_zb_cb_t function);
+
+ /** unregister_receive_cb - removes the rx packet callback */
+ void unregister_receive_cb();
+
+ /** register_io_sample_cb - registers the callback function that will be called
+ * when a IO Sample Data packet is received
+ *
+ * @param function function pointer with the callback function
+ */
+ void register_io_sample_cb(io_data_cb_zb_t function);
+
+ /** unregister_io_sample_cb - removes the IO Sample Data reception callback */
+ void unregister_io_sample_cb();
+
+ /** get_network_role - returns the role of this device in the ZigBee network
+ *
+ * @returns the role of this device
+ */
+ NetworkRole get_network_role();
+ /** */
+
+ /*********************** send_data member methods ************************/
+ /** send_data - sends data to a remote device waiting for the packet
+ * answer with the result of the operation
+ *
+ * @param remote remote device
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len);
+
+ /** send_data - sends data to a remote device waiting for the packet
+ * answer with the result of the operation
+ *
+ * @param remote64 64bit address of the remote device
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ TxStatus send_data(uint64_t remote64, const uint8_t *const data, uint16_t len);
+
+ /** send_data - sends data to a remote device waiting for the packet
+ * answer with the result of the operation. The main difference
+ * with the previous method is that includes the network address
+ * being more effective, not being neccesary to discover it
+ *
+ * @param remote64 64bit address of the remote device
+ * @param remote16 16bit network address of the remote device
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ TxStatus send_data(uint64_t remote64, uint16_t remote16,
+ const uint8_t *const data, uint16_t len);
+
+ /** send_data - sends data to a remote device waiting for the packet
+ * answer with the result of the operation. This method uses
+ * the explicit addressing frame, allowing to use source and
+ * destination end points and cluster and profile IDs
+ *
+ * @param remote remote device
+ * @param source_ep source end point
+ * @param dest_ep destination end point
+ * @param cluster_id cluster ID
+ * @param profile_id profile ID
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ TxStatus send_data(const RemoteXBee& remote, uint8_t source_ep,
+ uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
+ const uint8_t *const data, uint16_t len);
+
+ /** send_data - sends data to a remote device waiting for the packet
+ * answer with the result of the operation. This method uses
+ * the explicit addressing frame, allowing to use source and
+ * destination end points and cluster and profile IDs
+ *
+ * @param remote64 64bit address of the remote device
+ * @param remote16 16bit network address of the remote device
+ * @param source_ep source end point
+ * @param dest_ep destination end point
+ * @param cluster_id cluster ID
+ * @param profile_id profile ID
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ TxStatus send_data(uint64_t remote64, uint16_t remote16, uint8_t source_ep,
+ uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
+ const uint8_t *const data, uint16_t len);
+
+ /** send_data_to_coordinator - sends data to the ZigBee coordinator waiting for the
+ * packet answer with the result of the operation
+ *
+ * @param data pointer to the data that will be sent
+ * @param len number of bytes that will be transmitted
+ * @returns the result of the data transfer
+ * TxStatusSuccess if the operation was successful,
+ * the error code otherwise
+ */
+ TxStatus send_data_to_coordinator(const uint8_t *const data, uint16_t len);
+
+ /** is_joined - checks if the device is joined to ZigBee network
+ * @returns true if joined, false otherwise
+ */
+ bool is_joined();
+
+ /** get_remote_node_by_id - searches for a device in the network with the specified Node Identifier.
+ *
+ * @param node_id node id of the device we are looking for
+ * @returns a RemoteXBeeZB with the 16-bit and 64-bit address of the remote device whose node id matches with the parameter.
+ * If node is not found, the returned object will have invalid addresses (RemoteXBeeZB::is_valid() will return false).
+ */
+ RemoteXBeeZB get_remote_node_by_id(const char * const node_id);
+
+ /* Allow using XBee::set_param() methods for local radio from this class */
+ using XBee::set_param;
+
+ /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be set.
+ * @param data the parameter value (4 bytes) to be set.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data);
+
+ /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be set.
+ * @param data the parameter value byte array (len bytes) to be set.
+ * @param len number of bytes of the parameter value.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+ /* Allow using XBee::get_param() methods for local radio from this class */
+ using XBee::get_param;
+
+ /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be get.
+ * @param data pointer where the param value (4 bytes) will be stored.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data);
+
+ /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+ *
+ * @param remote remote device
+ * @param param parameter to be get.
+ * @param data pointer where the param value (n bytes) will be stored.
+ * @param len pointer where the number of bytes of the param value will be stored.
+ * @returns the command response status.
+ */
+ virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len);
+
+ /************************* IO member methods **************************/
+ /** set_pin_config - configures a radio IO line
+ *
+ * @param remote remote device
+ * @param line IO line being configured
+ * @param mode configuration mode for the selected line
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode);
+
+ /** get_pin_config - gets the configuration of a radio IO line
+ *
+ * @param remote remote device
+ * @param line IO line being read to get its configuration
+ * @param mode pointer where the configuration will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode);
+
+ /** set_dio - sets to low/high a DIO line
+ *
+ * @param remote remote device
+ * @param line DIO line being set
+ * @param val value that will be set in the DIO line
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_dio(const RemoteXBee& remote, IoLine line, DioVal val);
+
+ /** get_dio - read the value of a DIO configured as digital input
+ *
+ * @param remote remote device
+ * @param line DIO line being read
+ * @param val pointer where the DIO value read will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val);
+
+ /** get_adc - read the value of the espcified ADC line
+ *
+ * @param remote remote device
+ * @param line ADC line being read
+ * @param val pointer where the value read from hte ADC will be stored
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val);
+
+ /** set_pin_pull_up - enables or disables the internal pull-up resistor of a line
+ *
+ * @param remote remote device
+ * @param line line being configured for pull-up
+ * @param enable whether to enable the internal pull-up resistor.
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable);
+
+ /** enable_dio_change_detection - enables or disables the notification when a change is detected in a digital input line.
+ * In other words, it will force an IO Sample transmission when the DIO state changes. Only for DIO0 to DIO11.
+ *
+ * @param remote remote device
+ * @param line line being configured for pull-up
+ * @param enable whether to enable the internal pull-up resistor.
+ * @returns
+ * Success if the operation was successful,
+ * Failure otherwise
+ */
+ RadioStatus enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable);
+
+ protected:
+ /** Role of this device in the ZigBee network (coord, router or end device) */
+ NetworkRole _nw_role;
+
+ /** Indicates if the device is joined to a network. This variable is automatically updated
+ * by the library. If the device is acting as coordinator, its value its true */
+ volatile bool _joined_network;
+
+ /** Vcc exceeded counter, automatically updated by the library */
+ volatile uint16_t _vcc_exceeded_cnt;
+
+ /* TODO, add setter/getter */
+ uint8_t _broadcast_radious;
+
+ /** Frame handler used for the node discovery. Registered when a callback function
+ * is registered */
+ FH_NodeDiscoveryZB *_nd_handler;
+
+ /** Frame handler used for the rx packets. Automatically registered when a callback
+ * function is registered */
+ FH_RxPacketZB *_rx_pkt_handler;
+
+ /** Frame handler used for the IO Data Sample packets. Automatically registered when a callback
+ * function is registered */
+ FH_IoDataSampeZB *_io_data_handler;
+
+ /** Method called directly by the library when a modem status frame is received to
+ * update the internal status variables */
+ virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+ /* Allow using XBee::send_data() methods from this class */
+ using XBee::send_data;
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __XBEE_ZB_H_ */
+
+
