Semtech stack for ELMO - ver. 4.1.0.

Dependencies:   SX1272lib mbed

Fork of LoRaWAN_Semtech_stack_v4.1 by Michal Leksinski

Revision:
1:2be292bd43f9
Parent:
0:c58229885f95
Child:
3:73c2fa59588c
--- a/main.cpp	Wed Dec 16 14:25:16 2015 +0000
+++ b/main.cpp	Tue Mar 15 23:27:24 2016 +0000
@@ -1,34 +1,28 @@
-/* 
-
-Description: MBED LoRaWAN example application
-
+/*
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2013 Semtech
+Description: LoRaMac classA device implementation
 License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Espotel
+Maintainer: Miguel Luis and Gregory Cristian
 */
 
-#include "mbed.h"
+/*! \file classA/LoRaMote/main.c */
 
 #include <string.h>
 #include <math.h>
-//#include "board.h"
-
-#include "LoRaMac.h"
-#include "utilities.h"
+#include "mbed.h"
 
-#define USE_BAND_868
-/*!
- * 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
+#include "utilities.h"
+#include "LoRaMac.h"
+#include "Comissioning.h"
 
-/*!
- * 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 )
+DigitalOut Led1(LED1);
+DigitalOut Led2(LED2);
 
 /*!
  * Join requests trials duty cycle.
@@ -36,65 +30,15 @@
 #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)
- *
- * \remark In this application the value is automatically generated by calling
- *         BoardGetUniqueId function
+ * Defines the application data transmission duty cycle. 5s, value in [us].
  */
-#define LORAWAN_DEVICE_EUI                          { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-
-/*!
- * Application IEEE EUI
- *
- * \remark must be written as a little endian value (reverse order of normal reading)
- */
-//#define LORAWAN_APPLICATION_EUI                     { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }
-#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, 0x00 }
-//#define LORAWAN_APPLICATION_KEY                     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-
-#else
+#define APP_TX_DUTYCYCLE                            5000000
 
 /*!
- * 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)
- *
- * \remark In this application the value is automatically generated using
- *         a pseudo random generator seeded with a value derived from
- *         BoardUniqueId value
+ * Defines a random delay for application data transmission duty cycle. 1s,
+ * value in [us].
  */
-#define LORAWAN_DEVICE_ADDRESS                      ( uint32_t )0x00000000
-
-/*!
- * 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
-
-/*!
- * Defines the application data transmission duty cycle
- */
-#define APP_TX_DUTYCYCLE                            5000000  // 5 [s] value in us
-#define APP_TX_DUTYCYCLE_RND                        1000000  // 1 [s] value in us
+#define APP_TX_DUTYCYCLE_RND                        1000000
 
 /*!
  * LoRaWAN confirmed messages
@@ -102,19 +46,37 @@
 #define LORAWAN_CONFIRMED_MSG_ON                    false
 
 /*!
- * LoRaWAN Adaptative Data Rate
+ * LoRaWAN Adaptive Data Rate
  *
  * \remark Please note that when ADR is enabled the end-device should be static
  */
 #define LORAWAN_ADR_ON                              1
 
+#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                        true
-#define LORAWAN_DUTYCYCLE_OFF                       false
+
+#define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP          1
+
+#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) 
+
+#define LC4                { 867100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC5                { 867300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC6                { 867500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC7                { 867700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC8                { 867900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC9                { 868800000, { ( ( DR_7 << 4 ) | DR_7 ) }, 2 }
+
+#endif
+
+#endif
 
 /*!
  * LoRaWAN application port
@@ -124,8 +86,16 @@
 /*!
  * User application data buffer size
  */
+#if defined( USE_BAND_868 )
+
 #define LORAWAN_APP_DATA_SIZE                       16
 
+#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+
+#define LORAWAN_APP_DATA_SIZE                       11
+
+#endif
+
 #if( OVER_THE_AIR_ACTIVATION != 0 )
 
 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
