Example Tx Rx LoRa code for Multitech Conduit. Based on Semtech stack for ELMO - ver. 4.1.0.

Dependencies:   SX1272lib mbed

Revision:
5:be347c6040c1
Parent:
4:0aa5d153c316
Child:
6:71b489e70063
--- a/main.cpp	Tue Mar 22 16:20:41 2016 +0000
+++ b/main.cpp	Tue Apr 19 19:51:17 2016 +0000
@@ -1,615 +1,44 @@
 /*
- / _____)             _              | |
-( (____  _____ ____ _| |_ _____  ____| |__
- \____ \| ___ |    (_   _) ___ |/ ___)  _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
-    (C)2013 Semtech
-Description: LoRaMac classA device implementation
+
+ _______  ______ ______ _______ _______ _______ _       
+(_______)/ _____|_____ (_______|_______|_______|_)      
+ _____  ( (____  _____) )     _    _    _____   _       
+|  ___)  \____ \|  ____/ |   | |  | |  |  ___) | |      
+| |_____ _____) ) |    | |___| |  | |  | |_____| |_____ 
+|_______|______/|_|     \_____/   |_|  |_______)_______)
+
+    (C)2016 Espotel Oy/Etteplan Oyj
+Description: Main code for LORA radio code template
 License: Revised BSD License, see LICENSE.TXT file include in the project
-Maintainer: Miguel Luis and Gregory Cristian
+Maintainer: Pasi Pulkkinen
+Version 1.0
 */
 
-/*! \file classA/LoRaMote/main.c */
+#include "mbed.h"
+#include "RadioHandler.h"
 
-#include <string.h>
-#include <math.h>
-#include "mbed.h"
-
-#include "utilities.h"
-#include "LoRaMac.h"
-#include "Comissioning.h"
-#include "LoRaMac-api-v3.h"
+// --- Important notes! ---
+// USE_BAND_868 has been defined in LoRaMac-board.h
+// OVER_THE_AIR_ACTIVATION at Comissioning.h is enabled
+// LORAWAN_PUBLIC_NETWORK at Comissioning.h is true
+// LORAWAN_DEVICE_EUI at Comissioning.h should be unique for each board
+// LORAWAN_APPLICATION_EUI at Comissioning.h should be unique for each conduit. Copy this to conduit network ID EUI
+// LORAWAN_APPLICATION_KEY at Comissioning.h ensures secure end to end communication. Copy this to conduit network key
+// dConduitBugs at LoRaMac.cpp patches a bug in Multitech Conduit Firmware 1.1.2 2016-01-13T09:59:04
 
 DigitalOut Led1(LED1);
-DigitalOut Led2(LED2);
 
-/*!
- * Join requests trials duty cycle.
- */
-#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE           10000000  // 10 [s] value in us
-
-/*!
- * Defines the application data transmission duty cycle. 5s, value in [us].
- */
-#define APP_TX_DUTYCYCLE                            10000000
-
-/*!
- * Defines a random delay for application data transmission duty cycle. 1s,
- * value in [us].
- */
-#define APP_TX_DUTYCYCLE_RND                        1000000
-
-/*!
- * LoRaWAN confirmed messages
- */
-#define LORAWAN_CONFIRMED_MSG_ON                    false
-
-/*!
- * 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                        false
-
-#define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP          0
-
-#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
- */
-#define LORAWAN_APP_PORT                            2
-
-/*!
- * 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;
-static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
-static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;
-
-#else
-
-static uint8_t NwkSKey[] = LORAWAN_NWKSKEY;
-static uint8_t AppSKey[] = LORAWAN_APPSKEY;
-
-/*!
- * Device address
- */
-static uint32_t DevAddr;
-
-#endif
-
-/*!
- * Application port
- */
-static uint8_t AppPort = LORAWAN_APP_PORT;
-
-/*!
- * User application data size
- */
-static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE;
-
-/*!
- * User application data buffer size
- */
-#define LORAWAN_APP_DATA_MAX_SIZE                           64
-
-/*!
- * User application data
- */
-static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
-
-/*!
- * Indicates if the node is sending confirmed or unconfirmed messages
- */
-static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
-
-/*!
- * Defines the application data transmission duty cycle
- */
-static uint32_t TxDutyCycleTime;
-
-/*!
- * Timer to handle the application data transmission duty cycle
- */
-static Timeout TxNextPacketTimer;
-
-/*!
- * Specifies the state of the application LED
- */
-static bool AppLedStateOn = false;
-
-/*!
- * Timer to handle the state of LED1
+/*
+ * True if ELMO button was pressed
  */
