Serial port driven Elmo based on TxRxTemplate. Serial port communication has been expanded and configuration mode has been added.

Dependencies:   SX1272lib-PABOOST-HW-Modification mbed

Fork of LoRaWAN_ELMO_TxRx_Template by Espotel

RadioHandler.cpp

Committer:
KosTee
Date:
2016-10-10
Revision:
10:ceaf618066ca
Parent:
7:3d16d6fe3b12

File content as of revision 10:ceaf618066ca:

/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (C)2013 Semtech
Description: LoRaMac classA device implementation
License: Revised BSD License, see LICENSE.TXT file include in the project
Maintainer: Miguel Luis and Gregory Cristian
Latest modifier: Teemu Koskinen
*/

/*! \file classA/LoRaMote/main.c */

#include <string.h>
#include <math.h>
#include "mbed.h"
#include <stdio.h>
#include "utilities.h"
#include "LoRaMac.h"
#include "Comissioning.h"
#include "InterruptIn.h"
#include "RadioHandler.h"
#include <stdlib.h>

/* -- Latest updates -- */
//Version 1.0b
/* RadioHandler contains new funtions */
//void RadioSetup( void );
//void SetRadioValues(void);
//void SetDevEui(void);
//void SetAppEui(void);
//void SetAppKey(void);
/* Some of these functions should not be here cause they are not about radio handling. Refactoring is recommended if this branch is continued */





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                    true//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 )

/* Copied these values to .h for easier handling. TK */
//static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
//static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI;
//static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY;

//Setting the default values
uint8_t DevEui[8] = LORAWAN_DEVICE_EUI;
uint8_t AppEui[8] = LORAWAN_APPLICATION_EUI;
uint8_t AppKey[16] = 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];

/*!
 * User application data buffer
 */