@@ -145,11 +115,6 @@
 #endif
 
 /*!
- * Indicates if the MAC layer has already joined a network.
- */
-static bool IsNetworkJoined = false;
-
-/*!
  * Application port
  */
 static uint8_t AppPort = LORAWAN_APP_PORT;
@@ -169,7 +134,6 @@
  */
 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
 
-
 /*!
  * Indicates if the node is sending confirmed or unconfirmed messages
  */
@@ -180,49 +144,62 @@
  */
 static uint32_t TxDutyCycleTime;
 
+/*!
+ * Timer to handle the application data transmission duty cycle
+ */
+static Timeout TxNextPacketTimer;
 
-static void OnTxNextPacketTimerEvent( void );
-static Timeout TxNextPacketTimer;//(OnTxNextPacketTimerEvent, osTimerOnce);
-
-#if( OVER_THE_AIR_ACTIVATION != 0 )
+/*!
+ * Specifies the state of the application LED
+ */
+static bool AppLedStateOn = false;
 
-static void OnJoinReqTimerEvent( void );
 /*!
- * Defines the join request timer
+ * Timer to handle the state of LED1
  */
-static Timeout JoinReqTimer;//(OnJoinReqTimerEvent, osTimerOnce);
+static Timeout Led1Timer;
 
-#endif
+/*!
+ * Timer to handle the state of LED2
+ */
+static Timeout Led2Timer;
 
 /*!
  * Indicates if a new packet can be sent
  */
-static bool TxNextPacket = true;
-static bool ScheduleNextTx = false;
-static bool DownlinkStatusUpdate = false;
-
-static bool AppLedStateOn = false;
+static bool NextTx = true;
 
