LoRaWAN-hello-world_HSE_CLOCK

Dependencies:   mbed LoRaWAN-lib SX1276Lib

Files at this revision

API Documentation at this revision

Comitter:
mluis
Date:
Thu Jan 07 15:14:22 2016 +0000
Parent:
2:01e3c65c7c3a
Child:
4:00cf2370c99d
Commit message:
Updated according to https://github.com/Lora-net/LoRaMac-node git revision a2226468d470eceb251338e1acfb24cfd121effa

Changed in this revision

app/Comissioning.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/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.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
mbed.bld 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	Thu Jan 07 15:14:22 2016 +0000
@@ -0,0 +1,70 @@
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (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 EUI (big endian)
+ */
+#define LORAWAN_DEVICE_EUI                          { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }
+
+/*!
+ * 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                     { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+
+#else
+
+/*!
+ * Current network ID
+ */
+#define LORAWAN_NETWORK_ID                          ( uint32_t )0
+
+/*!
+ * Device address on the network (big endian)
+ */
+#define LORAWAN_DEVICE_ADDRESS                      ( uint32_t )0x12345678
+
+/*!
+ * 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__
--- a/app/SerialDisplay.cpp	Thu Nov 26 17:22:53 2015 +0000
+++ b/app/SerialDisplay.cpp	Thu Jan 07 15:14:22 2016 +0000
@@ -41,15 +41,11 @@
 }
 
 void SerialDisplayUpdateEui( uint8_t line, uint8_t *eui )
-{   //
-    // REMARK
-    //
-    // EUIs must be displayed in reverse order
-    //
+{
     vt.SetCursorPos( line, 27 );
     for( uint8_t i = 0; i < 8; i++ )
     {
-        vt.printf( "%02X ", eui[7 - i] );
+        vt.printf( "%02X ", eui[i] );
     }
     vt.SetCursorPos( line, 50 );
     vt.printf( "]" );
@@ -213,7 +209,7 @@
     SerialDisplayUpdateData( 28, buffer, bufferSize );
     // Help message
     vt.SetCursorPos( 42, 1 );
-    vt.printf( "To refresh screen please hit 'r' key.\r\n" );
+    vt.printf( "To refresh screen please hit 'r' key." );
 }
 
 void SerialDisplayUpdateDonwlinkRxData( bool state )
--- a/app/main.cpp	Thu Nov 26 17:22:53 2015 +0000
+++ b/app/main.cpp	Thu Jan 07 15:14:22 2016 +0000
@@ -17,73 +17,15 @@
 #include "radio.h"
 
 #include "LoRaMac.h"
-
+#include "Comissioning.h"
 #include "SerialDisplay.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 )
-
-/*!
  * Join requests trials duty cycle.
  */
 #define OVER_THE_AIR_ACTIVATION_DUTYCYCLE           10000000  // 10 [s] value in us
 
 /*!
- * Mote device IEEE EUI
- *
- * \remark must be written as a little endian value (reverse order of normal reading)
- */
-#define LORAWAN_DEVICE_EUI                          { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }
-
-/*!
- * Application IEEE EUI
- *
- * \remark must be written as a little endian value (reverse order of normal reading)
- */
-#define LORAWAN_APPLICATION_EUI                     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-
-/*!
- * AES encryption/decryption cipher application key
- */
-#define LORAWAN_APPLICATION_KEY                     { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01 }
-
-#else
-
-/*!
- * Current network ID
- */
-#define LORAWAN_NETWORK_ID                          ( uint32_t )0
-
-/*!
- * Device address on the network
- *
- * \remark must be written as a big endian value (normal reading order)
- */
-#define LORAWAN_DEVICE_ADDRESS                      ( uint32_t )0xFF000001
-
-/*!
- * AES encryption/decryption cipher network session key
- */
-#define LORAWAN_NWKSKEY                             { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01 }
-
-/*!
- * AES encryption/decryption cipher application session key
- */
-#define LORAWAN_APPSKEY                             { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01 }
-
-#endif
-
-/*!
  * Defines the application data transmission duty cycle. 5s, value in [us].
  */
 #define APP_TX_DUTYCYCLE                            5000000
@@ -95,12 +37,17 @@
 #define APP_TX_DUTYCYCLE_RND                        1000000
 
 /*!
+ * Default mote datarate
+ */
+#define LORAWAN_DEFAULT_DATARATE                    DR_0
+
+/*!
  * LoRaWAN confirmed messages
  */
 #define LORAWAN_CONFIRMED_MSG_ON                    true
 
 /*!
- * LoRaWAN Adaptative Data Rate
+ * LoRaWAN Adaptive Data Rate
  *
  * \remark Please note that when ADR is enabled the end-device should be static
  */
@@ -108,12 +55,14 @@
 
 #if defined( USE_BAND_868 )
 
+#include "LoRaMacTest.h"
+
 /*!
  * LoRaWAN ETSI duty cycle control enable/disable
  *
  * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes
  */
-#define LORAWAN_DUTYCYCLE_ON                        false
+#define LORAWAN_DUTYCYCLE_ON                        true
 
 #endif
 
@@ -144,13 +93,12 @@
 static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
 static uint8_t AppSKey[] = LORAWAN_APPSKEY;
 
-#endif
+/*!
+ * Device address
+ */
+static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
 
-/*!
- * Indicates if the MAC layer has already joined a network.
- */
-static bool IsNetworkJoined = false;
-static bool IsNetworkJoinedStatusUpdate = false;
+#endif
 
 /*!
  * Application port
@@ -187,43 +135,70 @@
  */
 static TimerEvent_t TxNextPacketTimer;
 
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-
+/*!
+ * Specifies the state of the application LED
+ */
+static bool AppLedStateOn = false;
+volatile bool Led3StateChanged = false;
 /*!
- * Defines the join request timer
+ * Timer to handle the state of LED1
  */
-static TimerEvent_t JoinReqTimer;
-
-#endif
+static TimerEvent_t Led1Timer;
+volatile bool Led1State = false;
+volatile bool Led1StateChanged = false;
+/*!
+ * Timer to handle the state of LED2
+ */
+static TimerEvent_t Led2Timer;
+volatile bool Led2State = false;
+volatile bool Led2StateChanged = false;
 
 /*!
  * Indicates if a new packet can be sent
  */
-static bool TxNextPacket = true;
-static bool ScheduleNextTx = false;
-
-static LoRaMacCallbacks_t LoRaMacCallbacks;
+static bool NextTx = true;
 
-static TimerEvent_t Led1Timer;
-volatile bool Led1State = false;
-volatile bool Led1StateChanged = false;
-
-static TimerEvent_t Led2Timer;
-volatile bool Led2State = false;
-volatile bool Led2StateChanged = false;
+/*!
+ * Device states
+ */
+static enum eDevicState
+{
+    DEVICE_STATE_INIT,
+    DEVICE_STATE_JOIN,
+    DEVICE_STATE_SEND,
+    DEVICE_STATE_CYCLE,
+    DEVICE_STATE_SLEEP
+}DeviceState;
 
-static bool AppLedStateOn = false;
-volatile bool Led3StateChanged = false;
-
-volatile bool LinkStatusUpdated = false;
+/*!
+ * LoRaWAN compliance tests support data
+ */
+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;
+}ComplianceTest;
 
