Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of XBeeLib by
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_ */
+
+