-static LoRaMacCallbacks_t LoRaMacCallbacks;
-/*
-static TimerEvent_t Led1Timer;
-volatile bool Led1StateChanged = false;
-static TimerEvent_t Led2Timer;
-volatile bool Led2StateChanged = false;
-static TimerEvent_t Led4Timer;
-volatile bool Led4StateChanged = false;
-
-volatile bool Led3StateChanged = false;
-*/
-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;
+/*!
+ * Device states
+ */
+static enum eDevicState
+{
+    DEVICE_STATE_INIT,
+    DEVICE_STATE_JOIN,
+    DEVICE_STATE_SEND,
+    DEVICE_STATE_CYCLE,
+    DEVICE_STATE_SLEEP
+}DeviceState;
 
 /*!
- * Prepares the frame buffer to be sent
+ * 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;
+
+/*!
+ * \brief   Prepares the payload of the frame
  */
 static void PrepareTxFrame( uint8_t port )
 {
@@ -230,6 +207,7 @@
     {
     case 2:
         {
+#if defined( USE_BAND_868 )
             uint16_t pressure = 0;
             int16_t altitudeBar = 0;
             int16_t temperature = 0;
@@ -260,109 +238,334 @@
             AppData[13] = longitude & 0xFF;
             AppData[14] = ( altitudeGps >> 8 ) & 0xFF;
             AppData[15] = altitudeGps & 0xFF;
+#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+            int16_t temperature = 0;
+            int32_t latitude, longitude = 0;
+            uint16_t altitudeGps = 0xFFFF;
+            uint8_t batteryLevel = 0;
+        
+            temperature = ( int16_t )( MPL3115ReadTemperature( ) * 100 );       // in °C * 100
+        
+            batteryLevel = BoardGetBatteryLevel( );                             // 1 (very low) to 254 (fully charged)
+            GpsGetLatestGpsPositionBinary( &latitude, &longitude );
+            altitudeGps = GpsGetLatestGpsAltitude( );                           // in m
+        
+            AppData[0] = AppLedStateOn;
+            AppData[1] = temperature;
+            AppData[2] = batteryLevel;
+            AppData[3] = ( latitude >> 16 ) & 0xFF;
+            AppData[4] = ( latitude >> 8 ) & 0xFF;
+            AppData[5] = latitude & 0xFF;
+            AppData[6] = ( longitude >> 16 ) & 0xFF;
+            AppData[7] = ( longitude >> 8 ) & 0xFF;
+            AppData[8] = longitude & 0xFF;
+            AppData[9] = ( altitudeGps >> 8 ) & 0xFF;
+            AppData[10] = altitudeGps & 0xFF;
+#endif
         }
         break;
     case 224:
-        if( ComplianceTestLinkCheck == true )
+        if( ComplianceTest.LinkCheck == true )
         {
-            printf("ComplianceTestLinkCheck\r\n");
-            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
         {
-            if( ComplianceTestState == 1 )
+            switch( ComplianceTest.State )
             {
-                printf("Sending downlink COUNTER!!!!\r\n");
+            case 4:
+                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 )
+/*!
+ * \brief   Prepares the payload of the frame
+ *
+ * \retval  [0: frame could be send, 1: error]
+ */
+static bool SendFrame( void )
 {
-    switch( info->RxPort ) // Check Rx port number
+    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 = DR_0;
+    }
+    else
+    {
+        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 = DR_0;
+        }
+        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 = DR_0;
+        }
+    }
+
+    if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
+    {
+        return false;
+    }
+    return true;
+}
+
+/*!
+ * \brief Function executed on TxNextPacket Timeout event
+ */
+static void OnTxNextPacketTimerEvent( void )
+{
+    MibRequestConfirm_t mibReq;
+    LoRaMacStatus_t status;
+
+    TxNextPacketTimer.detach();
+
+    mibReq.Type = MIB_NETWORK_JOINED;
+    status = LoRaMacMibGetRequestConfirm( &mibReq );
+
+    if( status == LORAMAC_STATUS_OK )
     {
-    case 1: // The application LED can be controlled on port 1 or 2
-    case 2:
-        if( info->RxBufferSize == 1 )
+        if( mibReq.Param.IsNetworkJoined == true )
+        {
+            DeviceState = DEVICE_STATE_SEND;
+            NextTx = true;
+        }
+        else
+        {
+            DeviceState = DEVICE_STATE_JOIN;
+        }
+    }
+}
+
+/*!
+ * \brief Function executed on Led 1 Timeout event
+ */
+static void OnLed1TimerEvent( void )
+{
+    Led1Timer.detach();
+    // Switch LED 1 OFF
+    Led1 = 1;
+}
+
+/*!
+ * \brief Function executed on Led 2 Timeout event
+ */
+static void OnLed2TimerEvent( void )
+{
+    Led2Timer.detach();
+    // Switch LED 2 OFF
+    Led2 = 1;
+}
+
+/*!
+ * \brief   MCPS-Confirm event function
+ *
+ * \param   [IN] McpsConfirm - Pointer to the confirm structure,
+ *               containing confirm attributes.
+ */
+static void McpsConfirm( McpsConfirm_t *McpsConfirm )
+{
+    if( McpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
+    {
+        switch( McpsConfirm->McpsRequest )
         {
-            AppLedStateOn = info->RxBuffer[0] & 0x01;
-            //Led3StateChanged = true;
+            case MCPS_UNCONFIRMED:
+            {
+                // Check Datarate
+                // Check TxPower
+                break;
+            }
+            case MCPS_CONFIRMED:
+            {
+                // Check Datarate
+                // Check TxPower
+                // Check AckReceived
+                // Check NbTrials
+                break;
+            }
+            case MCPS_PROPRIETARY:
+            {
+                break;
+            }
+            default:
+                break;
         }
-        break;
+
+        // Switch LED 1 ON
+        Led1 = 0;
+        Led1Timer.attach_us(OnLed1TimerEvent, 25000);
+    }
+    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
+
+    if( ComplianceTest.Running == true )
+    {
+        ComplianceTest.DownLinkCounter++;
+    }
+
+    if( McpsIndication->RxData == true )
+    {
+        switch( McpsIndication->Port )
+        {
+        case 1: // The application LED can be controlled on port 1 or 2
+        case 2:
+            if( McpsIndication->BufferSize == 1 )
+            {
+                AppLedStateOn = McpsIndication->Buffer[0] & 0x01;
+                //GpioWrite( &Led3, ( ( AppLedStateOn & 0x01 ) != 0 ) ? 0 : 1 );
+            }
+            break;
         case 224:
-            if( ComplianceTestOn == false )
+            if( ComplianceTest.Running == 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 ) )
+                if( ( McpsIndication->BufferSize == 4 ) && 
+                    ( McpsIndication->Buffer[0] == 0x01 ) &&
+                    ( McpsIndication->Buffer[1] == 0x01 ) &&
+                    ( McpsIndication->Buffer[2] == 0x01 ) &&
+                    ( McpsIndication->Buffer[3] == 0x01 ) )
                 {
                     IsTxConfirmed = false;
                     AppPort = 224;
                     AppDataSize = 2;
-                    ComplianceTestDownLinkCounter = 0;
-                    ComplianceTestLinkCheck = false;
-                    ComplianceTestDemodMargin = 0;
-                    ComplianceTestNbGateways = 0;
-                    ComplianceTestOn = true;
-                    ComplianceTestState = 1;
+                    ComplianceTest.DownLinkCounter = 0;
+                    ComplianceTest.LinkCheck = false;
+                    ComplianceTest.DemodMargin = 0;
+                    ComplianceTest.NbGateways = 0;
+                    ComplianceTest.Running = true;
+                    ComplianceTest.State = 1;
                     
-                    LoRaMacSetAdrOn( true );
-                    LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_OFF );
+                    MibRequestConfirm_t mibReq;
+                    mibReq.Type = MIB_ADR;
+                    mibReq.Param.AdrEnable = true;
+                    LoRaMacMibSetRequestConfirm( &mibReq );
+
+#if defined( USE_BAND_868 )
+                    LoRaMacTestSetDutyCycleOn( false );
+#endif
                 }
             }
             else
             {
-                ComplianceTestState = info->RxBuffer[0];
-                switch( ComplianceTestState )
+                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;
-                    ComplianceTestDownLinkCounter = 0;
-                    ComplianceTestOn = false;
+                    ComplianceTest.DownLinkCounter = 0;
+                    ComplianceTest.Running = false;
                     
-                    LoRaMacSetAdrOn( LORAWAN_ADR_ON );
+                    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;
-                    ComplianceTestState = 1;
+                    ComplianceTest.State = 1;
                     break;
                 case 3:  // Disable confirmed messages (vi)
                     IsTxConfirmed = false;
-                    ComplianceTestState = 1;    
+                    ComplianceTest.State = 1;
                     break;
                 case 4: // (vii)
-                    AppDataSize = info->RxBufferSize;
-                    printf("VII <------------------- rozmiar %i \r\n", AppDataSize);
+                    AppDataSize = McpsIndication->BufferSize;
+
                     AppData[0] = 4;
                     for( uint8_t i = 1; i < AppDataSize; i++ )
                     {
-                        
-                    printf("VII <-------------------dodaje \r\n");
-                        AppData[i] = info->RxBuffer[i] + 1;
+                        AppData[i] = McpsIndication->Buffer[i] + 1;
                     }
                     break;
                 case 5: // (viii)
-                    LoRaMacLinkCheckReq( );
+                    {
+                        MlmeReq_t mlmeReq;
+                        mlmeReq.Type = MLME_LINK_CHECK;
+                        LoRaMacMlmeRequest( &mlmeReq );
+                    }
                     break;
                 default:
                     break;
@@ -371,274 +574,196 @@
             break;
         default:
             break;
-    }
-
-    if( ( ComplianceTestOn == true ) && ( flags->Bits.LinkCheck == 1 ) )
-    {
-        ComplianceTestLinkCheck = true;
-        ComplianceTestDemodMargin = info->DemodMargin;
-        ComplianceTestNbGateways = info->NbGateways;
-    }
-    
-    #warning needed extension to check counter scopes
-}
-
-static bool SendFrame( void )
-{
-    uint8_t sendFrameStatus =   0;
-
-    if( IsTxConfirmed == false )
-    {
-        sendFrameStatus = LoRaMacSendFrame( AppPort, AppData, AppDataSize );
-    }
-    else
-    {
-        sendFrameStatus = LoRaMacSendConfirmedFrame( AppPort, AppData, AppDataSize, 8 );
+        }
     }
 
-    switch( sendFrameStatus )
-    {
-    case 5: // NO_FREE_CHANNEL
-        // Try again later
-        return true;
-    default:
-        return false;
-    }
-}
-
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-
-/*!
- * \brief Function executed on JoinReq Timeout event
- */
-static void OnJoinReqTimerEvent( void )
-{
-    JoinReqTimer.detach();
-    TxNextPacket = true;
-}
-
-#endif
-
-/*!
- * \brief Function executed on TxNextPacket Timeout event
- */
-static void OnTxNextPacketTimerEvent( void )
-{
-    //TimerStop( &TxNextPacketTimer );
-    //TxNextPacketTimer.stop();
-    TxNextPacketTimer.detach();
-    TxNextPacket = true;
+    // Switch LED 2 ON for each received downlink
+    Led2 = 0;
+    Led2Timer.attach_us(OnLed2TimerEvent, 25000);
 }
 
 /*!
- * \brief Function executed on Led 1 Timeout event
- */
-/*static void OnLed1TimerEvent( void )
-{
-    TimerStop( &Led1Timer );
-    Led1StateChanged = true;
-}*/
-
-/*!
- * \brief Function executed on Led 2 Timeout event
- */
-/*static void OnLed2TimerEvent( void )
-{
-    TimerStop( &Led2Timer );
-    Led2StateChanged = true;
-}*/
-
-/*!
- * \brief Function executed on Led 4 Timeout event
- */
-/*void OnLed4TimerEvent( void )
-{
-    TimerStop( &Led4Timer );
-    Led4StateChanged = true;
-}*/
-
-/*!
- * \brief Function to be executed on MAC layer event
+ * \brief   MLME-Confirm event function
+ *
+ * \param   [IN] MlmeConfirm - Pointer to the confirm structure,
+ *               containing confirm attributes.
  */