-static bool ComplianceTestOn = false;
-static uint8_t ComplianceTestState = 0;
-static uint16_t ComplianceTestDownLinkCounter = 0;
-static bool ComplianceTestLinkCheck = false;
-static uint8_t ComplianceTestDemodMargin = 0;
-static uint8_t ComplianceTestNbGateways = 0;
+/*
+ * SerialDisplay managment variables
+ */
 
+/*!
+ * Indicates if the MAC layer network join status has changed.
+ */
+static bool IsNetworkJoinedStatusUpdate = false;
+
+/*!
+ * Strucure containing the Uplink status
+ */
 struct sLoRaMacUplinkStatus
 {
     uint8_t Acked;
@@ -233,7 +208,11 @@
     uint8_t *Buffer;
     uint8_t BufferSize;
 }LoRaMacUplinkStatus;
+volatile bool UplinkStatusUpdated = false;
 
+/*!
+ * Strucure containing the Downlink status
+ */
 struct sLoRaMacDownlinkStatus
 {
     int16_t Rssi;
@@ -244,15 +223,18 @@
     uint8_t *Buffer;
     uint8_t BufferSize;
 }LoRaMacDownlinkStatus;
+volatile bool DownlinkStatusUpdated = false;
 
 void SerialDisplayRefresh( void )
 {
+    MibRequestConfirm_t mibReq;
+
     SerialDisplayInit( );
     SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
 
 #if( OVER_THE_AIR_ACTIVATION == 0 )
     SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
-    SerialDisplayUpdateDevAddr( LORAWAN_DEVICE_ADDRESS );
+    SerialDisplayUpdateDevAddr( DevAddr );
     SerialDisplayUpdateKey( 12, NwkSKey );
     SerialDisplayUpdateKey( 13, AppSKey );
 #else
@@ -260,7 +242,10 @@
     SerialDisplayUpdateEui( 6, AppEui );
     SerialDisplayUpdateKey( 7, AppKey );
 #endif
-    SerialDisplayUpdateNetworkIsJoined( IsNetworkJoined );
+
+    mibReq.Type = MIB_NETWORK_JOINED;
+    LoRaMacMibGetRequestConfirm( &mibReq );
+    SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
 
     SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
 #if defined( USE_BAND_868 )
@@ -291,7 +276,7 @@
 }
 
 /*!
- * Prepares the frame buffer to be sent
+ * \brief   Prepares the payload of the frame
  */
 static void PrepareTxFrame( uint8_t port )
 {
@@ -311,178 +296,118 @@
         }
         break;
     case 224:
-        if( ComplianceTestLinkCheck == true )
+        if( ComplianceTest.LinkCheck == true )
         {
-            ComplianceTestLinkCheck = false;
+            ComplianceTest.LinkCheck = false;
             AppDataSize = 3;
             AppData[0] = 5;
-            AppData[1] = ComplianceTestDemodMargin;
-            AppData[2] = ComplianceTestNbGateways;
-            ComplianceTestState = 1;
+            AppData[1] = ComplianceTest.DemodMargin;
+            AppData[2] = ComplianceTest.NbGateways;
+            ComplianceTest.State = 1;
         }
         else
         {
-            switch( ComplianceTestState )
+            switch( ComplianceTest.State )
             {
             case 4:
-                ComplianceTestState = 1;
+                ComplianceTest.State = 1;
                 break;
             case 1:
                 AppDataSize = 2;
-                AppData[0] = ComplianceTestDownLinkCounter >> 8;
-                AppData[1] = ComplianceTestDownLinkCounter;
+                AppData[0] = ComplianceTest.DownLinkCounter >> 8;
+                AppData[1] = ComplianceTest.DownLinkCounter;
                 break;
             }
         }
         break;
+    default:
+        break;
     }
 }
 
-static void ProcessRxFrame( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info )
-{
-    switch( info->RxPort ) // Check Rx port number
-    {
-        case 1: // The application LED can be controlled on port 1 or 2
-        case 2:
-            if( info->RxBufferSize == 1 )
-            {
-                AppLedStateOn = info->RxBuffer[0] & 0x01;
-                Led3StateChanged = true;
-            }
-            break;
-        case 224:
-            if( ComplianceTestOn == false )
-            {
-                // Check compliance test enable command (i)
-                if( ( info->RxBufferSize == 4 ) && 
-                    ( info->RxBuffer[0] == 0x01 ) &&
-                    ( info->RxBuffer[1] == 0x01 ) &&
-                    ( info->RxBuffer[2] == 0x01 ) &&
-                    ( info->RxBuffer[3] == 0x01 ) )
-                {
-                    IsTxConfirmed = false;
-                    AppPort = 224;
-                    AppDataSize = 2;
-                    ComplianceTestDownLinkCounter = 0;
-                    ComplianceTestLinkCheck = false;
-                    ComplianceTestDemodMargin = 0;
-                    ComplianceTestNbGateways = 0;
-                    ComplianceTestOn = true;
-                    ComplianceTestState = 1;
-                    
-                    LoRaMacSetAdrOn( true );
-#if defined( USE_BAND_868 )
-                    LoRaMacTestSetDutyCycleOn( false );
-#endif
-                }
-            }
-            else
-            {
-                ComplianceTestState = info->RxBuffer[0];
-                switch( ComplianceTestState )
-                {
-                case 0: // Check compliance test disable command (ii)
-                    IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
-                    AppPort = LORAWAN_APP_PORT;
-                    if( IsTxConfirmed == true )
-                    {
-                        AppDataSize = 6;
-                    }
-                    else
-                    {
-                        AppDataSize = 1;
-                    }
-                    ComplianceTestDownLinkCounter = 0;
-                    ComplianceTestOn = false;
-                    
-                    LoRaMacSetAdrOn( LORAWAN_ADR_ON );
-#if defined( USE_BAND_868 )
-                    LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
-#endif
-                    break;
-                case 1: // (iii, iv)
-                    AppDataSize = 2;
-                    break;
-                case 2: // Enable confirmed messages (v)
-                    IsTxConfirmed = true;
-                    ComplianceTestState = 1;
-                    break;
-                case 3:  // Disable confirmed messages (vi)
-                    IsTxConfirmed = false;
-                    ComplianceTestState = 1;
-                    break;
-                case 4: // (vii)
-                    AppDataSize = info->RxBufferSize;
-
-                    AppData[0] = 4;
-                    for( uint8_t i = 1; i < AppDataSize; i++ )
-                    {
-                        AppData[i] = info->RxBuffer[i] + 1;
-                    }
-                    break;
-                case 5: // (viii)
-                    LoRaMacLinkCheckReq( );
-                    break;
-                default:
-                    break;
-                }
-            }
-            break;
-        default:
-            break;
-    }
-}
-
+/*!
+ * \brief   Prepares the payload of the frame
+ *
+ * \retval  [0: frame could be send, 1: error]
+ */
 static bool SendFrame( void )
 {
-    uint8_t sendFrameStatus = 0;
-
-    LoRaMacUplinkStatus.Acked = false;
-    LoRaMacUplinkStatus.Port = AppPort;
-    LoRaMacUplinkStatus.Buffer = AppData;
-    LoRaMacUplinkStatus.BufferSize = AppDataSize;
+    McpsReq_t mcpsReq;
+    LoRaMacTxInfo_t txInfo;
     
-    SerialDisplayUpdateFrameType( IsTxConfirmed );
-
-    if( IsTxConfirmed == false )
+    if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
     {
-        sendFrameStatus = LoRaMacSendFrame( AppPort, AppData, AppDataSize );
+        // 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;
+        SerialDisplayUpdateFrameType( false );
     }
     else
     {
-        sendFrameStatus = LoRaMacSendConfirmedFrame( AppPort, AppData, AppDataSize, 8 );
+        LoRaMacUplinkStatus.Acked = false;
+        LoRaMacUplinkStatus.Port = AppPort;
+        LoRaMacUplinkStatus.Buffer = AppData;
+        LoRaMacUplinkStatus.BufferSize = AppDataSize;
+        SerialDisplayUpdateFrameType( IsTxConfirmed );
+
+        if( IsTxConfirmed == false )
+        {
+            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.nbRetries = 8;
+            mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
+        }
     }
 
-    switch( sendFrameStatus )
+    if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
     {
-    case 5: // NO_FREE_CHANNEL
-        // Try again later
-        return true;
-    default:
         return false;
     }
+    return true;
 }
 
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-
-/*!
- * \brief Function executed on JoinReq Timeout event
- */
-static void OnJoinReqTimerEvent( void )
-{
-    TimerStop( &JoinReqTimer );
-    TxNextPacket = true;
-}
-
-#endif
-
 /*!
  * \brief Function executed on TxNextPacket Timeout event
  */
 static void OnTxNextPacketTimerEvent( void )
 {
+    MibRequestConfirm_t mibReq;
+    LoRaMacStatus_t status;
+
     TimerStop( &TxNextPacketTimer );
-    TxNextPacket = true;
+
+    mibReq.Type = MIB_NETWORK_JOINED;
+    status = LoRaMacMibGetRequestConfirm( &mibReq );
+
+    if( status == LORAMAC_STATUS_OK )
+    {
+        if( mibReq.Param.IsNetworkJoined == true )
+        {
+            DeviceState = DEVICE_STATE_SEND;
+            NextTx = true;
+        }
+        else
+        {
+            DeviceState = DEVICE_STATE_JOIN;
+        }
+    }
 }
 
 /*!
@@ -491,6 +416,7 @@
 static void OnLed1TimerEvent( void )
 {
     TimerStop( &Led1Timer );
+    // Switch LED 1 OFF
     Led1State = false;
     Led1StateChanged = true;
 }
@@ -501,77 +427,262 @@
 static void OnLed2TimerEvent( void )
 {
     TimerStop( &Led2Timer );
+    // Switch LED 2 OFF
     Led2State = false;
     Led2StateChanged = true;
 }
 
 /*!
- * \brief Function to be executed on MAC layer event
+ * \brief   MCPS-Confirm event function
+ *
+ * \param   [IN] McpsConfirm - Pointer to the confirm structure,
+ *               containing confirm attributes.
  */