-static Timeout Led1Timer;
-
-/*!
- * Timer to handle the state of LED2
- */
-static Timeout Led2Timer;
-
-/*!
- * Indicates if a new packet can be sent
- */
-static bool NextTx = true;
-
-/*!
- * Device states
- */
-static enum eDevicState
-{
-    DEVICE_STATE_INIT,
-    DEVICE_STATE_JOIN,
-    DEVICE_STATE_SEND,
-    DEVICE_STATE_CYCLE,
-    DEVICE_STATE_SLEEP
-}DeviceState;
-
-/*!
- * 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 )
-{
-    switch( port )
-    {
-    case 2:
-        {
-#if defined( USE_BAND_868 )
-            uint16_t pressure = 0;
-            int16_t altitudeBar = 0;
-            int16_t temperature = 0;
-            int32_t latitude, longitude = 0;
-            uint16_t altitudeGps = 0xFFFF;
-            uint8_t batteryLevel = 0;
-
-            //pressure = ( uint16_t )( MPL3115ReadPressure( ) / 10 );             // in hPa / 10
-            //temperature = ( int16_t )( MPL3115ReadTemperature( ) * 100 );       // in °C * 100
-            //altitudeBar = ( int16_t )( MPL3115ReadAltitude( ) * 10 );           // in m * 10
-            //batteryLevel = BoardGetBatteryLevel( );                             // 1 (very low) to 254 (fully charged)
-            //GpsGetLatestGpsPositionBinary( &latitude, &longitude );
-            //altitudeGps = GpsGetLatestGpsAltitude( );                           // in m
+static bool ButtonPressed = false;
 
-            AppData[0] = AppLedStateOn;
-            AppData[1] = ( pressure >> 8 ) & 0xFF;
-            AppData[2] = pressure & 0xFF;
-            AppData[3] = ( temperature >> 8 ) & 0xFF;
-            AppData[4] = temperature & 0xFF;
-            AppData[5] = ( altitudeBar >> 8 ) & 0xFF;
-            AppData[6] = altitudeBar & 0xFF;
-            AppData[7] = batteryLevel;
-            AppData[8] = ( latitude >> 16 ) & 0xFF;
-            AppData[9] = ( latitude >> 8 ) & 0xFF;
-            AppData[10] = latitude & 0xFF;
-            AppData[11] = ( longitude >> 16 ) & 0xFF;
-            AppData[12] = ( longitude >> 8 ) & 0xFF;
-            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;
-        
-            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( 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 4:
-                ComplianceTest.State = 1;
-                break;
-            case 1:
-                AppDataSize = 2;
-                AppData[0] = ComplianceTest.DownLinkCounter >> 8;
-                AppData[1] = ComplianceTest.DownLinkCounter;
-                break;
-            }
-        }
-        break;
-    default:
-        break;
-    }
-}
-
-/*!
- * \brief   Prepares the payload of the frame
- *
- * \retval  [0: frame could be send, 1: error]
- */
-static bool SendFrame( void )
+/*
+    ELMO Pushbutton interrupt
+*/
+void ButtonHandler( 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 = 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 )
-    {
-        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 )
-        {
-            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;
-        }
-
-        // 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( 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 ) )
-                {
-                    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
-                }
-            }
-            else
-            {
-                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;
-                }
-            }
-            break;
-        default:
-            break;
-        }
-    }
-
-    // Switch LED 2 ON for each received downlink
-    Led2 = 0;
-    Led2Timer.attach_us(OnLed2TimerEvent, 25000);
-}
-
-/*!
- * \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
-                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;
+    ButtonPressed = true;
 }
 
 /**
@@ -617,148 +46,41 @@
  */
 int main( void )
 {
-    LoRaMacPrimitives_t LoRaMacPrimitives;
-    LoRaMacCallback_t LoRaMacCallbacks;
-    MibRequestConfirm_t mibReq;
+    char XmitBuffer[100]; // Max 16 bytes in LoRa packet!
+    uint16_t PacketCount = 0;
+    InterruptIn pushButton(USER_BUTTON);
+    Serial debugPort(SERIAL_TX, SERIAL_RX);
+
+    debugPort.baud(9600);
 
-    //BoardInitMcu( );
-    //BoardInitPeriph( );
+    debugPort.printf("\r\n\r\nELMO Debugger Screen\r\n");
 
-    DeviceState = DEVICE_STATE_INIT;
+    pushButton.rise(&ButtonHandler);
+    pushButton.enable_irq();
+
+    RadioInit();
 
     while( 1 )
     {
-        switch( DeviceState )
+        // Show some debug stuff in case Elmo button is pressed. Request packet transmission
+        if (ButtonPressed)
         {
-            case DEVICE_STATE_INIT:
+            debugPort.printf("\r\nButton was pressed\r\n");
+            Led1 = !Led1;
+            sprintf(XmitBuffer, "Elmo calling %d", PacketCount);
+            RequestPacketTx(XmitBuffer, true);  // true = enable periodic transmissions. False = send just one packet
+            if(PacketCount < 99)
             {
-                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
-
-#endif
-                DeviceState = DEVICE_STATE_JOIN;
-                break;
+                PacketCount++;
             }
-            case DEVICE_STATE_JOIN:
+            else
             {
-#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 );
+                // Start from 1 when 99 is reached
+                PacketCount = 1;
+            }
+            ButtonPressed = false;
+        }
 
-                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:
-            {
-                static uint8_t flag = 0; 
-                if( NextTx == true )
-                {
-                    PrepareTxFrame( AppPort );
-
-                    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;
-            }
-        }
+        RadioHandler();
     }
 }
\ No newline at end of file