Lorenzo Maiorfi / XBeeLib_Fixed

Dependents:   XBeeZB_Receive_Data

Fork of XBeeLib by Digi International Inc.

Files at this revision

API Documentation at this revision

Comitter:
spastor
Date:
Fri May 08 11:50:56 2015 +0200
Child:
1:794d1d3e4a08
Commit message:
Automatic upload

Changed in this revision

DigiLogger.lib Show annotated file Show diff for this revision Revisions of this file
FrameBuffer/FrameBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
FrameBuffer/FrameBuffer.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_AtCmdResp.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_AtCmdResp.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_IoDataSample802.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_IoDataSample802.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_IoDataSampleZB.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_IoDataSampleZB.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_ModemStatus.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_ModemStatus.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_RxPacket802.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_RxPacket802.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_RxPacketZB.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FH_RxPacketZB.h Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FrameHandler.cpp Show annotated file Show diff for this revision Revisions of this file
FrameHandlers/FrameHandler.h Show annotated file Show diff for this revision Revisions of this file
Frames/802_Frames.cpp Show annotated file Show diff for this revision Revisions of this file
Frames/802_Frames.h Show annotated file Show diff for this revision Revisions of this file
Frames/ApiFrame.cpp Show annotated file Show diff for this revision Revisions of this file
Frames/ApiFrame.h Show annotated file Show diff for this revision Revisions of this file
Frames/AtCmdFrame.cpp Show annotated file Show diff for this revision Revisions of this file
Frames/AtCmdFrame.h Show annotated file Show diff for this revision Revisions of this file
Frames/ZigbeeFrames.cpp Show annotated file Show diff for this revision Revisions of this file
Frames/ZigbeeFrames.h Show annotated file Show diff for this revision Revisions of this file
IO/IO.h Show annotated file Show diff for this revision Revisions of this file
IO/IOSample802.cpp Show annotated file Show diff for this revision Revisions of this file
IO/IOSample802.h Show annotated file Show diff for this revision Revisions of this file
IO/IOSampleZB.cpp Show annotated file Show diff for this revision Revisions of this file
IO/IOSampleZB.h Show annotated file Show diff for this revision Revisions of this file
RemoteXBee/RemoteXBee.cpp Show annotated file Show diff for this revision Revisions of this file
RemoteXBee/RemoteXBee.h Show annotated file Show diff for this revision Revisions of this file
Utils/Debug.h Show annotated file Show diff for this revision Revisions of this file
Utils/Utils.cpp Show annotated file Show diff for this revision Revisions of this file
Utils/Utils.h Show annotated file Show diff for this revision Revisions of this file
XBee/Addresses.h Show annotated file Show diff for this revision Revisions of this file
XBee/AtCommands.cpp Show annotated file Show diff for this revision Revisions of this file
XBee/RadioConfig.cpp Show annotated file Show diff for this revision Revisions of this file
XBee/XBee.cpp Show annotated file Show diff for this revision Revisions of this file
XBee/XBee.h Show annotated file Show diff for this revision Revisions of this file
XBee802/XBee802.cpp Show annotated file Show diff for this revision Revisions of this file
XBee802/XBee802.h Show annotated file Show diff for this revision Revisions of this file
XBeeLib.h Show annotated file Show diff for this revision Revisions of this file
XBeeZB/XBeeZB.cpp Show annotated file Show diff for this revision Revisions of this file
XBeeZB/XBeeZB.h Show annotated file Show diff for this revision Revisions of this file
--- /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_ */
+
+