static uint8_t AppDataBuffer[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;

/*!
 * Timer to handle the state of LED2
 */
static Timeout Led2Timer;

/*!
 * Indicates if a new packet can be sent
 */
static bool NextTx = true;

/*!
 * Packet send request
 */
static bool PacketTxReq = false;

/*!
 * Periodic packets enabled
 */
static bool PeriodicPackets = false;
/*!
 * 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 )
{
    uint16_t i;

    switch( port )
    {
    case 2:
        {
#if defined( USE_BAND_868 )

            for (i=0; i<LORAWAN_APP_DATA_SIZE; i++)
            {
                AppData[i] = AppDataBuffer[i];
            }

#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )

            for (i=0; i<LORAWAN_APP_DATA_SIZE; i++)
            {
                AppData[i] = AppDataBuffer[i];
            }

#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 )
{
    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 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 )
{
    printf("MCPS Confirm\r\n");
    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;
        }
    }
    NextTx = true;
}

/*!
 * \brief   MCPS-Indication event function
 *
 * \param   [IN] McpsIndication - Pointer to the indication structure,
 *               containing indication attributes.
 */
static void McpsIndication( McpsIndication_t *McpsIndication )
{
    printf("MCPS Indication\r\n");
    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:
        case 2:
            printf("Receive buffer : %s\r\n", (char*)McpsIndication->Buffer);
            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 )
{
    printf("MLME Confirm\r\n");
    if( MlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK )
    {
        switch( MlmeConfirm->MlmeRequest )
        {
            case MLME_JOIN:
            {
                // Status is OK, node has joined the network
                printf("\r\nElmo has joined the network\r\n\r\n");
                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;
}

/**
 * Radio state machine initialization
 */
void RadioInit( void )
{
    DeviceState = DEVICE_STATE_INIT;
}

/**
 * Request packet transmission
 */
void RequestPacketTx( char *DataString, bool PeriodicRequested  )
{
    PacketTxReq = true;
    PeriodicPackets = PeriodicRequested;

    // Copy string to buffer, truncated to max packet size if necessary with trailing zero
    // Packet size is always max allowed. Padded with zeroes
    strncpy((char*)AppDataBuffer, DataString, LORAWAN_APP_DATA_SIZE-1);
    AppDataBuffer[LORAWAN_APP_DATA_SIZE-1] = 0;
}
/**
 * Radio state machine.
 */
void RadioHandler( void )
{
    static LoRaMacPrimitives_t LoRaMacPrimitives;
    static LoRaMacCallback_t LoRaMacCallbacks;
    static MibRequestConfirm_t mibReq;

    switch( DeviceState )
    {
        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

#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 );

            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 )
            {
                printf("Packet sent\r\n");
                PrepareTxFrame( AppPort );

                NextTx = SendFrame( );
                if(PacketTxReq)
                {
                    printf("Unscheduled packet transmission\r\n");
                    PacketTxReq = false;
                }
            }
            if( ComplianceTest.Running == true )
            {
                // Schedule next packet transmission as soon as possible
                TxDutyCycleTime = 300000; // 300 ms
            }
            else
            {
                // Schedule next packet periodic 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
            if(PeriodicPackets)
            {
                TxNextPacketTimer.attach_us(OnTxNextPacketTimerEvent, TxDutyCycleTime);
            }
            break;
        }
        case DEVICE_STATE_SLEEP:
        {
            // Wake up through events
            if(PacketTxReq)
            {
                DeviceState = DEVICE_STATE_SEND;
            }
            #warning TimerLowPowerHandler disabled
            //TimerLowPowerHandler( );
            break;
        }
        default:
        {
            DeviceState = DEVICE_STATE_INIT;
            break;
        }
    }
}

/* This function prints current values and enables configuration for new values */
void RadioSetup(void)
{
    printf("Current settings:\r\n");
    int indexor=0;
    /* Print DevEui */
    printf("DevEui: ");
    while (indexor < sizeof(DevEui))
    {
        if (indexor == (sizeof(DevEui)-1))
            {
            printf("%02x", DevEui[indexor]);
            }
        else
            {
            printf("%02x-", DevEui[indexor]);
            }
        indexor++;
    }
    printf("\r\n");
    indexor=0;
    /* Print AppEui */
    printf("AppEui: ");
    while (indexor < sizeof(AppEui))
    {
        if (indexor == (sizeof(AppEui)-1))
        {
        printf("%02x", AppEui[indexor]);
        }
        else
        {
        printf("%02x-", AppEui[indexor]);  
        }
        indexor++;
    }
    printf("\r\n");
    indexor=0;
    /* Print AppKey */
    printf("AppKey: ");
    while (indexor < sizeof(AppKey))
    {
        if (indexor == (sizeof(AppKey)-1))
        {
        printf("%02x", AppKey[indexor]);   
        }
        else
        {
        printf("%02x-", AppKey[indexor]);
        }
        indexor++;
    }
    printf("\r\n");
    indexor=0;
      
    uint16_t index = 0;
    char answer[5];
    char answer_yes[5];
    strcpy(answer_yes,"YES\n");
    printf("Set new values?: YES | NO: \r\n");
    Serial port(SERIAL_TX, SERIAL_RX);
    port.baud(9600);
    
    /* Read answer to entering the configuration mode */
    while( 1 )
    {
        if (port.readable()) 
        {
            answer[index]=port.getc();
            
            if (answer[index]=='\n')
            {
                port.printf("Your input was: %s\r\n", answer);
                port.printf("Comparing to: %s\r\n", answer_yes);
                
                port.printf("%d\r\n",strncmp( answer, answer_yes, 3));
                if (strncmp( answer, answer_yes, 3) == 0 )
                {
                 /* Setting the new values function*/
                 SetRadioValues();            
                }
                memset(answer,' ', sizeof(answer));
                index=0;
                break;
            }
            index++;
            if (index>5)
            {
                index=0;
            }
        }  
   }
  
}

/* Function for setting new values */
void SetRadioValues(void)
{
    Serial port(SERIAL_TX, SERIAL_RX);
    port.baud(9600);
    char answer[10];
    char answer_yes[10];
    uint16_t index = 0;
    printf("\r\nWelcome configuration. Please enter your selection:\r\n\t1: SetDevEui\r\n\t2: SetAppEui\r\n\t3: SetAppKey\r\n");
    
    /* Read answer which item is goin to be updated */
    while( 1 )
    {
        if (port.readable()) 
        {
            answer[index]=port.getc();
            
            if (answer[index]=='\n')
            {
                port.printf("Your input was: %s\r\n", answer);
                strcpy(answer_yes,"1\n");
                port.printf("Comparing to: %s\r\n", answer_yes);            
                port.printf("%d\r\n",strncmp( answer, answer_yes, 3));
                if (strncmp( answer, answer_yes, 1) == 0 )
                {
                    /* Setting new DevEui */
                    SetDevEui();           
                }
                strcpy(answer_yes,"2\n");
                port.printf("Comparing to: %s\r\n", answer_yes);            
                port.printf("%d\r\n",strncmp( answer, answer_yes, 3));
                if (strncmp( answer, answer_yes, 1) == 0 )
                {
                    /* Setting new AppEui */
                    SetAppEui();           
                }
                strcpy(answer_yes,"3\n");
                port.printf("Comparing to: %s\r\n", answer_yes);            
                port.printf("%d\r\n",strncmp( answer, answer_yes, 3));
                if (strncmp( answer, answer_yes, 1) == 0 )
                {
                    /* Setting new AppKey */
                    SetAppKey();           
                }        
                memset(answer,' ', sizeof(answer));
                index=0;
                break;
            }
            index++;
            if (index>5)
            {
                index=0;
            }
        }
    }
    port.printf("Returning to setup\r\n");
    /* Init Radio with new values */
    RadioInit();
    /* Print current values, configure more or exit menu */ 
    RadioSetup();
}

/* Set new DevEui values one by one */
void SetDevEui(void)
{
    char answer[100];
    uint16_t index = 0;
    Serial port(SERIAL_TX, SERIAL_RX);
    port.baud(9600);
    uint8_t answer_int[8] = LORAWAN_DEVICE_EUI;
    char *ptr; 
    printf("\r\nSet new values\r\n");
    port.printf("Insert new DEVEUI value in integer (Will be converted to hex)\r\n"); 
    for( uint8_t a = 0; a < sizeof(answer_int); a = a + 1 )
    {
        port.printf("Value number %d for DEVEUI\r\n", a);
        while( 1 )
        {
            if (port.readable()) 
            {
                answer[index]=port.getc();
                
                if (answer[index]=='\n')
                {
                    port.printf("Your input was: %s\r\n", answer);
                    //port.printf("%d\r\n",answer_int[a]);
                    /* Set given value */
                    answer_int[a]=(uint8_t)strtol(answer, &ptr, 10);
                    port.printf("%d\r\n",answer_int[a]);   
                    DevEui[a]=answer_int[a];
                    index=0;
                    break;
                }
            index++;
            if (index>100)
                {
                    index=0;
                }
            }  
        }      
        memset(answer,' ', sizeof(answer));
        memset(answer_int,' ', sizeof(answer_int)); 
    }   
}

/* Set new AppEui values one by one */
void SetAppEui(void)
{
    char answer[100];
    uint16_t index = 0;
    Serial port(SERIAL_TX, SERIAL_RX);
    port.baud(9600);
    uint8_t answer_int[8] = LORAWAN_APPLICATION_EUI;
    char *ptr; 
    printf("\r\nSet new values\r\n");
    port.printf("Insert new APPEUI value in integer (Will be converted to hex)\r\n"); 
    for( uint8_t a = 0; a < sizeof(answer_int); a = a + 1 )
    {
        port.printf("Value number %d for APPEUI\r\n", a);
        while( 1 )
        {
            if (port.readable()) 
            {
                answer[index]=port.getc();
                
                if (answer[index]=='\n')
                {
                    port.printf("Your input was: %s\r\n", answer);
                    //port.printf("%d\r\n",answer_int[a]);
                    /* Set given value */
                    answer_int[a]=(uint8_t)strtol(answer, &ptr, 10);
                    port.printf("%d\r\n",answer_int[a]);   
                    AppEui[a]=answer_int[a];
                    index=0;
                    break;
                }
            index++;
            if (index>100)
                {
                    index=0;
                }
            }  
        }    
        memset(answer,' ', sizeof(answer));
        memset(answer_int,' ', sizeof(answer_int)); 
    }
      
}

/* Set new AppKey values one by one */
void SetAppKey(void)
{
    char answer[100];
    uint16_t index = 0;
    Serial port(SERIAL_TX, SERIAL_RX);
    port.baud(9600);
    uint8_t answer_int[16] = LORAWAN_APPLICATION_KEY;
    char *ptr; 
    printf("\r\nSet new values\r\n");
    port.printf("Insert new APPKEY value in integer (Will be converted to hex)\r\n"); 
    for( uint8_t a = 0; a < sizeof(answer_int); a = a + 1 )
    {
        port.printf("Value number %d for APPKEY\r\n", a);
        while( 1 )
        {
            if (port.readable()) 
            {
                answer[index]=port.getc();
                
                if (answer[index]=='\n')
                {
                    port.printf("Your input was: %s\r\n", answer);
                    /* Set given value */
                    answer_int[a]=(uint8_t)strtol(answer, &ptr, 10);
                    port.printf("%d\r\n",answer_int[a]);   
                    AppKey[a]=answer_int[a];
                    index=0;
                    break;
                }
            index++;
            if (index>100)
                {
                    index=0;
                }
            }  
        }       
        memset(answer,' ', sizeof(answer));
        memset(answer_int,' ', sizeof(answer_int)); 
    }
      
}