-static void OnMacEvent( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info )
+static void MlmeConfirm( MlmeConfirm_t *MlmeConfirm )
 {
-    if( flags->Bits.JoinAccept == 1 )
+    if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
     {
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-        JoinReqTimer.detach();
-#endif
-        IsNetworkJoined = true;
-    }
-    else
-    {
-        if( flags->Bits.Tx == 1 )
+        switch( MlmeConfirm->MlmeRequest )
         {
-        }
-
-        if( flags->Bits.Rx == 1 )
-        {
-            if( ComplianceTestOn == true )
+            case MLME_JOIN:
             {
-                ComplianceTestDownLinkCounter++;
+                // Status is OK, node has joined the network
+                break;
             }
-            if( flags->Bits.RxData == true )
+            case MLME_LINK_CHECK:
             {
-                ProcessRxFrame( flags, info );
+                // Check DemodMargin
+                // Check NbGateways
+                if( ComplianceTest.Running == true )
+                {
+                    ComplianceTest.LinkCheck = true;
+                    ComplianceTest.DemodMargin = MlmeConfirm->DemodMargin;
+                    ComplianceTest.NbGateways = MlmeConfirm->NbGateways;
+                }
+                break;
             }
-            
-            DownlinkStatusUpdate = true;
-            //TimerStart( &Led2Timer );
+            default:
+                break;
         }
     }
-    // Schedule a new transmission
-    ScheduleNextTx = true;
+    NextTx = true;
 }
 
 /**
  * Main application entry point.
  */