-static void OnMacEvent( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info )
+static void McpsConfirm( McpsConfirm_t *McpsConfirm )
 {
-    if( flags->Bits.JoinAccept == 1 )
+    if( McpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
     {
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-        TimerStop( &JoinReqTimer );
-#endif
-        IsNetworkJoined = true;
-        IsNetworkJoinedStatusUpdate = true;
+        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;
+    
+        UplinkStatusUpdated = true;
+    }
+    NextTx = true;
+}
+
+/*!
+ * \brief   MCPS-Indication event function
+ *
+ * \param   [IN] McpsIndication - Pointer to the indication structure,
+ *               containing indication attributes.
+ */
+static void McpsIndication( McpsIndication_t *McpsIndication )
+{
+    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
     {
-        if( flags->Bits.Tx == 1 )
-        {
-        }
+        // 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;
+
+    if( ComplianceTest.Running == true )
+    {
+        ComplianceTest.DownLinkCounter++;
+    }
 
-        if( flags->Bits.Rx == 1 )
+    if( McpsIndication->RxData == true )
+    {
+        switch( McpsIndication->Port )
         {
-            if( ComplianceTestOn == true )
+        case 1: // The application LED can be controlled on port 1 or 2
+        case 2:
+            if( McpsIndication->BufferSize == 1 )
             {
-                ComplianceTestDownLinkCounter++;
-                if( flags->Bits.LinkCheck == 1 )
+                AppLedStateOn = McpsIndication->Buffer[0] & 0x01;
+                Led3StateChanged = true;
+            }
+            break;
+        case 224:
+            if( ComplianceTest.Running == false )
+            {
+                // Check compliance test enable command (i)
+                if( ( McpsIndication->BufferSize == 4 ) && 
+                    ( McpsIndication->Buffer[0] == 0x01 ) &&
+                    ( McpsIndication->Buffer[1] == 0x01 ) &&
+                    ( McpsIndication->Buffer[2] == 0x01 ) &&
+                    ( McpsIndication->Buffer[3] == 0x01 ) )
                 {
-                    ComplianceTestLinkCheck = true;
-                    ComplianceTestDemodMargin = info->DemodMargin;
-                    ComplianceTestNbGateways = info->NbGateways;
+                    IsTxConfirmed = false;
+                    AppPort = 224;
+                    AppDataSize = 2;
+                    ComplianceTest.DownLinkCounter = 0;
+                    ComplianceTest.LinkCheck = false;
+                    ComplianceTest.DemodMargin = 0;
+                    ComplianceTest.NbGateways = 0;
+                    ComplianceTest.Running = true;
+                    ComplianceTest.State = 1;
+                    
+                    MibRequestConfirm_t mibReq;
+                    mibReq.Type = MIB_ADR;
+                    mibReq.Param.AdrEnable = true;
+                    LoRaMacMibSetRequestConfirm( &mibReq );
+
+#if defined( USE_BAND_868 )
+                    LoRaMacTestSetDutyCycleOn( false );
+#endif
                 }
             }
-            if( flags->Bits.RxData == true )
-            {
-                ProcessRxFrame( flags, info );
-            }
-            
-            LoRaMacDownlinkStatus.Rssi = info->RxRssi;
-            if( info->RxSnr & 0x80 ) // The SNR sign bit is 1
-            {
-                // Invert and divide by 4
-                LoRaMacDownlinkStatus.Snr = ( ( ~info->RxSnr + 1 ) & 0xFF ) >> 2;
-                LoRaMacDownlinkStatus.Snr = -LoRaMacDownlinkStatus.Snr;
-            }
             else
             {
-                // Divide by 4
-                LoRaMacDownlinkStatus.Snr = ( info->RxSnr & 0xFF ) >> 2;
+                ComplianceTest.State = McpsIndication->Buffer[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 );
+#if defined( USE_BAND_868 )
+                    LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
+#endif
+                    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;
+                }
             }
-            LoRaMacDownlinkStatus.DownlinkCounter++;
-            LoRaMacDownlinkStatus.RxData = flags->Bits.RxData;
-            LoRaMacDownlinkStatus.Port = info->RxPort;
-            LoRaMacDownlinkStatus.Buffer = info->RxBuffer;
-            LoRaMacDownlinkStatus.BufferSize = info->RxBufferSize;
-            
-            Led2State = true;
-            Led2StateChanged = true;
-            TimerStart( &Led2Timer );
+            break;
+        default:
+            break;
         }
-        
-        LoRaMacUplinkStatus.Acked = info->TxAckReceived;
-        LoRaMacUplinkStatus.Datarate = info->TxDatarate;
-        LoRaMacUplinkStatus.UplinkCounter = LoRaMacGetUpLinkCounter( ) - 1;
     }
 
-    LinkStatusUpdated = true;
-    // Schedule a new transmission
-    ScheduleNextTx = true;
+    // Switch LED 2 ON for each received downlink
+    Led2State = true;
+    Led2StateChanged = true;
+    TimerStart( &Led2Timer );
+    DownlinkStatusUpdated = true;
+}
+
+/*!
+ * \brief   MLME-Confirm event function
+ *
+ * \param   [IN] MlmeConfirm - Pointer to the confirm structure,
+ *               containing confirm attributes.
+ */
+static 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;
+        }
+    }
+    NextTx = true;
+    UplinkStatusUpdated = true;
 }
 
 /**
@@ -579,104 +690,24 @@
  */
 int main( void )
 {
-    SerialDisplayInit( );
-    
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-    uint8_t sendFrameStatus = 0;
-#endif
-    bool trySendingFrameAgain = false;
+    LoRaMacPrimitives_t LoRaMacPrimitives;
+    LoRaMacCallback_t LoRaMacCallbacks;
+    MibRequestConfirm_t mibReq;
 
     BoardInit( );
-
-    LoRaMacCallbacks.MacEvent = OnMacEvent;
-    LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
-    LoRaMacInit( &LoRaMacCallbacks );
-
-    IsNetworkJoined = false;
-
-    SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
-    
-#if( OVER_THE_AIR_ACTIVATION == 0 )
-    LoRaMacInitNwkIds( LORAWAN_NETWORK_ID, LORAWAN_DEVICE_ADDRESS, NwkSKey, AppSKey );
-    IsNetworkJoined = true;
-    
-    SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
-    SerialDisplayUpdateDevAddr( LORAWAN_DEVICE_ADDRESS );
-    SerialDisplayUpdateKey( 12, NwkSKey );
-    SerialDisplayUpdateKey( 13, AppSKey );
-#else
-    // Sends a JoinReq Command every 5 seconds until the network is joined
-    TimerInit( &JoinReqTimer, OnJoinReqTimerEvent ); 
-    TimerSetValue( &JoinReqTimer, OVER_THE_AIR_ACTIVATION_DUTYCYCLE );
-    
-    SerialDisplayUpdateEui( 5, DevEui );
-    SerialDisplayUpdateEui( 6, AppEui );
-    SerialDisplayUpdateKey( 7, AppKey );
+    SerialDisplayInit( );
 
-#endif
-
-    SerialDisplayUpdateNetworkIsJoined( IsNetworkJoined );
-
-    TxNextPacket = true;
-    TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
-    
-    TimerInit( &Led1Timer, OnLed1TimerEvent );
-    TimerSetValue( &Led1Timer, 500000 );
-
-    TimerInit( &Led2Timer, OnLed2TimerEvent );
-    TimerSetValue( &Led2Timer, 500000 );
-
-    LoRaMacSetAdrOn( LORAWAN_ADR_ON );
-#if defined( USE_BAND_868 )
-    LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
-#endif
-    LoRaMacSetPublicNetwork( LORAWAN_PUBLIC_NETWORK );
-
-    SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
-#if defined( USE_BAND_868 )
-    SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
-#else
-    SerialDisplayUpdateDutyCycle( false );
-#endif
-    SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
-    
-    LoRaMacDownlinkStatus.DownlinkCounter = 0;
+    DeviceState = DEVICE_STATE_INIT;
 
     while( 1 )
     {
-        while( IsNetworkJoined == false )
-        {
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-            if( TxNextPacket == true )
-            {
-                TxNextPacket = false;
-                
-                sendFrameStatus = LoRaMacJoinReq( DevEui, AppEui, AppKey );
-                switch( sendFrameStatus )
-                {
-                case 1: // BUSY
-                    break;
-                case 0: // OK
-                case 2: // NO_NETWORK_JOINED
-                case 3: // LENGTH_PORT_ERROR
-                case 4: // MAC_CMD_ERROR
-                case 6: // DEVICE_OFF
-                default:
-                    // Relaunch timer for next trial
-                    TimerStart( &JoinReqTimer );
-                    break;
-                }
-            }
-            SerialRxProcess( );
-#endif
-        }
-
         SerialRxProcess( );
-        
         if( IsNetworkJoinedStatusUpdate == true )
         {
             IsNetworkJoinedStatusUpdate = false;
-            SerialDisplayUpdateNetworkIsJoined( IsNetworkJoined );
+            mibReq.Type = MIB_NETWORK_JOINED;
+            LoRaMacMibGetRequestConfirm( &mibReq );
+            SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
         }
         if( Led1StateChanged == true )
         {
@@ -693,50 +724,159 @@
             Led3StateChanged = false;
             SerialDisplayUpdateLedState( 3, AppLedStateOn );
         }
-        if( LinkStatusUpdated == true )
+        if( UplinkStatusUpdated == true )
         {
-            LinkStatusUpdated = false;
+            UplinkStatusUpdated = false;
+            SerialDisplayUpdateUplink( LoRaMacUplinkStatus.Acked, LoRaMacUplinkStatus.Datarate, LoRaMacUplinkStatus.UplinkCounter, LoRaMacUplinkStatus.Port, LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
+        }
+        if( DownlinkStatusUpdated == true )
+        {
+            DownlinkStatusUpdated = false;
             SerialDisplayUpdateLedState( 2, Led2State );
-            SerialDisplayUpdateUplink( LoRaMacUplinkStatus.Acked, LoRaMacUplinkStatus.Datarate, LoRaMacUplinkStatus.UplinkCounter, LoRaMacUplinkStatus.Port, LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
             SerialDisplayUpdateDownlink( LoRaMacDownlinkStatus.RxData, LoRaMacDownlinkStatus.Rssi, LoRaMacDownlinkStatus.Snr, LoRaMacDownlinkStatus.DownlinkCounter, LoRaMacDownlinkStatus.Port, LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize );
         }
-
-        if( ScheduleNextTx == true )
+        
+        switch( DeviceState )
         {
-            ScheduleNextTx = false;
- 
-//            if( ComplianceTestOn == true )
-//            {
-//                TxNextPacket = true;
-//            }
-//            else
-//            {
+            case DEVICE_STATE_INIT:
+            {
+                LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
+                LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
+                LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
+                LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
+                LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks );
+
+                TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
+
+                TimerInit( &Led1Timer, OnLed1TimerEvent );
+                TimerSetValue( &Led1Timer, 25000 );
+
+                TimerInit( &Led2Timer, OnLed2TimerEvent );
+                TimerSetValue( &Led2Timer, 25000 );
+
+                mibReq.Type = MIB_ADR;
+                mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_PUBLIC_NETWORK;
+                mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+#if defined( USE_BAND_868 )
+                LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
+                SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
+#endif
+                SerialDisplayUpdateActivationMode( OVER_THE_AIR_ACTIVATION );
+                SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
+                SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
+
+                LoRaMacDownlinkStatus.DownlinkCounter = 0;
+
+                DeviceState = DEVICE_STATE_JOIN;
+                break;
+            }
+            case DEVICE_STATE_JOIN:
+            {
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+                MlmeReq_t mlmeReq;
+
+                mlmeReq.Type = MLME_JOIN;
+
+                mlmeReq.Req.Join.DevEui = DevEui;
+                mlmeReq.Req.Join.AppEui = AppEui;
+                mlmeReq.Req.Join.AppKey = AppKey;
+
+                if( NextTx == true )
+                {
+                    LoRaMacMlmeRequest( &mlmeReq );
+                }
+
+                SerialDisplayUpdateEui( 5, DevEui );
+                SerialDisplayUpdateEui( 6, AppEui );
+                SerialDisplayUpdateKey( 7, AppKey );
+
                 // Schedule next packet transmission
-                TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
+                TxDutyCycleTime = OVER_THE_AIR_ACTIVATION_DUTYCYCLE;
+                DeviceState = DEVICE_STATE_CYCLE;
+
+#else
+                mibReq.Type = MIB_NET_ID;
+                mibReq.Param.NetID = LORAWAN_NETWORK_ID;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_DEV_ADDR;
+                mibReq.Param.DevAddr = DevAddr;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_NWK_SKEY;
+                mibReq.Param.NwkSKey = NwkSKey;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_APP_SKEY;
+                mibReq.Param.AppSKey = AppSKey;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                mibReq.Type = MIB_NETWORK_JOINED;
+                mibReq.Param.IsNetworkJoined = true;
+                LoRaMacMibSetRequestConfirm( &mibReq );
+
+                SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
+                SerialDisplayUpdateDevAddr( DevAddr );
+                SerialDisplayUpdateKey( 12, NwkSKey );
+                SerialDisplayUpdateKey( 13, AppSKey );
+
+                DeviceState = DEVICE_STATE_SEND;
+#endif
+                IsNetworkJoinedStatusUpdate = true;
+                break;
+            }
+            case DEVICE_STATE_SEND:
+            {
+                if( NextTx == true )
+                {
+                    SerialDisplayUpdateUplinkAcked( false );
+                    SerialDisplayUpdateDonwlinkRxData( false );
+                    PrepareTxFrame( AppPort );
+
+                    NextTx = SendFrame( );
+
+                    // Switch LED 1 ON
+                    Led1State = true;
+                    Led1StateChanged = true;
+                    TimerStart( &Led1Timer );
+                }
+                if( ComplianceTest.Running == true )
+                {
+                    // Schedule next packet transmission as soon as possible
+                    TxDutyCycleTime = 1000; // 1 ms
+                }
+                else
+                {
+                    // Schedule next packet transmission
+                    TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
+                }
+                DeviceState = DEVICE_STATE_CYCLE;
+                break;
+            }
+            case DEVICE_STATE_CYCLE:
+            {
+                // Schedule next packet transmission
                 TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
                 TimerStart( &TxNextPacketTimer );
-//            }
-        }
 
-        if( trySendingFrameAgain == true )
-        {
-            trySendingFrameAgain = SendFrame( );
-        }
-        if( TxNextPacket == true )
-        {
-            TxNextPacket = false;
-        
-            SerialDisplayUpdateDonwlinkRxData( false );
-            
-            PrepareTxFrame( AppPort );
-            
-            Led1State = true;
-            SerialDisplayUpdateLedState( 1, Led1State );
-            TimerStart( &Led1Timer );
-
-            trySendingFrameAgain = SendFrame( );
-            
-            SerialDisplayUpdateUplink( LoRaMacUplinkStatus.Acked, LoRaMacUplinkStatus.Datarate, LoRaMacUplinkStatus.UplinkCounter, LoRaMacUplinkStatus.Port, LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize );
+                DeviceState = DEVICE_STATE_SLEEP;
+                break;
+            }
+            case DEVICE_STATE_SLEEP:
+            {
+                // Wake up through events
+                break;
+            }
+            default:
+            {
+                DeviceState = DEVICE_STATE_INIT;
+                break;
+            }
         }
     }
 }
--- a/app/vt100.h	Thu Nov 26 17:22:53 2015 +0000
+++ b/app/vt100.h	Thu Jan 07 15:14:22 2016 +0000
@@ -15,7 +15,16 @@
 #ifndef __VT100_H__
 #define __VT100_H__
 
-class VT100 : public Serial
+#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
@@ -42,10 +51,8 @@
         CYAN    = 6,
         WHITE   = 7,
     };
