Library for using the LSR SiFlex/ProFlex RF modules with mbed.

Files at this revision

API Documentation at this revision

Comitter:
Issus
Date:
Mon Jul 25 16:18:48 2016 +0000
Child:
1:8ecba4bfc183
Commit message:
Initial Commit

Changed in this revision

LsrModule.cpp Show annotated file Show diff for this revision Revisions of this file
LsrModule.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LsrModule.cpp	Mon Jul 25 16:18:48 2016 +0000
@@ -0,0 +1,945 @@
+/**
+ * @file LsrModule.cpp
+ * @author LS Research LLC
+ * @version 1.0
+ *
+ * @section LICENSE
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @section DESCRIPTION
+ *
+ * Implementation of contents in LsrModule.h.
+ */
+
+/**
+ * Modified by Mark Harris at SAIT.ca
+ * Improved functionality for mbed
+ */
+
+#include "LsrModule.h"
+#include "mbed.h"
+
+/**
+* C function pointer typedef.
+*
+*/
+typedef void (*ptrRxMsgCallback)(void);
+
+/**
+* Table used for subscribing callback functions for
+* received UART messages.
+*/
+ptrRxMsgCallback ptrRxMsgCallbackTable[69];
+
+
+/**
+* This table contains the min and max length for each message type.  The first array index
+* is the message type and the second index is the min value (0) or max value (1).
+*/
+const uint8_t cau8RxMsgLengthAndTypeTable[69][2] = {
+    {12, 39},   // 0x81 - Query Firmware Version Response
+    {0, 0},     // 0x82 - Invalid message type
+    {0, 0},     // 0x83 - Invalid message type
+    {0, 0},     // 0x84 - Invalid message type
+    {0, 0},     // 0x85 - Invalid message type
+    {0, 0},     // 0x86 - Invalid message type
+    {0, 0},     // 0x87 - Invalid message type
+    {0, 0},     // 0x88 - Invalid message type
+    {0, 0},     // 0x89 - Invalid message type
+    {0, 0},     // 0x8A - Invalid message type
+    {0, 0},     // 0x8B - Invalid message type
+    {5, 5},     // 0x8C - Set Security Transmit Frame Counter Ack
+    {11, 11},   // 0x8D - Query Security Transmit Frame Counter Response
+    {0, 0},     // 0x8E - Invalid message type
+    {0, 0},     // 0x8F - Invalid message type
+    {5, 5},     // 0x90 - Set Basic RF Settings Ack
+    {39, 39},   // 0x91 - Query Basic RF Settings Response
+    {5, 5},     // 0x92 - Save Settings to NV Memory Ack
+    {5, 5},     // 0x93 - Reset Request Ack
+    {9, 9},     // 0x94 - Query Supply Voltage Response
+    {21, 21},   // 0x95 - Query Statistics Response
+    {5, 5},     // 0x96 - Clear Statistics Ack
+    {0, 0},     // 0x97 - Invalid message type
+    {5, 5},     // 0x98 - Set Host Data Rate Ack
+    {0, 0},     // 0x99 - Invalid message type
+    {0, 0},     // 0x9A - Invalid message type
+    {0, 0},     // 0x9B - Invalid message type
+    {0, 0},     // 0x9C - Invalid message type
+    {0, 0},     // 0x9D - Invalid message type
+    {0, 0},     // 0x9E - Invalid message type
+    {0, 0},     // 0x9F - Invalid message type
+    {7, 7},     // 0xA0 - Send Simple Short Address RF Data Packet Ack
+    {17, 115},  // 0xA1 - Received Simple Short Address RF Data Packet
+    {7, 7},     // 0xA2 - Send Advanced Short Address RF Data Packet Ack
+    {21, 119},  // 0xA3 - Received Advanced Short Address RF Data Packet
+    {7, 7},     // 0xA4 - Send Simple Long Address RF Data Packet Ack
+    {29, 127},  // 0xA5 - Received Simple Long Address RF Data Packet
+    {7, 7},     // 0xA6 - Send Advanced Long Address RF Data Packet Ack
+    {33, 131},  // 0xA7 - Received Advanced Long Address RF Data Packet
+    {0, 0},     // 0xA8 - Invalid message type
+    {0, 0},     // 0xA9 - Invalid message type
+    {0, 0},     // 0xAA - Invalid message type
+    {0, 0},     // 0xAB - Invalid message type
+    {0, 0},     // 0xAC - Invalid message type
+    {0, 0},     // 0xAD - Invalid message type
+    {13, 131},  // 0xAE - Received Promiscuous Mode Packet
+    {0, 0},     // 0xAF - Invalid message type
+    {0, 0},     // 0xB0 - Invalid message type
+    {0, 0},     // 0xB1 - Invalid message type
+    {0, 0},     // 0xB2 - Invalid message type
+    {0, 0},     // 0xB3 - Invalid message type
+    {0, 0},     // 0xB4 - Invalid message type
+    {0, 0},     // 0xB5 - Invalid message type
+    {0, 0},     // 0xB6 - Invalid message type
+    {0, 0},     // 0xB7 - Invalid message type
+    {0, 0},     // 0xB8 - Invalid message type
+    {0, 0},     // 0xB9 - Invalid message type
+    {0, 0},     // 0xBA - Invalid message type
+    {0, 0},     // 0xBB - Invalid message type
+    {0, 0},     // 0xBC - Invalid message type
+    {0, 0},     // 0xBD - Invalid message type
+    {0, 0},     // 0xBE - Invalid message type
+    {0, 0},     // 0xBF - Invalid message type
+    {0, 0},     // 0xC0 - Invalid message type
+    {0, 0},     // 0xC1 - Invalid message type
+    {0, 0},     // 0xC2 - Invalid message type
+    {0 ,0},     // 0xC3 - Invalid message type
+    {5, 5},     // 0xC4 - Channel Energy Scan Ack
+    {23, 23}    // 0xC5 - Channel Energy Scan Results
+};
+
+/**
+* Construnctor.
+*
+* Example:
+*
+* LsrModule(false, 19200);
+*
+*/
+LsrModule::LsrModule(PinName tx, PinName rx, int baudRate) : Serial(tx, rx)
+{
+    baud(baudRate);
+    
+    ptrHostState = &LsrModule::HostRxWaitForMsgStartByteState;   
+}   /*** End LsrModule ***/
+
+
+/**
+* Destructor.  Called automatically, de-allocates resources.
+*
+*/
+LsrModule::~LsrModule(void)
+{
+    pu8RxBuffer = NULL;
+    ptrHostState = NULL;
+    ptrHostProcessCallbackState = NULL;
+    
+    for (u8ForLoopCounter = 0; u8ForLoopCounter < sizeof(ptrRxMsgCallbackTable); u8ForLoopCounter++)
+    {
+        ptrRxMsgCallbackTable[u8ForLoopCounter] = NULL;
+    }
+}   /*** End ~LsrModule ***/
+
+
+/**
+* Creates a callback for specific received UART message.  Call this function from your main application in 
+* this manner: "SubscribeRxMsgCallback(0xA1, &simpleShortAddrCallback)", where simpleShortAddrCallback is 
+* defined like this: void simpleShortAddrCallback(void) in your main application.  
+* IMPORTANT: All user defined callback methods must return void and take no parameters (void).
+*
+* @return True: Subscribed callback.  False: Did not subscribe callback.
+*
+*/
+bool LsrModule::SubscribeRxMsgCallback(uint8_t u8RxMsgType ///< The received message for which you want the callback to execute.
+                    , void (*callback)(void) ///< C function pointer to the specified callback function.
+                     )
+{
+    if ((u8RxMsgType > LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE) && (u8RxMsgType < LSR_MODULE_MAX_SERIAL_RX_MSG_TYPE))
+    {
+        ptrRxMsgCallbackTable[u8RxMsgType- LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE] = callback;
+        return true;
+    }
+
+    return false;
+}   /*** End SubscribeRxMsgCallback ***/
+
+
+/**
+* Removes a callback for specific received UART message.  See SubscribeRxMsgCallback's description for 
+* more information.
+*
+* @return True: Unsubscribed callback.  False: Did not unsubscribed callback.
+*
+*/
+bool LsrModule::UnsubscribeRxMsgCallback(uint8_t u8RxMsgType ///< The received message for which you want the callback to be removed.
+                       )
+{
+    if ((u8RxMsgType > LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE) && (u8RxMsgType < LSR_MODULE_MAX_SERIAL_RX_MSG_TYPE))
+    {
+        ptrRxMsgCallbackTable[u8RxMsgType - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE] = NULL;
+        return true;
+    }
+
+    return false;
+}   /*** End UnsubscribeRxMsgCallback ***/
+
+
+/**
+* Executes host RX state machine.  This function must be executed continually from the loop function in your main
+* application.
+*
+*/
+void LsrModule::RunHostRxStateMachine(void)
+{
+    (this->*ptrHostState)();
+}   /*** End RunHostRxStateMachine ***/
+
+
+/**
+* Flushes appropriate serial port.
+*
+*/
+void LsrModule::SerialFlush(void)
+{
+    // Serial.flush(); 
+    // i think this is meant to clean out the rx buffer
+    /*** End SerialFlush ***/
+}
+
+/**
+* Adds header to the UART transmit buffer.
+*
+*/
+void LsrModule::AddSerialMsgHeader(uint8_t u8MsgType, uint8_t u8MsgLength)
+{
+    SerialFlush();
+    u8UartTxBufferIndex = LSR_MODULE_MSG_START_BYTE_INDEX;
+    au8UartTxBuffer[u8UartTxBufferIndex++] = LSR_MODULE_SERIAL_MSG_START_BYTE;
+    au8UartTxBuffer[u8UartTxBufferIndex++] = u8MsgLength;
+    au8UartTxBuffer[u8UartTxBufferIndex++] = u8MsgType;
+    u8TxMsgChecksum = (LSR_MODULE_SERIAL_MSG_START_BYTE + u8MsgLength + u8MsgType);
+}   /*** End LsrModuleAddSerialMsgHeader ***/
+
+
+/**
+* Adds data bytes to the UART transmit buffer.
+*
+*/
+void LsrModule::AddSerialByteToMsgBuffer(uint8_t u8Data ///< The data to add.
+                                           )
+{
+    au8UartTxBuffer[u8UartTxBufferIndex++] = u8Data;
+    u8TxMsgChecksum += u8Data;
+}   /*** End LsrModuleAddSerialByteToMsgBuffer ***/
+
+
+/**
+* Adds message trailer to the UART transmit buffer.
+*
+*/
+void LsrModule::AddSerialMsgTrailer(void)
+{
+    au8UartTxBuffer[u8UartTxBufferIndex++] = u8TxMsgChecksum;
+    au8UartTxBuffer[u8UartTxBufferIndex] = LSR_MODULE_SERIAL_MSG_END_BYTE;
+    WriteSerialMsg();
+}   /*** End AddSerialMsgTrailer ***/
+
+
+/**
+* Writes the UART transmit buffer using the appropriate serial port.
+*
+*/
+void LsrModule::WriteSerialMsg(void)
+{
+    //write (const uint8_t *buffer, int length, const event_callback_t &callback, int event=SERIAL_EVENT_TX_COMPLETE)
+    write(au8UartTxBuffer, au8UartTxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX]);
+    
+}   /*** End WriteSerialMsg ***/
+
+
+/**
+* Sends message type 0x01 (Query Version) to the module via UART communication.  This will spark
+* a response message from the module to the Arduino of type 0x81.  Subscribing to 0x81 in 
+* your main application will allow you to parse the response data.  See the description for 
+* SubscribeRxMsgCallback for more information.
+*
+*/
+void LsrModule::QueryVersionMsg(void)
+{
+    AddSerialMsgHeader(LSR_MODULE_QUERY_VERSION_MSG_TYPE, 5);
+    AddSerialMsgTrailer();
+}   /*** End QueryVersionMsg ***/
+
+
+/**
+* Sends message type 0x0C (Sets Security Transmit Frame Counter) to the module via UART communication.  
+* This frame counter is used with RF messages transmitted with security to ensure sequential freshness. 
+* This sets the starting frame count and is automatically incremented on every secured packet sent.  
+* This will spark an ACK message from the module to the Arduino of type 0x8C.  Subscribing to 0x8C in 
+* your main application will allow you to parse the response data.  See the description for 
+* SubscribeRxMsgCallback for more information.
+*
+* Example:
+*
+* uint32_t u32FrameCounter = 0xAEDFEDFA;
+* SetSecurityTransmitFrameCounterMsg(&u32FrameCounter);
+*
+*/
+void LsrModule::SetSecurityTransmitFrameCounterMsg(uint32_t* pu32FrameCounter ///< Pointer to 4 byte frame counter (LSB to MSB).
+                             )
+{
+    DWordu_t dwuFrameCounter;
+
+    dwuFrameCounter.u32 = *pu32FrameCounter;
+      
+    AddSerialMsgHeader(LSR_MODULE_SET_SECURITY_TX_FRAME_COUNTER_MSG_TYPE, 11);
+    AddSerialByteToMsgBuffer(dwuFrameCounter.dws.lb);
+    AddSerialByteToMsgBuffer(dwuFrameCounter.dws.mlb);
+    AddSerialByteToMsgBuffer(dwuFrameCounter.dws.mhb);
+    AddSerialByteToMsgBuffer(dwuFrameCounter.dws.hb);
+    AddSerialByteToMsgBuffer(0x00);        // Add filler byte.
+    AddSerialByteToMsgBuffer(0x00);        // Add filler byte.
+    AddSerialMsgTrailer();
+}   /*** End SetSecurityTransmitFrameCounterMsg ***/ 
+
+
+/**
+* Sends message type 0x0D (Query Security Transmit Frame Counter) to the module via UART communication.  This
+* will spark a response message from the module to the Arduino of type 0x8D.  Subscribing to 0x8D in your main 
+* application will allow you to parse the response data.  See the description for SubscribeRxMsgCallback
+* for more information.
+*
+*/
+void LsrModule::QuerySecurityTransmitFrameCounterMsg(void)
+{
+    AddSerialMsgHeader(LSR_MODULE_QUERY_SECURITY_TX_FRAME_COUNTER_MSG_TYPE, 5);
+    AddSerialMsgTrailer();
+}   /*** End QuerySecurityTransmitFrameCounterMsg ***/ 
+
+
+/**
+* Sends message type 0x10 (Set Basic RF Settings) to the module via UART communication.
+* This will spark an ACK message from the module to the Arduino of type 0x90.  Subscribing to 0x90 in 
+* your main application will allow you to parse the response data.  See the description for 
+* SubscribeRxMsgCallback for more information.
+*
+*/
+void LsrModule::SetBasicRfSettingsMsg(uint16_t u16PanId ///< Personal Area Network (PAN) ID assigned to module.
+                                       , uint16_t u16AddrShort ///< 2 byte short address assigned to module.
+                       , uint8_t* pu8AddrLong ///< Pointer to 8 byte long address assigned to module.  Do not assign a zero, even if using short addressing.
+                       , uint8_t u8RfChannel ///< RF channel assigned to module.
+                       , uint8_t u8TxPowerLevel ///< Transmit power assigned to module.
+                       , uint8_t u8ReceiverConfig ///< 1 byte bitmask of receiver options.
+                       , uint8_t* pu8SecurityKey ///< Pointer to 32 byte security key assigned to module.
+                    )
+{
+    Wordu_t wuPanId;
+    Wordu_t wuShortAddr;
+    
+    wuPanId.u16 = u16PanId;
+    wuShortAddr.u16 = u16AddrShort;
+    
+    if ((u8RfChannel >= LSR_MODULE_RF_CHANNEL_MIN) && (u8RfChannel <= LSR_MODULE_RF_CHANNEL_MAX) &&
+        (u8TxPowerLevel <= LSR_MODULE_TX_POWER_LEVEL_MAX) &&
+        (u8ReceiverConfig <= LSR_MODULE_RX_CONFIG_MAX))
+    {
+        AddSerialMsgHeader(LSR_MODULE_SET_BASIC_RF_SETTINGS_MSG_TYPE, 39);
+        AddSerialByteToMsgBuffer(wuPanId.ws.lb);
+        AddSerialByteToMsgBuffer(wuPanId.ws.hb);
+        AddSerialByteToMsgBuffer(wuShortAddr.ws.lb);
+        AddSerialByteToMsgBuffer(wuShortAddr.ws.hb);
+
+        for (u8ForLoopCounter = 0; u8ForLoopCounter < 8; u8ForLoopCounter++)
+        {
+            AddSerialByteToMsgBuffer(*pu8AddrLong);
+            pu8AddrLong++;
+        }
+    
+        AddSerialByteToMsgBuffer(u8RfChannel);
+        AddSerialByteToMsgBuffer(u8TxPowerLevel);
+        AddSerialByteToMsgBuffer(u8ReceiverConfig);
+
+        AddSerialByteToMsgBuffer(0x00);        // Add filler byte.
+        AddSerialByteToMsgBuffer(0x00);        // Add filler byte.
+        AddSerialByteToMsgBuffer(0x00);        // Add filler byte.
+
+        for (u8ForLoopCounter = 0; u8ForLoopCounter < 16; u8ForLoopCounter++)
+        {
+            AddSerialByteToMsgBuffer(*pu8SecurityKey);
+            pu8SecurityKey++;
+        }
+
+        AddSerialMsgTrailer();
+    }
+}   /*** End SetBasicRfSettingsMsg ***/
+
+
+/**
+* Sends message type 0x11 (Query Basic RF Settings) to the module via UART communication.  This will spark
+* a response message from the module to the Arduino of type 0x91.  Subscribing to 0x91 in your main 
+* application will allow you to parse the response data.  See the description for SubscribeRxMsgCallback 
+* for more information.
+*
+*/
+void LsrModule::QueryBasicRfSettingsMsg(void)
+{
+    AddSerialMsgHeader(LSR_MODULE_QUERY_BASIC_RF_SETTINGS_MSG_TYPE, 5);
+    AddSerialMsgTrailer();
+}   /*** End QueryBasicRfSettingsMsg ***/
+
+
+/**
+* Sends message type 0x12 (Save Settings to non-volatile Memory) to the module via UART communication.  Calling
+* this command will make your module retain all basic configuration settings on boot up.  This will spark an ACK 
+* message from the module to the Arduino of type 0x92.  Subscribing to 0x92 in your main application will allow 
+* you to parse the response data.  See the description for SubscribeRxMsgCallback for more information.
+*
+*/
+void LsrModule::SaveSettingsToNVMemoryMsg(void)
+{
+    AddSerialMsgHeader(LSR_MODULE_SAVE_SETTINGS_TO_NV_MEMORY_MSG_TYPE, 5);
+    AddSerialMsgTrailer();
+}   /*** End SaveSettingsToNVMemoryMsg ***/
+
+
+/**
+* Sends message type 0x13 (Reset Request) to the module via UART communication.  This will make your module perform
+* a restart.  This will spark an ACK message from the module to the Arduino of type 0x93.  Subscribing to 0x93 in 
+* your main application will allow you to parse the response data.  See the description for SubscribeRxMsgCallback
+* for more information.
+*
+*/
+void LsrModule::ResetRequestMsg(void)
+{
+    AddSerialMsgHeader(LSR_MODULE_RESET_REQUEST_MSG_TYPE, 5);
+    AddSerialMsgTrailer();
+}   /*** End ResetRequestMsg ***/
+
+
+/**
+* Sends message type 0x14 (Query Supply Voltage) to the module via UART communication.  This will spark a 
+* response message from the module to the Arduino of type 0x94.  Subscribing to 0x94 in your main application
+* will allow you to parse the response data.  See the description for SubscribeRxMsgCallback for more information.
+*
+*/
+void LsrModule::QuerySupplyVoltageMsg(void)
+{
+    AddSerialMsgHeader(LSR_MODULE_QUERY_SUPPLY_VOLTAGE_MSG_TYPE, 5);
+    AddSerialMsgTrailer();
+}   /*** End QuerySupplyVoltageMsg ***/
+
+
+/**
+* Sends message type 0x15 (Query Statistics) to the module via UART communication.  Statistics include packets sent, 
+* acks received, packets received and broadcast packets received.  This will spark a response message from the module 
+* to the Arduino of type 0x95.  Subscribing to 0x94 in your main application will allow you to parse the response 
+* data.  See the description for SubscribeRxMsgCallback for more information.
+*
+*/
+void LsrModule::QueryStatisticsMsg(void)
+{
+    AddSerialMsgHeader(LSR_MODULE_QUERY_STATISTICS_MSG_TYPE, 5);
+    AddSerialMsgTrailer();
+}   /*** End QueryStatisticsMsg ***/
+
+
+/**
+* Sends message type 0x16 (Clear Statistics) to the module via UART communication.  This will spark an ACK message 
+* from the module to the Arduino of type 0x96.  Subscribing to 0x96 in your main application will allow you to 
+* Parse the response data.  See the description for SubscribeRxMsgCallback for more information.
+*
+*/
+void LsrModule::ClearStatisticsMsg(void)
+{
+    AddSerialMsgHeader(LSR_MODULE_CLEAR_STATISTICS_MSG_TYPE, 5);
+    AddSerialMsgTrailer();
+}   /*** End ClearStatisticsMsg ***/
+
+
+/**
+* Sends message type 0x18 (Set Host Data Rate) to the module via UART communication.  This will spark an ACK message 
+* from the module to the Arduino of type 0x98.  Subscribing to 0x98 in your main application will allow you to parse 
+* the response data.  See the description for SubscribeRxMsgCallback for more information.
+*
+*/
+void LsrModule::SetHostDataRateMsg(uint8_t u8HostDataRate ///< Data rate for module to use when communicating via UART:
+                                 ///< 0 = 1,200 bits/s
+                                 ///< 1 = 2,400 bits/s
+                                 ///< 2 = 4,800 bits/s
+                                 ///< 3 = 9,600 bits/s
+                                 ///< 4 = 19,200 bits/s
+                                 ///< 5 = 38,400 bits/s
+                                 ///< 6 = 57,600 bits/s
+                                 ///< 7 = 115,200 bits/s
+                                     )
+{
+    if (u8HostDataRate <= LSR_MODULE_HOST_DATA_RATE_MAX)
+    {
+        AddSerialMsgHeader(LSR_MODULE_SET_HOST_DATA_RATE_MSG_TYPE, 6);
+        AddSerialByteToMsgBuffer(u8HostDataRate);
+        AddSerialMsgTrailer();
+    }
+}   /*** End SetHostDataRateMsg ***/
+
+
+/**
+* Sends message type 0x20 (Send Simple Short Address RF Data Packet) to the module via UART communication.
+* This will spark an ACK message from the module to the Arduino of type 0xA0.  Subscribing to 0xA0 in 
+* your main application will allow you to parse the response data.  See the description for SubscribeRxMsgCallback
+* for more information.
+*
+* Example:
+*
+* uint8_t u8Data[5] = {4, 7, 3, 5, 8};
+* uint8_t u8PacketID;
+*
+* SendSimpleShortAddrRfDataPacketMsg(&u8Data, sizeof(u8Data, 213, 0, packetID++);
+*
+*/
+void LsrModule::SendSimpleShortAddrRfDataPacketMsg(uint8_t* pu8Data ///< Pointer to data being sent.
+                                                    , uint8_t u8DataLength ///< Length of data being sent.
+                            , uint16_t u16DestAddress ///< 2 byte destination address.
+                            , uint8_t u8TxOptions ///< 1 byte bit mask of transmit options.
+                            , uint8_t u8PacketId ///< ID assigned to packet.
+                             )
+{
+    if ((u8TxOptions <= LSR_MODULE_TX_OPTIONS_MAX) &&
+        ((((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) != 0) && (u8DataLength <= (LSR_MODULE_SIMPLE_SHORT_RF_DATA_LENGTH - LSR_MODULE_SECURITY_OVERHEAD))) ||
+         (((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) == 0) && (u8DataLength <= LSR_MODULE_SIMPLE_SHORT_RF_DATA_LENGTH))))
+    {
+        AddSerialMsgHeader(LSR_MODULE_SEND_SIMPLE_SHORT_RF_DATA_PACKET_MSG_TYPE, (u8DataLength + 9));
+    
+        AddSerialByteToMsgBuffer(u8TxOptions);
+        AddSerialByteToMsgBuffer(u16DestAddress % 256);
+        AddSerialByteToMsgBuffer(u16DestAddress >> 8);
+        AddSerialByteToMsgBuffer(u8PacketId);
+          
+        while (u8DataLength != 0)
+        {
+            AddSerialByteToMsgBuffer(*pu8Data);
+            pu8Data++;
+            u8DataLength--;
+        }
+        
+        AddSerialMsgTrailer();
+    }
+}   /*** End SendSimpleShortAddrRfDataPacketMsg ***/
+
+
+/**
+* Sends message type 0x22 (Send Advanced Short Address RF Data Packet) to the module via UART communication.
+* This will spark an ACK message from the module to the Arduino of type 0xA2.  Subscribing to 0xA2 in 
+* your main application will allow you to parse the response data.  See the description for SubscribeRxMsgCallback
+* for more information.
+*
+* Example:
+*
+* uint8_t u8Data[5] = {4, 7, 3, 5, 8};
+* uint8_t u8PacketID;
+*
+* SendAdvancedShortAddrRfDataPacketMsg(&u8Data, sizeof(u8Data, 1111, 213, 0, packetID++);
+*
+*/
+void LsrModule::SendAdvancedShortAddrRfDataPacketMsg(uint8_t* pu8Data ///< Pointer to data being sent.
+                                                      , uint8_t u8DataLength ///< Length of data being sent.
+                              , uint16_t u16DestPanId ///< 2 byte Personal Area Network (PAN) ID.
+                              , uint16_t u16DestAddress ///< 2 byte destination address.
+                              , uint8_t u8TxOptions ///< 1 byte bit mask of transmit options.
+                              , uint8_t u8PacketId ///< ID assigned to packet.
+                            )
+{
+    if ((u8TxOptions <= LSR_MODULE_TX_OPTIONS_MAX) &&
+        ((((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) != 0) && (u8DataLength <= (LSR_MODULE_ADVANCED_SHORT_RF_DATA_LENGTH - LSR_MODULE_SECURITY_OVERHEAD))) ||
+         (((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) == 0) && (u8DataLength <= LSR_MODULE_ADVANCED_SHORT_RF_DATA_LENGTH))))
+    {
+        AddSerialMsgHeader(LSR_MODULE_SEND_ADVANCED_SHORT_RF_DATA_PACKET_MSG_TYPE, (u8DataLength + 11));
+    
+        AddSerialByteToMsgBuffer(u8TxOptions);
+        AddSerialByteToMsgBuffer(u16DestPanId % 256);
+        AddSerialByteToMsgBuffer(u16DestPanId >> 8);
+        AddSerialByteToMsgBuffer(u16DestAddress % 256);
+        AddSerialByteToMsgBuffer(u16DestAddress >> 8);
+        AddSerialByteToMsgBuffer(u8PacketId);
+          
+        while (u8DataLength != 0)
+        {
+            AddSerialByteToMsgBuffer(*pu8Data);
+            pu8Data++;
+            u8DataLength--;
+        }
+        
+        AddSerialMsgTrailer();
+    }
+}   /*** End SendAdvancedShortAddrRfDataPacketMsg ***/
+
+
+/**
+* Sends message type 0x24 (Send Simple Long Address RF Data Packet) to the module via UART communication.
+* This will spark an ACK message from the module to the Arduino of type 0xA4.  Subscribing to 0xA4 in 
+* your main application will allow you to parse the response data.  See the description for SubscribeRxMsgCallback
+* for more information.
+*
+* Example:
+*
+* uint8_t u8Data[5] = {4, 7, 3, 5, 8};
+* uint8_t u8DestAddress[8] = {2, 3, 6, 5, 2, 3, 6, 5};
+* uint8_t u8PacketID;
+*
+* SendSimpleLongAddrRfDataPacketMsg(&u8Data, sizeof(u8Data), &u8DestAddress, 0, packetID++);
+*
+*/
+void LsrModule::SendSimpleLongAddrRfDataPacketMsg(uint8_t* pu8Data ///< Pointer to data being sent.
+                                                   , uint8_t u8DataLength ///< Length of data being sent.
+                           , uint8_t* pu8DestAddress ///< Pointer to 8 byte destination address.
+                           , uint8_t u8TxOptions ///< 1 byte bit mask of transmit options.
+                           , uint8_t u8PacketId ///< ID assigned to packet.
+                            )
+{
+    if ((u8TxOptions <= LSR_MODULE_TX_OPTIONS_MAX) &&
+        ((((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) != 0) && (u8DataLength <= (LSR_MODULE_SIMPLE_LONG_RF_DATA_LENGTH - LSR_MODULE_SECURITY_OVERHEAD))) ||
+         (((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) == 0) && (u8DataLength <= LSR_MODULE_SIMPLE_LONG_RF_DATA_LENGTH))))
+    {
+        AddSerialMsgHeader(LSR_MODULE_SEND_SIMPLE_LONG_RF_DATA_PACKET_MSG_TYPE, (u8DataLength + 15));
+    
+        AddSerialByteToMsgBuffer(u8TxOptions);
+        
+        for (u8ForLoopCounter = 0; u8ForLoopCounter < 8; u8ForLoopCounter++)
+        {
+            AddSerialByteToMsgBuffer(*pu8DestAddress);
+            pu8DestAddress++;
+        }
+        
+        AddSerialByteToMsgBuffer(u8PacketId);
+          
+        while (u8DataLength != 0)
+        {
+            AddSerialByteToMsgBuffer(*pu8Data);
+            pu8Data++;
+            u8DataLength--;
+        }
+        
+        AddSerialMsgTrailer();
+    }
+}   /*** End SendSimpleLongAddrRfDataPacketMsg ***/
+
+
+/**
+* Sends message type 0x26 (Send Advanced Long Address RF Data Packet) to the module via UART communication.
+* This will spark an ACK message from the module to the Arduino of type 0xA6.  Subscribing to 0xA6 in 
+* your main application will allow you to parse the response data.  See the description for SubscribeRxMsgCallback
+* for more information.
+*
+* Example:
+*
+* uint8_t u8Data[5] = {4, 7, 3, 5, 8};
+* uint8_t u8DestAddress[8] = {2, 3, 6, 5, 2, 3, 6, 5};
+* uint8_t u8PacketID;
+*
+* SendAdvancedLongAddrRfDataPacketMsg(&u8Data, sizeof(u8Data), 1111, &u8DestAddress, 0, packetID++);
+*
+*/
+void LsrModule::SendAdvancedLongAddrRfDataPacketMsg(uint8_t* pu8Data ///< Pointer to data being sent.
+                                                     , uint8_t u8DataLength ///< Length of data being sent.
+                             , uint16_t u16DestPanId ///< 2 byte Personal Area Network (PAN) ID.
+                             , uint8_t* pu8DestAddress ///< Pointer to 8 byte destination address.
+                             , uint8_t u8TxOptions ///< 1 byte bit mask of transmit options.
+                             , uint8_t u8PacketId ///< ID assigned to packet.
+                               )
+{
+    if ((u8TxOptions <= LSR_MODULE_TX_OPTIONS_MAX) &&
+        ((((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) != 0) && (u8DataLength <= (LSR_MODULE_ADVANCED_LONG_RF_DATA_LENGTH - LSR_MODULE_SECURITY_OVERHEAD))) ||
+         (((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) == 0) && (u8DataLength <= LSR_MODULE_ADVANCED_LONG_RF_DATA_LENGTH))))
+    {
+        AddSerialMsgHeader(LSR_MODULE_SEND_ADVANCED_LONG_RF_DATA_PACKET_MSG_TYPE, (u8DataLength + 17));
+    
+        AddSerialByteToMsgBuffer(u8TxOptions);
+        AddSerialByteToMsgBuffer(u16DestPanId % 256);
+        AddSerialByteToMsgBuffer(u16DestPanId >> 8);
+
+        for (u8ForLoopCounter = 0; u8ForLoopCounter < 8; u8ForLoopCounter++)
+        {
+            AddSerialByteToMsgBuffer(*pu8DestAddress);
+            pu8DestAddress++;
+        }
+
+        AddSerialByteToMsgBuffer(u8PacketId);
+          
+        while (u8DataLength != 0)
+        {
+            AddSerialByteToMsgBuffer(*pu8Data);
+            pu8Data++;
+            u8DataLength--;
+        }
+        
+        AddSerialMsgTrailer();
+    }
+}   /*** End SendAdvancedLongAddrRfDataPacketMsg ***/
+
+
+/**
+* Sends message type 0x44 (Channel Energy Scan) to the module via UART communication.  This will spark a response message from the module 
+* to the Arduino of type 0xC5.  Subscribing to 0xC5 in your main application will allow you to parse the response 
+* data.  See the description for SubscribeRxMsgCallback for more information.
+*
+* Example (Channel 5 for SiFLEX02, Channel 15 for ProFLEX01):
+*
+* ChannelEnergyScanMsg(11110111, 7);
+*
+*/
+void LsrModule::ChannelEnergyScanMsg(uint16_t u16ChannelMask ///< Two byte bitmask (LSB to MSB) of the RF channels to perfom an enrgy scan on.
+                                      , uint8_t u8ScanDuration ///< Duration to scan for:
+                                   ///< 0 = 61.4 mSec
+                                   ///< 1 = 92.2 mSec
+                                   ///< 2 = 154 mSec
+                                   ///< 3 = 276 mSec
+                                   ///< 4 = 522 mSec
+                                   ///< 5 = 1.01 Sec
+                                   ///< 6 = 2.00 Sec
+                                   ///< 7 = 3.96 Sec
+                                   ///< 8 = 7.90 Sec
+                                   ///< 9 = 15.8 Sec
+                                   ///< 10 = 31.5 Sec
+                                   ///< 11 = 62.9 Sec
+                                   ///< 12 = 126 Sec
+                                   ///< 13 = 252 Sec
+                                   ///< 14 = 503 Sec
+                                                                
+                                       )
+{
+    Wordu_t wuChannelMask;
+    
+    wuChannelMask.u16 = u16ChannelMask;
+    
+    if (u8ScanDuration <= LSR_MODULE_SCAN_DURATION_MAX)
+    {
+        AddSerialMsgHeader(LSR_MODULE_CHANNEL_ENERGY_SCAN_MSG_TYPE, 8);
+        AddSerialByteToMsgBuffer(wuChannelMask.ws.lb);
+        AddSerialByteToMsgBuffer(wuChannelMask.ws.hb);
+        AddSerialByteToMsgBuffer(u8ScanDuration);
+        AddSerialMsgTrailer();
+    }
+}   /*** End ChannelEnergyScanMsg ***/
+
+
+/**
+* Verifies msg type and length.
+* @return True: Valid msg length and type.  False: Invalid msg length or type.
+*
+*/
+bool LsrModule::ValidMsgLengthAndType(uint8_t u8MsgType ///< Received UART message type.
+                                       , uint8_t u8MsgLength ///< Received UART message length.
+                                        )
+{
+    if ((u8MsgLength >= cau8RxMsgLengthAndTypeTable[u8MsgType - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE][0]) &&
+        (u8MsgLength <= cau8RxMsgLengthAndTypeTable[u8MsgType - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE][1]))
+    {
+        return true;
+    }
+    return false;
+}  /*** End ValidMsgLengthAndType ***/
+
+
+/**
+* Verifies message checksum.
+* @return True: Valid checksum.  False: Invalid checksum.
+*
+*/
+bool LsrModule::ValidRxChecksum(uint8_t* pu8MsgBuffer ///< Pointer to received UART buffer.
+                                 , uint8_t u8MsgLength ///< Received UART message length.
+                                  )
+{
+    uint8_t u8Checksum = 0;
+
+    for (u8ForLoopCounter = 0; u8ForLoopCounter < (u8MsgLength - 2); u8ForLoopCounter++)
+    {
+        u8Checksum += au8UartRxBuffer[u8ForLoopCounter];
+    }
+
+    if (au8UartRxBuffer[u8MsgLength-2] == u8Checksum)
+    {
+        return true;
+    }
+    
+    return false;
+}  /*** End ValidRxChecksum ***/
+
+
+/**
+* Calls appropriate callback function for received message.
+* 
+*/
+void LsrModule::HostProcessCallbackMsgStart(uint8_t* pu8MsgBuffer ///< Pointer to received message.
+                                             , uint8_t u8Length ///< Length of received message.
+                                              )
+{
+    if ((ptrRxMsgCallbackTable[(*(pu8MsgBuffer + LSR_MODULE_MSG_TYPE_BYTE_INDEX)) - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE]) != NULL)
+    {
+        ptrRxMsgCallbackTable[(*(pu8MsgBuffer + LSR_MODULE_MSG_TYPE_BYTE_INDEX)) - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE]();
+    }
+}   /*** End HostProcessCallbackMsgStart ***/
+
+
+/**
+* Determines if appropriate serial port is available.
+* @return True: Serial is available.  False: Serial is unavailable.
+*
+*/
+bool LsrModule::SerialAvailable(void)
+{
+    if (readable())
+    {
+        return true;
+    }
+    
+    return false;
+}   /*** End SerialAvailable ***/
+
+
+/**
+* Reads appropriate serial port.
+* @return Byte read.
+*
+*/
+uint8_t LsrModule::SerialRead(void)
+{
+    return getc();
+    
+}   /*** End SerialRead ***/
+
+
+/**
+* Refreshes and restarts Rx state machine.
+*
+*/
+void LsrModule::SerialRxCleanupRestart(void)
+{
+    SerialFlush();
+    u8UartRxBufferIndex = LSR_MODULE_MSG_START_BYTE_INDEX;
+    ptrHostState = &LsrModule::HostRxWaitForMsgStartByteState;
+}   /*** End SerialRxCleanupRestart ***/
+
+
+/**
+* Waits for data packet start byte.
+*
+*/
+void LsrModule::HostRxWaitForMsgStartByteState(void)
+{
+    if (SerialAvailable() && (SerialRead() == LSR_MODULE_SERIAL_MSG_START_BYTE))
+    {
+        au8UartRxBuffer[u8UartRxBufferIndex++] = LSR_MODULE_SERIAL_MSG_START_BYTE;
+        ptrHostState = &LsrModule::HostRxGetMsgLengthState;
+    }
+}   /*** End HostRxWaitForMsgStartByteState ***/
+
+
+/**
+* Gets data packet length byte.
+*
+*/
+void LsrModule::HostRxGetMsgLengthState(void)
+{
+    if (SerialAvailable())
+    {
+        u8RxReadByte = SerialRead();
+
+        if ((u8RxReadByte >= LSR_MODULE_MIN_SERIAL_RX_MSG_LENGTH) &&
+            (u8RxReadByte <= LSR_MODULE_MAX_SERIAL_RX_MSG_LENGTH))
+        {
+            au8UartRxBuffer[u8UartRxBufferIndex++] = u8RxReadByte;
+            ptrHostState = &LsrModule::HostRxGetMsgTypeState;
+        }
+        else
+        {
+            ptrHostState = &LsrModule::SerialRxCleanupRestart;
+        }
+    }
+}   /*** End HostRxGetMsgLengthState ***/
+
+
+/**
+* Gets data packet type byte.
+*
+*/
+void LsrModule::HostRxGetMsgTypeState(void)
+{
+    if (SerialAvailable())
+    {
+
+        u8RxReadByte = SerialRead();
+        
+        if (ValidMsgLengthAndType(u8RxReadByte, au8UartRxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX]))
+        {
+            au8UartRxBuffer[u8UartRxBufferIndex++] = u8RxReadByte;
+            ptrHostState = &LsrModule::HostRxWaitToGetRestOfMsgState;
+        }
+        else
+        {
+            ptrHostState = &LsrModule::SerialRxCleanupRestart;
+        }
+    }
+}   /*** End HostRxGetMsgTypeState ***/
+
+
+/**
+* Grabs rest of data packet bytes.
+*
+*/
+void LsrModule::HostRxWaitToGetRestOfMsgState(void)
+{
+    if (SerialAvailable())
+    {
+        u8RxReadByte = SerialRead();
+        au8UartRxBuffer[u8UartRxBufferIndex++] = u8RxReadByte;
+        
+        if (u8UartRxBufferIndex > LSR_MODULE_MAX_SERIAL_RX_MSG_LENGTH)
+        {
+            ptrHostState = &LsrModule::SerialRxCleanupRestart;
+        }
+        else if ((u8RxReadByte == LSR_MODULE_SERIAL_MSG_END_BYTE) && (u8UartRxBufferIndex == au8UartRxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX]))
+        {
+            ptrHostState = &LsrModule::HostRxValidateMsgState;
+        }
+    }
+}   /*** End HostRxWaitToGetRestOfMsgState ***/
+
+
+/**
+* Validates received message.
+*
+*/
+void LsrModule::HostRxValidateMsgState(void)
+{
+
+    if (ValidRxChecksum(au8UartRxBuffer, au8UartRxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX]))    // Is checksum good?
+    {
+        ptrHostState = &LsrModule::HostRxGoodMsgState;     // Good checksum - next state
+    }
+    else
+    {
+        ptrHostState = &LsrModule::SerialRxCleanupRestart;   // Bad checksum - restart
+    }
+}   /*** End HostRxValidateMsgState ***/
+
+
+/**
+* Calls appropriate received UART message callback and starts state machine over.
+*
+*/
+void LsrModule::HostRxGoodMsgState(void)
+{   
+    pu8RxBuffer = au8UartRxBuffer;
+    u8RxMsgLength = au8UartRxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX];
+    HostProcessCallbackMsgStart(au8UartRxBuffer, u8RxMsgLength);
+    ptrHostState = &LsrModule::SerialRxCleanupRestart;      // Start new RX sequence
+}   /*** End HostRxGoodMsgState ***/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LsrModule.h	Mon Jul 25 16:18:48 2016 +0000
@@ -0,0 +1,296 @@
+/**
+ * @file LsrModule.h
+ * @author LS Research LLC
+ * @version 1.0
+ *
+ * @section LICENSE
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details at
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @section DESCRIPTION
+ *
+ * UART communication API for LS Research's ProFLEX01 and SiFLEX02 ModFLEX Shields.
+ */
+
+/**
+ * Modified by Mark Harris at SAIT.ca
+ * Improved functionality for mbed
+ */
+
+#ifndef LsrModule_h
+#define LsrModule_h
+
+#include <inttypes.h>
+#include "mbed.h"
+
+#ifndef NULL
+    #define NULL    0
+#endif
+
+#define SIFLEX02  ///< Use with a SiFLEX02 ModFLEX Shield (900MHz)
+//#define PROFLEX01  ///< Use with a ProFLEX01 ModFLEX Shield (2.4GHz)
+
+/**
+* Message Index Defintions.
+*
+*/
+#define LSR_MODULE_MSG_START_BYTE_INDEX                                 0
+#define LSR_MODULE_MSG_LENGTH_BYTE_INDEX                                1
+#define LSR_MODULE_MSG_TYPE_BYTE_INDEX                                  2
+
+/**
+* Message Byte Types.
+*
+*/
+#define LSR_MODULE_SERIAL_MSG_START_BYTE                                0x01
+#define LSR_MODULE_SERIAL_MSG_END_BYTE                                  0x04
+
+/**
+* Rx Message Type Limits.
+*
+*/
+#define LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE                               0x81
+#define LSR_MODULE_MAX_SERIAL_RX_MSG_TYPE                               0xC5
+
+/**
+* LSR Module Host TX Message Definitions.
+*
+*/
+#define LSR_MODULE_QUERY_VERSION_MSG_TYPE                               0x01
+#define LSR_MODULE_SET_SECURITY_TX_FRAME_COUNTER_MSG_TYPE               0x0C
+#define LSR_MODULE_QUERY_SECURITY_TX_FRAME_COUNTER_MSG_TYPE             0x0D
+#define LSR_MODULE_SET_BASIC_RF_SETTINGS_MSG_TYPE                       0x10
+#define LSR_MODULE_QUERY_BASIC_RF_SETTINGS_MSG_TYPE                     0x11
+#define LSR_MODULE_SAVE_SETTINGS_TO_NV_MEMORY_MSG_TYPE                  0x12
+#define LSR_MODULE_RESET_REQUEST_MSG_TYPE                               0x13
+#define LSR_MODULE_QUERY_SUPPLY_VOLTAGE_MSG_TYPE                        0x14
+#define LSR_MODULE_QUERY_STATISTICS_MSG_TYPE                            0x15
+#define LSR_MODULE_CLEAR_STATISTICS_MSG_TYPE                            0x16
+#define LSR_MODULE_SET_HOST_DATA_RATE_MSG_TYPE                          0x18
+#define LSR_MODULE_SEND_SIMPLE_SHORT_RF_DATA_PACKET_MSG_TYPE            0x20
+#define LSR_MODULE_SEND_ADVANCED_SHORT_RF_DATA_PACKET_MSG_TYPE          0x22
+#define LSR_MODULE_SEND_SIMPLE_LONG_RF_DATA_PACKET_MSG_TYPE             0x24
+#define LSR_MODULE_SEND_ADVANCED_LONG_RF_DATA_PACKET_MSG_TYPE           0x26
+#define LSR_MODULE_SEND_SIMPLE_REPEATED_RF_DATA_PACKET_MSG_TYPE         0x2A
+#define LSR_MODULE_CHANNEL_ENERGY_SCAN_MSG_TYPE                         0x44
+
+/**
+* LSR Module Settings Definitions.
+*
+*/
+#define LSR_MODULE_TX_POWER_LEVEL_MIN                                   0
+#define LSR_MODULE_SECURITY_OVERHEAD                                    14
+#define LSR_MODULE_MIN_SERIAL_RX_MSG_LENGTH                             5
+#define LSR_MODULE_MAX_SERIAL_RX_MSG_LENGTH                             131
+
+#ifdef PROFLEX01
+    #define LSR_MODULE_RF_CHANNEL_MIN                                   11
+    #define LSR_MODULE_RF_CHANNEL_MAX                                   25
+    #define LSR_MODULE_TX_POWER_LEVEL_MAX                               19
+    #define LSR_MODULE_SIMPLE_SHORT_RF_DATA_LENGTH                      98
+    #define LSR_MODULE_ADVANCED_SHORT_RF_DATA_LENGTH                    98
+    #define LSR_MODULE_SIMPLE_LONG_RF_DATA_LENGTH                       98
+    #define LSR_MODULE_ADVANCED_LONG_RF_DATA_LENGTH                     98
+    #define LSR_MODULE_MAX_SERIAL_TX_MSG_LENGTH                         115
+#elif defined SIFLEX02
+    #define LSR_MODULE_RF_CHANNEL_MIN                                   1
+    #define LSR_MODULE_RF_CHANNEL_MAX                                   10
+    #define LSR_MODULE_TX_POWER_LEVEL_MAX                               21
+    #define LSR_MODULE_SIMPLE_SHORT_RF_DATA_LENGTH                      112
+    #define LSR_MODULE_ADVANCED_SHORT_RF_DATA_LENGTH                    110
+    #define LSR_MODULE_SIMPLE_LONG_RF_DATA_LENGTH                       100
+    #define LSR_MODULE_ADVANCED_LONG_RF_DATA_LENGTH                     98
+    #define LSR_MODULE_MAX_SERIAL_TX_MSG_LENGTH                         121
+#else
+    #error "Incorrect module type"
+#endif
+
+/**
+* Receiver ConfigurationBitmask Definitions.
+*
+*/
+#define LSR_MODULE_RX_CONFIG_ALLOW_BROADCAST_ADDRESS_BITMASK            0x01
+#define LSR_MODULE_RX_CONFIG_ALLOW_BROADCAST_PAN_BITMASK                0x02
+#define LSR_MODULE_RX_CONFIG_PROMISCUOUS_MODE_BITMASK                   0x04
+#define LSR_MODULE_RX_CONFIG_ALLOW_SECURED_PACKETS_MODE_BITMASK         0x08
+#define LSR_MODULE_RX_CONFIG_MAX                                        (LSR_MODULE_RX_CONFIG_ALLOW_BROADCAST_ADDRESS_BITMASK + LSR_MODULE_RX_CONFIG_ALLOW_BROADCAST_PAN_BITMASK + LSR_MODULE_RX_CONFIG_PROMISCUOUS_MODE_BITMASK + LSR_MODULE_RX_CONFIG_ALLOW_SECURED_PACKETS_MODE_BITMASK)
+
+/**
+* Transmit Options Bitmask Definitions.
+*
+*/
+#define LSR_MODULE_TX_OPTIONS_RETRIES_ACKS_BITMASK                      0x01
+#define LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK                      0x02
+#define LSR_MODULE_TX_OPTIONS_MAX                                       (LSR_MODULE_TX_OPTIONS_RETRIES_ACKS_BITMASK + LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK)
+
+/**
+* Host UART Data Rate Definitions.
+*
+*/
+#define LSR_MODULE_HOST_DATA_RATE_1200                                  0
+#define LSR_MODULE_HOST_DATA_RATE_2400                                  1
+#define LSR_MODULE_HOST_DATA_RATE_4800                                  2
+#define LSR_MODULE_HOST_DATA_RATE_9600                                  3
+#define LSR_MODULE_HOST_DATA_RATE_19200                                 4
+#define LSR_MODULE_HOST_DATA_RATE_38400                                 5
+#define LSR_MODULE_HOST_DATA_RATE_57600                                 6
+#define LSR_MODULE_HOST_DATA_RATE_115200                                7
+#define LSR_MODULE_HOST_DATA_RATE_MAX                                   LSR_MODULE_HOST_DATA_RATE_115200
+#define LSR_MODULE_10MS_UART_TIMEOUT                                    239
+
+/**
+* Channel Energy Scan Duration Definitions.
+*
+*/
+#define LSR_MODULE_SCAN_DURATION_MAX                                    14
+
+/**
+* Type Defintions.
+*
+*/
+typedef unsigned int    word_t;
+
+/**
+* Word structure.
+*
+*/
+typedef struct _words
+{
+    uint8_t lb; ///< Low byte.
+    uint8_t hb; ///< High byte.
+} Words_t;
+
+/**
+* Word union.
+*
+*/
+typedef union _wordu
+{
+    word_t   w; ///< Word.
+    uint16_t    u16; ///< Unsigned 16.
+    Words_t  ws; ///< Word structure.
+} Wordu_t;
+
+/**
+* Word structure.
+*
+*/
+typedef struct _dwords
+{
+    uint8_t lb; ///< Low byte.
+    uint8_t mlb; ///< Middle low byte.
+    uint8_t mhb; ///< Middle high byte.
+    uint8_t hb; ///<  High byte.
+} DWords_t;
+
+/**
+* Double word union.
+*
+*/
+typedef union _dwordu
+{
+    uint32_t u32; ///< Unsigned 32.
+    DWords_t dws; ///< Double word structure.
+} DWordu_t;
+
+
+class LsrModule : Serial
+{
+    public:
+    uint8_t* pu8RxBuffer; ///< Pointer to private UART receive buffer.
+    uint8_t u8RxMsgLength; ///< Length of private UART receive buffer.
+    //Functions:
+    LsrModule(PinName tx, PinName rx, int baudRate = 19200);
+    ~LsrModule();
+    bool SubscribeRxMsgCallback(uint8_t u8RxMsgType, void (*callback)(void)); 
+    bool UnsubscribeRxMsgCallback(uint8_t u8RxMsgType); 
+    void RunHostRxStateMachine(void);
+    // Tx Messages:
+    // 0x01
+    void QueryVersionMsg(void);
+    // 0x0C
+    void SetSecurityTransmitFrameCounterMsg(uint32_t* pu32FrameCounter);
+    // 0x0D
+    void QuerySecurityTransmitFrameCounterMsg(void);
+    // 0x10
+    void SetBasicRfSettingsMsg(uint16_t u16PanId, uint16_t u16AddrShort, uint8_t* pu8AddrLong, uint8_t u8RfChannel, uint8_t u8TxPowerLevel, uint8_t u8ReceiverConfig, uint8_t* pu8SecurityKey);
+    // 0x11
+    void QueryBasicRfSettingsMsg(void);
+    // 0x12
+    void SaveSettingsToNVMemoryMsg(void);
+    // 0x13
+    void ResetRequestMsg(void);
+    // 0x14
+    void QuerySupplyVoltageMsg(void);
+    // 0x15
+    void QueryStatisticsMsg(void);
+    // 0x16
+    void ClearStatisticsMsg(void);
+    // 0x18
+    void SetHostDataRateMsg(uint8_t u8HostDataRate);
+    // 0x20
+    void SendSimpleShortAddrRfDataPacketMsg(uint8_t* pu8Data, uint8_t u8DataLength, uint16_t u16DestAddress, uint8_t u8TxOptions, uint8_t u8PacketId);
+    // 0x22
+    void SendAdvancedShortAddrRfDataPacketMsg(uint8_t* pu8Data, uint8_t u8DataLength, uint16_t u16DestPanId, uint16_t u16DestAddress, uint8_t u8TxOptions, uint8_t u8PacketId);
+    // 0x24
+    void SendSimpleLongAddrRfDataPacketMsg(uint8_t* pu8Data, uint8_t u8DataLength, uint8_t* pu8DestAddress, uint8_t u8TxOptions, uint8_t u8PacketId);
+    // 0x26
+    void SendAdvancedLongAddrRfDataPacketMsg(uint8_t* pu8Data, uint8_t u8DataLength, uint16_t u16DestPanId, uint8_t* pu8DestAddress, uint8_t u8TxOptions, uint8_t u8PacketId);
+    // 0x44
+    void ChannelEnergyScanMsg(uint16_t u16ChannelMask, uint8_t u8ScanDuration);
+
+
+    private:
+    // Variables
+    uint8_t u8RxReadByte;
+    uint8_t u8ForLoopCounter;
+    uint8_t u8UartRxBufferIndex;
+    uint8_t u8UartTxBufferIndex;
+    uint8_t u8TxMsgChecksum;///< Transmit message checksum.
+    uint8_t au8UartRxBuffer[LSR_MODULE_MAX_SERIAL_RX_MSG_LENGTH];///< Receive buffer for UART communication from module.
+    uint8_t au8UartTxBuffer[LSR_MODULE_MAX_SERIAL_TX_MSG_LENGTH];///< Transmit buffer for UART communication to module.
+    bool bUartMethodFlag;
+
+    
+    // Function Pointers
+    void (LsrModule::*ptrHostState)(void);///< Runs uart UART receive state machine.
+    void (LsrModule::*ptrHostProcessCallbackState)(uint8_t*);///< Used to process received UART messages.
+    
+    
+    // Functions
+    void AddSerialMsgHeader(uint8_t u8MsgType, uint8_t u8MsgLength);
+    void AddSerialByteToMsgBuffer(uint8_t u8Data);
+    void AddSerialMsgTrailer(void);
+    void WriteSerialMsg(void);
+    void HostProcessCallbackMsgStart (uint8_t* pu8MsgBuffer, uint8_t u8Length);
+    // Rx Message Callbacks
+    
+
+    // Rx functions
+    bool ValidMsgLengthAndType(uint8_t u8MsgType, uint8_t u8MsgLength);
+    bool ValidRxChecksum(uint8_t* pu8MsgBuffer, uint8_t u8MsgLength);
+    void SerialFlush(void);
+    bool SerialAvailable(void);
+    uint8_t SerialRead(void);
+    
+    
+    // Rx State Machine States
+    void SerialRxCleanupRestart(void);
+    void HostRxWaitForMsgStartByteState(void);
+    void HostRxGetMsgLengthState(void);
+    void HostRxGetMsgTypeState(void);
+    void HostRxWaitToGetRestOfMsgState(void);
+    void HostRxValidateMsgState(void);
+    void HostRxGoodMsgState(void);
+};
+
+#endif
\ No newline at end of file