-   
 int main( void )
 {
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-    uint8_t sendFrameStatus = 0;
-#endif
-    bool trySendingFrameAgain = false;
+    LoRaMacPrimitives_t LoRaMacPrimitives;
+    LoRaMacCallback_t LoRaMacCallbacks;
+    MibRequestConfirm_t mibReq;
 
-#warning HW and RADIO CHIP must be configured!!!!
     //BoardInitMcu( );
     //BoardInitPeriph( );
-    //hal_init();
-    //radio_init();
 
-    LoRaMacCallbacks.MacEvent = OnMacEvent;
-    //LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
-    LoRaMacInit( &LoRaMacCallbacks );
-
-    IsNetworkJoined = false;
-
-#if( OVER_THE_AIR_ACTIVATION == 0 )
-    // Random seed initialization
-    #warning seed initialization must be implemented
-    srand1( 1 );
-    // Choose a random device address based on Board unique ID
-    // NwkAddr rand [0, 33554431]
-    DevAddr = randr( 0, 0x01FFFFFF );
-
-    LoRaMacInitNwkIds( LORAWAN_NETWORK_ID, DevAddr, NwkSKey, AppSKey );
-    IsNetworkJoined = true;
-#else
-    // Initialize LoRaMac device unique ID
-    //BoardGetUniqueId( DevEui );
-#endif
-
-    TxNextPacket = true;
-    
-    //TimerInit( &Led1Timer, OnLed1TimerEvent );
-    //TimerSetValue( &Led1Timer, 25000 );
-
-    //TimerInit( &Led2Timer, OnLed2TimerEvent );
-    //TimerSetValue( &Led2Timer, 25000 );
-
-    //TimerInit( &Led4Timer, OnLed4TimerEvent );
-    //TimerSetValue( &Led4Timer, 25000 );
-
-    LoRaMacSetAdrOn( LORAWAN_ADR_ON );
-    #warning dutycycleON OFFFFFFFFFFFFF!!!!!!!!!!!!!!!!!!!!!!!
-//    LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON );
-    LoRaMacTestSetDutyCycleOn( 0 );
-    LoRaMacSetPublicNetwork( LORAWAN_PUBLIC_NETWORK );
+    DeviceState = DEVICE_STATE_INIT;
 
     while( 1 )
     {
-        while( IsNetworkJoined == false )
-        {
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-            if( TxNextPacket == true )
-            {
-                printf("Trial to join network... txnextpacket %i \r\n", TxNextPacket);
-                TxNextPacket = false;
-                
-                sendFrameStatus = LoRaMacJoinReq( DevEui, AppEui, AppKey );
-                printf("status = %i\r\n", sendFrameStatus);
-                switch( sendFrameStatus )
-                {
-                case 1: // BUSY
-                    printf("busy...\r\n");
-                    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
-                    JoinReqTimer.attach_us(OnJoinReqTimerEvent, OVER_THE_AIR_ACTIVATION_DUTYCYCLE);
-                    break;
-                }
-            }
-            //TimerLowPowerHandler( );
-#endif
-        }
-
-/*  
-        if( Led1StateChanged == true )
-        {
-            Led1StateChanged = false;
-            // Switch LED 1 OFF
-            GpioWrite( &Led1, 1 );
-        }
-        if( Led2StateChanged == true )
-        {
-            Led2StateChanged = false;
-            // Switch LED 2 OFF
-            GpioWrite( &Led2, 1 );
-        }
-        if( Led3StateChanged == true )
+        switch( DeviceState )
         {
-            Led3StateChanged = false;
-            GpioWrite( &Led3, ( ( AppLedStateOn & 0x01 ) != 0 ) ? 0 : 1 );
-        }
-        if( Led4StateChanged == true )
-        {
-            Led4StateChanged = false;
-            // Switch LED 4 OFF
-            GpioWrite( &Led4, 1 );
-        }*/
-        if( DownlinkStatusUpdate == true )
-        {
-            DownlinkStatusUpdate = false;
-            // Switch LED 2 ON for each received downlink
-            //GpioWrite( &Led2, 0 );
-        }
+            case DEVICE_STATE_INIT:
+            {
+                LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
+                LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
+                LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
+                //LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
+                LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks );
+
+                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 );
+
+#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) 
+                LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 );
+                LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 );
+                LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 );
+                LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 );
+                LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 );
+                LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 );
+#endif
 