-    /*!
-     *
-     */
-    VT100( PinName tx, PinName rx ): Serial( tx, rx )
+
+    VT100( PinName tx, PinName rx ): SerialBase( tx, rx )
     {
         this->baud( 115200 );
         // initializes terminal to "power-on" settings
@@ -59,7 +66,6 @@
         // 0    Clear screen from cursor down
         // 1    Clear screen from cursor up
         // 2    Clear entire screen 
-
         this->printf( "\x1B[%dJ", param );
     }
 
@@ -69,7 +75,6 @@
         // 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 );
     }
 
@@ -137,6 +142,70 @@
     {
         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:
     
 };
--- a/board/board.h	Thu Nov 26 17:22:53 2015 +0000
+++ b/board/board.h	Thu Jan 07 15:14:22 2016 +0000
@@ -21,7 +21,7 @@
 #include "system/utilities.h"
 #include "sx1276-hal.h"
 
-#define USE_BAND_915_HYBRID
+#define USE_BAND_868
 
 extern SX1276MB1xAS Radio;
 
@@ -37,5 +37,4 @@
  */
 uint8_t BoardGetBatteryLevel( void );
 
-
 #endif // __BOARD_H__
--- a/mac/LoRaWAN-lib.lib	Thu Nov 26 17:22:53 2015 +0000
+++ b/mac/LoRaWAN-lib.lib	Thu Jan 07 15:14:22 2016 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/teams/Semtech/code/LoRaWAN-lib/#91e4e6c60d1e
+http://developer.mbed.org/teams/Semtech/code/LoRaWAN-lib/#14a5d6ad92d5
--- a/mbed.bld	Thu Nov 26 17:22:53 2015 +0000
+++ b/mbed.bld	Thu Jan 07 15:14:22 2016 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/165afa46840b
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/4336505e4b1c
\ No newline at end of file
--- a/system/utilities.cpp	Thu Nov 26 17:22:53 2015 +0000
+++ b/system/utilities.cpp	Thu Jan 07 15:14:22 2016 +0000
@@ -51,6 +51,15 @@
     }
 }
 
+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-- )
--- a/system/utilities.h	Thu Nov 26 17:22:53 2015 +0000
+++ b/system/utilities.h	Thu Jan 07 15:14:22 2016 +0000
@@ -69,6 +69,15 @@
 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