1

Dependencies:   X_NUCLEO_IKS01A1 LoRaWAN-lib SX1276Lib mbed

Files at this revision

API Documentation at this revision

Comitter:
ubhat
Date:
Fri Aug 26 19:36:35 2016 +0000
Child:
1:80c1daf19aa4
Commit message:
SX1276 Shield based Applications

Changed in this revision

app/Comissioning.h Show annotated file Show diff for this revision Revisions of this file
app/Common.h Show annotated file Show diff for this revision Revisions of this file
app/ComplianceTest.cpp Show annotated file Show diff for this revision Revisions of this file
app/ComplianceTest.h Show annotated file Show diff for this revision Revisions of this file
app/Config.h Show annotated file Show diff for this revision Revisions of this file
app/LoRaApp.cpp Show annotated file Show diff for this revision Revisions of this file
app/LoRaApp.h Show annotated file Show diff for this revision Revisions of this file
app/LoRaDeviceStateProc.cpp Show annotated file Show diff for this revision Revisions of this file
app/LoRaDeviceStateProc.h Show annotated file Show diff for this revision Revisions of this file
app/LoRaEventProc.cpp Show annotated file Show diff for this revision Revisions of this file
app/LoRaEventProc.h Show annotated file Show diff for this revision Revisions of this file
app/LoRaMacLayerService.cpp Show annotated file Show diff for this revision Revisions of this file
app/LoRaMacLayerService.h Show annotated file Show diff for this revision Revisions of this file
app/SerialDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
app/SerialDisplay.h Show annotated file Show diff for this revision Revisions of this file
app/main.cpp Show annotated file Show diff for this revision Revisions of this file
app/vt100.h Show annotated file Show diff for this revision Revisions of this file
board/board.cpp Show annotated file Show diff for this revision Revisions of this file
board/board.h Show annotated file Show diff for this revision Revisions of this file
mac/LoRaWAN-lib.lib Show annotated file Show diff for this revision Revisions of this file
radio/SX1276Lib.lib Show annotated file Show diff for this revision Revisions of this file
system/crypto/aes.cpp Show annotated file Show diff for this revision Revisions of this file
system/crypto/aes.h Show annotated file Show diff for this revision Revisions of this file
system/crypto/cmac.cpp Show annotated file Show diff for this revision Revisions of this file
system/crypto/cmac.h Show annotated file Show diff for this revision Revisions of this file
system/mbed.bld Show annotated file Show diff for this revision Revisions of this file
system/timer.cpp Show annotated file Show diff for this revision Revisions of this file
system/timer.h Show annotated file Show diff for this revision Revisions of this file
system/utilities.cpp Show annotated file Show diff for this revision Revisions of this file
system/utilities.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/Comissioning.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,78 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: End device comissioning parameters
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __LORA_COMISSIONING_H__
+#define __LORA_COMISSIONING_H__
+
+/*!
+ * When set to 1 the application uses the Over-the-Air activation procedure
+ * When set to 0 the application uses the Personalization activation procedure
+ */
+#define OVER_THE_AIR_ACTIVATION                     1
+
+/*!
+ * Indicates if the end-device is to be connected to a private or public network
+ */
+#define LORAWAN_PUBLIC_NETWORK                      true
+
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+
+/*!
+ * Mote device IEEE OUI (big endian)
+ * \remark This is unique to a company or organization
+ */
+#define IEEE_OUI                                    0x00, 0x00, 0x00
+
+/*!
+ * Mote device IEEE EUI (big endian)
+ *
+ * \remark In this application, if the last 4 bytes are all 0, then the 32 bit address is automatically generated using a pseudo random generator seeded with a value derived from BoardUniqueId value
+ * If provided by user, e.g. { IEEE_OUI, 0x00, 0x00, 0x00, 0xFF, 0x01 }, then this value is used by the application
+ */
+#define LORAWAN_DEVICE_EUI                          { IEEE_OUI, 0x00, 0x00, 0x00, 0x00, 0x00 }
+
+/*!
+ * Application IEEE EUI (big endian)
+ */
+#define LORAWAN_APPLICATION_EUI                     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+
+/*!
+ * AES encryption/decryption cipher application key
+ */
+#define LORAWAN_APPLICATION_KEY                     { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }
+
+#else
+
+/*!
+ * Device address on the network (big endian)
+ *
+ * \remark In this application, if the value is 0, then the address is automatically generated using a pseudo random generator seeded with a value derived from BoardUniqueId value
+ * If provided by user, e.g. 0x78563412, then this value is used by the application
+ */
+#define LORAWAN_DEVICE_ADDRESS                      ( uint32_t )0x0
+
+/*!
+ * AES encryption/decryption cipher network session key
+ */
+#define LORAWAN_NWKSKEY                             { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+
+/*!
+ * AES encryption/decryption cipher application session key
+ */
+#define LORAWAN_APPSKEY                             { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+
+#endif
+
+
+#endif // __LORA_COMISSIONING_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/Common.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,72 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Extern declaration of parameters defined in main.cpp
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include "Comissioning.h"
+#include "board.h"
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_MAX_SIZE                           64
+
+/*!
+ * Current network ID
+ */
+#define LORAWAN_NETWORK_ID                          ( uint32_t )0
+
+
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+/*!
+ * Over the Air Activation 
+ */
+
+extern uint8_t DevEui[];
+extern uint8_t AppEui[];
+extern uint8_t AppKey[];
+
+#else
+/*!
+ * Activation by Personalization 
+ */
+
+extern uint8_t NwkSKey[];
+extern uint8_t AppSKey[];
+extern uint32_t DevAddr;
+
+#endif
+
+extern uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; //  User application data size
+
+extern uint8_t AppPort; // Application port
+
+extern uint8_t AppDataSize; // Application size
+
+extern uint8_t IsTxConfirmed; // Indicates if the node is sending confirmed or unconfirmed messages
+
+extern bool IsTxIntUpdate; // Indicates if a new transmit interrupt can be set
+
+extern bool NextTx; // Indicates if a new packet can be sent
+
+extern bool IsNetworkJoinedStatusUpdate; // Indicates if the MAC layer network join status has changed.
+
+extern bool IsTxUpdate; // Indicates if the message sent
+
+extern bool IsRxUpdate; // Indicates if the message received in the RX window.
+
+extern TimerEvent_t TxNextPacketTimer; // Timer to handle the application data transmission duty cycle
+
+#endif // __COMMON_H__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/ComplianceTest.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,117 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Compliance Test for LoRaWAN End-Device
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#include "ComplianceTest.h"
+
+
+void PrepareComplianceTestFrame( McpsIndication_t *McpsIndication )
+{
+    uint8_t *pData;
+
+    pData = &McpsIndication->Buffer[0];
+    
+    if( ComplianceTest.Running == false )
+    {
+        // Check compliance test enable command (i)
+        if( ( McpsIndication->BufferSize == 4 ) && 
+            ( pData[0] == 0x01 ) && ( pData[1] == 0x01 ) && ( pData[2] == 0x01 ) && (pData[3] == 0x01 ) )
+        {
+            AppPort = 224;
+            AppDataSize = 2;
+            ComplianceTest.DownLinkCounter = 0;
+            ComplianceTest.LinkCheck = false;
+            ComplianceTest.DemodMargin = 0;
+            ComplianceTest.NbGateways = 0;
+            ComplianceTest.Running = true;
+            ComplianceTest.State = 1;       
+        }
+    }
+    else
+    {    
+        ComplianceTest.State = pData[0];
+        switch( ComplianceTest.State )
+        {
+        case 0: // Check compliance test disable command (ii)
+            IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
+            AppPort = LORAWAN_APP_PORT;
+            AppDataSize = LORAWAN_APP_DATA_SIZE;
+            ComplianceTest.DownLinkCounter = 0;
+            ComplianceTest.Running = false;
+            
+            MibRequestConfirm_t mibReq;
+            mibReq.Type = MIB_ADR;
+            mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
+            LoRaMacMibSetRequestConfirm( &mibReq );
+            break;
+        case 1: // (iii, iv)
+            AppDataSize = 2;
+            break;
+        case 2: // Enable confirmed messages (v)
+            IsTxConfirmed = true;
+            ComplianceTest.State = 1;
+            break;
+        case 3:  // Disable confirmed messages (vi)
+            IsTxConfirmed = false;
+            ComplianceTest.State = 1;
+            break;
+        case 4: // (vii)
+            AppDataSize = McpsIndication->BufferSize;
+
+            AppData[0] = 4;
+            for( uint8_t i = 1; i < AppDataSize; i++ )
+            {
+                AppData[i] = McpsIndication->Buffer[i] + 1;
+            }
+            break;
+        case 5: // (viii)
+            {
+                MlmeReq_t mlmeReq;
+                mlmeReq.Type = MLME_LINK_CHECK;
+                LoRaMacMlmeRequest( &mlmeReq );
+            }
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void RunComplianceTest( void )
+{
+    if( ComplianceTest.LinkCheck == true )
+    {
+        ComplianceTest.LinkCheck = false;
+        AppDataSize = 3;
+        AppData[0] = 5;
+        AppData[1] = ComplianceTest.DemodMargin;
+        AppData[2] = ComplianceTest.NbGateways;
+        ComplianceTest.State = 1;
+    }
+    else
+    {
+        switch( ComplianceTest.State )
+        {        
+        case 1:
+            AppDataSize = 2;
+            AppData[0] = ComplianceTest.DownLinkCounter >> 8;
+            AppData[1] = ComplianceTest.DownLinkCounter;
+            break;
+
+        case 4:
+            ComplianceTest.State = 1;
+            break;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/ComplianceTest.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,44 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Definition of parameters for Compliance Test
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __COMPLIANCE_H__
+#define __COMPLIANCE_H__
+
+#include "mbed.h"
+#include "Common.h"
+#include "Config.h"
+#include "LoRaMac.h"
+
+#define COMPLIANCE_TX_DUTYCYCLE 5000000 // 5sec
+
+struct ComplianceTest_s
+{
+    bool Running;
+    uint8_t State;
+    bool IsTxConfirmed;
+    uint8_t AppPort;
+    uint8_t AppDataSize;
+    uint8_t *AppDataBuffer;
+    uint16_t DownLinkCounter;
+    bool LinkCheck;
+    uint8_t DemodMargin;
+    uint8_t NbGateways;
+};
+
+extern ComplianceTest_s ComplianceTest;
+
+void PrepareComplianceTestFrame( McpsIndication_t *McpsIndication );
+void RunComplianceTest( void );
+
+#endif // __COMPLIANCE_H__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/Config.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,138 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: End device communication parameters
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#ifndef __LORA_CONFIG_H__
+#define __LORA_CONFIG_H__
+
+/*!
+ * Configure End-Device to use 8-channels corresponding to Block A
+ * Comment/Uncomment to disable/enable Hybrid mode
+ */
+#define USE_BAND_915_HYBRID
+
+#ifndef USE_BAND_915_HYBRID
+/*!
+ * Configure End-Device to use 64-channels across to Block A thru Block H
+ */
+#define USE_BAND_915
+
+#endif
+
+/*!
+ * Join requests trials periodicity. It is the time between RX1/RX2 and next TX
+ */
+#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE           5000000  // value in us
+
+/*!
+ * Defines the application data transmission periodicity. It is the time between RX1/RX2 and next TX
+ */
+#define APP_TX_DUTYCYCLE                            5000000  // value in us
+
+/*!
+ * LoRaWAN confirmed messages
+ * \remark 1 : Confirmed messages enabled. Must receive ACK from network server
+           0 : Confirmed messages disabled. 
+ */
+#define LORAWAN_CONFIRMED_MSG_ON                    1
+
+/*!
+ * LoRaWAN Adaptive Data Rate
+ *
+ * \remark Please note that when ADR is enabled the end-device uses default datarate of DR_0
+ */
+#define LORAWAN_ADR_ON                              0
+
+/*!
+ * Default mote datarate
+ * \remark DR_0 : 980 bps; DR_1 : 1760 bps; DR_2 : 3125 bps; DR_3 : 5470 bps; DR_4 : 12500 bps
+ */
+#define LORAWAN_DEFAULT_DATARATE                    DR_0
+
+/*!
+ * LoRaWAN application port
+ */
+#define LORAWAN_APP_PORT                            5
+
+/*!
+ * LoRaWAN User defined Tx Power
+ *
+ * \remark The Tx power level is set as TX_POWER_P_DBM, where 10 <= P <= 30 and P is even value { i.e. P = 10, 12, 14 ... 28 or 30 }
+ */
+#define LORAWAN_TX_POWER                            TX_POWER_20_DBM
+
+#if ( LORAWAN_APP_PORT == 5 )
+/*====================================================
+            US01 GPS APPLICATION DEMO (PORT 5)
+====================================================*/
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_SIZE                       11
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#elif ( LORAWAN_APP_PORT == 6 )
+/*====================================================
+                SENET M2X DEMO (PORT 6)
+====================================================*/
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_SIZE                       2
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#elif ( LORAWAN_APP_PORT == 7 )
+/*====================================================
+                SENET GPS DEMO (PORT 7)
+====================================================*/
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_SIZE                       11
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#elif ( LORAWAN_APP_PORT == 11 )
+/*====================================================
+                PUSH BUTTON DEMO (PORT 11)
+====================================================*/
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_SIZE                       2
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#elif ( LORAWAN_APP_PORT == 12 )
+/*====================================================
+                TRANSMIT ON VERTICAL ORIENTATION DEMO (PORT 12)
+====================================================*/
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_SIZE                       2
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+#endif
+
+#endif //  __LORA_CONFIG_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/LoRaApp.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,404 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: User-defined applications such as GPS, Temp, Accelerometer, LED indications etc.
+            Event based actions such as LED blink on Tx, LED toggle on downlink etc
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#include "LoRaApp.h"
+
+bool VerticalStatus = false;
+
+
+Application::Application( uint8_t * memptr )
+{
+    BuffAddr = memptr;
+    memset( BuffAddr, 0, LORAWAN_APP_DATA_MAX_SIZE );
+    BuffPtr = 0;    
+}
+
+Application::~Application( )
+{
+}
+
+void Application::ApplicationAppendData( uint8_t *pData, uint8_t len )
+{
+    memcpy( BuffAddr + BuffPtr, pData, len );
+    BuffPtr += len;
+}
+
+void Application::ApplicationPtrPos( uint8_t ptrPos )
+{
+    BuffPtr = ptrPos;
+}
+
+void Application::ApplicationCall( eAppType App )
+{
+    switch( App )
+    {
+        // Appends 8 Bytes (3 bytes longitude, 3 bytes latitude, 2 bytes altitude) to TX buffer
+        case AppGps:
+        {
+            /*
+            Gps.service( );
+
+            uint16_t altitudeGps = atoi( Gps.NmeaGpsData.NmeaAltitude );
+
+            if( ( BuffPtr + 8 ) <= LORAWAN_APP_DATA_SIZE )
+            {               
+                BuffAddr[BuffPtr++] = ( Gps.LatitudeBinary >> 16 ) & 0xFF;
+                BuffAddr[BuffPtr++] = ( Gps.LatitudeBinary >> 8 ) & 0xFF;
+                BuffAddr[BuffPtr++] = Gps.LatitudeBinary & 0xFF;
+                BuffAddr[BuffPtr++] = ( Gps.LongitudeBinary >> 16 ) & 0xFF;
+                BuffAddr[BuffPtr++] = ( Gps.LongitudeBinary >> 8 ) & 0xFF;
+                BuffAddr[BuffPtr++] = Gps.LongitudeBinary & 0xFF;           
+                BuffAddr[BuffPtr++] = ( altitudeGps >> 8 ) & 0xFF;
+                BuffAddr[BuffPtr++] = altitudeGps & 0xFF;
+            }
+            */
+            break;
+        }
+
+        // Appends 1 Byte to TX buffer
+        case AppTemp:
+        {    
+            /*       
+            Mpl3115a2.ReadTemperature( );
+            if( ( BuffPtr + 1 ) <= LORAWAN_APP_DATA_SIZE )
+            {
+                BuffAddr[BuffPtr++] = ( int32_t )Mpl3115a2.Temperature;     // Signed degrees Celcius in half degree units. So, +/-63 °C                         
+            }
+            */
+            break;
+        }
+
+        // Appends 1 Byte to TX buffer
+        case AppBat:
+        {  
+            if( ( BuffPtr + 1 ) <= LORAWAN_APP_DATA_SIZE )
+            {
+                BuffAddr[BuffPtr++] = BoardGetBatteryLevel( );              // Per LoRaWAN spec; 0 = Charging; 1...254 = level, 255 = N/A
+            }
+            break;
+        }
+
+        // Appends incremental values of 1 Byte each to TX buffer until Full
+        case AppRamp:
+        {
+            int32_t i, j;
+
+            // Populate Tx Buffer with increasing byte values starting from 0x00, 0x01, 0x02 ... 
+            for( i = BuffPtr, j = 0; i < LORAWAN_APP_DATA_SIZE; i++ )
+            {
+                BuffAddr[i] = j++;
+            }
+            BuffPtr = LORAWAN_APP_DATA_SIZE;
+            break;
+        }
+
+        // Appends 2 Bytes to TX buffer
+        case AppAccl:
+        {  
+            /* 
+            uint8_t statusReg; 
+
+            // Read the PS_STATUS register
+            statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );
+
+            // Display Orientation of NAMote on Serial Port
+            SerialAcclMetrDisplay( statusReg );
+
+            // If Orientation of the Mote changed then let Green LED ON
+            if( ( statusReg & 0x80 ) != 0 )
+            {
+                AppLed = 1;
+                CtrlLED( Green, LED_ON );
+            }
+
+            // Read and populate device orientation in Tx Buffer
+            if( ( BuffPtr + 2 ) <= LORAWAN_APP_DATA_SIZE )
+            {
+                if( statusReg & 0x40 )
+                {
+                    if( statusReg & 0x01 )
+                    {
+                        BuffAddr[BuffPtr++] = 0x66; // horizontal + faceup
+                    }
+                    else
+                    {
+                        BuffAddr[BuffPtr++] = 0x99; // horizontal + facedown
+                    }
+
+                    BuffAddr[BuffPtr++] = 0; // vertical = false
+                }
+                else
+                {
+                    BuffAddr[BuffPtr++] = 0; // horizontal = false
+                    BuffAddr[BuffPtr++] = 0x11; // vertical = true
+                }               
+            }       
+            */
+            break;
+        }       
+
+        case AppAcclSenet:
+        {   
+            /*
+            uint8_t statusReg; 
+
+            // Read the PS_STATUS register
+            statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );
+
+            // Display Orientation of NAMote on Serial Port 
+            SerialAcclMetrDisplay( statusReg );
+
+            // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer                       
+            if( ( statusReg & 0x40 ) != 0 )
+            {   
+                AppLed = 0;
+                CtrlLED( Green, LED_OFF );
+                BuffAddr[BuffPtr++] = 0; // horizontal
+            }
+            else
+            {
+                AppLed = 1;
+                CtrlLED( Green, LED_ON );
+                BuffAddr[BuffPtr++] = 10; // vertical
+            }                       
+            */
+            break;
+        }
+
+        case AppPushButton:
+        {   
+            uint16_t PushButtonCnt;
+            uint8_t *p = (uint8_t *) &PushButtonCnt;
+
+            PushButtonCnt = LoRaMacUplinkStatus.UplinkCounter;
+                
+            memcpy( &BuffAddr[BuffPtr], p, sizeof(uint16_t) );
+            
+            break;
+        }
+
+        default:
+        {            
+            break;
+        }
+    }
+}
+
+/*
+static void OnRedLedTimerEvent( void )
+{
+    TimerStop( &RedLedTimer.LedTimer );
+
+    if( RedLed == LED_OFF )
+    {
+        RedLed = LED_ON;
+    }
+    else
+    {
+        RedLed = LED_OFF;
+    }
+}
+
+static void OnYellowLedTimerEvent( void )
+{
+    TimerStop( &YellowLedTimer.LedTimer );
+
+    if( YellowLed == LED_OFF )
+    {
+        YellowLed = LED_ON;
+    }
+    else
+    {
+        YellowLed = LED_OFF;
+    }
+}
+
+static void OnGreenLedTimerEvent( void )
+{
+    TimerStop( &GreenLedTimer.LedTimer );
+
+    if( GreenLed == LED_OFF )
+    {
+        GreenLed = LED_ON;
+    }
+    else
+    {
+        GreenLed = LED_OFF;
+    }
+}
+
+TimerLed::TimerLed( eLedType led )
+{
+    switch( led )
+    {
+        case Red:
+        {
+            TimerInit( &LedTimer, OnRedLedTimerEvent );
+            break;
+        }
+
+        case Yellow:
+        {
+            TimerInit( &LedTimer, OnYellowLedTimerEvent );
+            break;
+        }
+
+        case Green:
+        {
+            TimerInit( &LedTimer, OnGreenLedTimerEvent );
+            break;
+        }
+    }
+    
+}
+        
+TimerLed::~TimerLed( )
+{
+}
+
+void BlinkLED( eLedType led, uint32_t time )
+{
+    switch( led )
+    {
+        case Red:
+        {
+            TimerSetValue( &RedLedTimer.LedTimer, time );
+            TimerStart( &RedLedTimer.LedTimer );
+            RedLed = LED_ON;
+            break;
+        }
+
+        case Yellow:
+        {
+            TimerSetValue( &YellowLedTimer.LedTimer, time );
+            TimerStart( &YellowLedTimer.LedTimer );
+            YellowLed = LED_ON;
+            break;
+        }
+
+        case Green:
+        {
+            TimerSetValue( &GreenLedTimer.LedTimer, time );
+            TimerStart( &GreenLedTimer.LedTimer );
+            GreenLed = LED_ON;
+            break;
+        }
+    }
+}
+
+void ToggleLED( eLedType led )
+{
+    switch( led )
+    {
+        case Red:
+        {
+            if( RedLed == LED_OFF )
+            {
+                RedLed = LED_ON;
+            }
+            else
+            {
+                RedLed = LED_OFF;
+            }
+            break;
+        }
+
+        case Yellow:
+        {
+            if( YellowLed == LED_OFF )
+            {
+                YellowLed = LED_ON;
+            }
+            else
+            {
+                YellowLed = LED_OFF;
+            }
+            break;
+        }
+
+        case Green:
+        {
+            if( GreenLed == LED_OFF )
+            {
+                GreenLed = LED_ON;
+            }
+            else
+            {
+                GreenLed = LED_OFF;
+            }
+            break;
+        }
+    }
+}   
+
+void CtrlLED( eLedType led, uint8_t state )
+{
+    switch( led )
+    {
+        case Red:
+        {
+            RedLed = state;
+            break;
+        }
+
+        case Yellow:
+        {
+            YellowLed = state;
+            break;
+        }
+
+        case Green:
+        {
+            GreenLed = state;
+            break;
+        }
+
+        case Usr:
+        {
+            if( state )
+            {
+                UsrLed = LED_ON;
+            }
+            else
+            {
+                UsrLed = LED_OFF;
+            }
+            break;
+        }
+    }
+}
+*/
+void CheckOrientation( void )
+{
+    /*
+    uint8_t statusReg; 
+    
+    // Read the PS_STATUS register
+    statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );
+
+     // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer                       
+    if( ( statusReg & 0x40 ) != 0 )
+    {           
+        CtrlLED( Green, LED_OFF );
+        VerticalStatus = false; // horizontal
+    }
+    else
+    {        
+        CtrlLED( Green, LED_ON );
+        VerticalStatus = true; // vertical
+    } 
+    */      
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/LoRaApp.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,151 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: User-defined applications such as GPS, Temp, Accelerometer, LED indications etc.
+            Event based actions such as LED blink on Tx, LED toggle on downlink etc
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#ifndef __APPLICATION_H__
+#define __APPLICATION_H__
+
+#include "board.h"
+#include "Common.h"
+#include "SerialDisplay.h"
+
+/*!
+ * LED ON/OFF definition
+ */
+#define LED_ON          0
+#define LED_OFF         1
+
+/*!
+ * LED types
+ */
+enum eLedType
+{
+    Red = 0,// Red LED
+    Yellow = 1, // Yellow LED
+    Green = 2, // Green LED
+    Usr = 3, // USR LED
+};
+
+/*!
+ * user-defined Application names
+ */
+enum eAppType
+{
+    AppGps = 0, // GPS application
+    AppTemp = 1, // Temperature measurement application
+    AppBat = 2, // Battery measurement application
+    AppRamp = 3, // Generate Ramp bytes
+    AppAccl = 4, // Accelerometer application
+    AppAcclSenet = 5, // Senet + M2X application example
+    AppPushButton = 6, // Push button application example
+};
+
+/*!
+ * Application
+ */
+class Application 
+{
+public:
+    /*!  
+     * \brief Initializes TX buffer address to private pointer
+     *
+     * \param [IN] memptr pointer to TX buffer
+     */
+    Application( uint8_t * memptr );
+
+    /*!
+     * \brief Application Destructor
+     */
+    ~Application( );
+    
+     /*!     
+     * \brief Call application type and append to application buffer
+     *
+     * \param [IN] AppType application type: GPS, Battery, Temp etc.
+     */
+    void ApplicationCall( eAppType AppType );
+     
+     /*!     
+     * \brief Append data to the TX buffer
+     *
+     * \param [IN] pData pointer to the data to be appended to TX buffer
+     * \param [IN] Len lenght of the data to be appended to TX buffer
+     */
+    void ApplicationAppendData( uint8_t *pData, uint8_t len );
+    
+     /*!     
+     * \brief Point the pointer corresponding to the TX buffer to specified index
+     *
+     * \param [IN] ptrPos index to where to point to in the TX buffer
+     */
+    void ApplicationPtrPos( uint8_t ptrPos );
+
+private:
+    /*!
+     * Index to the application buffer
+     */
+    uint8_t BuffPtr;
+    /*!
+     * Application buffer address pointer
+     */
+    uint8_t *BuffAddr;   
+};
+
+class TimerLed
+{
+public:
+    TimerEvent_t LedTimer;      
+    TimerLed( eLedType );
+    ~TimerLed( );
+};
+
+extern TimerLed RedLedTimer;
+
+extern TimerLed YellowLedTimer;
+
+extern TimerLed GreenLedTimer;
+
+extern Application LoRaApp;
+
+extern bool AppLed;
+
+extern bool VerticalStatus;
+
+/*!  
+* \brief Blink LED
+*
+* \param [IN] led Red, yellow or green LED
+* \param [IN] time time in usec for which the LED must be ON
+ */
+void BlinkLED( eLedType led, uint32_t time );
+
+/*!  
+* \brief Turn LED ON if OFF; OFF if ON
+*
+* \param [IN] led Red, yellow or green LED
+*/
+void ToggleLED( eLedType led );
+
+/*!  
+* \brief Control the State of the LED
+*
+* \param [IN] led Red, yellow or green LED
+* \param [IN] state ON or OFF
+*/
+void CtrlLED( eLedType led, uint8_t state );
+
+void CheckOrientation( void );
+
+#endif // __APPLICATION_H__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/LoRaDeviceStateProc.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,225 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Process function calls from various Device states
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#include "LoRaDeviceStateProc.h"
+#include "LoRaMacLayerService.h"
+
+eDevicState DeviceState;
+
+sLoRaMacUplinkStatus LoRaMacUplinkStatus;
+
+sLoRaMacDownlinkStatus LoRaMacDownlinkStatus;
+
+LoRaMacPrimitives_t LoRaPrimitives;
+
+LoRaMacCallback_t LoRaCallbacks;
+
+MibRequestConfirm_t LoRaMibReq;
+
+MlmeReq_t mlmeReq;
+
+
+/*!
+ * \brief Function executed on TxNextPacket Timeout event
+ */
+static void OnTxNextPacketTimerEvent( void )
+{
+    MibRequestConfirm_t mibReq;
+    LoRaMacStatus_t status;
+
+    TimerStop( &TxNextPacketTimer );
+
+    mibReq.Type = MIB_NETWORK_JOINED;
+    status = LoRaMacMibGetRequestConfirm( &mibReq );
+
+    if( status == LORAMAC_STATUS_OK )
+    {
+        if( mibReq.Param.IsNetworkJoined == true )
+        {
+            DeviceState = DEVICE_STATE_SEND;            
+        }
+        else
+        {
+            DeviceState = DEVICE_STATE_JOIN;
+        }
+        NextTx = true;
+    }
+}
+
+void DeviceInit( void )
+{
+    LoRaPrimitives.MacMcpsConfirm = McpsConfirm;
+    LoRaPrimitives.MacMcpsIndication = McpsIndication;
+    LoRaPrimitives.MacMlmeConfirm = MlmeConfirm;
+    LoRaCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
+    LoRaMacInitialization( &LoRaPrimitives, &LoRaCallbacks );
+
+    TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
+
+    LoRaMibReq.Type = MIB_ADR;
+    LoRaMibReq.Param.AdrEnable = LORAWAN_ADR_ON;
+    LoRaMacMibSetRequestConfirm( &LoRaMibReq );
+
+    LoRaMibReq.Type = MIB_PUBLIC_NETWORK;
+    LoRaMibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
+    LoRaMacMibSetRequestConfirm( &LoRaMibReq );
+
+    LoRaMibReq.Type = MIB_CHANNELS_TX_POWER;
+    LoRaMibReq.Param.ChannelsTxPower = LORAWAN_TX_POWER;
+    LoRaMacMibSetRequestConfirm( &LoRaMibReq );
+
+    LoRaMacDownlinkStatus.DownlinkCounter = 0;
+}
+
+void DeviceJoinUpdate( void )
+{
+    LoRaMibReq.Type = MIB_NETWORK_JOINED;
+    LoRaMacMibGetRequestConfirm( &LoRaMibReq );            
+}
+
+void DeviceJoin( void )
+{
+#if( OVER_THE_AIR_ACTIVATION != 0 )    
+
+    mlmeReq.Type = MLME_JOIN;
+
+    mlmeReq.Req.Join.DevEui = DevEui;
+    mlmeReq.Req.Join.AppEui = AppEui;
+    mlmeReq.Req.Join.AppKey = AppKey;
+
+    if( NextTx == true )
+    {
+        LoRaMacMlmeRequest( &mlmeReq );
+    }
+
+#else   
+    // Choose a random device address if not already defined in Config.h
+    if( DevAddr == 0 )
+    {
+        // Random seed initialization
+        srand1( BoardGetRandomSeed( ) );
+        DevAddr = randr( 0, 0x01FFFFFF );
+    }
+
+    LoRaMibReq.Type = MIB_NET_ID;
+    LoRaMibReq.Param.NetID = LORAWAN_NETWORK_ID;
+    LoRaMacMibSetRequestConfirm( &LoRaMibReq );
+
+    LoRaMibReq.Type = MIB_DEV_ADDR;
+    LoRaMibReq.Param.DevAddr = DevAddr;
+    LoRaMacMibSetRequestConfirm( &LoRaMibReq );
+
+    LoRaMibReq.Type = MIB_NWK_SKEY;
+    LoRaMibReq.Param.NwkSKey = NwkSKey;
+    LoRaMacMibSetRequestConfirm( &LoRaMibReq );
+
+    LoRaMibReq.Type = MIB_APP_SKEY;
+    LoRaMibReq.Param.AppSKey = AppSKey;
+    LoRaMacMibSetRequestConfirm( &LoRaMibReq );
+
+    LoRaMibReq.Type = MIB_NETWORK_JOINED;
+    LoRaMibReq.Param.IsNetworkJoined = true;
+    LoRaMacMibSetRequestConfirm( &LoRaMibReq );
+
+#endif
+}
+
+/*!
+ * \brief   Prepares the payload of the frame
+ */
+void PrepareTxFrame( uint8_t port )
+{
+    MibRequestConfirm_t mibReq;
+
+    if( BoardGetBatteryLevel( ) < LOW_BAT_THRESHOLD )
+    {
+        mibReq.Type = MIB_CHANNELS_TX_POWER;
+        LoRaMacMibGetRequestConfirm( &mibReq );
+        // TX_POWER_30_DBM = 0, TX_POWER_28_DBM = 1, ..., TX_POWER_20_DBM = 5, ..., TX_POWER_10_DBM = 10
+        // The if condition is then "less than" to check if the power is greater than 20 dBm
+        if( mibReq.Param.ChannelsTxPower < TX_POWER_20_DBM )
+        {
+            mibReq.Param.ChannelsTxPower = TX_POWER_20_DBM;
+            LoRaMacMibSetRequestConfirm( &mibReq );
+        }
+    }
+    
+    if( port == 224 )
+    {
+        RunComplianceTest( );        
+    }
+    else
+    {
+        PrepareLoRaFrame( port );
+    }
+}
+
+/*!
+ * \brief   Prepares the payload of the frame
+ *
+ * \retval  [0: frame could be send, 1: error]
+ */
+bool SendFrame( void )
+{
+    McpsReq_t mcpsReq;
+    LoRaMacTxInfo_t txInfo;
+    
+    if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
+    {
+        // Send empty frame in order to flush MAC commands
+        mcpsReq.Type = MCPS_UNCONFIRMED;
+        mcpsReq.Req.Unconfirmed.fBuffer = NULL;
+        mcpsReq.Req.Unconfirmed.fBufferSize = 0;
+        mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
+        
+        LoRaMacUplinkStatus.Acked = false;
+        LoRaMacUplinkStatus.Port = 0;
+        LoRaMacUplinkStatus.Buffer = NULL;
+        LoRaMacUplinkStatus.BufferSize = 0;        
+    }
+    else
+    {
+        LoRaMacUplinkStatus.Acked = false;
+        LoRaMacUplinkStatus.Port = AppPort;
+        LoRaMacUplinkStatus.Buffer = AppData;
+        LoRaMacUplinkStatus.BufferSize = AppDataSize;
+
+        if( ( IsTxConfirmed == false ) || ( LoRaMacUplinkStatus.UplinkCounter == 0 ) )
+        {
+            mcpsReq.Type = MCPS_UNCONFIRMED;
+            mcpsReq.Req.Unconfirmed.fPort = AppPort;
+            mcpsReq.Req.Unconfirmed.fBuffer = AppData;
+            mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize;
+            mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
+        }
+        else
+        {
+            mcpsReq.Type = MCPS_CONFIRMED;
+            mcpsReq.Req.Confirmed.fPort = AppPort;
+            mcpsReq.Req.Confirmed.fBuffer = AppData;
+            mcpsReq.Req.Confirmed.fBufferSize = AppDataSize;
+            mcpsReq.Req.Confirmed.NbTrials = 8;
+            mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
+        }
+    }
+
+    LoRaMacUplinkStatus.Type = mcpsReq.Type;
+
+    if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
+    {
+        return false;
+    }
+    return true;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/LoRaDeviceStateProc.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,105 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Process function calls from various Device states
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+#ifndef __LORA_DEVICE_STATE_H__
+#define __LORA_DEVICE_STATE_H__
+
+#include "Common.h"
+#include "board.h"
+#include "LoRaMac.h"
+#include "LoRaEventProc.h"
+#include "SerialDisplay.h"
+#include "mbed.h"
+#include "LoRaMacLayerService.h"
+
+/*!
+ * Strucure containing the Uplink status
+ */
+struct sLoRaMacUplinkStatus
+{
+    /*!
+     * MCPS-Request type
+     */
+    Mcps_t Type;    
+    uint8_t Acked;
+    int8_t Datarate;
+    uint16_t UplinkCounter;
+    uint8_t Port;
+    uint8_t *Buffer;
+    uint8_t BufferSize;
+    int8_t TxPower;
+};
+
+/*!
+ * Strucure containing the Downlink status
+ */
+struct sLoRaMacDownlinkStatus
+{
+    int16_t Rssi;
+    int8_t Snr;
+    uint16_t DownlinkCounter;
+    bool RxData;
+    uint8_t Port;
+    uint8_t *Buffer;
+    uint8_t BufferSize;
+    uint8_t RxSlot;
+};
+
+/*!
+ * Device states
+ */
+enum eDevicState
+{
+    DEVICE_STATE_INIT,
+    DEVICE_STATE_JOIN,
+    DEVICE_STATE_SEND,
+    DEVICE_STATE_SLEEP
+};
+
+extern sLoRaMacUplinkStatus LoRaMacUplinkStatus;
+
+extern sLoRaMacDownlinkStatus LoRaMacDownlinkStatus;
+
+extern eDevicState DeviceState;
+
+/*!
+ * \brief Initialize Device: Timer, MAC Services, MAC
+ */
+void DeviceInit( void );
+
+/*!
+ * \brief Device Join update
+ */
+void DeviceJoinUpdate( void );
+
+/*!
+ * \brief OTA: if device not joined, send JOIN REQUEST to network
+ *      ABP: Request DevAddr if not already set
+ */
+void DeviceJoin( void );
+
+/*!
+ * \brief   Prepares the payload of the frame to be transmitted
+ *
+ * \param [IN] port application port corresponding to which payload is generated
+ */
+void PrepareTxFrame( uint8_t port );
+
+/*!
+ * \brief   Send the frame
+ *
+ */
+bool SendFrame( void );
+
+#endif // __LORA_DEVICE_STATE_H__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/LoRaEventProc.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,312 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Define events during Join, Tx & Rx
+            Prepare TX packet by appending with appropriate application data
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#include "LoRaEventProc.h"
+
+/*!
+ * Defines the application data transmission duty cycle
+ */
+uint32_t TxDutyCycleTime = APP_TX_DUTYCYCLE;
+
+bool AppLed = 0;
+
+/*!
+ * \brief   Prepares the payload of the frame based on application port
+ */
+void PrepareLoRaFrame( uint8_t port )
+{
+
+    switch( port )
+    {    
+    case 5:
+        {   
+            uint8_t tmp;
+            uint8_t tmpLength;
+            uint8_t ptrIndex = 0;
+            
+            // Point the pointer to position index of Tx Buffer
+            LoRaApp.ApplicationPtrPos( ptrIndex );
+
+            tmp = ( AppLed != 0 ) ? 0x0F : 0x00;
+            tmpLength = 1;
+            
+            LoRaApp.ApplicationAppendData( &tmp, tmpLength ); // Populate lower nibble of 0th Byte with LED state            
+
+            /*!
+            *  Read Temperature
+            *  Appends 1 Byte to TX buffer
+            */
+            LoRaApp.ApplicationCall( AppTemp );
+
+            /*!
+            *  Read Battery
+            *  Appends 1 Byte to TX buffer
+            */
+            LoRaApp.ApplicationCall( AppBat );
+
+            /*!
+            *  Read GPS coordinates
+            *  Appends 8 Bytes (3 bytes longitude, 3 bytes latitude, 2 bytes altitude) to TX buffer
+            */
+            LoRaApp.ApplicationCall( AppGps );            
+
+            /*!
+            *  Read Accelerometer
+            *  Appends 2 Bytes to TX buffer
+            *   Value       Orientation
+            *   0x99 0x00   horizontal + faceup
+            *   0x66 0x00   horizontal + facedown
+            *   0x00 0x11   vertical
+            */
+            LoRaApp.ApplicationCall( AppAccl ); // Generate Accelerometer data bytes    
+
+            /*!
+            *  Generate Ramp data bytes
+            *  Appends incremental values of 1 Byte each to TX buffer until Full
+            */
+            LoRaApp.ApplicationCall( AppRamp );
+
+            break;
+        }   
+
+    // Senet M2X ORIENTATION Demo 
+    // Set LORAWAN_APP_DATA_SIZE to 2
+    case 6: 
+        { 
+            uint8_t ptrIndex = 1;
+            
+            //Point the pointer to position index of Tx Buffer
+            LoRaApp.ApplicationPtrPos( ptrIndex );
+            
+            LoRaApp.ApplicationCall( AppAcclSenet ); // Generate Accelerometer data bytes    
+            
+            
+
+            break;
+        }
+        
+    /* Senet GPS Demo 
+       Data Format (in Hex):
+            [01, 02, Lattitude (3 bytes), Longitude (3 Bytes), Elevation (2 bytes), Tx Power (1 byte)]
+    */  
+    case 7: 
+        { 
+            uint8_t ptrIndex = 0;
+            uint8_t tmp[] = {0x01, 0x02};
+            
+            //Point the pointer to position index of Tx Buffer
+            LoRaApp.ApplicationPtrPos( ptrIndex );
+            
+            LoRaApp.ApplicationAppendData( tmp, 2 );  
+            
+            LoRaApp.ApplicationCall( AppGps ); // Generate Accelerometer data bytes  
+            
+            uint8_t pow = 30 - 2*(( uint8_t ) LoRaMacUplinkStatus.TxPower);
+            LoRaApp.ApplicationAppendData( &pow, 1 );  
+
+            break;
+        }
+
+    // Push-Button Demo     
+    case 11: 
+        { 
+            uint8_t ptrIndex = 0;
+            
+            //Point the pointer to position index of Tx Buffer
+            LoRaApp.ApplicationPtrPos( ptrIndex );
+            
+            LoRaApp.ApplicationCall( AppPushButton ); // Transmit uplink counter   
+            
+            break;
+        }
+
+    // Transmit on Vertical Orientation Demo     
+    case 12: 
+        { 
+            uint8_t ptrIndex = 0;
+            
+            //Point the pointer to position index of Tx Buffer
+            LoRaApp.ApplicationPtrPos( ptrIndex );
+            
+            LoRaApp.ApplicationCall( AppPushButton ); // Transmit uplink counter      
+            
+            break;
+        }
+        
+    default:
+        break;
+    }
+}
+
+
+/*!
+ * \brief   Sets Interrupt for next payload transmission
+ */
+void InitNextTxInterrupt( uint8_t port )
+{   
+    switch( port )
+    {  
+    /* GPS Application Demo
+        Set Timer interrupt for next uplink
+    */
+    case 5:
+        { 
+        }
+
+    /* Senet + M2X demo
+    Set Timer interrupt for next uplink
+    */
+    case 6: 
+        { 
+            
+        }
+        
+    /* Senet GPS Demo 
+       Set Timer interrupt for next uplink
+    */  
+    case 7: 
+        { 
+            // Schedule next packet transmission
+            TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
+            TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
+            TimerStart( &TxNextPacketTimer );
+            break;
+        }
+
+    /* Push Button Demo 
+       Send Packet Immedietly if PC0 = GND
+    */  
+    case 11: 
+        { 
+            /*
+            volatile bool PushButtonStatus;
+
+            PushButtonStatus = PC0;
+            
+            if(PushButtonStatus == 0)
+            {
+                // Send Pkt immedietly if PC = GND
+                DeviceState = DEVICE_STATE_SEND;
+                NextTx = true;
+            }
+            else
+            {
+                // Keep polling
+                IsTxIntUpdate = true;
+            }
+            */
+            break;
+        }   
+
+    /* Orientation Demo 
+       Send Packet Immedietly if Mote is Vertical
+    */  
+    case 12: 
+        {             
+            CheckOrientation( );
+            
+            if(VerticalStatus == true)
+            {
+                // Send Pkt immedietly if PC = GND
+                DeviceState = DEVICE_STATE_SEND;
+                NextTx = true;
+            }
+            else
+            {
+                // Keep polling
+                IsTxIntUpdate = true;
+            }
+            break;
+        }   
+
+    /* Compliance Test 
+       Set Timer interrupt for next uplink
+    */
+    case 224:
+        {               
+            // Schedule next packet transmission
+            TimerSetValue( &TxNextPacketTimer, COMPLIANCE_TX_DUTYCYCLE );
+            TimerStart( &TxNextPacketTimer );
+            break;
+        }
+
+    default:
+        {
+            // Schedule next packet transmission
+            TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
+            TimerStart( &TxNextPacketTimer );
+            break;
+        }
+    }
+
+}
+
+/*!
+ * \brief   What to do during JOIN process ? blink/toggle LED etc.
+ */
+void JoinEvent( void )
+{
+    // CtrlLED is defined in LoRaBoardAppIf.h
+    // param 1: LED color (Red, Yellow or Green)
+    // param 2: LED_ON or LED_OFF
+    //CtrlLED( Red, LED_ON ); 
+}
+
+
+/*!
+ * \brief   What to do during TX ? blink/toggle LED etc.
+ */
+void TxEvent( void )
+{
+    int blinkTime = 25000;
+
+    // Blink Red LED for 25msec
+    //BlinkLED( Red, blinkTime );
+}
+
+void RxEvent()
+{
+    // Toggle yellow LED
+    //ToggleLED( Yellow );  
+
+    // If Rx Data is 0x01 turn on Green LED else if 0x0 Turn Green LED off
+    if( LoRaMacDownlinkStatus.BufferSize == 1 )
+    {       
+        if( LoRaMacDownlinkStatus.Buffer[0] == 0x01 )
+        {
+            AppLed = 1;
+        }
+        else
+        {
+            if( LoRaMacDownlinkStatus.Buffer[0] == 0x00 )
+            {
+                AppLed = 0;
+            }
+        }
+    }
+
+    if( AppLed != 0 )
+    {
+        // Turn  USR_LED ON
+        //CtrlLED( Usr, LED_ON );
+    }
+    else
+    {
+        // Turn  USR_LED OFF
+        //CtrlLED( Usr, LED_OFF );
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/LoRaEventProc.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,53 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Define events during Join, Tx & Rx
+            Prepare TX packet by appending with appropriate application data
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#ifndef __LORA_EVENT_PROC_H__
+#define __LORA_EVENT_PROC_H__
+
+#include "board.h"
+#include "LoRaApp.h"
+#include "LoRaDeviceStateProc.h"
+
+#define APP_TX_DUTYCYCLE_RND                        1000000
+
+/*!
+ * \brief   Prepares the payload of the frame specific to the application port
+ *
+ * \param [IN] port application port 
+ */
+void PrepareLoRaFrame( uint8_t port );
+
+/*!
+ * \brief   Prepares the payload of the frame based on application port
+ */
+void InitNextTxInterrupt( uint8_t port );
+
+/*!
+ * \brief  Define action during the Network Join process: Blink, Toggle or Set LED ON
+ */
+void JoinEvent( void );
+
+/*!
+ * \brief  Define action during the Transmit process: Blink, Toggle or Set LED ON
+ */
+void TxEvent( void );
+
+/*!
+ * \brief  Define action when downlink received: Blink, Toggle or Set LED ON
+ */
+void RxEvent( void );
+
+#endif // __LORA_EVENT_PROC_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/LoRaMacLayerService.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,195 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: MAC Layer Services: MLME & MCPS
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#include "LoRaMacLayerService.h"
+
+/*!
+ * \brief   MCPS-Confirm event function
+ *
+ * \param   [IN] McpsConfirm - Pointer to the confirm structure,
+ *               containing confirm attributes.
+ */
+void McpsConfirm( McpsConfirm_t *McpsConfirm )
+{
+    if( McpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
+    {
+        switch( McpsConfirm->McpsRequest )
+        {
+            case MCPS_UNCONFIRMED:
+            {
+                // Check Datarate
+                // Check TxPower
+                break;
+            }
+            case MCPS_CONFIRMED:
+            {
+                // Check Datarate
+                // Check TxPower
+                // Check AckReceived
+                // Check NbRetries
+                LoRaMacUplinkStatus.Acked = McpsConfirm->AckReceived;
+                break;
+            }
+            case MCPS_PROPRIETARY:
+            {
+                break;
+            }
+            default:
+                break;
+        }        
+    }
+
+    LoRaMacUplinkStatus.Datarate = McpsConfirm->Datarate;
+    LoRaMacUplinkStatus.UplinkCounter = McpsConfirm->UpLinkCounter;
+    LoRaMacUplinkStatus.TxPower = McpsConfirm->TxPower;
+
+    IsTxIntUpdate = true;
+}
+
+/*!
+ * \brief   MCPS-Indication event function
+ *
+ * \param   [IN] McpsIndication - Pointer to the indication structure,
+ *               containing indication attributes.
+ */
+void McpsIndication( McpsIndication_t *McpsIndication )
+{
+    uint8_t port;
+
+    if( McpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK )
+    {
+        return;
+    }
+
+    switch( McpsIndication->McpsIndication )
+    {
+        case MCPS_UNCONFIRMED:
+        {
+            break;
+        }
+        case MCPS_CONFIRMED:
+        {
+            break;
+        }
+        case MCPS_PROPRIETARY:
+        {
+            break;
+        }
+        case MCPS_MULTICAST:
+        {
+            break;
+        }
+        default:
+            break;
+    }
+
+    // Check Multicast
+    // Check Port
+    // Check Datarate
+    // Check FramePending
+    // Check Buffer
+    // Check BufferSize
+    // Check Rssi
+    // Check Snr
+    // Check RxSlot
+    LoRaMacDownlinkStatus.Rssi = McpsIndication->Rssi;
+    if( McpsIndication->Snr & 0x80 ) // The SNR sign bit is 1
+    {
+        // Invert and divide by 4
+        LoRaMacDownlinkStatus.Snr = ( ( ~McpsIndication->Snr + 1 ) & 0xFF ) >> 2;
+        LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
+    }
+    else
+    {
+        // Divide by 4
+        LoRaMacDownlinkStatus.Snr = ( McpsIndication->Snr & 0xFF ) >> 2;
+    }
+    LoRaMacDownlinkStatus.DownlinkCounter++;
+    LoRaMacDownlinkStatus.RxData = McpsIndication->RxData;      
+    LoRaMacDownlinkStatus.Port = McpsIndication->Port;
+    LoRaMacDownlinkStatus.Buffer = McpsIndication->Buffer;
+    LoRaMacDownlinkStatus.BufferSize = McpsIndication->BufferSize;
+    LoRaMacDownlinkStatus.RxSlot = McpsIndication->RxSlot;
+
+    if( ComplianceTest.Running == 1 )
+    {
+        port = 224;
+        ComplianceTest.DownLinkCounter++;
+    }
+    else
+    {
+        port = McpsIndication->Port;
+    }
+    
+    if( McpsIndication->RxData == true )
+    {
+        switch( port )
+        {
+        case 1: // The application LED can be controlled on port 1 or 2
+        case 2:            
+            break;
+        case 224:
+            PrepareComplianceTestFrame( McpsIndication );            
+            break;
+        default:
+            break;
+        }
+    }
+
+    IsRxUpdate = true;
+
+}
+
+/*!
+ * \brief   MLME-Confirm event function
+ *
+ * \param   [IN] MlmeConfirm - Pointer to the confirm structure,
+ *               containing confirm attributes.
+ */
+void MlmeConfirm( MlmeConfirm_t *MlmeConfirm )
+{
+    if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
+    {
+        switch( MlmeConfirm->MlmeRequest )
+        {
+            case MLME_JOIN:
+            {
+                // Status is OK, node has joined the network
+                IsNetworkJoinedStatusUpdate = true;
+                break;
+            }
+            case MLME_LINK_CHECK:
+            {
+                // Check DemodMargin
+                // Check NbGateways
+                if( ComplianceTest.Running == true )
+                {
+                    ComplianceTest.LinkCheck = true;
+                    ComplianceTest.DemodMargin = MlmeConfirm->DemodMargin;
+                    ComplianceTest.NbGateways = MlmeConfirm->NbGateways;
+                }
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    // Schedule next packet transmission
+    TimerSetValue( &TxNextPacketTimer, OVER_THE_AIR_ACTIVATION_DUTYCYCLE );
+    TimerStart( &TxNextPacketTimer );
+
+    DeviceState = DEVICE_STATE_SLEEP;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/LoRaMacLayerService.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,33 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: MAC Layer Services: MLME & MCPS
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+
+#ifndef __LORA_MAC_LAYER_SERVICE__
+#define __LORA_MAC_LAYER_SERVICE__
+
+#include "board.h"
+#include "LoRaMac.h"
+#include "Common.h"
+#include "LoRaEventProc.h"
+#include "ComplianceTest.h"
+#include "SerialDisplay.h"
+#include "mbed.h"
+
+
+void McpsConfirm( McpsConfirm_t *McpsConfirm );
+void McpsIndication( McpsIndication_t *McpsIndication );
+void MlmeConfirm( MlmeConfirm_t *MlmeConfirm );
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/SerialDisplay.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,157 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: VT100 serial display management
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+
+#include "SerialDisplay.h"
+
+VT100 vt( USBTX, USBRX );
+
+void SerialDisplayJoinUpdate( void )
+{
+    printf( "###### ===== JOINING ==== ######\r\n" );
+    
+    DisplayNetworkParam( );
+
+    printf( "\r\n" );
+}
+
+void SerialDisplayTxUpdate(void)
+{
+    printf( "###### ===== UPLINK FRAME %d ==== ######\r\n", LoRaMacUplinkStatus.UplinkCounter );
+
+    DisplayNetworkParam( );
+    
+    printf( "TX PORT: %d\r\n", LoRaMacUplinkStatus.Port );
+
+    if( LoRaMacUplinkStatus.BufferSize != 0 )
+    {
+        printf( "TX DATA: " );
+        if( LoRaMacUplinkStatus.Type == MCPS_CONFIRMED )
+        {
+            printf( "CONFIRMED\r\n" );
+        }
+        else
+        {
+            printf( "UNCONFIRMED\r\n" );
+        }
+        SerialDisplayHex( LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
+    }
+
+    printf( "DATA RATE: DR%d\r\n", LoRaMacUplinkStatus.Datarate );
+
+    printf( "TX POWER: %d dBm\r\n", 30 - ( LoRaMacUplinkStatus.TxPower << 1 ) );
+
+    printf( "BATTERY: %2.2fV\r\n", BoardGetBatteryLevel( ) );
+
+    printf( "\r\n");
+}
+
+void SerialDisplayRxUpdate( void )
+{
+    printf( "###### ===== DOWNLINK FRAME %d ==== ######\r\n", LoRaMacDownlinkStatus.DownlinkCounter );
+
+    printf( "RX WINDOW: %d\r\n", LoRaMacDownlinkStatus.RxSlot + 1 );
+    
+    printf( "RX PORT: %d\r\n", LoRaMacDownlinkStatus.Port );
+
+    if( LoRaMacDownlinkStatus.BufferSize != 0 )
+    {
+        printf( "RX DATA: \r\n" );
+        SerialDisplayHex( LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize );
+    }
+
+    printf( "RX RSSI: %d\r\n", LoRaMacDownlinkStatus.Rssi );
+
+    printf( "RX SNR: %d\r\n", LoRaMacDownlinkStatus.Snr );
+
+    printf( "\r\n" );
+}
+
+void SerialDisplayHex( uint8_t *pData, uint8_t len )
+{
+    int i;
+    bool newline = 0;
+
+    for( i = 0; i < len; i++ )
+    {
+        if( newline != 0 )
+        {
+            printf( "\r\n" );
+            newline = 0;
+        }
+
+        printf( "%02X ", pData[i] );
+
+        if( ( ( i + 1 ) % 16 ) == 0 )
+        {
+            newline = 1;
+        }
+    }
+    printf( "\r\n" );
+}
+
+void SerialAcclMetrDisplay( uint8_t statusReg )
+{
+    printf( "===== DEVICE ORIENTATION ====\r\n" );
+    if( ( statusReg & 0x40 ) != 0 )
+    {
+        printf( "HORIZONTAL + " );
+        if( ( statusReg & 0x01 ) != 0 )
+        {
+            printf( "FACE DOWN" );
+        }
+        else
+        {
+            printf( "FACE UP" );
+        }
+    }
+    else
+    {
+        printf( "VERTICAL" ); 
+    }
+    printf( "\r\n\r\n" );
+}
+
+void DisplayNetworkParam( void )
+{
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+
+    printf( "DEVEUI: " );
+    SerialDisplayHex( DevEui, 8 );
+
+    printf( "APPEUI: " );
+    SerialDisplayHex( AppEui, 8 );
+
+    printf( "APPKEY: " );
+    SerialDisplayHex( AppKey, 16 );
+
+#else
+
+    printf( "DEVADDR: " );
+    
+    uint8_t *pData = ( uint8_t* )&DevAddr;
+    for( int32_t i = 3; i >= 0; i-- )
+    {
+        printf( "%02X ", pData[i] );
+    }
+    printf( "\r\n" );
+
+    printf( "NWKSKEY: " );
+    SerialDisplayHex( NwkSKey, 16 );
+
+    printf( "APPSKEY: " );
+    SerialDisplayHex( AppSKey, 16 );
+
+#endif
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/SerialDisplay.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,32 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Serial display management
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Uttam Bhat
+*/
+#ifndef __SERIAL_DISPLAY_H__
+#define __SERIAL_DISPLAY_H__
+
+#include "board.h"
+#include "vt100.h"
+#include "Comissioning.h"
+#include "LoRaMac.h"
+#include "Common.h"
+#include "LoRaDeviceStateProc.h"
+
+void SerialDisplayJoinUpdate( void );
+void SerialDisplayTxUpdate( void );
+void SerialDisplayRxUpdate( void );
+void SerialDisplayHex( uint8_t *pData, uint8_t len );
+void SerialAcclMetrDisplay( uint8_t statusReg );
+void DisplayNetworkParam( void );
+
+#endif // __SERIAL_DISPLAY_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/main.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,229 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: LoRaMac classA device implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#include "mbed.h"
+#include "board.h"
+#include "radio.h"
+
+#include "LoRaMac.h"
+#include "Comissioning.h"
+#include "SerialDisplay.h"
+#include "ComplianceTest.h"
+#include "LoRaDeviceStateProc.h"
+#include "LoRaEventProc.h"
+#include "LoRaApp.h"
+
+/*!
+ * Defines a random delay for application data transmission duty cycle. 1s,
+ * value in [us].
+ */
+
+
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+
+uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
+uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
+uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
+
+#else
+
+uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
+uint8_t AppSKey[] = LORAWAN_APPSKEY;
+
+/*!
+ * Device address
+ */
+uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
+
+#endif
+
+/*!
+ * Application port
+ */
+uint8_t AppPort = LORAWAN_APP_PORT;
+
+/*!
+ * User application data size
+ */
+uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
+
+/*!
+ * User application data
+ */
+uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
+
+/*!
+ * Application to handle functions
+ */
+Application LoRaApp( AppData );
+
+/*!
+ * Indicates if the node is sending confirmed or unconfirmed messages
+ */
+uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
+
+/*!
+ * Timer to handle the application data transmission duty cycle
+ */
+TimerEvent_t TxNextPacketTimer;
+
+/*!
+ * Indicates if a new transmit interrupt can be set
+ */
+bool IsTxIntUpdate = false;
+
+/*!
+ * Indicates if a new packet can be sent
+ */
+bool NextTx = true;
+
+/*!
+ * LoRaWAN compliance tests support data
+ */
+ComplianceTest_s ComplianceTest;
+
+/*!
+ * Indicates if the MAC layer network join status has changed.
+ */
+bool IsNetworkJoinedStatusUpdate = false;
+
+/*!
+ * Indicates if the message sent.
+ */
+bool IsTxUpdate = false;
+
+/*!
+ * Indicates if the message received in the RX window.
+ */
+bool IsRxUpdate = false;
+
+
+/**
+ * Main application entry point.
+ */
+int main( void )
+{
+
+    // Initialize board peripherals
+    BoardInit( );
+
+    // Initialize Device state
+    DeviceState = DEVICE_STATE_INIT;
+
+    while( 1 )
+    {           
+        if( IsNetworkJoinedStatusUpdate == true )
+        {
+            IsNetworkJoinedStatusUpdate = false;
+
+            DeviceJoinUpdate( );
+        }
+
+        if( IsTxUpdate == true )
+        {
+            // If downlink received then update Serial Terminal and execute Rx event
+            IsTxUpdate = false;
+            
+            // Update serial terminal
+            SerialDisplayTxUpdate( );           
+        }
+
+        if( IsTxIntUpdate == true )
+        {
+            IsTxIntUpdate = false;
+            
+            // Initialize next Tx Interrupt
+            InitNextTxInterrupt( AppPort );
+        }
+
+        if( IsRxUpdate == true )
+        {
+            // If downlink received then update Serial Terminal and execute Rx event
+            IsRxUpdate = false;
+            RxEvent( );
+            SerialDisplayRxUpdate( );            
+        }
+        
+        switch( DeviceState )
+        {
+            case DEVICE_STATE_INIT:
+            {
+                // Initialize MAC, MAC services, Primitives
+                DeviceInit( );
+
+                // Change Device state
+                DeviceState = DEVICE_STATE_JOIN;
+                break;
+            }
+            case DEVICE_STATE_JOIN:
+            {
+#if( OVER_THE_AIR_ACTIVATION != 0 )                // OTA 
+
+                // Generate DevEUI if not defined by User
+                BoardGetDevEUI( DevEui );
+
+                // Join N/w server
+                DeviceJoin( );                
+
+                // Show on serial terminal
+                SerialDisplayJoinUpdate( );
+
+                // Execute Join event
+                JoinEvent( );
+
+                DeviceState = DEVICE_STATE_SLEEP;
+
+#else                                           // ABP
+                DeviceJoin( );
+
+                DeviceState = DEVICE_STATE_SEND;
+#endif
+                IsNetworkJoinedStatusUpdate = true;
+                break;
+            }
+            case DEVICE_STATE_SEND:
+            {               
+                if( NextTx == true )
+                {
+                    // Prepare payload frame based on application port
+                    PrepareTxFrame( AppPort );
+
+                    // Send payload over the air
+                    NextTx = SendFrame( );
+
+                    // Execute transmit event
+                    TxEvent( );                 
+                }
+
+                if( NextTx == false )
+                {
+                    IsTxUpdate = true;
+                }
+                
+                DeviceState = DEVICE_STATE_SLEEP;
+                break;
+            }            
+            case DEVICE_STATE_SLEEP:
+            {
+                // Wake up through events
+                break;
+            }
+            default:
+            {
+                DeviceState = DEVICE_STATE_INIT;
+                break;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/vt100.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,213 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: VT100 terminal support class
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __VT100_H__
+#define __VT100_H__
+
+#ifndef STRING_STACK_LIMIT
+#define STRING_STACK_LIMIT    120
+#endif
+
+/**
+ * Implements VT100 terminal commands support.
+ * Implments also the same behaviour has RawSerial class. The only difference
+ * is located in putc fucntion where writeable check is made befor sending the character.
+ */
+class VT100 : public SerialBase
+{
+public:
+    enum TextAttributes
+    {
+        ATTR_OFF      = 0,
+        BOLD          = 1,
+        USCORE        = 4,
+        BLINK         = 5,
+        REVERSE       = 7,
+        BOLD_OFF      = 21,
+        USCORE_OFF    = 24,
+        BLINK_OFF     = 25,
+        REVERSE_OFF   = 27,
+    };
+
+    enum Colors
+    {
+        BLACK   = 0,
+        RED     = 1,
+        GREEN   = 2,
+        BROWN   = 3,
+        BLUE    = 4,
+        MAGENTA = 5,
+        CYAN    = 6,
+        WHITE   = 7,
+    };
+
+    VT100( PinName tx, PinName rx ): SerialBase( tx, rx )
+    {
+        this->baud( 115200 );
+        // initializes terminal to "power-on" settings
+        // ESC c
+        this->printf( "\x1B\x63" );
+    }
+    
+    void ClearScreen( uint8_t param )
+    {
+        // ESC [ Ps J
+        // 0    Clear screen from cursor down
+        // 1    Clear screen from cursor up
+        // 2    Clear entire screen 
+        this->printf( "\x1B[%dJ", param );
+    }
+
+    void ClearLine( uint8_t param )
+    {
+        // ESC [ Ps K
+        // 0    Erase from the active position to the end of the line, inclusive (default)
+        // 1    Erase from the start of the screen to the active position, inclusive
+        // 2    Erase all of the line, inclusive
+        this->printf( "\x1B[%dK", param );
+    }
+
+    void SetAttribute( uint8_t attr )
+    {
+        // ESC [ Ps;...;Ps m
+        this->printf( "\x1B[%dm", attr );
+    }
+
+    void SetAttribute( uint8_t attr, uint8_t fgcolor, uint8_t bgcolor )
+    {
+        // ESC [ Ps;...;Ps m
+        this->printf( "\x1B[%d;%d;%dm", attr, fgcolor + 30, bgcolor + 40 );
+    }
+
+    void SetCursorMode( uint8_t visible )
+    {
+        if( visible == true )
+        {
+            // ESC [ ? 25 h
+            this->printf( "\x1B[?25h" );
+        }
+        else
+        {
+            // ESC [ ? 25 l
+            this->printf( "\x1B[?25l" );
+        }
+    }
+
+    void SetCursorPos( uint8_t line, uint8_t col )
+    {
+        // ESC [ Pl ; Pc H
+        this->printf( "\x1B[%d;%dH", line, col );
+    }
+
+    void PutStringAt( uint8_t line, uint8_t col, const char *s )
+    {
+        this->SetCursorPos( line, col );
+        this->printf( "%s", s );
+    }
+
+    void PutCharAt( uint8_t line, uint8_t col, uint8_t c )
+    {
+        this->SetCursorPos( line, col );
+        this->printf( "%c", c );
+    }
+
+    void PutHexAt( uint8_t line, uint8_t col, uint16_t n )
+    {
+        this->SetCursorPos( line, col );
+        this->printf( "%X", n );
+    }
+
+    void PutBoxDrawingChar( uint8_t c )
+    {
+        this->printf( "\x1B(0%c\x1b(B", c );
+    }
+    
+    bool Readable( void )
+    {
+        return this->readable( );
+    }
+    
+    uint8_t GetChar( void )
+    {
+        return this->getc( );
+    }
+
+    /*
+     * RawSerial class implmentation copy.
+     */
+    /** Read a char from the serial port
+     *
+     * @returns The char read from the serial port
+     */
+    int getc( )
+    {
+        return _base_getc();
+    }
+
+    /** Write a char to the serial port
+     *
+     * @param c The char to write
+     *
+     * @returns The written char or -1 if an error occured
+     */
+    int putc( int c )
+    {
+        while( this->writeable( ) != 1 );
+        return _base_putc( c );
+    }
+
+    /** Write a string to the serial port
+     *
+     * @param str The string to write
+     *
+     * @returns 0 if the write succeeds, EOF for error
+     */
+    int puts( const char *str )
+    {
+        while( *str )
+            putc( *str++ );
+        return 0;
+    }
+
+    // Experimental support for printf in RawSerial. No Stream inheritance
+    // means we can't call printf() directly, so we use sprintf() instead.
+    // We only call malloc() for the sprintf() buffer if the buffer
+    // length is above a certain threshold, otherwise we use just the stack.
+    int printf( const char *format, ... )
+    {
+        std::va_list arg;
+        va_start( arg, format );
+        int len = vsnprintf( NULL, 0, format, arg );
+        if( len < STRING_STACK_LIMIT )
+        {
+            char temp[STRING_STACK_LIMIT];
+            vsprintf( temp, format, arg );
+            puts( temp );
+        }
+        else
+        {
+            char *temp = new char[len + 1];
+            vsprintf( temp, format, arg );
+            puts( temp );
+            delete[] temp;
+        }
+        va_end( arg );
+        return len;
+    }
+
+private:
+    
+};
+
+#endif // __VT100_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/board/board.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,69 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Target board general functions implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#include "mbed.h"
+#include "board.h"
+
+MoteVersion_t BoardGetVersion( void );
+
+DigitalIn I2cInterrupt( PB_4 );
+I2C I2c(I2C_SDA, I2C_SCL);
+
+DigitalOut Pc7( PC_7 );
+DigitalIn Pc1( PC_1 );
+
+#define AIN_VREF            3.3     // STM32 internal refernce
+#define AIN_VBAT_DIV        2       // Resistor divider
+
+SX1276MB1xAS Radio( NULL );
+
+void BoardInit( void )
+{
+    TimerTimeCounterInit( );
+}
+
+
+uint8_t BoardGetBatteryLevel( void ) 
+{
+    return 0xFE;
+}
+
+uint32_t BoardGetRandomSeed( void )
+{
+    return ( ( *( uint32_t* )ID1 ) ^ ( *( uint32_t* )ID2 ) ^ ( *( uint32_t* )ID3 ) );
+}
+
+void BoardGetDevEUI( uint8_t *id )
+{
+    uint32_t *pDevEuiHWord = ( uint32_t* )&id[4];
+
+    if( *pDevEuiHWord == 0 )
+    {        
+        *pDevEuiHWord = BoardGetRandomSeed( );
+    }
+    
+}
+
+void BoardGetUniqueId( uint8_t *id )
+{
+    id[7] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 24;
+    id[6] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 16;
+    id[5] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 8;
+    id[4] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) );
+    id[3] = ( ( *( uint32_t* )ID2 ) ) >> 24;
+    id[2] = ( ( *( uint32_t* )ID2 ) ) >> 16;
+    id[1] = ( ( *( uint32_t* )ID2 ) ) >> 8;
+    id[0] = ( ( *( uint32_t* )ID2 ) );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/board/board.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,77 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2015 Semtech
+
+Description: Target board general functions implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+#include "Config.h"
+#include "mbed.h"
+#include "system/timer.h"
+#include "debug.h"
+#include "system/utilities.h"
+#include "sx1276-hal.h"
+
+/*!
+ * Unique Devices IDs register set ( STM32L1xxx )
+ */
+#define         ID1                                 ( 0x1FF800D0 )
+#define         ID2                                 ( 0x1FF800D4 )
+#define         ID3                                 ( 0x1FF800E4 )
+
+#define LOW_BAT_THRESHOLD   3.45
+
+extern SX1276MB1xAS Radio;
+
+typedef enum
+{
+    MOTE_VERSION_NONE = 0,
+    MOTE_VERSION_2,
+    MOTE_VERSION_3,
+}MoteVersion_t;
+
+
+/*!
+ * \brief Initializes the target board peripherals.
+ */
+void BoardInit( void );
+
+/*!
+ * \brief Measure the Battery level
+ *
+ * \retval value  battery level ( 0: very low, 254: fully charged )
+ */
+uint8_t BoardGetBatteryLevel( void );
+
+/*!
+ * Returns a pseudo random seed generated using the MCU Unique ID
+ *
+ * \retval seed Generated pseudo random seed
+ */
+uint32_t BoardGetRandomSeed( void );
+
+/*!
+ * \brief Generates Lower 32 bits of DEVEUI using 96 bits unique device ID 
+ *
+ * \param [IN] id Pointer to an array that will contain the Unique ID
+ */
+void BoardGetDevEUI( uint8_t *id );
+
+/*!
+ * \brief Gets the board 64 bits unique ID 
+ *
+ * \param [IN] id Pointer to an array that will contain the Unique ID
+ */
+void BoardGetUniqueId( uint8_t *id );
+
+#endif // __BOARD_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mac/LoRaWAN-lib.lib	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/Semtech/code/LoRaWAN-lib/#d7a34ded7c87
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/radio/SX1276Lib.lib	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/Semtech/code/SX1276Lib/#3778e6204cc1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/crypto/aes.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,936 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state (there are options to use 32-bit types if available).
+
+ The combination of mix columns and byte substitution used here is based on
+ that developed by Karl Malbrain. His contribution is acknowledged.
+ */
+
+/* define if you have a fast memcpy function on your system */
+#if 0
+#  define HAVE_MEMCPY
+#  include <string.h>
+#  if defined( _MSC_VER )
+#    include <intrin.h>
+#    pragma intrinsic( memcpy )
+#  endif
+#endif
+
+
+#include <stdlib.h>
+#include <stdint.h>
+
+/* define if you have fast 32-bit types on your system */
+#if ( __CORTEX_M != 0 ) // if Cortex is different from M0/M0+
+#  define HAVE_UINT_32T
+#endif
+
+/* define if you don't want any tables */
+#if 1
+#  define USE_TABLES
+#endif
+
+/*  On Intel Core 2 duo VERSION_1 is faster */
+
+/* alternative versions (test for performance on your system) */
+#if 1
+#  define VERSION_1
+#endif
+
+#include "aes.h"
+
+//#if defined( HAVE_UINT_32T )
+//  typedef unsigned long uint32_t;
+//#endif
+
+/* functions for finite field multiplication in the AES Galois field    */
+
+#define WPOLY   0x011b
+#define BPOLY     0x1b
+#define DPOLY   0x008d
+
+#define f1(x)   (x)
+#define f2(x)   ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
+#define f4(x)   ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
+#define f8(x)   ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \
+                          ^ (((x >> 5) & 4) * WPOLY))
+#define d2(x)   (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
+
+#define f3(x)   (f2(x) ^ x)
+#define f9(x)   (f8(x) ^ x)
+#define fb(x)   (f8(x) ^ f2(x) ^ x)
+#define fd(x)   (f8(x) ^ f4(x) ^ x)
+#define fe(x)   (f8(x) ^ f4(x) ^ f2(x))
+
+#if defined( USE_TABLES )
+
+#define sb_data(w) {    /* S Box data values */                            \
+    w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+    w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+    w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+    w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+    w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+    w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+    w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+    w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+    w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+    w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+    w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+    w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+    w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+    w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+    w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+    w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+    w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+    w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+    w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+    w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+    w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+    w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+    w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+    w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+    w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+    w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+    w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+    w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+    w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+    w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+    w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+    w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
+
+#define isb_data(w) {   /* inverse S Box data values */                    \
+    w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
+    w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
+    w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
+    w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
+    w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
+    w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
+    w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
+    w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
+    w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
+    w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
+    w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
+    w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
+    w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
+    w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
+    w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
+    w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
+    w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
+    w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
+    w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
+    w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
+    w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
+    w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
+    w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
+    w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
+    w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
+    w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
+    w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
+    w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
+    w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
+    w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
+    w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
+    w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
+
+#define mm_data(w) {    /* basic data for forming finite field tables */   \
+    w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
+    w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
+    w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
+    w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
+    w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
+    w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
+    w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
+    w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
+    w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
+    w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
+    w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
+    w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
+    w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
+    w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
+    w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
+    w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
+    w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
+    w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
+    w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
+    w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
+    w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
+    w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
+    w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
+    w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
+    w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
+    w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
+    w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
+    w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
+    w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
+    w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
+    w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
+    w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
+
+static const uint8_t sbox[256]  =  sb_data(f1);
+
+#if defined( AES_DEC_PREKEYED )
+static const uint8_t isbox[256] = isb_data(f1);
+#endif
+
+static const uint8_t gfm2_sbox[256] = sb_data(f2);
+static const uint8_t gfm3_sbox[256] = sb_data(f3);
+
+#if defined( AES_DEC_PREKEYED )
+static const uint8_t gfmul_9[256] = mm_data(f9);
+static const uint8_t gfmul_b[256] = mm_data(fb);
+static const uint8_t gfmul_d[256] = mm_data(fd);
+static const uint8_t gfmul_e[256] = mm_data(fe);
+#endif
+
+#define s_box(x)     sbox[(x)]
+#if defined( AES_DEC_PREKEYED )
+#define is_box(x)    isbox[(x)]
+#endif
+#define gfm2_sb(x)   gfm2_sbox[(x)]
+#define gfm3_sb(x)   gfm3_sbox[(x)]
+#if defined( AES_DEC_PREKEYED )
+#define gfm_9(x)     gfmul_9[(x)]
+#define gfm_b(x)     gfmul_b[(x)]
+#define gfm_d(x)     gfmul_d[(x)]
+#define gfm_e(x)     gfmul_e[(x)]
+#endif
+#else
+
+/* this is the high bit of x right shifted by 1 */
+/* position. Since the starting polynomial has  */
+/* 9 bits (0x11b), this right shift keeps the   */
+/* values of all top bits within a byte         */
+
+static uint8_t hibit(const uint8_t x)
+{   uint8_t r = (uint8_t)((x >> 1) | (x >> 2));
+
+    r |= (r >> 2);
+    r |= (r >> 4);
+    return (r + 1) >> 1;
+}
+
+/* return the inverse of the finite field element x */
+
+static uint8_t gf_inv(const uint8_t x)
+{   uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
+
+    if(x < 2)
+        return x;
+
+    for( ; ; )
+    {
+        if(n1)
+            while(n2 >= n1)             /* divide polynomial p2 by p1    */
+            {
+                n2 /= n1;               /* shift smaller polynomial left */
+                p2 ^= (p1 * n2) & 0xff; /* and remove from larger one    */
+                v2 ^= (v1 * n2);        /* shift accumulated value and   */
+                n2 = hibit(p2);         /* add into result               */
+            }
+        else
+            return v1;
+
+        if(n2)                          /* repeat with values swapped    */
+            while(n1 >= n2)
+            {
+                n1 /= n2;
+                p1 ^= p2 * n1;
+                v1 ^= v2 * n1;
+                n1 = hibit(p1);
+            }
+        else
+            return v2;
+    }
+}
+
+/* The forward and inverse affine transformations used in the S-box */
+uint8_t fwd_affine(const uint8_t x)
+{
+#if defined( HAVE_UINT_32T )
+    uint32_t w = x;
+    w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
+    return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
+#else
+    return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4)
+                    ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4);
+#endif
+}
+
+uint8_t inv_affine(const uint8_t x)
+{
+#if defined( HAVE_UINT_32T )
+    uint32_t w = x;
+    w = (w << 1) ^ (w << 3) ^ (w << 6);
+    return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
+#else
+    return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6)
+                ^ (x >> 7) ^ (x >> 5) ^ (x >> 2);
+#endif
+}
+
+#define s_box(x)   fwd_affine(gf_inv(x))
+#define is_box(x)  gf_inv(inv_affine(x))
+#define gfm2_sb(x) f2(s_box(x))
+#define gfm3_sb(x) f3(s_box(x))
+#define gfm_9(x)   f9(x)
+#define gfm_b(x)   fb(x)
+#define gfm_d(x)   fd(x)
+#define gfm_e(x)   fe(x)
+
+#endif
+
+#if defined( HAVE_MEMCPY )
+#  define block_copy_nn(d, s, l)    memcpy(d, s, l)
+#  define block_copy(d, s)          memcpy(d, s, N_BLOCK)
+#else
+#  define block_copy_nn(d, s, l)    copy_block_nn(d, s, l)
+#  define block_copy(d, s)          copy_block(d, s)
+#endif
+
+static void copy_block( void *d, const void *s )
+{
+#if defined( HAVE_UINT_32T )
+    ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0];
+    ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1];
+    ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2];
+    ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3];
+#else
+    ((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0];
+    ((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1];
+    ((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2];
+    ((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3];
+    ((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4];
+    ((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5];
+    ((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6];
+    ((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7];
+    ((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8];
+    ((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9];
+    ((uint8_t*)d)[10] = ((uint8_t*)s)[10];
+    ((uint8_t*)d)[11] = ((uint8_t*)s)[11];
+    ((uint8_t*)d)[12] = ((uint8_t*)s)[12];
+    ((uint8_t*)d)[13] = ((uint8_t*)s)[13];
+    ((uint8_t*)d)[14] = ((uint8_t*)s)[14];
+    ((uint8_t*)d)[15] = ((uint8_t*)s)[15];
+#endif
+}
+
+static void copy_block_nn( uint8_t * d, const uint8_t *s, uint8_t nn )
+{
+    while( nn-- )
+        //*((uint8_t*)d)++ = *((uint8_t*)s)++;
+        *d++ = *s++;
+}
+
+static void xor_block( void *d, const void *s )
+{
+#if defined( HAVE_UINT_32T )
+    ((uint32_t*)d)[ 0] ^= ((uint32_t*)s)[ 0];
+    ((uint32_t*)d)[ 1] ^= ((uint32_t*)s)[ 1];
+    ((uint32_t*)d)[ 2] ^= ((uint32_t*)s)[ 2];
+    ((uint32_t*)d)[ 3] ^= ((uint32_t*)s)[ 3];
+#else
+    ((uint8_t*)d)[ 0] ^= ((uint8_t*)s)[ 0];
+    ((uint8_t*)d)[ 1] ^= ((uint8_t*)s)[ 1];
+    ((uint8_t*)d)[ 2] ^= ((uint8_t*)s)[ 2];
+    ((uint8_t*)d)[ 3] ^= ((uint8_t*)s)[ 3];
+    ((uint8_t*)d)[ 4] ^= ((uint8_t*)s)[ 4];
+    ((uint8_t*)d)[ 5] ^= ((uint8_t*)s)[ 5];
+    ((uint8_t*)d)[ 6] ^= ((uint8_t*)s)[ 6];
+    ((uint8_t*)d)[ 7] ^= ((uint8_t*)s)[ 7];
+    ((uint8_t*)d)[ 8] ^= ((uint8_t*)s)[ 8];
+    ((uint8_t*)d)[ 9] ^= ((uint8_t*)s)[ 9];
+    ((uint8_t*)d)[10] ^= ((uint8_t*)s)[10];
+    ((uint8_t*)d)[11] ^= ((uint8_t*)s)[11];
+    ((uint8_t*)d)[12] ^= ((uint8_t*)s)[12];
+    ((uint8_t*)d)[13] ^= ((uint8_t*)s)[13];
+    ((uint8_t*)d)[14] ^= ((uint8_t*)s)[14];
+    ((uint8_t*)d)[15] ^= ((uint8_t*)s)[15];
+#endif
+}
+
+static void copy_and_key( void *d, const void *s, const void *k )
+{
+#if defined( HAVE_UINT_32T )
+    ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0] ^ ((uint32_t*)k)[ 0];
+    ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1] ^ ((uint32_t*)k)[ 1];
+    ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2] ^ ((uint32_t*)k)[ 2];
+    ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3] ^ ((uint32_t*)k)[ 3];
+#elif 1
+    ((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0] ^ ((uint8_t*)k)[ 0];
+    ((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1] ^ ((uint8_t*)k)[ 1];
+    ((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2] ^ ((uint8_t*)k)[ 2];
+    ((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3] ^ ((uint8_t*)k)[ 3];
+    ((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4] ^ ((uint8_t*)k)[ 4];
+    ((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5] ^ ((uint8_t*)k)[ 5];
+    ((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6] ^ ((uint8_t*)k)[ 6];
+    ((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7] ^ ((uint8_t*)k)[ 7];
+    ((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8] ^ ((uint8_t*)k)[ 8];
+    ((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9] ^ ((uint8_t*)k)[ 9];
+    ((uint8_t*)d)[10] = ((uint8_t*)s)[10] ^ ((uint8_t*)k)[10];
+    ((uint8_t*)d)[11] = ((uint8_t*)s)[11] ^ ((uint8_t*)k)[11];
+    ((uint8_t*)d)[12] = ((uint8_t*)s)[12] ^ ((uint8_t*)k)[12];
+    ((uint8_t*)d)[13] = ((uint8_t*)s)[13] ^ ((uint8_t*)k)[13];
+    ((uint8_t*)d)[14] = ((uint8_t*)s)[14] ^ ((uint8_t*)k)[14];
+    ((uint8_t*)d)[15] = ((uint8_t*)s)[15] ^ ((uint8_t*)k)[15];
+#else
+    block_copy(d, s);
+    xor_block(d, k);
+#endif
+}
+
+static void add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] )
+{
+    xor_block(d, k);
+}
+
+static void shift_sub_rows( uint8_t st[N_BLOCK] )
+{   uint8_t tt;
+
+    st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]);
+    st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]);
+
+    tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]);
+    st[ 9] = s_box(st[13]); st[13] = s_box( tt );
+
+    tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt );
+    tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt );
+
+    tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]);
+    st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt );
+}
+
+#if defined( AES_DEC_PREKEYED )
+
+static void inv_shift_sub_rows( uint8_t st[N_BLOCK] )
+{   uint8_t tt;
+
+    st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]);
+    st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]);
+
+    tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]);
+    st[ 5] = is_box(st[1]); st[ 1] = is_box( tt );
+
+    tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt );
+    tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt );
+
+    tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]);
+    st[11] = is_box(st[15]); st[15] = is_box( tt );
+}
+
+#endif
+
+#if defined( VERSION_1 )
+  static void mix_sub_columns( uint8_t dt[N_BLOCK] )
+  { uint8_t st[N_BLOCK];
+    block_copy(st, dt);
+#else
+  static void mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] )
+  {
+#endif
+    dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]);
+    dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]);
+    dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]);
+    dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]);
+
+    dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]);
+    dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]);
+    dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]);
+    dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]);
+
+    dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]);
+    dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]);
+    dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]);
+    dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]);
+
+    dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]);
+    dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]);
+    dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]);
+    dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]);
+  }
+
+#if defined( AES_DEC_PREKEYED )
+
+#if defined( VERSION_1 )
+  static void inv_mix_sub_columns( uint8_t dt[N_BLOCK] )
+  { uint8_t st[N_BLOCK];
+    block_copy(st, dt);
+#else
+  static void inv_mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] )
+  {
+#endif
+    dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3]));
+    dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3]));
+    dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3]));
+    dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3]));
+
+    dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7]));
+    dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7]));
+    dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7]));
+    dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7]));
+
+    dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11]));
+    dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11]));
+    dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11]));
+    dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11]));
+
+    dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15]));
+    dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15]));
+    dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15]));
+    dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15]));
+  }
+
+#endif
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+/*  Set the cipher key for the pre-keyed version */
+
+return_type aes_set_key( const uint8_t key[], length_type keylen, aes_context ctx[1] )
+{
+    uint8_t cc, rc, hi;
+
+    switch( keylen )
+    {
+    case 16:
+    case 24:
+    case 32:
+        break;
+    default:
+        ctx->rnd = 0;
+        return ( uint8_t )-1;
+    }
+    block_copy_nn(ctx->ksch, key, keylen);
+    hi = (keylen + 28) << 2;
+    ctx->rnd = (hi >> 4) - 1;
+    for( cc = keylen, rc = 1; cc < hi; cc += 4 )
+    {   uint8_t tt, t0, t1, t2, t3;
+
+        t0 = ctx->ksch[cc - 4];
+        t1 = ctx->ksch[cc - 3];
+        t2 = ctx->ksch[cc - 2];
+        t3 = ctx->ksch[cc - 1];
+        if( cc % keylen == 0 )
+        {
+            tt = t0;
+            t0 = s_box(t1) ^ rc;
+            t1 = s_box(t2);
+            t2 = s_box(t3);
+            t3 = s_box(tt);
+            rc = f2(rc);
+        }
+        else if( keylen > 24 && cc % keylen == 16 )
+        {
+            t0 = s_box(t0);
+            t1 = s_box(t1);
+            t2 = s_box(t2);
+            t3 = s_box(t3);
+        }
+        tt = cc - keylen;
+        ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0;
+        ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1;
+        ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2;
+        ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3;
+    }
+    return 0;
+}
+
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+/*  Encrypt a single block of 16 bytes */
+
+return_type aes_encrypt( const uint8_t in[N_BLOCK], uint8_t  out[N_BLOCK], const aes_context ctx[1] )
+{
+    if( ctx->rnd )
+    {
+        uint8_t s1[N_BLOCK], r;
+        copy_and_key( s1, in, ctx->ksch );
+
+        for( r = 1 ; r < ctx->rnd ; ++r )
+#if defined( VERSION_1 )
+        {
+            mix_sub_columns( s1 );
+            add_round_key( s1, ctx->ksch + r * N_BLOCK);
+        }
+#else
+        {   uint8_t s2[N_BLOCK];
+            mix_sub_columns( s2, s1 );
+            copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK);
+        }
+#endif
+        shift_sub_rows( s1 );
+        copy_and_key( out, s1, ctx->ksch + r * N_BLOCK );
+    }
+    else
+        return ( uint8_t )-1;
+    return 0;
+}
+
+/* CBC encrypt a number of blocks (input and return an IV) */
+
+return_type aes_cbc_encrypt( const uint8_t *in, uint8_t *out,
+                         int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] )
+{
+
+    while(n_block--)
+    {
+        xor_block(iv, in);
+        if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+            return EXIT_FAILURE;
+        //memcpy(out, iv, N_BLOCK);
+        block_copy(out, iv);
+        in += N_BLOCK;
+        out += N_BLOCK;
+    }
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+/*  Decrypt a single block of 16 bytes */
+
+return_type aes_decrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] )
+{
+    if( ctx->rnd )
+    {
+        uint8_t s1[N_BLOCK], r;
+        copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK );
+        inv_shift_sub_rows( s1 );
+
+        for( r = ctx->rnd ; --r ; )
+#if defined( VERSION_1 )
+        {
+            add_round_key( s1, ctx->ksch + r * N_BLOCK );
+            inv_mix_sub_columns( s1 );
+        }
+#else
+        {   uint8_t s2[N_BLOCK];
+            copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK );
+            inv_mix_sub_columns( s1, s2 );
+        }
+#endif
+        copy_and_key( out, s1, ctx->ksch );
+    }
+    else
+        return -1;
+    return 0;
+}
+
+/* CBC decrypt a number of blocks (input and return an IV) */
+
+return_type aes_cbc_decrypt( const uint8_t *in, uint8_t *out,
+                         int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] )
+{
+    while(n_block--)
+    {   uint8_t tmp[N_BLOCK];
+
+        //memcpy(tmp, in, N_BLOCK);
+        block_copy(tmp, in);
+        if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS)
+            return EXIT_FAILURE;
+        xor_block(out, iv);
+        //memcpy(iv, tmp, N_BLOCK);
+        block_copy(iv, tmp);
+        in += N_BLOCK;
+        out += N_BLOCK;
+    }
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_ENC_128_OTFK )
+
+/*  The 'on the fly' encryption key update for for 128 bit keys */
+
+static void update_encrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc )
+{   uint8_t cc;
+
+    k[0] ^= s_box(k[13]) ^ *rc;
+    k[1] ^= s_box(k[14]);
+    k[2] ^= s_box(k[15]);
+    k[3] ^= s_box(k[12]);
+    *rc = f2( *rc );
+
+    for(cc = 4; cc < 16; cc += 4 )
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+}
+
+/*  Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
+
+void aes_encrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
+                     const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] )
+{   uint8_t s1[N_BLOCK], r, rc = 1;
+
+    if(o_key != key)
+        block_copy( o_key, key );
+    copy_and_key( s1, in, o_key );
+
+    for( r = 1 ; r < 10 ; ++r )
+#if defined( VERSION_1 )
+    {
+        mix_sub_columns( s1 );
+        update_encrypt_key_128( o_key, &rc );
+        add_round_key( s1, o_key );
+    }
+#else
+    {   uint8_t s2[N_BLOCK];
+        mix_sub_columns( s2, s1 );
+        update_encrypt_key_128( o_key, &rc );
+        copy_and_key( s1, s2, o_key );
+    }
+#endif
+
+    shift_sub_rows( s1 );
+    update_encrypt_key_128( o_key, &rc );
+    copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+
+/*  The 'on the fly' decryption key update for for 128 bit keys */
+
+static void update_decrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc )
+{   uint8_t cc;
+
+    for( cc = 12; cc > 0; cc -= 4 )
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+    *rc = d2(*rc);
+    k[0] ^= s_box(k[13]) ^ *rc;
+    k[1] ^= s_box(k[14]);
+    k[2] ^= s_box(k[15]);
+    k[3] ^= s_box(k[12]);
+}
+
+/*  Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
+
+void aes_decrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
+                      const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] )
+{
+    uint8_t s1[N_BLOCK], r, rc = 0x6c;
+    if(o_key != key)
+        block_copy( o_key, key );
+
+    copy_and_key( s1, in, o_key );
+    inv_shift_sub_rows( s1 );
+
+    for( r = 10 ; --r ; )
+#if defined( VERSION_1 )
+    {
+        update_decrypt_key_128( o_key, &rc );
+        add_round_key( s1, o_key );
+        inv_mix_sub_columns( s1 );
+    }
+#else
+    {   uint8_t s2[N_BLOCK];
+        update_decrypt_key_128( o_key, &rc );
+        copy_and_key( s2, s1, o_key );
+        inv_mix_sub_columns( s1, s2 );
+    }
+#endif
+    update_decrypt_key_128( o_key, &rc );
+    copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+
+/*  The 'on the fly' encryption key update for for 256 bit keys */
+
+static void update_encrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc )
+{   uint8_t cc;
+
+    k[0] ^= s_box(k[29]) ^ *rc;
+    k[1] ^= s_box(k[30]);
+    k[2] ^= s_box(k[31]);
+    k[3] ^= s_box(k[28]);
+    *rc = f2( *rc );
+
+    for(cc = 4; cc < 16; cc += 4)
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+
+    k[16] ^= s_box(k[12]);
+    k[17] ^= s_box(k[13]);
+    k[18] ^= s_box(k[14]);
+    k[19] ^= s_box(k[15]);
+
+    for( cc = 20; cc < 32; cc += 4 )
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+}
+
+/*  Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */
+
+void aes_encrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
+                      const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] )
+{
+    uint8_t s1[N_BLOCK], r, rc = 1;
+    if(o_key != key)
+    {
+        block_copy( o_key, key );
+        block_copy( o_key + 16, key + 16 );
+    }
+    copy_and_key( s1, in, o_key );
+
+    for( r = 1 ; r < 14 ; ++r )
+#if defined( VERSION_1 )
+    {
+        mix_sub_columns(s1);
+        if( r & 1 )
+            add_round_key( s1, o_key + 16 );
+        else
+        {
+            update_encrypt_key_256( o_key, &rc );
+            add_round_key( s1, o_key );
+        }
+    }
+#else
+    {   uint8_t s2[N_BLOCK];
+        mix_sub_columns( s2, s1 );
+        if( r & 1 )
+            copy_and_key( s1, s2, o_key + 16 );
+        else
+        {
+            update_encrypt_key_256( o_key, &rc );
+            copy_and_key( s1, s2, o_key );
+        }
+    }
+#endif
+
+    shift_sub_rows( s1 );
+    update_encrypt_key_256( o_key, &rc );
+    copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+
+/*  The 'on the fly' encryption key update for for 256 bit keys */
+
+static void update_decrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc )
+{   uint8_t cc;
+
+    for(cc = 28; cc > 16; cc -= 4)
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+
+    k[16] ^= s_box(k[12]);
+    k[17] ^= s_box(k[13]);
+    k[18] ^= s_box(k[14]);
+    k[19] ^= s_box(k[15]);
+
+    for(cc = 12; cc > 0; cc -= 4)
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+
+    *rc = d2(*rc);
+    k[0] ^= s_box(k[29]) ^ *rc;
+    k[1] ^= s_box(k[30]);
+    k[2] ^= s_box(k[31]);
+    k[3] ^= s_box(k[28]);
+}
+
+/*  Decrypt a single block of 16 bytes with 'on the fly'
+    256 bit keying
+*/
+void aes_decrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK],
+                      const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] )
+{
+    uint8_t s1[N_BLOCK], r, rc = 0x80;
+
+    if(o_key != key)
+    {
+        block_copy( o_key, key );
+        block_copy( o_key + 16, key + 16 );
+    }
+
+    copy_and_key( s1, in, o_key );
+    inv_shift_sub_rows( s1 );
+
+    for( r = 14 ; --r ; )
+#if defined( VERSION_1 )
+    {
+        if( ( r & 1 ) )
+        {
+            update_decrypt_key_256( o_key, &rc );
+            add_round_key( s1, o_key + 16 );
+        }
+        else
+            add_round_key( s1, o_key );
+        inv_mix_sub_columns( s1 );
+    }
+#else
+    {   uint8_t s2[N_BLOCK];
+        if( ( r & 1 ) )
+        {
+            update_decrypt_key_256( o_key, &rc );
+            copy_and_key( s2, s1, o_key + 16 );
+        }
+        else
+            copy_and_key( s2, s1, o_key );
+        inv_mix_sub_columns( s1, s2 );
+    }
+#endif
+    copy_and_key( out, s1, o_key );
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/crypto/aes.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,160 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#if 1
+#  define AES_ENC_PREKEYED  /* AES encryption with a precomputed key schedule  */
+#endif
+#if 0
+#  define AES_DEC_PREKEYED  /* AES decryption with a precomputed key schedule  */
+#endif
+#if 0
+#  define AES_ENC_128_OTFK  /* AES encryption with 'on the fly' 128 bit keying */
+#endif
+#if 0
+#  define AES_DEC_128_OTFK  /* AES decryption with 'on the fly' 128 bit keying */
+#endif
+#if 0
+#  define AES_ENC_256_OTFK  /* AES encryption with 'on the fly' 256 bit keying */
+#endif
+#if 0
+#  define AES_DEC_256_OTFK  /* AES decryption with 'on the fly' 256 bit keying */
+#endif
+
+#define N_ROW                   4
+#define N_COL                   4
+#define N_BLOCK   (N_ROW * N_COL)
+#define N_MAX_ROUNDS           14
+
+typedef uint8_t return_type;
+
+/*  Warning: The key length for 256 bit keys overflows a byte
+    (see comment below)
+*/
+
+typedef uint8_t length_type;
+
+typedef struct
+{   uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
+    uint8_t rnd;
+} aes_context;
+
+/*  The following calls are for a precomputed key schedule
+
+    NOTE: If the length_type used for the key length is an
+    unsigned 8-bit character, a key length of 256 bits must
+    be entered as a length in bytes (valid inputs are hence
+    128, 192, 16, 24 and 32).
+*/
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+return_type aes_set_key( const uint8_t key[],
+                         length_type keylen,
+                         aes_context ctx[1] );
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+return_type aes_encrypt( const uint8_t in[N_BLOCK],
+                         uint8_t out[N_BLOCK],
+                         const aes_context ctx[1] );
+
+return_type aes_cbc_encrypt( const uint8_t *in,
+                         uint8_t *out,
+                         int32_t n_block,
+                         uint8_t iv[N_BLOCK],
+                         const aes_context ctx[1] );
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+return_type aes_decrypt( const uint8_t in[N_BLOCK],
+                         uint8_t out[N_BLOCK],
+                         const aes_context ctx[1] );
+
+return_type aes_cbc_decrypt( const uint8_t *in,
+                         uint8_t *out,
+                         int32_t n_block,
+                         uint8_t iv[N_BLOCK],
+                         const aes_context ctx[1] );
+#endif
+
+/*  The following calls are for 'on the fly' keying.  In this case the
+    encryption and decryption keys are different.
+
+    The encryption subroutines take a key in an array of bytes in
+    key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
+    192, and 256 bits respectively.  They then encrypts the input
+    data, in[] with this key and put the reult in the output array
+    out[].  In addition, the second key array, o_key[L], is used
+    to output the key that is needed by the decryption subroutine
+    to reverse the encryption operation.  The two key arrays can
+    be the same array but in this case the original key will be
+    overwritten.
+
+    In the same way, the decryption subroutines output keys that
+    can be used to reverse their effect when used for encryption.
+
+    Only 128 and 256 bit keys are supported in these 'on the fly'
+    modes.
+*/
+
+#if defined( AES_ENC_128_OTFK )
+void aes_encrypt_128( const uint8_t in[N_BLOCK],
+                      uint8_t out[N_BLOCK],
+                      const uint8_t key[N_BLOCK],
+                      uint8_t o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+void aes_decrypt_128( const uint8_t in[N_BLOCK],
+                      uint8_t out[N_BLOCK],
+                      const uint8_t key[N_BLOCK],
+                      uint8_t o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+void aes_encrypt_256( const uint8_t in[N_BLOCK],
+                      uint8_t out[N_BLOCK],
+                      const uint8_t key[2 * N_BLOCK],
+                      uint8_t o_key[2 * N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+void aes_decrypt_256( const uint8_t in[N_BLOCK],
+                      uint8_t out[N_BLOCK],
+                      const uint8_t key[2 * N_BLOCK],
+                      uint8_t o_key[2 * N_BLOCK] );
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/crypto/cmac.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,153 @@
+/**************************************************************************
+Copyright (C) 2009 Lander Casado, Philippas Tsigas
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files 
+(the "Software"), to deal with the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, 
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions: 
+
+Redistributions of source code must retain the above copyright notice, 
+this list of conditions and the following disclaimers. Redistributions in
+binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimers in the documentation and/or 
+other materials provided with the distribution.
+
+In no event shall the authors or copyright holders be liable for any special,
+incidental, indirect or consequential damages of any kind, or any damages 
+whatsoever resulting from loss of use, data or profits, whether or not 
+advised of the possibility of damage, and on any theory of liability, 
+arising out of or in connection with the use or performance of this software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+DEALINGS WITH THE SOFTWARE
+
+*****************************************************************************/
+//#include <sys/param.h>
+//#include <sys/systm.h> 
+#include <stdint.h>
+#include "aes.h"
+#include "cmac.h"
+#include "utilities.h"
+
+#define LSHIFT(v, r) do {                                       \
+  int32_t i;                                                  \
+           for (i = 0; i < 15; i++)                                \
+                    (r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7;         \
+            (r)[15] = (v)[15] << 1;                                 \
+    } while (0)
+    
+#define XOR(v, r) do {                                          \
+            int32_t i;                                                  \
+            for (i = 0; i < 16; i++)     \
+        {   \
+                    (r)[i] = (r)[i] ^ (v)[i]; \
+        }                          \
+    } while (0) \
+
+
+void AES_CMAC_Init(AES_CMAC_CTX *ctx)
+{
+            memset1(ctx->X, 0, sizeof ctx->X);
+            ctx->M_n = 0;
+        memset1(ctx->rijndael.ksch, '\0', 240);
+}
+    
+void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH])
+{
+           //rijndael_set_key_enc_only(&ctx->rijndael, key, 128);
+       aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael);
+}
+    
+void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len)
+{
+            uint32_t mlen;
+        uint8_t in[16];
+    
+            if (ctx->M_n > 0) {
+                  mlen = MIN(16 - ctx->M_n, len);
+                    memcpy1(ctx->M_last + ctx->M_n, data, mlen);
+                    ctx->M_n += mlen;
+                    if (ctx->M_n < 16 || len == mlen)
+                            return;
+                   XOR(ctx->M_last, ctx->X);
+                    //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
+            aes_encrypt( ctx->X, ctx->X, &ctx->rijndael);
+                    data += mlen;
+                    len -= mlen;
+            }
+            while (len > 16) {      /* not last block */
+
+                    XOR(data, ctx->X);
+                    //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X);
+
+                    memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
+            aes_encrypt( in, in, &ctx->rijndael);
+                    memcpy1(&ctx->X[0], in, 16);
+
+                    data += 16;
+                    len -= 16;
+            }
+            /* potential last block, save it */
+            memcpy1(ctx->M_last, data, len);
+            ctx->M_n = len;
+}
+   
+void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx)
+{
+            uint8_t K[16];
+        uint8_t in[16];
+            /* generate subkey K1 */
+            memset1(K, '\0', 16);
+
+            //rijndael_encrypt(&ctx->rijndael, K, K);
+
+            aes_encrypt( K, K, &ctx->rijndael);
+
+            if (K[0] & 0x80) {
+                    LSHIFT(K, K);
+                   K[15] ^= 0x87;
+            } else
+                    LSHIFT(K, K);
+
+
+            if (ctx->M_n == 16) {
+                    /* last block was a complete block */
+                    XOR(K, ctx->M_last);
+
+           } else {
+                   /* generate subkey K2 */
+                  if (K[0] & 0x80) {
+                          LSHIFT(K, K);
+                          K[15] ^= 0x87;
+                  } else
+                           LSHIFT(K, K);
+
+                   /* padding(M_last) */
+                   ctx->M_last[ctx->M_n] = 0x80;
+                   while (++ctx->M_n < 16)
+                         ctx->M_last[ctx->M_n] = 0;
+   
+                  XOR(K, ctx->M_last);
+
+
+           }
+           XOR(ctx->M_last, ctx->X);
+
+           //rijndael_encrypt(&ctx->rijndael, ctx->X, digest);
+
+       memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten
+       aes_encrypt(in, digest, &ctx->rijndael);
+           memset1(K, 0, sizeof K);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/crypto/cmac.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,63 @@
+/**************************************************************************
+Copyright (C) 2009 Lander Casado, Philippas Tsigas
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files 
+(the "Software"), to deal with the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, 
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions: 
+
+Redistributions of source code must retain the above copyright notice, 
+this list of conditions and the following disclaimers. Redistributions in
+binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimers in the documentation and/or 
+other materials provided with the distribution.
+
+In no event shall the authors or copyright holders be liable for any special,
+incidental, indirect or consequential damages of any kind, or any damages 
+whatsoever resulting from loss of use, data or profits, whether or not 
+advised of the possibility of damage, and on any theory of liability, 
+arising out of or in connection with the use or performance of this software.
+ 
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+DEALINGS WITH THE SOFTWARE
+
+*****************************************************************************/
+
+#ifndef _CMAC_H_
+#define _CMAC_H_
+
+#include "aes.h" 
+  
+#define AES_CMAC_KEY_LENGTH     16
+#define AES_CMAC_DIGEST_LENGTH  16
+ 
+typedef struct _AES_CMAC_CTX {
+            aes_context    rijndael;
+            uint8_t        X[16];
+            uint8_t        M_last[16];
+            uint32_t       M_n;
+    } AES_CMAC_CTX;
+   
+//#include <sys/cdefs.h>
+    
+//__BEGIN_DECLS
+void     AES_CMAC_Init(AES_CMAC_CTX * ctx);
+void     AES_CMAC_SetKey(AES_CMAC_CTX * ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]);
+void     AES_CMAC_Update(AES_CMAC_CTX * ctx, const uint8_t * data, uint32_t len);
+          //          __attribute__((__bounded__(__string__,2,3)));
+void     AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX  * ctx);
+            //     __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH)));
+//__END_DECLS
+
+#endif /* _CMAC_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/mbed.bld	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7c328cabac7e
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/timer.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,78 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: Timer objects and scheduling management
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#include "board.h"
+
+Timer TimeCounter;
+Ticker LoadTimeCounter;
+
+volatile uint32_t CurrentTime = 0;
+
+void TimerResetTimeCounter( void )
+{
+    CurrentTime = CurrentTime + TimeCounter.read_us( );
+    TimeCounter.reset( );
+    TimeCounter.start( );
+}
+
+void TimerTimeCounterInit( void )
+{
+    TimeCounter.start( );
+    LoadTimeCounter.attach( &TimerResetTimeCounter, 10 );
+}
+
+TimerTime_t TimerGetCurrentTime( void )
+{
+    CurrentTime += TimeCounter.read_us( );
+    TimeCounter.reset( );
+    TimeCounter.start( );
+    return ( ( TimerTime_t )CurrentTime );
+}
+
+TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime )
+{
+    CurrentTime += TimeCounter.read_us( );
+    TimeCounter.reset( );
+    TimeCounter.start( );
+    return ( TimerTime_t )( CurrentTime - savedTime );
+}
+
+TimerTime_t TimerGetFutureTime( TimerTime_t eventInFuture )
+{
+    CurrentTime += TimeCounter.read_us( );
+    TimeCounter.reset( );
+    TimeCounter.start( );
+    return ( TimerTime_t )( CurrentTime + eventInFuture );
+}
+
+void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) )
+{
+    obj->value = 0;
+    obj->Callback = callback;
+}
+
+void TimerStart( TimerEvent_t *obj )
+{
+    obj->Timer.attach_us( obj->Callback, obj->value );
+}
+
+void TimerStop( TimerEvent_t *obj )
+{
+    obj->Timer.detach( );
+}
+
+void TimerSetValue( TimerEvent_t *obj, uint32_t value )
+{
+    obj->value = value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/timer.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,107 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: Timer objects and scheduling management
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+#include "mbed.h"
+
+/*!
+ * \brief Timer object description
+ */
+typedef struct TimerEvent_s
+{
+    uint32_t value;
+    void ( *Callback )( void );
+    Ticker Timer;
+}TimerEvent_t;
+
+/*!
+ * \brief Timer time variable definition
+ */
+#ifndef TimerTime_t
+typedef uint32_t TimerTime_t;
+#endif
+
+/*!
+ * \brief Inializes the timer used to get current time.
+ *
+ * \remark Current time corresponds to the time since system startup
+ */
+void TimerTimeCounterInit( void );
+
+/*!
+ * \brief Initializes the timer object
+ *
+ * \remark TimerSetValue function must be called before starting the timer.
+ *         this function initializes timestamp and reload value at 0.
+ *
+ * \param [IN] obj          Structure containing the timer object parameters
+ * \param [IN] callback     Function callback called at the end of the timeout
+ */
+void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) );
+
+/*!
+ * \brief Starts and adds the timer object to the list of timer events
+ *
+ * \param [IN] obj Structure containing the timer object parameters
+ */
+void TimerStart( TimerEvent_t *obj );
+
+/*!
+ * \brief Stops and removes the timer object from the list of timer events
+ *
+ * \param [IN] obj Structure containing the timer object parameters
+ */
+void TimerStop( TimerEvent_t *obj );
+
+/*!
+ * \brief Resets the timer object
+ *
+ * \param [IN] obj Structure containing the timer object parameters
+ */
+void TimerReset( TimerEvent_t *obj );
+
+/*!
+ * \brief Set timer new timeout value
+ *
+ * \param [IN] obj   Structure containing the timer object parameters
+ * \param [IN] value New timer timeout value
+ */
+void TimerSetValue( TimerEvent_t *obj, uint32_t value );
+
+/*!
+ * \brief Read the current time
+ *
+ * \retval time returns current time
+ */
+TimerTime_t TimerGetCurrentTime( void );
+
+/*!
+ * \brief Return the Time elapsed since a fix moment in Time
+ *
+ * \param [IN] savedTime    fix moment in Time
+ * \retval time             returns elapsed time
+ */
+TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime );
+
+/*!
+ * \brief Return the Time elapsed since a fix moment in Time
+ *
+ * \param [IN] eventInFuture    fix moment in the future
+ * \retval time             returns difference between now and future event
+ */
+TimerTime_t TimerGetFutureTime( TimerTime_t eventInFuture );
+
+#endif // __TIMER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/utilities.cpp	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,85 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: Helper functions implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include "board.h"
+#include "utilities.h"
+
+/*!
+ * Redefinition of rand() and srand() standard C functions.
+ * These functions are redefined in order to get the same behavior across
+ * different compiler toolchains implementations.
+ */
+// Standard random functions redefinition start
+#define RAND_LOCAL_MAX 2147483647L
+
+static uint32_t next = 1;
+
+int32_t rand1( void )
+{
+    return ( ( next = next * 1103515245L + 12345L ) % RAND_LOCAL_MAX );
+}
+
+void srand1( uint32_t seed )
+{
+    next = seed;
+}
+// Standard random functions redefinition end
+
+int32_t randr( int32_t min, int32_t max )
+{
+    return ( int32_t )rand1( ) % ( max - min + 1 ) + min;
+}
+
+void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size )
+{
+    while( size-- )
+    {
+        *dst++ = *src++;
+    }
+}
+
+void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size )
+{
+    dst = dst + ( size - 1 );
+    while( size-- )
+    {
+        *dst-- = *src++;
+    }
+}
+
+void memset1( uint8_t *dst, uint8_t value, uint16_t size )
+{
+    while( size-- )
+    {
+        *dst++ = value;
+    }
+}
+
+int8_t Nibble2HexChar( uint8_t a )
+{
+    if( a < 10 )
+    {
+        return '0' + a;
+    }
+    else if( a < 16 )
+    {
+        return 'A' + ( a - 10 );
+    }
+    else
+    {
+        return '?';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/system/utilities.h	Fri Aug 26 19:36:35 2016 +0000
@@ -0,0 +1,99 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+
+Description: Helper functions implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __UTILITIES_H__
+#define __UTILITIES_H__
+
+/*!
+ * \brief Returns the minimum value betwen a and b
+ *
+ * \param [IN] a 1st value
+ * \param [IN] b 2nd value
+ * \retval minValue Minimum value
+ */
+#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
+
+/*!
+ * \brief Returns the maximum value betwen a and b
+ *
+ * \param [IN] a 1st value
+ * \param [IN] b 2nd value
+ * \retval maxValue Maximum value
+ */
+#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
+
+/*!
+ * \brief Returns 2 raised to the power of n
+ *
+ * \param [IN] n power value
+ * \retval result of raising 2 to the power n
+ */
+#define POW2( n ) ( 1 << n )
+
+/*!
+ * \brief Initializes the pseudo ramdom generator initial value
+ *
+ * \param [IN] seed Pseudo ramdom generator initial value
+ */
+void srand1( uint32_t seed );
+
+/*!
+ * \brief Computes a random number between min and max
+ *
+ * \param [IN] min range minimum value
+ * \param [IN] max range maximum value
+ * \retval random random value in range min..max
+ */
+int32_t randr( int32_t min, int32_t max );
+
+/*!
+ * \brief Copies size elements of src array to dst array
+ * 
+ * \remark STM32 Standard memcpy function only works on pointers that are aligned
+ *
+ * \param [OUT] dst  Destination array
+ * \param [IN]  src  Source array
+ * \param [IN]  size Number of bytes to be copied
+ */
+void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size );
+
+/*!
+ * \brief Copies size elements of src array to dst array reversing the byte order
+ *
+ * \param [OUT] dst  Destination array
+ * \param [IN]  src  Source array
+ * \param [IN]  size Number of bytes to be copied
+ */
+void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size );
+
+/*!
+ * \brief Set size elements of dst array with value 
+ * 
+ * \remark STM32 Standard memset function only works on pointers that are aligned
+ *
+ * \param [OUT] dst   Destination array
+ * \param [IN]  value Default value
+ * \param [IN]  size  Number of bytes to be copied
+ */
+void memset1( uint8_t *dst, uint8_t value, uint16_t size );
+
+/*!
+ * \brief Converts a nibble to an hexadecimal character
+ * 
+ * \param [IN] a   Nibble to be converted
+ * \retval hexChar Converted hexadecimal character
+ */
+int8_t Nibble2HexChar( uint8_t a );
+
+#endif // __UTILITIES_H__