-        if( ScheduleNextTx == true )
-        {
-            printf("Sending data...");
-            ScheduleNextTx = false;
+#endif
+                DeviceState = DEVICE_STATE_JOIN;
+                break;
+            }
+            case DEVICE_STATE_JOIN:
+            {
+#if( OVER_THE_AIR_ACTIVATION != 0 )
+                MlmeReq_t mlmeReq;
+
+                #warning BoardGetUniqueId not needed in test software - commented out
+                // Initialize LoRaMac device unique ID
+                // BoardGetUniqueId( DevEui );
+
+                mlmeReq.Type = MLME_JOIN;
+
+                mlmeReq.Req.Join.DevEui = DevEui;
+                mlmeReq.Req.Join.AppEui = AppEui;
+                mlmeReq.Req.Join.AppKey = AppKey;
+
+                if( NextTx == true )
+                {
+                    LoRaMacMlmeRequest( &mlmeReq );
+                }
+
+                // Schedule next packet transmission
+                TxDutyCycleTime = OVER_THE_AIR_ACTIVATION_DUTYCYCLE;
+                DeviceState = DEVICE_STATE_CYCLE;
+
+#else
+                // Random seed initialization
+                srand1( BoardGetRandomSeed( ) );
+
+                // Choose a random device address
+                DevAddr = randr( 0, 0x01FFFFFF );
 
-            // Schedule next packet transmission
-            TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
-            TxNextPacketTimer.attach_us(OnTxNextPacketTimerEvent, TxDutyCycleTime);
-        }
+                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 );
+
+                DeviceState = DEVICE_STATE_SEND;
+#endif
+                break;
+            }
+            case DEVICE_STATE_SEND:
+            {
+                if( NextTx == true )
+                {
+                    PrepareTxFrame( AppPort );
 
-        if( trySendingFrameAgain == true )
-        {
-            trySendingFrameAgain = SendFrame( );
+                    NextTx = SendFrame( );
+                }
+                if( ComplianceTest.Running == true )
+                {
+                    // Schedule next packet transmission as soon as possible
+                    TxDutyCycleTime = 300000; // 300 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:
+            {
+                DeviceState = DEVICE_STATE_SLEEP;
+
+                // Schedule next packet transmission
+                TxNextPacketTimer.attach_us(OnTxNextPacketTimerEvent, TxDutyCycleTime);
+                break;
+            }
+            case DEVICE_STATE_SLEEP:
+            {
+                // Wake up through events
+                #warning TimerLowPowerHandler disabled
+                //TimerLowPowerHandler( );
+                break;
+            }
+            default:
+            {
+                DeviceState = DEVICE_STATE_INIT;
+                break;
+            }
         }
-        if( TxNextPacket == true )
-        {
-            TxNextPacket = false;
-            
-            PrepareTxFrame( AppPort );
-            
-            // Switch LED 1 ON
-            //GpioWrite( &Led1, 0 );
-            //TimerStart( &Led1Timer );
-            
-            trySendingFrameAgain = SendFrame( );
-        }
-
-        //TimerLowPowerHandler( );
     }
-} 
+}
\ No newline at end of file