LoRaWAN MAC layer implementation

Dependents:   LoRaWAN-demo-72_tjm LoRaWAN-demo-72_jlc LoRaWAN-demo-elmo frdm_LoRa_Connect_Woodstream_Demo_tjm ... more

LoRAWAN-lib is a port of the GitHub LoRaMac-node LoRaWAN MAC layer implementation.

This library depends on the SX1276Lib or SX1272Lib radio drivers depending on the used mbed component shield.

This library depends also on some cryptographic helper functions as well as helper functions for the timers management. These can be found on the example projects under the system directory.

The example projects are:

  1. LoRaWAN-demo-72
  2. LoRaWAN-demo-76
  3. LoRaWAN-demo-NAMote72

The LoRaWAN specification specifies different ISM bands operating parameters. These are all implemented under the LoRaMac-board.h file.

In order to select which band to use, please change line 24 of board.h file provided on the examples projects as follows:


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433

Files at this revision

API Documentation at this revision

Comitter:
mluis
Date:
Mon Apr 24 09:42:37 2017 +0000
Parent:
7:c16969e0f70f
Child:
9:db4900d60c37
Commit message:
WARNING: Radio API timings changed from micro-seconds to milliseconds; ; Synchronized with https://github.com/Lora-net/LoRaMac-node git revision e506c246652fa44c3f24cecb89d0707b49ece739;

Changed in this revision

LoRaMac-api-v3.cpp Show diff for this revision Revisions of this file
LoRaMac-api-v3.h Show diff for this revision Revisions of this file
LoRaMac-definitions.h Show annotated file Show diff for this revision Revisions of this file
LoRaMac.cpp Show annotated file Show diff for this revision Revisions of this file
LoRaMac.h Show annotated file Show diff for this revision Revisions of this file
LoRaMacTest.h Show annotated file Show diff for this revision Revisions of this file
--- a/LoRaMac-api-v3.cpp	Tue Jul 05 13:24:54 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,626 +0,0 @@
-/*
- / _____)             _              | |
-( (____  _____ ____ _| |_ _____  ____| |__
- \____ \| ___ |    (_   _) ___ |/ ___)  _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
-    (C)2013 Semtech
- ___ _____ _   ___ _  _____ ___  ___  ___ ___
-/ __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC layer implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
-*/
-#include "board.h"
-
-#include "LoRaMac-api-v3.h"
-#include "LoRaMacTest.h"
-
-/*!
- *  Extern function declarations.
- */
-extern LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort,
-                             void *fBuffer, uint16_t fBufferSize );
-extern LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl,
-                                     uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-extern LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel );
-extern uint32_t LoRaMacState;
-extern LoRaMacFlags_t LoRaMacFlags;
-
-/*!
- * Static variables
- */
-static LoRaMacEventFlags_t LoRaMacEventFlags;
-static LoRaMacEventInfo_t LoRaMacEventInfo;
-static LoRaMacPrimitives_t LoRaMacPrimitives;
-static LoRaMacCallback_t LoRaMacCallback;
-static LoRaMacCallbacks_t LoRaMacCallbacks;
-
-/*!
- * \brief   MCPS-Confirm event function
- *
- * \param   [IN] mcpsConfirm - Pointer to the confirm structure,
- *               containing confirm attributes.
- */
-static void McpsConfirm( McpsConfirm_t *mcpsConfirm )
-{
-    LoRaMacEventInfo.Status = mcpsConfirm->Status;
-    LoRaMacEventFlags.Bits.Tx = 1;
-
-    LoRaMacEventInfo.TxDatarate = mcpsConfirm->Datarate;
-    LoRaMacEventInfo.TxNbRetries = mcpsConfirm->NbRetries;
-    LoRaMacEventInfo.TxAckReceived = mcpsConfirm->AckReceived;
-
-    if( ( LoRaMacFlags.Bits.McpsInd != 1 ) && ( LoRaMacFlags.Bits.MlmeReq != 1 ) )
-    {
-        LoRaMacCallbacks.MacEvent( &LoRaMacEventFlags, &LoRaMacEventInfo );
-        LoRaMacEventFlags.Value = 0;
-    }
-}
-
-/*!
- * \brief   MCPS-Indication event function
- *
- * \param   [IN] mcpsIndication - Pointer to the indication structure,
- *               containing indication attributes.
- */
-static void McpsIndication( McpsIndication_t *mcpsIndication )
-{
-    LoRaMacEventInfo.Status = mcpsIndication->Status;
-    LoRaMacEventFlags.Bits.Rx = 1;
-    LoRaMacEventFlags.Bits.RxSlot = mcpsIndication->RxSlot;
-    LoRaMacEventFlags.Bits.Multicast = mcpsIndication->Multicast;
-    if( mcpsIndication->RxData == true )
-    {
-        LoRaMacEventFlags.Bits.RxData = 1;
-    }
-
-    LoRaMacEventInfo.RxPort = mcpsIndication->Port;
-    LoRaMacEventInfo.RxBuffer = mcpsIndication->Buffer;
-    LoRaMacEventInfo.RxBufferSize = mcpsIndication->BufferSize;
-    LoRaMacEventInfo.RxRssi = mcpsIndication->Rssi;
-    LoRaMacEventInfo.RxSnr = mcpsIndication->Snr;
-
-    LoRaMacCallbacks.MacEvent( &LoRaMacEventFlags, &LoRaMacEventInfo );
-    LoRaMacEventFlags.Value = 0;
-}
-
-/*!
- * \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
-                LoRaMacEventFlags.Bits.Tx = 1;
-                LoRaMacEventFlags.Bits.Rx = 1;
-                LoRaMacEventFlags.Bits.JoinAccept = 1;
-                break;
-            }
-            case MLME_LINK_CHECK:
-            {
-                LoRaMacEventFlags.Bits.Tx = 1;
-                LoRaMacEventFlags.Bits.Rx = 1;
-                LoRaMacEventFlags.Bits.LinkCheck = 1;
-
-                LoRaMacEventInfo.DemodMargin = mlmeConfirm->DemodMargin;
-                LoRaMacEventInfo.NbGateways = mlmeConfirm->NbGateways;
-                break;
-            }
-            default:
-                break;
-        }
-    }
-    LoRaMacEventInfo.Status = mlmeConfirm->Status;
-
-    if( LoRaMacFlags.Bits.McpsInd != 1 )
-    {
-        LoRaMacCallbacks.MacEvent( &LoRaMacEventFlags, &LoRaMacEventInfo );
-        LoRaMacEventFlags.Value = 0;
-    }
-}
-
-void LoRaMacInit( LoRaMacCallbacks_t *callbacks )
-{
-    LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm;
-    LoRaMacPrimitives.MacMcpsIndication = McpsIndication;
-    LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
-
-    LoRaMacCallbacks.MacEvent = callbacks->MacEvent;
-    LoRaMacCallbacks.GetBatteryLevel = callbacks->GetBatteryLevel;
-    LoRaMacCallback.GetBatteryLevel = callbacks->GetBatteryLevel;
-
-    LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallback );
-}
-
-void LoRaMacSetAdrOn( bool enable )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_ADR;
-    mibSet.Param.AdrEnable = enable;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacInitNwkIds( uint32_t netID, uint32_t devAddr, uint8_t *nwkSKey, uint8_t *appSKey )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_NET_ID;
-    mibSet.Param.NetID = netID;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-
-    mibSet.Type = MIB_DEV_ADDR;
-    mibSet.Param.DevAddr = devAddr;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-
-    mibSet.Type = MIB_NWK_SKEY;
-    mibSet.Param.NwkSKey = nwkSKey;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-
-    mibSet.Type = MIB_APP_SKEY;
-    mibSet.Param.AppSKey = appSKey;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-
-    mibSet.Type = MIB_NETWORK_JOINED;
-    mibSet.Param.IsNetworkJoined = true;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacMulticastChannelAdd( MulticastParams_t *channelParam )
-{
-    LoRaMacMulticastChannelLink( channelParam );
-}
-
-void LoRaMacMulticastChannelRemove( MulticastParams_t *channelParam )
-{
-    LoRaMacMulticastChannelUnlink( channelParam );
-}
-
-uint8_t LoRaMacJoinReq( uint8_t *devEui, uint8_t *appEui, uint8_t *appKey )
-{
-    MlmeReq_t mlmeRequest;
-    uint8_t status;
-
-    mlmeRequest.Type = MLME_JOIN;
-    mlmeRequest.Req.Join.AppEui = appEui;
-    mlmeRequest.Req.Join.AppKey = appKey;
-    mlmeRequest.Req.Join.DevEui = devEui;
-
-    switch( LoRaMacMlmeRequest( &mlmeRequest ) )
-    {
-        case LORAMAC_STATUS_OK:
-        {
-            status = 0;
-            break;
-        }
-        case LORAMAC_STATUS_BUSY:
-        {
-            status = 1;
-            break;
-        }
-        case LORAMAC_STATUS_NO_NETWORK_JOINED:
-        {
-            status = 2;
-            break;
-        }
-        case LORAMAC_STATUS_LENGTH_ERROR:
-        case LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR:
-        {
-            status = 3;
-            break;
-        }
-        case LORAMAC_STATUS_SERVICE_UNKNOWN:
-        {
-            status = 4;
-            break;
-        }
-        case LORAMAC_STATUS_DEVICE_OFF:
-        {
-            status = 6;
-            break;
-        }
-        default:
-        {
-            status = 1;
-            break;
-        }
-    }
-
-    return status;
-}
-
-uint8_t LoRaMacLinkCheckReq( void )
-{
-    MlmeReq_t mlmeRequest;
-    uint8_t status;
-
-    mlmeRequest.Type = MLME_LINK_CHECK;
-
-    switch( LoRaMacMlmeRequest( &mlmeRequest ) )
-    {
-        case LORAMAC_STATUS_OK:
-        {
-            status = 0;
-            break;
-        }
-        case LORAMAC_STATUS_SERVICE_UNKNOWN:
-        {
-            status = 1;
-            break;
-        }
-        default:
-        {
-            status = 1;
-            break;
-        }
-    }
-
-    return status;
-}
-
-uint8_t LoRaMacSendFrame( uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
-{
-    MibRequestConfirm_t mibGet;
-    McpsReq_t mcpsRequest;
-    uint8_t retStatus;
-
-    memset1( ( uint8_t* )&LoRaMacEventInfo, 0, sizeof( LoRaMacEventInfo ) );
-
-    mibGet.Type = MIB_CHANNELS_DATARATE;
-    LoRaMacMibGetRequestConfirm( &mibGet );
-
-    mcpsRequest.Type = MCPS_UNCONFIRMED;
-    mcpsRequest.Req.Unconfirmed.fBuffer = fBuffer;
-    mcpsRequest.Req.Unconfirmed.fBufferSize = fBufferSize;
-    mcpsRequest.Req.Unconfirmed.fPort = fPort;
-    mcpsRequest.Req.Unconfirmed.Datarate = mibGet.Param.ChannelsDatarate;
-
-    switch( LoRaMacMcpsRequest( &mcpsRequest ) )
-    {
-        case LORAMAC_STATUS_OK:
-            retStatus = 0U;
-            break;
-        case LORAMAC_STATUS_BUSY:
-            retStatus = 1U;
-            break;
-        case LORAMAC_STATUS_NO_NETWORK_JOINED:
-            retStatus = 2U;
-            break;
-        case LORAMAC_STATUS_LENGTH_ERROR:
-        case LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR:
-            retStatus = 3U;
-            break;
-        case LORAMAC_STATUS_SERVICE_UNKNOWN:
-            retStatus = 4U;
-            break;
-        case LORAMAC_STATUS_DEVICE_OFF:
-            retStatus = 6U;
-            break;
-        default:
-            retStatus = 1U;
-            break;
-    }
-
-    return retStatus;
-}
-
-uint8_t LoRaMacSendConfirmedFrame( uint8_t fPort, void *fBuffer, uint16_t fBufferSize, uint8_t nbRetries )
-{
-    MibRequestConfirm_t mibGet;
-    McpsReq_t mcpsRequest;
-    uint8_t retStatus;
-
-    memset1( ( uint8_t* )&LoRaMacEventInfo, 0, sizeof( LoRaMacEventInfo ) );
-
-    mibGet.Type = MIB_CHANNELS_DATARATE;
-    LoRaMacMibGetRequestConfirm( &mibGet );
-
-    mcpsRequest.Type = MCPS_CONFIRMED;
-    mcpsRequest.Req.Confirmed.fBuffer = fBuffer;
-    mcpsRequest.Req.Confirmed.fBufferSize = fBufferSize;
-    mcpsRequest.Req.Confirmed.fPort = fPort;
-    mcpsRequest.Req.Confirmed.NbTrials = nbRetries;
-    mcpsRequest.Req.Confirmed.Datarate = mibGet.Param.ChannelsDatarate;
-
-    switch( LoRaMacMcpsRequest( &mcpsRequest ) )
-    {
-        case LORAMAC_STATUS_OK:
-            retStatus = 0U;
-            break;
-        case LORAMAC_STATUS_BUSY:
-            retStatus = 1U;
-            break;
-        case LORAMAC_STATUS_NO_NETWORK_JOINED:
-            retStatus = 2U;
-            break;
-        case LORAMAC_STATUS_LENGTH_ERROR:
-        case LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR:
-            retStatus = 3U;
-            break;
-        case LORAMAC_STATUS_SERVICE_UNKNOWN:
-            retStatus = 4U;
-            break;
-        case LORAMAC_STATUS_DEVICE_OFF:
-            retStatus = 6U;
-            break;
-        default:
-            retStatus = 1U;
-            break;
-    }
-
-    return retStatus;
-}
-
-uint8_t LoRaMacSend( LoRaMacHeader_t *macHdr, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
-{
-    uint8_t retStatus;
-
-    memset1( ( uint8_t* ) &LoRaMacEventInfo, 0, sizeof( LoRaMacEventInfo ) );
-
-    switch( Send( macHdr, fPort, fBuffer, fBufferSize ) )
-    {
-        case LORAMAC_STATUS_OK:
-            retStatus = 0U;
-            break;
-        case LORAMAC_STATUS_BUSY:
-            retStatus = 1U;
-            break;
-        case LORAMAC_STATUS_NO_NETWORK_JOINED:
-            retStatus = 2U;
-            break;
-        case LORAMAC_STATUS_LENGTH_ERROR:
-        case LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR:
-            retStatus = 3U;
-            break;
-        case LORAMAC_STATUS_SERVICE_UNKNOWN:
-            retStatus = 4U;
-            break;
-        case LORAMAC_STATUS_DEVICE_OFF:
-            retStatus = 6U;
-            break;
-        default:
-            retStatus = 1U;
-            break;
-    }
-
-    return retStatus;
-}
-
-uint8_t LoRaMacPrepareFrame( ChannelParams_t channel,LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
-{
-    uint8_t retStatus;
-
-    switch( PrepareFrame( macHdr, fCtrl, fPort, fBuffer, fBufferSize ) )
-    {
-        case LORAMAC_STATUS_OK:
-            retStatus = 0U;
-            break;
-        case LORAMAC_STATUS_BUSY:
-            retStatus = 1U;
-            break;
-        case LORAMAC_STATUS_NO_NETWORK_JOINED:
-            retStatus = 2U;
-            break;
-        case LORAMAC_STATUS_LENGTH_ERROR:
-        case LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR:
-            retStatus = 3U;
-            break;
-        case LORAMAC_STATUS_SERVICE_UNKNOWN:
-            retStatus = 4U;
-            break;
-        default:
-            retStatus = 1U;
-            break;
-    }
-
-    return retStatus;
-}
-
-uint8_t LoRaMacSendFrameOnChannel( ChannelParams_t channel )
-{
-    memset1( ( uint8_t* ) &LoRaMacEventInfo, 0, sizeof( LoRaMacEventInfo ) );
-
-    SendFrameOnChannel( channel );
-
-    /* SendFrameOnChannel has always status "OK" */
-    return 0;
-}
-
-uint8_t LoRaMacSendOnChannel( ChannelParams_t channel, LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
-{
-    uint8_t status = 0;
-
-    if( ( LoRaMacState & 0x00000001 ) == 0x00000001 )
-    {
-        return 1; // MAC is busy transmitting a previous frame
-    }
-
-    status = LoRaMacPrepareFrame( channel, macHdr, fCtrl, fOpts, fPort, fBuffer, fBufferSize );
-    if( status != 0 )
-    {
-        return status;
-    }
-
-    LoRaMacEventInfo.TxNbRetries = 0;
-    LoRaMacEventInfo.TxAckReceived = false;
-
-    return LoRaMacSendFrameOnChannel( channel );
-}
-
-void LoRaMacSetDeviceClass( DeviceClass_t deviceClass )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_DEVICE_CLASS;
-    mibSet.Param.Class = deviceClass;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetPublicNetwork( bool enable )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_PUBLIC_NETWORK;
-    mibSet.Param.EnablePublicNetwork = enable;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetDutyCycleOn( bool enable )
-{
-    LoRaMacTestSetDutyCycleOn( enable );
-}
-
-void LoRaMacSetChannel( uint8_t id, ChannelParams_t params )
-{
-    LoRaMacChannelAdd( id, params );
-}
-
-void LoRaMacSetRx2Channel( Rx2ChannelParams_t param )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_RX2_CHANNEL;
-    mibSet.Param.Rx2Channel = param;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetChannelsMask( uint16_t *mask )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_CHANNELS_MASK;
-    mibSet.Param.ChannelsMask = mask;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetChannelsNbRep( uint8_t nbRep )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_CHANNELS_NB_REP;
-    mibSet.Param.ChannelNbRep = nbRep;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetMaxRxWindow( uint32_t delay )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_MAX_RX_WINDOW_DURATION;
-    mibSet.Param.MaxRxWindow = delay;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetReceiveDelay1( uint32_t delay )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_RECEIVE_DELAY_1;
-    mibSet.Param.ReceiveDelay1 = delay;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetReceiveDelay2( uint32_t delay )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_RECEIVE_DELAY_2;
-    mibSet.Param.ReceiveDelay2 = delay;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetJoinAcceptDelay1( uint32_t delay )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_JOIN_ACCEPT_DELAY_1;
-    mibSet.Param.JoinAcceptDelay1 = delay;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetJoinAcceptDelay2( uint32_t delay )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_JOIN_ACCEPT_DELAY_2;
-    mibSet.Param.JoinAcceptDelay2 = delay;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetChannelsDatarate( int8_t datarate )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_CHANNELS_DATARATE;
-    mibSet.Param.ChannelsDatarate = datarate;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-void LoRaMacSetChannelsTxPower( int8_t txPower )
-{
-    MibRequestConfirm_t mibSet;
-
-    mibSet.Type = MIB_CHANNELS_TX_POWER;
-    mibSet.Param.ChannelsTxPower = txPower;
-
-    LoRaMacMibSetRequestConfirm( &mibSet );
-}
-
-uint32_t LoRaMacGetUpLinkCounter( void )
-{
-    MibRequestConfirm_t mibGet;
-
-    mibGet.Type = MIB_UPLINK_COUNTER;
-
-    LoRaMacMibGetRequestConfirm( &mibGet );
-
-    return mibGet.Param.UpLinkCounter;
-}
-
-uint32_t LoRaMacGetDownLinkCounter( void )
-{
-    MibRequestConfirm_t mibGet;
-
-    mibGet.Type = MIB_DOWNLINK_COUNTER;
-
-    LoRaMacMibGetRequestConfirm( &mibGet );
-
-    return mibGet.Param.DownLinkCounter;
-}
-
-void LoRaMacSetMicTest( uint16_t txPacketCounter )
-{
-    LoRaMacTestSetMic( txPacketCounter );
-}
--- a/LoRaMac-api-v3.h	Tue Jul 05 13:24:54 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,474 +0,0 @@
-/*!
- * \file      LoRaMac-api-v3.h
- *
- * \brief     LoRa MAC wrapper layer implementation
- *
- * \copyright Revised BSD License, see section \ref LICENSE.
- *
- * \code
- *                ______                              _
- *               / _____)             _              | |
- *              ( (____  _____ ____ _| |_ _____  ____| |__
- *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
- *               _____) ) ____| | | || |_| ____( (___| | | |
- *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
- *              (C)2013 Semtech
- *
- *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
- *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
- *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
- *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
- *              embedded.connectivity.solutions===============
- *
- * \endcode
- *
- * \author    Miguel Luis ( Semtech )
- *
- * \author    Gregory Cristian ( Semtech )
- *
- * \author    Daniel Jäckle ( STACKFORCE )
- */
-#ifndef __LORAMAC_API_V3_H__
-#define __LORAMAC_API_V3_H__
-
-// Includes board dependent definitions such as channels frequencies
-#include "LoRaMac.h"
-
-/*!
- * Beacon interval in us
- */
-#define BEACON_INTERVAL                             128000000
-
-/*!
- * Class A&B receive delay 1 in us
- */
-#define RECEIVE_DELAY1                              1000000
-
-/*!
- * Class A&B receive delay 2 in us
- */
-#define RECEIVE_DELAY2                              2000000
-
-/*!
- * Join accept receive delay 1 in us
- */
-#define JOIN_ACCEPT_DELAY1                          5000000
-
-/*!
- * Join accept receive delay 2 in us
- */
-#define JOIN_ACCEPT_DELAY2                          6000000
-
-/*!
- * Class A&B maximum receive window delay in us
- */
-#define MAX_RX_WINDOW                               3000000
-
-/*!
- * Maximum allowed gap for the FCNT field
- */
-#define MAX_FCNT_GAP                                16384
-
-/*!
- * ADR acknowledgement counter limit
- */
-#define ADR_ACK_LIMIT                               64
-
-/*!
- * Number of ADR acknowledgement requests before returning to default datarate
- */
-#define ADR_ACK_DELAY                               32
-
-/*!
- * Number of seconds after the start of the second reception window without
- * receiving an acknowledge.
- * AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
- */
-#define ACK_TIMEOUT                                 2000000
-
-/*!
- * Random number of seconds after the start of the second reception window without
- * receiving an acknowledge
- * AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
- */
-#define ACK_TIMEOUT_RND                             1000000
-
-/*!
- * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in us
- */
-#define MAC_STATE_CHECK_TIMEOUT                     1000000
-
-/*!
- * Maximum number of times the MAC layer tries to get an acknowledge.
- */
-#define MAX_ACK_RETRIES                             8
-
-/*!
- * RSSI free threshold [dBm]
- */
-#define RSSI_FREE_TH                                ( int8_t )( -90 )
-
-/*!
- * Frame direction definition for up-link communications
- */
-#define UP_LINK                                     0
-
-/*!
- * Frame direction definition for down-link communications
- */
-#define DOWN_LINK                                   1
-
-/*!
- * Sets the length of the LoRaMAC footer field.
- * Mainly indicates the MIC field length
- */
-#define LORAMAC_MFR_LEN                             4
-
-/*!
- * Syncword for Private LoRa networks
- */
-#define LORA_MAC_PRIVATE_SYNCWORD                   0x12
-
-/*!
- * Syncword for Public LoRa networks
- */
-#define LORA_MAC_PUBLIC_SYNCWORD                    0x34
-
-/*!
- * LoRaMAC event flags
- */
-typedef union
-{
-    uint8_t Value;
-    struct
-    {
-        uint8_t Tx              : 1;
-        uint8_t Rx              : 1;
-        uint8_t RxData          : 1;
-        uint8_t Multicast       : 1;
-        uint8_t RxSlot          : 2;
-        uint8_t LinkCheck       : 1;
-        uint8_t JoinAccept      : 1;
-    }Bits;
-}LoRaMacEventFlags_t;
-
-/*!
- * LoRaMAC event information
- */
-typedef struct
-{
-    LoRaMacEventInfoStatus_t Status;
-    bool TxAckReceived;
-    uint8_t TxNbRetries;
-    uint8_t TxDatarate;
-    uint8_t RxPort;
-    uint8_t *RxBuffer;
-    uint8_t RxBufferSize;
-    int16_t RxRssi;
-    uint8_t RxSnr;
-    uint16_t Energy;
-    uint8_t DemodMargin;
-    uint8_t NbGateways;
-}LoRaMacEventInfo_t;
-
-/*!
- * LoRaMAC events structure
- * Used to notify upper layers of MAC events
- */
-typedef struct sLoRaMacCallbacks
-{
-    /*!
-     * MAC layer event callback prototype.
-     *
-     * \param [IN] flags Bit field indicating the MAC events occurred
-     * \param [IN] info  Details about MAC events occurred
-     */
-    void ( *MacEvent )( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info );
-    /*!
-     * Function callback to get the current battery level
-     *
-     * \retval batteryLevel Current battery level
-     */
-    uint8_t ( *GetBatteryLevel )( void );
-}LoRaMacCallbacks_t;
-
-/*!
- * LoRaMAC layer initialization
- *
- * \param [IN] callbacks     Pointer to a structure defining the LoRaMAC
- *                           callback functions.
- */
-void LoRaMacInit( LoRaMacCallbacks_t *callbacks );
-
-/*!
- * Enables/Disables the ADR (Adaptive Data Rate)
- *
- * \param [IN] enable [true: ADR ON, false: ADR OFF]
- */
-void LoRaMacSetAdrOn( bool enable );
-
-/*!
- * Initializes the network IDs. Device address,
- * network session AES128 key and application session AES128 key.
- *
- * \remark To be only used when Over-the-Air activation isn't used.
- *
- * \param [IN] netID   24 bits network identifier
- *                     ( provided by network operator )
- * \param [IN] devAddr 32 bits device address on the network
- *                     (must be unique to the network)
- * \param [IN] nwkSKey Pointer to the network session AES128 key array
- *                     ( 16 bytes )
- * \param [IN] appSKey Pointer to the application session AES128 key array
- *                     ( 16 bytes )
- */
-void LoRaMacInitNwkIds( uint32_t netID, uint32_t devAddr, uint8_t *nwkSKey, uint8_t *appSKey );
-
-/*
- * Wrapper function which calls \ref LoRaMacMulticastChannelLink.
- */
-void LoRaMacMulticastChannelAdd( MulticastParams_t *channelParam );
-
-/*
- * Wrapper function which calls \ref LoRaMacMulticastChannelUnlink.
- */
-void LoRaMacMulticastChannelRemove( MulticastParams_t *channelParam );
-
-/*!
- * Initiates the Over-the-Air activation
- *
- * \param [IN] devEui Pointer to the device EUI array ( 8 bytes )
- * \param [IN] appEui Pointer to the application EUI array ( 8 bytes )
- * \param [IN] appKey Pointer to the application AES128 key array ( 16 bytes )
- *
- * \retval status [0: OK, 1: Tx error, 2: Already joined a network]
- */
-uint8_t LoRaMacJoinReq( uint8_t *devEui, uint8_t *appEui, uint8_t *appKey );
-
-/*!
- * Sends a LinkCheckReq MAC command on the next uplink frame
- *
- * \retval status Function status [0: OK, 1: Busy]
- */
-uint8_t LoRaMacLinkCheckReq( void );
-
-/*!
- * LoRaMAC layer send frame
- *
- * \param [IN] fPort       MAC payload port (must be > 0)
- * \param [IN] fBuffer     MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- *
- * \retval status          [0: OK, 1: Busy, 2: No network joined,
- *                          3: Length or port error, 4: Unknown MAC command
- *                          5: Unable to find a free channel
- *                          6: Device switched off]
- */
-uint8_t LoRaMacSendFrame( uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-
-/*!
- * LoRaMAC layer send frame
- *
- * \param [IN] fPort       MAC payload port (must be > 0)
- * \param [IN] fBuffer     MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \param [IN] fBufferSize MAC data buffer size
- * \param [IN] nbRetries   Number of retries to receive the acknowledgement
- *
- * \retval status          [0: OK, 1: Busy, 2: No network joined,
- *                          3: Length or port error, 4: Unknown MAC command
- *                          5: Unable to find a free channel
- *                          6: Device switched off]
- */
-uint8_t LoRaMacSendConfirmedFrame( uint8_t fPort, void *fBuffer, uint16_t fBufferSize, uint8_t nbRetries );
-
-/*!
- * ============================================================================
- * = LoRaMac test functions                                                   =
- * ============================================================================
- */
-
-/*!
- * LoRaMAC layer generic send frame
- *
- * \param [IN] macHdr      MAC header field
- * \param [IN] fOpts       MAC commands buffer
- * \param [IN] fPort       MAC payload port
- * \param [IN] fBuffer     MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status          [0: OK, 1: Busy, 2: No network joined,
- *                          3: Length or port error, 4: Unknown MAC command
- *                          5: Unable to find a free channel
- *                          6: Device switched off]
- */
-uint8_t LoRaMacSend( LoRaMacHeader_t *macHdr, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-
-/*!
- * LoRaMAC layer frame buffer initialization.
- *
- * \param [IN] channel     Channel parameters
- * \param [IN] macHdr      MAC header field
- * \param [IN] fCtrl       MAC frame control field
- * \param [IN] fOpts       MAC commands buffer
- * \param [IN] fPort       MAC payload port
- * \param [IN] fBuffer     MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status          [0: OK, 1: N/A, 2: No network joined,
- *                          3: Length or port error, 4: Unknown MAC command]
- */
-uint8_t LoRaMacPrepareFrame( ChannelParams_t channel,LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-
-/*!
- * LoRaMAC layer prepared frame buffer transmission with channel specification
- *
- * \remark LoRaMacPrepareFrame must be called at least once before calling this
- *         function.
- *
- * \param [IN] channel     Channel parameters
- * \retval status          [0: OK, 1: Busy]
- */
-uint8_t LoRaMacSendFrameOnChannel( ChannelParams_t channel );
-
-/*!
- * LoRaMAC layer generic send frame with channel specification
- *
- * \param [IN] channel     Channel parameters
- * \param [IN] macHdr      MAC header field
- * \param [IN] fCtrl       MAC frame control field
- * \param [IN] fOpts       MAC commands buffer
- * \param [IN] fPort       MAC payload port
- * \param [IN] fBuffer     MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status          [0: OK, 1: Busy, 2: No network joined,
- *                          3: Length or port error, 4: Unknown MAC command]
- */
-uint8_t LoRaMacSendOnChannel( ChannelParams_t channel, LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-
-/*!
- * ============================================================================
- * = LoRaMac setup functions                                                  =
- * ============================================================================
- */
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the LoRaWan device class.
- */
-void LoRaMacSetDeviceClass( DeviceClass_t deviceClass );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the network type to public or private.
- */
-void LoRaMacSetPublicNetwork( bool enable );
-
-/*
- * Wrapper function which calls \ref LoRaMacChannelAdd.
- */
-void LoRaMacSetChannel( uint8_t id, ChannelParams_t params );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the receive window 2 channel.
- */
-void LoRaMacSetRx2Channel( Rx2ChannelParams_t param );
-
-/*!
- * Sets channels tx output power
- *
- * \param [IN] txPower [TX_POWER_20_DBM, TX_POWER_14_DBM,
-                        TX_POWER_11_DBM, TX_POWER_08_DBM,
-                        TX_POWER_05_DBM, TX_POWER_02_DBM]
- */
-void LoRaMacSetChannelsTxPower( int8_t txPower );
-
-/*!
- * Sets channels datarate
- *
- * \param [IN] datarate eu868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
- *                      us915 - [DR_0, DR_1, DR_2, DR_3, DR_4]
- */
-void LoRaMacSetChannelsDatarate( int8_t datarate );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the channels mask.
- */
-void LoRaMacSetChannelsMask( uint16_t *mask );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the number of repetitions on a channel.
- */
-void LoRaMacSetChannelsNbRep( uint8_t nbRep );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the maximum receive window duration in [us].
- */
-void LoRaMacSetMaxRxWindow( uint32_t delay );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the receive delay 1 in [us].
- */
-void LoRaMacSetReceiveDelay1( uint32_t delay );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the receive delay 2 in [us].
- */
-void LoRaMacSetReceiveDelay2( uint32_t delay );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the join accept delay 1 in [us].
- */
-void LoRaMacSetJoinAcceptDelay1( uint32_t delay );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibSetRequestConfirm to
- * set the join accept delay 2 in [us].
- */
-void LoRaMacSetJoinAcceptDelay2( uint32_t delay );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibGetRequestConfirm to
- * get the up-link counter.
- */
-uint32_t LoRaMacGetUpLinkCounter( void );
-
-/*
- * Wrapper function which calls \ref LoRaMacMibGetRequestConfirm to
- * get the down-link counter.
- */
-uint32_t LoRaMacGetDownLinkCounter( void );
-
-/*
- * ============================================================================
- * = LoRaMac test functions                                                   =
- * ============================================================================
- */
-
-/*!
- * Disables/Enables the duty cycle enforcement (EU868)
- *
- * \param   [IN] enable - Enabled or disables the duty cycle
- */
-void LoRaMacTestSetDutyCycleOn( bool enable );
-
-/*!
- * Disables/Enables the reception windows opening
- *
- * \param [IN] enable [true: enable, false: disable]
- */
-void LoRaMacTestRxWindowsOn( bool enable );
-
-/*!
- * Enables the MIC field test
- *
- * \param [IN] upLinkCounter Fixed Tx packet counter value
- */
-void LoRaMacTestSetMic( uint16_t upLinkCounter );
-
-#endif /* __LORAMAC_API_V3_H__ */
--- a/LoRaMac-definitions.h	Tue Jul 05 13:24:54 2016 +0000
+++ b/LoRaMac-definitions.h	Mon Apr 24 09:42:37 2017 +0000
@@ -103,6 +103,13 @@
 #define DR_7                                        7  // FSK
 
 /*!
+ * Verification of default datarate
+ */
+#if ( LORAMAC_DEFAULT_DATARATE > DR_5 )
+#error "A default DR higher than DR_5 may lead to connectivity loss."
+#endif
+
+/*!
  * Second reception window channel definition.
  */
 // Channel = { Frequency [Hz], Datarate }
@@ -125,19 +132,104 @@
 #define LC3                { 433575000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
 
 /*!
- * LoRaMac duty cycle for the back-off procedure
- */
-#define BACKOFF_DC_1_HOUR       100
-#define BACKOFF_DC_10_HOURS     1000
-#define BACKOFF_DC_24_HOURS     10000
-
-#define BACKOFF_RND_OFFSET      600000
-
-/*!
  * LoRaMac channels which are allowed for the join procedure
  */
 #define JOIN_CHANNELS      ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
 
+#elif defined( USE_BAND_470 )
+
+/*!
+ * LoRaMac maximum number of channels
+ */
+#define LORA_MAX_NB_CHANNELS                        96
+
+/*!
+ * Minimal datarate that can be used by the node
+ */
+#define LORAMAC_TX_MIN_DATARATE                     DR_0
+
+/*!
+ * Maximal datarate that can be used by the node
+ */
+#define LORAMAC_TX_MAX_DATARATE                     DR_5
+
+/*!
+ * Minimal datarate that can be used by the node
+ */
+#define LORAMAC_RX_MIN_DATARATE                     DR_0
+
+/*!
+ * Maximal datarate that can be used by the node
+ */
+#define LORAMAC_RX_MAX_DATARATE                     DR_5
+
+/*!
+ * Default datarate used by the node
+ */
+#define LORAMAC_DEFAULT_DATARATE                    DR_0
+
+/*!
+ * Minimal Rx1 receive datarate offset
+ */
+#define LORAMAC_MIN_RX1_DR_OFFSET                   0
+
+/*!
+ * Maximal Rx1 receive datarate offset
+ */
+#define LORAMAC_MAX_RX1_DR_OFFSET                   3
+
+/*!
+ * Minimal Tx output power that can be used by the node
+ */
+#define LORAMAC_MIN_TX_POWER                        TX_POWER_2_DBM
+
+/*!
+ * Maximal Tx output power that can be used by the node
+ */
+#define LORAMAC_MAX_TX_POWER                        TX_POWER_17_DBM
+
+/*!
+ * Default Tx output power used by the node
+ */
+#define LORAMAC_DEFAULT_TX_POWER                    TX_POWER_14_DBM
+
+/*!
+ * LoRaMac TxPower definition
+ */
+#define TX_POWER_17_DBM                             0
+#define TX_POWER_16_DBM                             1
+#define TX_POWER_14_DBM                             2
+#define TX_POWER_12_DBM                             3
+#define TX_POWER_10_DBM                             4
+#define TX_POWER_7_DBM                              5
+#define TX_POWER_5_DBM                              6
+#define TX_POWER_2_DBM                              7
+
+
+/*!
+ * LoRaMac datarates definition
+ */
+#define DR_0                                        0  // SF12 - BW125 |
+#define DR_1                                        1  // SF11 - BW125 |
+#define DR_2                                        2  // SF10 - BW125 |
+#define DR_3                                        3  // SF9  - BW125 |
+#define DR_4                                        4  // SF8  - BW125 |
+#define DR_5                                        5  // SF7  - BW125 |
+
+/*!
+ * Second reception window channel definition.
+ */
+// Channel = { Frequency [Hz], Datarate }
+#define RX_WND_2_CHANNEL                                  { 505300000, DR_0 }
+
+/*!
+ * LoRaMac maximum number of bands
+ */
+#define LORA_MAX_NB_BANDS                           1
+
+// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+#define BAND0              { 1, TX_POWER_17_DBM, 0,  0 } //  100.0 %
+
 #elif defined( USE_BAND_780 )
 
 /*!
@@ -218,6 +310,13 @@
 #define DR_7                                        7  // FSK
 
 /*!
+ * Verification of default datarate
+ */
+#if ( LORAMAC_DEFAULT_DATARATE > DR_5 )
+#error "A default DR higher than DR_5 may lead to connectivity loss."
+#endif
+
+/*!
  * Second reception window channel definition.
  */
 // Channel = { Frequency [Hz], Datarate }
@@ -240,15 +339,6 @@
 #define LC3                { 779900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
 
 /*!
- * LoRaMac duty cycle for the back-off procedure
- */
-#define BACKOFF_DC_1_HOUR       100
-#define BACKOFF_DC_10_HOURS     1000
-#define BACKOFF_DC_24_HOURS     10000
-
-#define BACKOFF_RND_OFFSET      600000
-
-/*!
  * LoRaMac channels which are allowed for the join procedure
  */
 #define JOIN_CHANNELS      ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
@@ -333,6 +423,13 @@
 #define DR_7                                        7  // FSK
 
 /*!
+ * Verification of default datarate
+ */
+#if ( LORAMAC_DEFAULT_DATARATE > DR_5 )
+#error "A default DR higher than DR_5 may lead to connectivity loss."
+#endif
+
+/*!
  * Second reception window channel definition.
  */
 // Channel = { Frequency [Hz], Datarate }
@@ -371,15 +468,6 @@
 #define LC3                { 868500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
 
 /*!
- * LoRaMac duty cycle for the back-off procedure
- */
-#define BACKOFF_DC_1_HOUR       100
-#define BACKOFF_DC_10_HOURS     1000
-#define BACKOFF_DC_24_HOURS     10000
-
-#define BACKOFF_RND_OFFSET      600000
-
-/*!
  * LoRaMac channels which are allowed for the join procedure
  */
 #define JOIN_CHANNELS      ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
@@ -490,8 +578,6 @@
 // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
 #define BAND0              { 1, TX_POWER_20_DBM, 0,  0 } //  100.0 %
 
-#define BACKOFF_RND_OFFSET      600000
-
 /*!
  * LoRaMac default channels
  */
--- a/LoRaMac.cpp	Tue Jul 05 13:24:54 2016 +0000
+++ b/LoRaMac.cpp	Mon Apr 24 09:42:37 2017 +0000
@@ -17,6 +17,7 @@
 
 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
 */
+#include <math.h>
 #include "board.h"
 
 #include "LoRaMacCrypto.h"
@@ -41,6 +42,21 @@
 #define LORA_MAC_FRMPAYLOAD_OVERHEAD                13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
 
 /*!
+ * LoRaMac duty cycle for the back-off procedure during the first hour.
+ */
+#define BACKOFF_DC_1_HOUR                           100
+
+/*!
+ * LoRaMac duty cycle for the back-off procedure during the next 10 hours.
+ */
+#define BACKOFF_DC_10_HOURS                         1000
+
+/*!
+ * LoRaMac duty cycle for the back-off procedure during the next 24 hours.
+ */
+#define BACKOFF_DC_24_HOURS                         10000
+
+/*!
  * Device IEEE EUI
  */
 static uint8_t *LoRaMacDevEui;
@@ -120,16 +136,20 @@
 static uint16_t LoRaMacBufferPktLen = 0;
 
 /*!
+ * Length of the payload in LoRaMacBuffer
+ */
+static uint8_t LoRaMacTxPayloadLen = 0;
+
+/*!
  * Buffer containing the upper layer data.
  */
-static uint8_t LoRaMacPayload[LORAMAC_PHY_MAXPAYLOAD];
 static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];
 
 /*!
  * LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
  * Only the 16 LSB bits are sent
  */
-static uint32_t UpLinkCounter = 1;
+static uint32_t UpLinkCounter = 0;
 
 /*!
  * LoRaMAC frame counter. Each time a packet is received the counter is incremented.
@@ -207,19 +227,24 @@
 const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
 
 /*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 250e3, 0 };
+
+/*!
  * Maximum payload with respect to the datarate index. Cannot operate with repeater.
  */
-const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
+const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
 
 /*!
  * Maximum payload with respect to the datarate index. Can operate with repeater.
  */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
+const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
 
 /*!
  * Tx output powers table definition
  */
-const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
+const int8_t TxPowers[]    = { 10, 7, 4, 1, -2, -5 };
 
 /*!
  * LoRaMac bands
@@ -238,6 +263,61 @@
     LC2,
     LC3,
 };
+#elif defined( USE_BAND_470 )
+
+/*!
+ * Data rates table definition
+ */
+const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7 };
+
+/*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3 };
+
+/*!
+ * Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ */
+const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 222, 222 };
+
+/*!
+ * Maximum payload with respect to the datarate index. Can operate with repeater.
+ */
+const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222 };
+
+/*!
+ * Tx output powers table definition
+ */
+const int8_t TxPowers[]    = { 17, 16, 14, 12, 10, 7, 5, 2 };
+
+/*!
+ * LoRaMac bands
+ */
+static Band_t Bands[LORA_MAX_NB_BANDS] =
+{
+    BAND0,
+};
+
+/*!
+ * LoRaMAC channels
+ */
+static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS];
+
+/*!
+ * Defines the first channel for RX window 1 for CN470 band
+ */
+#define LORAMAC_FIRST_RX1_CHANNEL           ( (uint32_t) 500.3e6 )
+
+/*!
+ * Defines the last channel for RX window 1 for CN470 band
+ */
+#define LORAMAC_LAST_RX1_CHANNEL            ( (uint32_t) 509.7e6 )
+
+/*!
+ * Defines the step width of the channels for RX window 1
+ */
+#define LORAMAC_STEPWIDTH_RX1_CHANNEL       ( (uint32_t) 200e3 )
+
 #elif defined( USE_BAND_780 )
 /*!
  * Data rates table definition
@@ -245,19 +325,24 @@
 const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
 
 /*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 250e3, 0 };
+
+/*!
  * Maximum payload with respect to the datarate index. Cannot operate with repeater.
  */
-const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
+const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
 
 /*!
  * Maximum payload with respect to the datarate index. Can operate with repeater.
  */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
+const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
 
 /*!
  * Tx output powers table definition
  */
-const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
+const int8_t TxPowers[]    = { 10, 7, 4, 1, -2, -5 };
 
 /*!
  * LoRaMac bands
@@ -283,6 +368,11 @@
 const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
 
 /*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 250e3, 0 };
+
+/*!
  * Maximum payload with respect to the datarate index. Cannot operate with repeater.
  */
 const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
@@ -325,9 +415,14 @@
 const uint8_t Datarates[]  = { 10, 9, 8,  7,  8,  0,  0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
 
 /*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 500e3, 0, 0, 0, 500e3, 500e3, 500e3, 500e3, 500e3, 500e3, 0, 0 };
+
+/*!
  * Up/Down link data rates offset definition
  */
-const int8_t datarateOffsets[16][4] =
+const int8_t DatarateOffsets[5][4] =
 {
     { DR_10, DR_9 , DR_8 , DR_8  }, // DR_0
     { DR_11, DR_10, DR_9 , DR_8  }, // DR_1
@@ -370,19 +465,19 @@
 static uint16_t ChannelsMaskRemaining[6];
 
 /*!
- * Defines the first channel for RX window 2 for US band
+ * Defines the first channel for RX window 1 for US band
  */
-#define LORAMAC_FIRST_RX2_CHANNEL           ( (uint32_t) 923.3e6 )
+#define LORAMAC_FIRST_RX1_CHANNEL           ( (uint32_t) 923.3e6 )
 
 /*!
- * Defines the last channel for RX window 2 for US band
+ * Defines the last channel for RX window 1 for US band
  */
-#define LORAMAC_LAST_RX2_CHANNEL            ( (uint32_t) 927.5e6 )
+#define LORAMAC_LAST_RX1_CHANNEL            ( (uint32_t) 927.5e6 )
 
 /*!
- * Defines the step width of the channels for RX window 2
+ * Defines the step width of the channels for RX window 1
  */
-#define LORAMAC_STEPWIDTH_RX2_CHANNEL       ( (uint32_t) 600e3 )
+#define LORAMAC_STEPWIDTH_RX1_CHANNEL       ( (uint32_t) 600e3 )
 
 #else
     #error "Please define a frequency band in the compiler options."
@@ -427,29 +522,31 @@
 static uint8_t Channel;
 
 /*!
- * Channel index of the last transmission
+ * Stores the time at LoRaMac initialization.
+ *
+ * \remark Used for the BACKOFF_DC computation.
  */
-static uint8_t LastTxChannel;
+static TimerTime_t LoRaMacInitializationTime = 0;
 
 /*!
  * LoRaMac internal states
  */
 enum eLoRaMacState
 {
-    MAC_IDLE          = 0x00000000,
-    MAC_TX_RUNNING    = 0x00000001,
-    MAC_RX            = 0x00000002,
-    MAC_ACK_REQ       = 0x00000004,
-    MAC_ACK_RETRY     = 0x00000008,
-    MAC_TX_DELAYED    = 0x00000010,
-    MAC_TX_CONFIG     = 0x00000020,
-    MAC_RX_ABORT      = 0x00000040,
+    LORAMAC_IDLE          = 0x00000000,
+    LORAMAC_TX_RUNNING    = 0x00000001,
+    LORAMAC_RX            = 0x00000002,
+    LORAMAC_ACK_REQ       = 0x00000004,
+    LORAMAC_ACK_RETRY     = 0x00000008,
+    LORAMAC_TX_DELAYED    = 0x00000010,
+    LORAMAC_TX_CONFIG     = 0x00000020,
+    LORAMAC_RX_ABORT      = 0x00000040,
 };
 
 /*!
  * LoRaMac internal state
  */
-uint32_t LoRaMacState = MAC_IDLE;
+uint32_t LoRaMacState = LORAMAC_IDLE;
 
 /*!
  * LoRaMac timer used to check the LoRaMacState (runs every second)
@@ -491,6 +588,22 @@
 static uint32_t RxWindow2Delay;
 
 /*!
+ * Rx window parameters
+ */
+typedef struct
+{
+    int8_t Datarate;
+    uint8_t Bandwidth;
+    uint32_t RxWindowTimeout;
+    int32_t RxOffset;
+}RxConfigParams_t;
+
+/*!
+ * Rx windows params
+ */
+static RxConfigParams_t RxWindowsParams[2];
+
+/*!
  * Acknowledge timeout timer. Used for packet retransmissions.
  */
 static TimerEvent_t AckTimeoutTimer;
@@ -518,7 +631,12 @@
 /*!
  * Number of trials for the Join Request
  */
-static uint16_t JoinRequestTrials;
+static uint8_t JoinRequestTrials;
+
+/*!
+ * Maximum number of trials for the Join Request
+ */
+static uint8_t MaxJoinRequestTrials;
 
 /*!
  * Structure to hold an MCPS indication data.
@@ -613,21 +731,16 @@
 static bool SetNextChannel( TimerTime_t* time );
 
 /*!
- * \brief Sets the network to public or private. Updates the sync byte.
- *
- * \param [IN] enable if true, it enables a public network
- */
-static void SetPublicNetwork( bool enable );
-
-/*!
  * \brief Initializes and opens the reception window
  *
  * \param [IN] freq window channel frequency
  * \param [IN] datarate window channel datarate
  * \param [IN] bandwidth window channel bandwidth
  * \param [IN] timeout window channel timeout
+ *
+ * \retval status Operation status [true: Success, false: Fail]
  */
-static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
+static bool RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
 
 /*!
  * \brief Verifies if the RX window 2 frequency is in range
@@ -717,7 +830,7 @@
  * \param [IN] mask Block definition to set.
  * \param [OUT] channelsMask Pointer to the first element of the channel mask
  */
-static void ReenableChannels( uint16_t mask, uint16_t* channelMask );
+static void ReenableChannels( uint16_t mask, uint16_t* channelsMask );
 
 /*!
  * \brief Validates the correctness of the channel mask for US915, hybrid mode.
@@ -726,17 +839,30 @@
  *
  * \retval [true: channel mask correct, false: channel mask not correct]
  */
-static bool ValidateChannelMask( uint16_t* channelMask );
+static bool ValidateChannelMask( uint16_t* channelsMask );
 #endif
 
 #endif
 
 /*!
+ * \brief Validates the correctness of the datarate against the enable channels.
+ *
+ * \param [IN] datarate Datarate to be check
+ * \param [IN] channelsMask Pointer to the first element of the channel mask
+ *
+ * \retval [true: datarate can be used, false: datarate can not be used]
+ */
+static bool ValidateDatarate( int8_t datarate, uint16_t* channelsMask );
+
+/*!
  * \brief Limits the Tx power according to the number of enabled channels
  *
+ * \param [IN] txPower txPower to limit
+ * \param [IN] maxBandTxPower Maximum band allowed TxPower
+ *
  * \retval Returns the maximum valid tx power
  */
-static int8_t LimitTxPower( int8_t txPower );
+static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower );
 
 /*!
  * \brief Verifies, if a value is in a given range.
@@ -812,11 +938,11 @@
 static LoRaMacStatus_t ScheduleTx( void );
 
 /*
- * \brief Sets the duty cycle for retransmissions
+ * \brief Sets the duty cycle for the join procedure.
  *
  * \retval Duty cycle
  */
-static uint16_t RetransmissionDutyCylce( void );
+static uint16_t JoinDutyCycle( void );
 
 /*
  * \brief Calculates the back-off time for the band of a channel.
@@ -845,13 +971,86 @@
 LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel );
 
 /*!
+ * \brief Sets the radio in continuous transmission mode
+ *
+ * \remark Uses the radio parameters set on the previous transmission.
+ *
+ * \param [IN] timeout     Time in seconds while the radio is kept in continuous wave mode
+ * \retval status          Status of the operation.
+ */
+LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout );
+
+/*!
+ * \brief Sets the radio in continuous transmission mode
+ *
+ * \remark Uses the radio parameters set on the previous transmission.
+ *
+ * \param [IN] timeout     Time in seconds while the radio is kept in continuous wave mode
+ * \param [IN] frequency   RF frequency to be set.
+ * \param [IN] power       RF ouptput power to be set.
+ * \retval status          Status of the operation.
+ */
+LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power );
+
+/*!
  * \brief Resets MAC specific parameters to default
  */
 static void ResetMacParameters( void );
 
+/*
+ * Rx window precise timing
+ *
+ * For more details please consult the following document, chapter 3.1.2.
+ * http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
+ * or
+ * http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
+ *
+ *                 Downlink start: T = Tx + 1s (+/- 20 us)
+ *                            |
+ *             TRxEarly       |        TRxLate
+ *                |           |           |
+ *                |           |           +---+---+---+---+---+---+---+---+
+ *                |           |           |       Latest Rx window        |
+ *                |           |           +---+---+---+---+---+---+---+---+
+ *                |           |           |
+ *                +---+---+---+---+---+---+---+---+
+ *                |       Earliest Rx window      |
+ *                +---+---+---+---+---+---+---+---+
+ *                            |
+ *                            +---+---+---+---+---+---+---+---+
+ *Downlink preamble 8 symbols |   |   |   |   |   |   |   |   |
+ *                            +---+---+---+---+---+---+---+---+
+ *
+ *                     Worst case Rx window timings
+ *
+ * TRxLate  = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
+ * TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
+ *
+ * TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
+ *
+ * RxOffset = ( TRxLate + TRxEarly ) / 2
+ *
+ * RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
+ * RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
+ *
+ * Minimal value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
+ */
+/*!
+ * Computes the Rx window parameters.
+ *
+ * \param [IN] datarate     Rx window datarate to be used
+ * \param [IN] rxError      Maximum timing error of the receiver. in milliseconds
+ *                          The receiver will turn on in a [-rxError : +rxError] ms
+ *                          interval around RxOffset
+ *
+ * \retval rxConfigParams   Returns a RxConfigParams_t structure.
+ */
+static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError );
+
 static void OnRadioTxDone( void )
 {
     TimerTime_t curTime = TimerGetCurrentTime( );
+
     if( LoRaMacDeviceClass != CLASS_C )
     {
         Radio.Sleep( );
@@ -861,13 +1060,7 @@
         OnRxWindow2TimerEvent( );
     }
 
-    // Store last Tx channel
-    LastTxChannel = Channel;
-    // Update last tx done time for the current channel
-    Bands[Channels[LastTxChannel].Band].LastTxDoneTime = curTime;
-    // Update Aggregated last tx done time
-    AggregatedLastTxDoneTime = curTime;
-
+    // Setup timers
     if( IsRxWindowsEnabled == true )
     {
         TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
@@ -896,6 +1089,13 @@
         LoRaMacFlags.Bits.MacDone = 1;
     }
 
+    // Update last tx done time for the current channel
+    Bands[Channels[Channel].Band].LastTxDoneTime = curTime;
+    // Update Aggregated last tx done time
+    AggregatedLastTxDoneTime = curTime;
+    // Update Backoff
+    CalculateBackOff( Channel );
+
     if( NodeAckRequested == false )
     {
         McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
@@ -905,23 +1105,18 @@
 
 static void PrepareRxDoneAbort( void )
 {
-    LoRaMacState |= MAC_RX_ABORT;
+    LoRaMacState |= LORAMAC_RX_ABORT;
 
     if( NodeAckRequested )
     {
         OnAckTimeoutTimerEvent( );
     }
 
-    if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
     LoRaMacFlags.Bits.McpsInd = 1;
     LoRaMacFlags.Bits.MacDone = 1;
 
     // Trig OnMacCheckTimerEvent call as soon as possible
-    TimerSetValue( &MacStateCheckTimer, 1000 );
+    TimerSetValue( &MacStateCheckTimer, 1 );
     TimerStart( &MacStateCheckTimer );
 }
 
@@ -966,10 +1161,7 @@
     McpsIndication.DownLinkCounter = 0;
     McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
 
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
-    }
+    Radio.Sleep( );
     TimerStop( &RxWindowTimer2 );
 
     macHdr.Value = payload[pktHeaderLen++];
@@ -979,7 +1171,9 @@
         case FRAME_TYPE_JOIN_ACCEPT:
             if( IsLoRaMacNetworkJoined == true )
             {
-                break;
+                McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+                PrepareRxDoneAbort( );
+                return;
             }
             LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
 
@@ -1008,24 +1202,15 @@
                 // DLSettings
                 LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
                 LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                /*
-                 * WARNING: To be removed once Semtech server implementation
-                 *          is corrected.
-                 */
-                if( LoRaMacParams.Rx2Channel.Datarate == DR_3 )
-                {
-                    LoRaMacParams.Rx2Channel.Datarate = DR_8;
-                }
-#endif
+
                 // RxDelay
                 LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
                 if( LoRaMacParams.ReceiveDelay1 == 0 )
                 {
                     LoRaMacParams.ReceiveDelay1 = 1;
                 }
-                LoRaMacParams.ReceiveDelay1 *= 1e6;
-                LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6;
+                LoRaMacParams.ReceiveDelay1 *= 1e3;
+                LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e3;
 
 #if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
                 //CFList
@@ -1034,13 +1219,20 @@
                     ChannelParams_t param;
                     param.DrRange.Value = ( DR_5 << 4 ) | DR_0;
 
-                    LoRaMacState |= MAC_TX_CONFIG;
+                    LoRaMacState |= LORAMAC_TX_CONFIG;
                     for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 )
                     {
                         param.Frequency = ( ( uint32_t )LoRaMacRxPayload[13 + j] | ( ( uint32_t )LoRaMacRxPayload[14 + j] << 8 ) | ( ( uint32_t )LoRaMacRxPayload[15 + j] << 16 ) ) * 100;
-                        LoRaMacChannelAdd( i, param );
+                        if( param.Frequency != 0 )
+                        {
+                            LoRaMacChannelAdd( i, param );
+                        }
+                        else
+                        {
+                            LoRaMacChannelRemove( i );
+                        }
                     }
-                    LoRaMacState &= ~MAC_TX_CONFIG;
+                    LoRaMacState &= ~LORAMAC_TX_CONFIG;
                 }
 #endif
                 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
@@ -1176,6 +1368,10 @@
                                 ( DownLinkCounter != 0 ) )
                             {
                                 // Duplicated confirmed downlink. Skip indication.
+                                // In this case, the MAC layer shall accept the MAC commands
+                                // which are included in the downlink retransmission.
+                                // It should not provide the same frame to the application
+                                // layer again.
                                 skipIndication = true;
                             }
                         }
@@ -1196,28 +1392,23 @@
                         DownLinkCounter = downLinkCounter;
                     }
 
-                    // Check if the frame is an acknowledgement
-                    if( fCtrl.Bits.Ack == 1 )
+                    // This must be done before parsing the payload and the MAC commands.
+                    // We need to reset the MacCommandsBufferIndex here, since we need
+                    // to take retransmissions and repititions into account. Error cases
+                    // will be handled in function OnMacStateCheckTimerEvent.
+                    if( McpsConfirm.McpsRequest == MCPS_CONFIRMED )
                     {
-                        McpsConfirm.AckReceived = true;
-                        McpsIndication.AckReceived = true;
-
-                        // Stop the AckTimeout timer as no more retransmissions
-                        // are needed.
-                        TimerStop( &AckTimeoutTimer );
+                        if( fCtrl.Bits.Ack == 1 )
+                        {// Reset MacCommandsBufferIndex when we have received an ACK.
+                            MacCommandsBufferIndex = 0;
+                        }
                     }
                     else
-                    {
-                        McpsConfirm.AckReceived = false;
-
-                        if( AckTimeoutRetriesCounter > AckTimeoutRetries )
-                        {
-                            // Stop the AckTimeout timer as no more retransmissions
-                            // are needed.
-                            TimerStop( &AckTimeoutTimer );
-                        }
+                    {// Reset the variable if we have received any valid frame.
+                        MacCommandsBufferIndex = 0;
                     }
 
+                    // Process payload and MAC commands
                     if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
                     {
                         port = payload[appPayloadStartIndex++];
@@ -1227,6 +1418,7 @@
 
                         if( port == 0 )
                         {
+                            // Only allow frames which do not have fOpts
                             if( fCtrl.Bits.FOptsLen == 0 )
                             {
                                 LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
@@ -1280,8 +1472,32 @@
 
                     if( skipIndication == false )
                     {
-                        LoRaMacFlags.Bits.McpsInd = 1;
+                        // Check if the frame is an acknowledgement
+                        if( fCtrl.Bits.Ack == 1 )
+                        {
+                            McpsConfirm.AckReceived = true;
+                            McpsIndication.AckReceived = true;
+
+                            // Stop the AckTimeout timer as no more retransmissions
+                            // are needed.
+                            TimerStop( &AckTimeoutTimer );
+                        }
+                        else
+                        {
+                            McpsConfirm.AckReceived = false;
+
+                            if( AckTimeoutRetriesCounter > AckTimeoutRetries )
+                            {
+                                // Stop the AckTimeout timer as no more retransmissions
+                                // are needed.
+                                TimerStop( &AckTimeoutTimer );
+                            }
+                        }
                     }
+                    // Provide always an indication, skip the callback to the user application,
+                    // in case of a confirmed downlink retransmission.
+                    LoRaMacFlags.Bits.McpsInd = 1;
+                    LoRaMacFlags.Bits.McpsIndSkip = skipIndication;
                 }
                 else
                 {
@@ -1309,15 +1525,10 @@
             PrepareRxDoneAbort( );
             break;
     }
-
-    if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
-    {
-        OnRxWindow2TimerEvent( );
-    }
     LoRaMacFlags.Bits.MacDone = 1;
 
     // Trig OnMacCheckTimerEvent call as soon as possible
-    TimerSetValue( &MacStateCheckTimer, 1000 );
+    TimerSetValue( &MacStateCheckTimer, 1 );
     TimerStart( &MacStateCheckTimer );
 }
 
@@ -1348,7 +1559,20 @@
         OnRxWindow2TimerEvent( );
     }
 
-    if( RxSlot == 1 )
+    if( RxSlot == 0 )
+    {
+        if( NodeAckRequested == true )
+        {
+            McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
+        }
+        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
+
+        if( TimerGetElapsedTime( AggregatedLastTxDoneTime ) >= RxWindow2Delay )
+        {
+            LoRaMacFlags.Bits.MacDone = 1;
+        }
+    }
+    else
     {
         if( NodeAckRequested == true )
         {
@@ -1388,10 +1612,10 @@
 
     if( LoRaMacFlags.Bits.MacDone == 1 )
     {
-        if( ( LoRaMacState & MAC_RX_ABORT ) == MAC_RX_ABORT )
+        if( ( LoRaMacState & LORAMAC_RX_ABORT ) == LORAMAC_RX_ABORT )
         {
-            LoRaMacState &= ~MAC_RX_ABORT;
-            LoRaMacState &= ~MAC_TX_RUNNING;
+            LoRaMacState &= ~LORAMAC_RX_ABORT;
+            LoRaMacState &= ~LORAMAC_TX_RUNNING;
         }
 
         if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
@@ -1400,7 +1624,8 @@
                 ( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) )
             {
                 // Stop transmit cycle due to tx timeout.
-                LoRaMacState &= ~MAC_TX_RUNNING;
+                LoRaMacState &= ~LORAMAC_TX_RUNNING;
+                MacCommandsBufferIndex = 0;
                 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
                 McpsConfirm.AckReceived = false;
                 McpsConfirm.TxTimeOnAir = 0;
@@ -1410,46 +1635,64 @@
 
         if( ( NodeAckRequested == false ) && ( txTimeout == false ) )
         {
-            if( LoRaMacFlags.Bits.MlmeReq == 1 )
-            {
-                if( MlmeConfirm.MlmeRequest == MLME_JOIN )
-                {
-                    // Retransmit only if the answer is not OK
-                    ChannelsNbRepCounter = 0;
-
-                    if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
-                    {
-                        // Stop retransmission
-                        ChannelsNbRepCounter = LoRaMacParams.ChannelsNbRep;
-                        UpLinkCounter = 0;
-                    }
-                }
-            }
             if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
             {
-                if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
-                {
-                    ChannelsNbRepCounter = 0;
-
-                    AdrAckCounter++;
-                    if( IsUpLinkCounterFixed == false )
+                if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
+                {// Procedure for the join request
+                    MlmeConfirm.NbRetries = JoinRequestTrials;
+
+                    if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
+                    {// Node joined successfully
+                        UpLinkCounter = 0;
+                        ChannelsNbRepCounter = 0;
+                        LoRaMacState &= ~LORAMAC_TX_RUNNING;
+                    }
+                    else
                     {
-                        UpLinkCounter++;
+                        if( JoinRequestTrials >= MaxJoinRequestTrials )
+                        {
+                            LoRaMacState &= ~LORAMAC_TX_RUNNING;
+                        }
+                        else
+                        {
+                            LoRaMacFlags.Bits.MacDone = 0;
+                            // Sends the same frame again
+                            OnTxDelayedTimerEvent( );
+                        }
                     }
-
-                    LoRaMacState &= ~MAC_TX_RUNNING;
                 }
                 else
-                {
-                    LoRaMacFlags.Bits.MacDone = 0;
-                    // Sends the same frame again
-                    ScheduleTx( );
+                {// Procedure for all other frames
+                    if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
+                    {
+                        if( LoRaMacFlags.Bits.McpsInd == 0 )
+                        {   // Maximum repititions without downlink. Reset MacCommandsBufferIndex. Increase ADR Ack counter.
+                            // Only process the case when the MAC did not receive a downlink.
+                            MacCommandsBufferIndex = 0;
+                            AdrAckCounter++;
+                        }
+
+                        ChannelsNbRepCounter = 0;
+
+                        if( IsUpLinkCounterFixed == false )
+                        {
+                            UpLinkCounter++;
+                        }
+
+                        LoRaMacState &= ~LORAMAC_TX_RUNNING;
+                    }
+                    else
+                    {
+                        LoRaMacFlags.Bits.MacDone = 0;
+                        // Sends the same frame again
+                        OnTxDelayedTimerEvent( );
+                    }
                 }
             }
         }
 
         if( LoRaMacFlags.Bits.McpsInd == 1 )
-        {
+        {// Procedure if we received a frame
             if( ( McpsConfirm.AckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) )
             {
                 AckTimeoutRetry = false;
@@ -1460,12 +1703,12 @@
                 }
                 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
 
-                LoRaMacState &= ~MAC_TX_RUNNING;
+                LoRaMacState &= ~LORAMAC_TX_RUNNING;
             }
         }
 
-        if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & MAC_TX_DELAYED ) == 0 ) )
-        {
+        if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & LORAMAC_TX_DELAYED ) == 0 ) )
+        {// Retransmissions procedure for confirmed uplinks
             AckTimeoutRetry = false;
             if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) )
             {
@@ -1475,31 +1718,48 @@
                 {
                     LoRaMacParams.ChannelsDatarate = MAX( LoRaMacParams.ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
                 }
-                LoRaMacFlags.Bits.MacDone = 0;
-                // Sends the same frame again
-                ScheduleTx( );
+                // Try to send the frame again
+                if( ScheduleTx( ) == LORAMAC_STATUS_OK )
+                {
+                    LoRaMacFlags.Bits.MacDone = 0;
+                }
+                else
+                {
+                    // The DR is not applicable for the payload size
+                    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR;
+
+                    MacCommandsBufferIndex = 0;
+                    LoRaMacState &= ~LORAMAC_TX_RUNNING;
+                    NodeAckRequested = false;
+                    McpsConfirm.AckReceived = false;
+                    McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
+                    McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
+                    if( IsUpLinkCounterFixed == false )
+                    {
+                        UpLinkCounter++;
+                    }
+                }
             }
             else
             {
 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
                 // Re-enable default channels LC1, LC2, LC3
                 LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
+#elif defined( USE_BAND_470 )
+                // Re-enable default channels
+                memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
 #elif defined( USE_BAND_915 )
                 // Re-enable default channels
-                LoRaMacParams.ChannelsMask[0] = 0xFFFF;
-                LoRaMacParams.ChannelsMask[1] = 0xFFFF;
-                LoRaMacParams.ChannelsMask[2] = 0xFFFF;
-                LoRaMacParams.ChannelsMask[3] = 0xFFFF;
-                LoRaMacParams.ChannelsMask[4] = 0x00FF;
-                LoRaMacParams.ChannelsMask[5] = 0x0000;
+                memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
 #elif defined( USE_BAND_915_HYBRID )
                 // Re-enable default channels
-                ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
+                ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
 #else
     #error "Please define a frequency band in the compiler options."
 #endif
-                LoRaMacState &= ~MAC_TX_RUNNING;
-
+                LoRaMacState &= ~LORAMAC_TX_RUNNING;
+
+                MacCommandsBufferIndex = 0;
                 NodeAckRequested = false;
                 McpsConfirm.AckReceived = false;
                 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
@@ -1511,11 +1771,11 @@
         }
     }
     // Handle reception for Class B and Class C
-    if( ( LoRaMacState & MAC_RX ) == MAC_RX )
+    if( ( LoRaMacState & LORAMAC_RX ) == LORAMAC_RX )
     {
-        LoRaMacState &= ~MAC_RX;
+        LoRaMacState &= ~LORAMAC_RX;
     }
-    if( LoRaMacState == MAC_IDLE )
+    if( LoRaMacState == LORAMAC_IDLE )
     {
         if( LoRaMacFlags.Bits.McpsReq == 1 )
         {
@@ -1529,6 +1789,7 @@
             LoRaMacFlags.Bits.MlmeReq = 0;
         }
 
+        // Procedure done. Reset variables.
         LoRaMacFlags.Bits.MacDone = 0;
     }
     else
@@ -1540,7 +1801,15 @@
 
     if( LoRaMacFlags.Bits.McpsInd == 1 )
     {
-        LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
+        if( LoRaMacDeviceClass == CLASS_C )
+        {// Activate RX2 window for Class C
+            OnRxWindow2TimerEvent( );
+        }
+        if( LoRaMacFlags.Bits.McpsIndSkip == 0 )
+        {
+            LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
+        }
+        LoRaMacFlags.Bits.McpsIndSkip = 0;
         LoRaMacFlags.Bits.McpsInd = 0;
     }
 }
@@ -1551,17 +1820,21 @@
     LoRaMacFrameCtrl_t fCtrl;
 
     TimerStop( &TxDelayedTimer );
-    LoRaMacState &= ~MAC_TX_DELAYED;
+    LoRaMacState &= ~LORAMAC_TX_DELAYED;
 
     if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
     {
+        ResetMacParameters( );
+        // Add a +1, since we start to count from 0
+        LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials + 1 );
+
         macHdr.Value = 0;
         macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
 
         fCtrl.Value = 0;
         fCtrl.Bits.Adr = AdrCtrlOn;
 
-        /* In case of a join request retransmission, the stack must prepare
+        /* In case of join request retransmissions, the stack must prepare
          * the frame again, because the network server keeps track of the random
          * LoRaMacDevNonce values to prevent reply attacks. */
         PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 );
@@ -1572,10 +1845,6 @@
 
 static void OnRxWindow1TimerEvent( void )
 {
-    uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
-    int8_t datarate = 0;
-    uint32_t bandwidth = 0; // LoRa 125 kHz
-
     TimerStop( &RxWindowTimer1 );
     RxSlot = 0;
 
@@ -1585,69 +1854,11 @@
     }
 
 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    datarate = LoRaMacParams.ChannelsDatarate - LoRaMacParams.Rx1DrOffset;
-    if( datarate < 0 )
-    {
-        datarate = DR_0;
-    }
-
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    if( ( datarate == DR_3 ) || ( datarate == DR_4 ) )
-    { // DR_4, DR_3
-        symbTimeout = 8;
-    }
-    else if( datarate == DR_5 )
-    {
-        symbTimeout = 10;
-    }
-    else if( datarate == DR_6 )
-    {// LoRa 250 kHz
-        bandwidth  = 1;
-        symbTimeout = 14;
-    }
-    RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
+    RxWindowSetup( Channels[Channel].Frequency, RxWindowsParams[0].Datarate, RxWindowsParams[0].Bandwidth, RxWindowsParams[0].RxWindowTimeout, false );
+#elif defined( USE_BAND_470 )
+    RxWindowSetup( LORAMAC_FIRST_RX1_CHANNEL + ( Channel % 48 ) * LORAMAC_STEPWIDTH_RX1_CHANNEL, RxWindowsParams[0].Datarate, RxWindowsParams[0].Bandwidth, RxWindowsParams[0].RxWindowTimeout, false );
 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    datarate = datarateOffsets[LoRaMacParams.ChannelsDatarate][LoRaMacParams.Rx1DrOffset];
-    if( datarate < 0 )
-    {
-        datarate = DR_0;
-    }
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    switch( datarate )
-    {
-        case DR_0:       // SF10 - BW125
-            symbTimeout = 5;
-            break;
-
-        case DR_1:       // SF9  - BW125
-        case DR_2:       // SF8  - BW125
-        case DR_8:       // SF12 - BW500
-        case DR_9:       // SF11 - BW500
-        case DR_10:      // SF10 - BW500
-            symbTimeout = 8;
-            break;
-
-        case DR_3:       // SF7  - BW125
-        case DR_11:      // SF9  - BW500
-            symbTimeout = 10;
-            break;
-
-        case DR_4:       // SF8  - BW500
-        case DR_12:      // SF8  - BW500
-            symbTimeout = 14;
-            break;
-
-        case DR_13:      // SF7  - BW500
-            symbTimeout = 16;
-            break;
-        default:
-            break;
-    }
-    if( datarate >= DR_4 )
-    {// LoRa 500 kHz
-        bandwidth  = 2;
-    }
-    RxWindowSetup( LORAMAC_FIRST_RX2_CHANNEL + ( Channel % 8 ) * LORAMAC_STEPWIDTH_RX2_CHANNEL, datarate, bandwidth, symbTimeout, false );
+    RxWindowSetup( LORAMAC_FIRST_RX1_CHANNEL + ( Channel % 8 ) * LORAMAC_STEPWIDTH_RX1_CHANNEL, RxWindowsParams[0].Datarate, RxWindowsParams[0].Bandwidth, RxWindowsParams[0].RxWindowTimeout, false );
 #else
     #error "Please define a frequency band in the compiler options."
 #endif
@@ -1655,73 +1866,17 @@
 
 static void OnRxWindow2TimerEvent( void )
 {
-    uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
-    uint32_t bandwidth = 0; // LoRa 125 kHz
+    bool rxContinuousMode = false;
 
     TimerStop( &RxWindowTimer2 );
-    RxSlot = 1;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    if( ( LoRaMacParams.Rx2Channel.Datarate == DR_3 ) || ( LoRaMacParams.Rx2Channel.Datarate == DR_4 ) )
-    { // DR_4, DR_3
-        symbTimeout = 8;
-    }
-    else if( LoRaMacParams.Rx2Channel.Datarate == DR_5 )
-    {
-        symbTimeout = 10;
-    }
-    else if( LoRaMacParams.Rx2Channel.Datarate == DR_6 )
-    {// LoRa 250 kHz
-        bandwidth  = 1;
-        symbTimeout = 14;
-    }
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    switch( LoRaMacParams.Rx2Channel.Datarate )
+
+    if( LoRaMacDeviceClass == CLASS_C )
     {
-        case DR_0:       // SF10 - BW125
-            symbTimeout = 5;
-            break;
-
-        case DR_1:       // SF9  - BW125
-        case DR_2:       // SF8  - BW125
-        case DR_8:       // SF12 - BW500
-        case DR_9:       // SF11 - BW500
-        case DR_10:      // SF10 - BW500
-            symbTimeout = 8;
-            break;
-
-        case DR_3:       // SF7  - BW125
-        case DR_11:      // SF9  - BW500
-            symbTimeout = 10;
-            break;
-
-        case DR_4:       // SF8  - BW500
-        case DR_12:      // SF8  - BW500
-            symbTimeout = 14;
-            break;
-
-        case DR_13:      // SF7  - BW500
-            symbTimeout = 16;
-            break;
-        default:
-            break;
+        rxContinuousMode = true;
     }
-    if( LoRaMacParams.Rx2Channel.Datarate >= DR_4 )
-    {// LoRa 500 kHz
-        bandwidth  = 2;
-    }
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-    if( LoRaMacDeviceClass != CLASS_C )
+    if( RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, RxWindowsParams[1].Datarate, RxWindowsParams[1].Bandwidth, RxWindowsParams[1].RxWindowTimeout, rxContinuousMode ) == true )
     {
-        RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, false );
-    }
-    else
-    {
-        RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, true );
+        RxSlot = 1;
     }
 }
 
@@ -1732,7 +1887,7 @@
     if( NodeAckRequested == true )
     {
         AckTimeoutRetry = true;
-        LoRaMacState &= ~MAC_ACK_REQ;
+        LoRaMacState &= ~LORAMAC_ACK_REQ;
     }
     if( LoRaMacDeviceClass == CLASS_C )
     {
@@ -1758,6 +1913,16 @@
     { // Make sure, that the channels are activated
         ChannelsMaskRemaining[4] = LoRaMacParams.ChannelsMask[4];
     }
+#elif defined( USE_BAND_470 )
+    if( ( CountBits( LoRaMacParams.ChannelsMask[0], 16 ) == 0 ) &&
+        ( CountBits( LoRaMacParams.ChannelsMask[1], 16 ) == 0 ) &&
+        ( CountBits( LoRaMacParams.ChannelsMask[2], 16 ) == 0 ) &&
+        ( CountBits( LoRaMacParams.ChannelsMask[3], 16 ) == 0 ) &&
+        ( CountBits( LoRaMacParams.ChannelsMask[4], 16 ) == 0 ) &&
+        ( CountBits( LoRaMacParams.ChannelsMask[5], 16 ) == 0 ) )
+    {
+        memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
+    }
 #else
     if( CountBits( LoRaMacParams.ChannelsMask[0], 16 ) == 0 )
     {
@@ -1774,7 +1939,7 @@
         // Update bands Time OFF
         for( uint8_t i = 0; i < LORA_MAX_NB_BANDS; i++ )
         {
-            if( DutyCycleOn == true )
+            if( ( IsLoRaMacNetworkJoined == false ) || ( DutyCycleOn == true ) )
             {
                 if( Bands[i].TimeOff <= TimerGetElapsedTime( Bands[i].LastTxDoneTime ) )
                 {
@@ -1782,15 +1947,15 @@
                 }
                 if( Bands[i].TimeOff != 0 )
                 {
-                    nextTxDelay = MIN( Bands[i].TimeOff -
-                                       TimerGetElapsedTime( Bands[i].LastTxDoneTime ),
-                                       nextTxDelay );
+                    nextTxDelay = MIN( Bands[i].TimeOff - TimerGetElapsedTime( Bands[i].LastTxDoneTime ), nextTxDelay );
                 }
             }
             else
             {
-                nextTxDelay = 0;
-                Bands[i].TimeOff = 0;
+                if( DutyCycleOn == false )
+                {
+                    Bands[i].TimeOff = 0;
+                }
             }
         }
 
@@ -1865,23 +2030,7 @@
     }
 }
 
-static void SetPublicNetwork( bool enable )
-{
-    PublicNetwork = enable;
-    Radio.SetModem( MODEM_LORA );
-    if( PublicNetwork == true )
-    {
-        // Change LoRa modem SyncWord
-        Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD );
-    }
-    else
-    {
-        // Change LoRa modem SyncWord
-        Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD );
-    }
-}
-
-static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
+static bool RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
 {
     uint8_t downlinkDatarate = Datarates[datarate];
     RadioModems_t modem;
@@ -1897,14 +2046,14 @@
         if( datarate == DR_7 )
         {
             modem = MODEM_FSK;
-            Radio.SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, rxContinuous );
+            Radio.SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, timeout, false, 0, true, 0, 0, false, rxContinuous );
         }
         else
         {
             modem = MODEM_LORA;
             Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
         }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+#elif defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
         modem = MODEM_LORA;
         Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
 #endif
@@ -1926,18 +2075,20 @@
         {
             Radio.Rx( 0 ); // Continuous mode
         }
+        return true;
     }
+    return false;
 }
 
 static bool Rx2FreqInRange( uint32_t freq )
 {
 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
     if( Radio.CheckRfFrequency( freq ) == true )
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+#elif defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
     if( ( Radio.CheckRfFrequency( freq ) == true ) &&
-        ( freq >= LORAMAC_FIRST_RX2_CHANNEL ) &&
-        ( freq <= LORAMAC_LAST_RX2_CHANNEL ) &&
-        ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX2_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX2_CHANNEL ) == 0 ) )
+        ( freq >= LORAMAC_FIRST_RX1_CHANNEL ) &&
+        ( freq <= LORAMAC_LAST_RX1_CHANNEL ) &&
+        ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX1_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX1_CHANNEL ) == 0 ) )
 #endif
     {
         return true;
@@ -1999,27 +2150,27 @@
 }
 
 #if defined( USE_BAND_915_HYBRID )
-static void ReenableChannels( uint16_t mask, uint16_t* channelMask )
+static void ReenableChannels( uint16_t mask, uint16_t* channelsMask )
 {
     uint16_t blockMask = mask;
 
     for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
     {
-        channelMask[i] = 0;
+        channelsMask[i] = 0;
         if( ( blockMask & ( 1 << j ) ) != 0 )
         {
-            channelMask[i] |= 0x00FF;
+            channelsMask[i] |= 0x00FF;
         }
         if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
         {
-            channelMask[i] |= 0xFF00;
+            channelsMask[i] |= 0xFF00;
         }
     }
-    channelMask[4] = blockMask;
-    channelMask[5] = 0x0000;
+    channelsMask[4] = blockMask;
+    channelsMask[5] = 0x0000;
 }
 
-static bool ValidateChannelMask( uint16_t* channelMask )
+static bool ValidateChannelMask( uint16_t* channelsMask )
 {
     bool chanMaskState = false;
     uint16_t block1 = 0;
@@ -2028,20 +2179,20 @@
 
     for( uint8_t i = 0; i < 4; i++ )
     {
-        block1 = channelMask[i] & 0x00FF;
-        block2 = channelMask[i] & 0xFF00;
+        block1 = channelsMask[i] & 0x00FF;
+        block2 = channelsMask[i] & 0xFF00;
 
         if( ( CountBits( block1, 16 ) > 5 ) && ( chanMaskState == false ) )
         {
-            channelMask[i] &= block1;
-            channelMask[4] = 1 << ( i * 2 );
+            channelsMask[i] &= block1;
+            channelsMask[4] = 1 << ( i * 2 );
             chanMaskState = true;
             index = i;
         }
         else if( ( CountBits( block2, 16 ) > 5 ) && ( chanMaskState == false ) )
         {
-            channelMask[i] &= block2;
-            channelMask[4] = 1 << ( i * 2 + 1 );
+            channelsMask[i] &= block2;
+            channelsMask[4] = 1 << ( i * 2 + 1 );
             chanMaskState = true;
             index = i;
         }
@@ -2054,7 +2205,7 @@
         {
             if( i != index )
             {
-                channelMask[i] = 0;
+                channelsMask[i] = 0;
             }
         }
     }
@@ -2063,9 +2214,36 @@
 #endif
 #endif
 
-static int8_t LimitTxPower( int8_t txPower )
+static bool ValidateDatarate( int8_t datarate, uint16_t* channelsMask )
+{
+    if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false )
+    {
+        return false;
+    }
+    for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
+    {
+        for( uint8_t j = 0; j < 16; j++ )
+        {
+            if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) )
+            {// Check datarate validity for enabled channels
+                if( ValueInRange( datarate, Channels[i + j].DrRange.Fields.Min, Channels[i + j].DrRange.Fields.Max ) == true )
+                {
+                    // At least 1 channel has been found we can return OK.
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower )
 {
     int8_t resultTxPower = txPower;
+
+    // Limit tx power to the band max
+    resultTxPower =  MAX( txPower, maxBandTxPower );
+
 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
     if( ( LoRaMacParams.ChannelsDatarate == DR_4 ) ||
         ( ( LoRaMacParams.ChannelsDatarate >= DR_8 ) && ( LoRaMacParams.ChannelsDatarate <= DR_13 ) ) )
@@ -2125,6 +2303,7 @@
             if( AdrAckCounter >= ADR_ACK_LIMIT )
             {
                 adrAckReq = true;
+                LoRaMacParams.ChannelsTxPower = LORAMAC_MAX_TX_POWER;
             }
             else
             {
@@ -2132,7 +2311,7 @@
             }
             if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) )
             {
-                if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 )
+                if( ( AdrAckCounter % ADR_ACK_DELAY ) == 1 )
                 {
 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
                     if( datarate > LORAMAC_TX_MIN_DATARATE )
@@ -2147,6 +2326,19 @@
                             LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
                         }
                     }
+#elif defined( USE_BAND_470 )
+                    if( datarate > LORAMAC_TX_MIN_DATARATE )
+                    {
+                        datarate--;
+                    }
+                    if( datarate == LORAMAC_TX_MIN_DATARATE )
+                    {
+                        if( updateChannelMask == true )
+                        {
+                            // Re-enable default channels
+                            memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
+                        }
+                    }
 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
                     if( ( datarate > LORAMAC_TX_MIN_DATARATE ) && ( datarate == DR_8 ) )
                     {
@@ -2162,15 +2354,10 @@
                         {
 #if defined( USE_BAND_915 )
                             // Re-enable default channels
-                            LoRaMacParams.ChannelsMask[0] = 0xFFFF;
-                            LoRaMacParams.ChannelsMask[1] = 0xFFFF;
-                            LoRaMacParams.ChannelsMask[2] = 0xFFFF;
-                            LoRaMacParams.ChannelsMask[3] = 0xFFFF;
-                            LoRaMacParams.ChannelsMask[4] = 0x00FF;
-                            LoRaMacParams.ChannelsMask[5] = 0x0000;
+                            memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
 #else // defined( USE_BAND_915_HYBRID )
                             // Re-enable default channels
-                            ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
+                            ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
 #endif
                         }
                     }
@@ -2281,10 +2468,10 @@
     {
         switch( cmdBufIn[i] )
         {
+            // STICKY
             case MOTE_MAC_RX_PARAM_SETUP_ANS:
             {
                 cmdBufOut[cmdCount++] = cmdBufIn[i++];
-                cmdBufOut[cmdCount++] = cmdBufIn[i++];
                 cmdBufOut[cmdCount++] = cmdBufIn[i];
                 break;
             }
@@ -2293,6 +2480,23 @@
                 cmdBufOut[cmdCount++] = cmdBufIn[i];
                 break;
             }
+            // NON-STICKY
+            case MOTE_MAC_DEV_STATUS_ANS:
+            { // 2 bytes payload
+                i += 2;
+                break;
+            }
+            case MOTE_MAC_LINK_ADR_ANS:
+            case MOTE_MAC_NEW_CHANNEL_ANS:
+            { // 1 byte payload
+                i++;
+                break;
+            }
+            case MOTE_MAC_DUTY_CYCLE_ANS:
+            case MOTE_MAC_LINK_CHECK_REQ:
+            { // 0 byte payload
+                break;
+            }
             default:
                 break;
         }
@@ -2387,11 +2591,11 @@
                         }
                         channelsMask[0] = chMask;
                     }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+#elif defined( USE_BAND_470 )
                     if( chMaskCntl == 6 )
                     {
                         // Enable all 125 kHz channels
-                        for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
+                        for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
                         {
                             for( uint8_t j = 0; j < 16; j++ )
                             {
@@ -2404,15 +2608,6 @@
                     }
                     else if( chMaskCntl == 7 )
                     {
-                        // Disable all 125 kHz channels
-                        channelsMask[0] = 0x0000;
-                        channelsMask[1] = 0x0000;
-                        channelsMask[2] = 0x0000;
-                        channelsMask[3] = 0x0000;
-                    }
-                    else if( chMaskCntl == 5 )
-                    {
-                        // RFU
                         status &= 0xFE; // Channel mask KO
                     }
                     else
@@ -2426,8 +2621,39 @@
                             }
                         }
                         channelsMask[chMaskCntl] = chMask;
-
-                        if( CountNbEnabled125kHzChannels( channelsMask ) < 6 )
+                    }
+#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+                    if( chMaskCntl == 6 )
+                    {
+                        // Enable all 125 kHz channels
+                        channelsMask[0] = 0xFFFF;
+                        channelsMask[1] = 0xFFFF;
+                        channelsMask[2] = 0xFFFF;
+                        channelsMask[3] = 0xFFFF;
+                        // Apply chMask to channels 64 to 71
+                        channelsMask[4] = chMask;
+                    }
+                    else if( chMaskCntl == 7 )
+                    {
+                        // Disable all 125 kHz channels
+                        channelsMask[0] = 0x0000;
+                        channelsMask[1] = 0x0000;
+                        channelsMask[2] = 0x0000;
+                        channelsMask[3] = 0x0000;
+                        // Apply chMask to channels 64 to 71
+                        channelsMask[4] = chMask;
+                    }
+                    else if( chMaskCntl == 5 )
+                    {
+                        // RFU
+                        status &= 0xFE; // Channel mask KO
+                    }
+                    else
+                    {
+                        channelsMask[chMaskCntl] = chMask;
+
+                        // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
+                        if( ( datarate < DR_4 ) && ( CountNbEnabled125kHzChannels( channelsMask ) < 2 ) )
                         {
                             status &= 0xFE; // Channel mask KO
                         }
@@ -2442,7 +2668,7 @@
 #else
     #error "Please define a frequency band in the compiler options."
 #endif
-                    if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false )
+                    if( ValidateDatarate( datarate, channelsMask ) == false )
                     {
                         status &= 0xFD; // Datarate KO
                     }
@@ -2459,14 +2685,18 @@
                         LoRaMacParams.ChannelsDatarate = datarate;
                         LoRaMacParams.ChannelsTxPower = txPower;
 
-                        LoRaMacParams.ChannelsMask[0] = channelsMask[0];
-                        LoRaMacParams.ChannelsMask[1] = channelsMask[1];
-                        LoRaMacParams.ChannelsMask[2] = channelsMask[2];
-                        LoRaMacParams.ChannelsMask[3] = channelsMask[3];
-                        LoRaMacParams.ChannelsMask[4] = channelsMask[4];
-                        LoRaMacParams.ChannelsMask[5] = channelsMask[5];
+                        memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )channelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
 
                         LoRaMacParams.ChannelsNbRep = nbRep;
+#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+                        // Reset ChannelsMaskRemaining to the new ChannelsMask
+                        ChannelsMaskRemaining[0] &= channelsMask[0];
+                        ChannelsMaskRemaining[1] &= channelsMask[1];
+                        ChannelsMaskRemaining[2] &= channelsMask[2];
+                        ChannelsMaskRemaining[3] &= channelsMask[3];
+                        ChannelsMaskRemaining[4] = channelsMask[4];
+                        ChannelsMaskRemaining[5] = channelsMask[5];
+#endif
                     }
                     AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
                 }
@@ -2536,7 +2766,7 @@
                 {
                     uint8_t status = 0x03;
 
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+#if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
                     status &= 0xFC; // Channel frequency and datarate KO
                     macIndex += 5;
 #else
@@ -2550,7 +2780,7 @@
                     chParam.Frequency *= 100;
                     chParam.DrRange.Value = payload[macIndex++];
 
-                    LoRaMacState |= MAC_TX_CONFIG;
+                    LoRaMacState |= LORAMAC_TX_CONFIG;
                     if( chParam.Frequency == 0 )
                     {
                         if( channelIndex < 3 )
@@ -2595,7 +2825,7 @@
                             }
                         }
                     }
-                    LoRaMacState &= ~MAC_TX_CONFIG;
+                    LoRaMacState &= ~LORAMAC_TX_CONFIG;
 #endif
                     AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
                 }
@@ -2608,8 +2838,8 @@
                     {
                         delay++;
                     }
-                    LoRaMacParams.ReceiveDelay1 = delay * 1e6;
-                    LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6;
+                    LoRaMacParams.ReceiveDelay1 = delay * 1e3;
+                    LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e3;
                     AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
                 }
                 break;
@@ -2651,7 +2881,7 @@
     return status;
 }
 
-static LoRaMacStatus_t ScheduleTx( )
+static LoRaMacStatus_t ScheduleTx( void )
 {
     TimerTime_t dutyCycleTimeOff = 0;
 
@@ -2665,8 +2895,6 @@
         AggregatedTimeOff = 0;
     }
 
-    CalculateBackOff( LastTxChannel );
-
     // Select channel
     while( SetNextChannel( &dutyCycleTimeOff ) == false )
     {
@@ -2679,6 +2907,30 @@
 #endif
     }
 
+    // Compute Rx1 windows parameters
+#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+    RxWindowsParams[0] = ComputeRxWindowParameters( DatarateOffsets[LoRaMacParams.ChannelsDatarate][LoRaMacParams.Rx1DrOffset], LoRaMacParams.SystemMaxRxError );
+#else
+    RxWindowsParams[0] = ComputeRxWindowParameters( MAX( DR_0, LoRaMacParams.ChannelsDatarate - LoRaMacParams.Rx1DrOffset ), LoRaMacParams.SystemMaxRxError );
+#endif
+    // Compute Rx2 windows parameters
+    RxWindowsParams[1] = ComputeRxWindowParameters( LoRaMacParams.Rx2Channel.Datarate, LoRaMacParams.SystemMaxRxError );
+
+    if( IsLoRaMacNetworkJoined == false )
+    {
+        RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 + RxWindowsParams[0].RxOffset;
+        RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 + RxWindowsParams[1].RxOffset;
+    }
+    else
+    {
+        if( ValidatePayloadLength( LoRaMacTxPayloadLen, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false )
+        {
+            return LORAMAC_STATUS_LENGTH_ERROR;
+        }
+        RxWindow1Delay = LoRaMacParams.ReceiveDelay1 + RxWindowsParams[0].RxOffset;
+        RxWindow2Delay = LoRaMacParams.ReceiveDelay2 + RxWindowsParams[1].RxOffset;
+    }
+
     // Schedule transmission of frame
     if( dutyCycleTimeOff == 0 )
     {
@@ -2688,7 +2940,7 @@
     else
     {
         // Send later - prepare timer
-        LoRaMacState |= MAC_TX_DELAYED;
+        LoRaMacState |= LORAMAC_TX_DELAYED;
         TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
         TimerStart( &TxDelayedTimer );
 
@@ -2696,18 +2948,16 @@
     }
 }
 
-static uint16_t RetransmissionDutyCylce( void )
+static uint16_t JoinDutyCycle( void )
 {
     uint16_t dutyCycle = 0;
-
-#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
-    TimerTime_t timeElapsed = TimerGetElapsedTime( 0 );
-
-    if( timeElapsed < 3600000000 )
+    TimerTime_t timeElapsed = TimerGetElapsedTime( LoRaMacInitializationTime );
+
+    if( timeElapsed < 3600e3 )
     {
         dutyCycle = BACKOFF_DC_1_HOUR;
     }
-    else if( timeElapsed < ( 3600000000 + 36000000000 ) )
+    else if( timeElapsed < ( 3600e3 + 36000e3 ) )
     {
         dutyCycle = BACKOFF_DC_10_HOURS;
     }
@@ -2715,7 +2965,6 @@
     {
         dutyCycle = BACKOFF_DC_24_HOURS;
     }
-#endif
     return dutyCycle;
 }
 
@@ -2723,34 +2972,25 @@
 {
     uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
     uint16_t joinDutyCycle = 0;
-    bool rndTimeOff = false;
+
+    // Reset time-off to initial value.
+    Bands[Channels[channel].Band].TimeOff = 0;
 
     if( IsLoRaMacNetworkJoined == false )
     {
-        joinDutyCycle = RetransmissionDutyCylce( );
+        // The node has not joined yet. Apply join duty cycle to all regions.
+        joinDutyCycle = JoinDutyCycle( );
         dutyCycle = MAX( dutyCycle, joinDutyCycle );
 
-        // Make sure to not apply the random back-off to the first TX
-        if( TxTimeOnAir > 0 )
-        {
-            rndTimeOff = true;
-        }
-    }
-
-    // Update Band Time OFF
-    if( DutyCycleOn == true )
-    {
+        // Update Band time-off.
         Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
     }
     else
     {
-        Bands[Channels[channel].Band].TimeOff = 0;
-    }
-
-    if( rndTimeOff == true )
-    {
-        Bands[Channels[channel].Band].TimeOff = randr( Bands[Channels[channel].Band].TimeOff,
-                                                       Bands[Channels[channel].Band].TimeOff + BACKOFF_RND_OFFSET );
+        if( DutyCycleOn == true )
+        {
+            Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
+        }
     }
 
     // Update Aggregated Time OFF
@@ -2766,7 +3006,7 @@
     LoRaMacParams.ChannelsMask[4] = 0x00FF;
 #else // defined( USE_BAND_915_HYBRID )
     // Re-enable 500 kHz default channels
-    ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
+    ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
 #endif
 
     if( ( nbTrials & 0x01 ) == 0x01 )
@@ -2775,7 +3015,7 @@
     }
     else
     {
-        datarate = DR_1;
+        datarate = DR_0;
     }
 #else
     if( ( nbTrials % 48 ) == 0 )
@@ -2811,7 +3051,7 @@
     IsLoRaMacNetworkJoined = false;
 
     // Counters
-    UpLinkCounter = 1;
+    UpLinkCounter = 0;
     DownLinkCounter = 0;
     AdrAckCounter = 0;
 
@@ -2832,15 +3072,7 @@
     LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
     LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
 
-    LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow;
-    LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1;
-    LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2;
-    LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1;
-    LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2;
-
     LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset;
-    LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep;
-
     LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
 
     memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
@@ -2872,7 +3104,6 @@
     uint8_t pktHeaderLen = 0;
     uint32_t mic = 0;
     const void* payload = fBuffer;
-    uint8_t payloadSize = fBufferSize;
     uint8_t framePort = fPort;
 
     LoRaMacBufferPktLen = 0;
@@ -2884,14 +3115,13 @@
         fBufferSize = 0;
     }
 
+    LoRaMacTxPayloadLen = fBufferSize;
+
     LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
 
     switch( macHdr->Bits.MType )
     {
         case FRAME_TYPE_JOIN_REQ:
-            RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
-            RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
-
             LoRaMacBufferPktLen = pktHeaderLen;
 
             memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
@@ -2914,7 +3144,7 @@
             break;
         case FRAME_TYPE_DATA_CONFIRMED_UP:
             NodeAckRequested = true;
-            //Intentional falltrough
+            //Intentional fallthrough
         case FRAME_TYPE_DATA_UNCONFIRMED_UP:
             if( IsLoRaMacNetworkJoined == false )
             {
@@ -2923,14 +3153,6 @@
 
             fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate );
 
-            if( ValidatePayloadLength( fBufferSize, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false )
-            {
-                return LORAMAC_STATUS_LENGTH_ERROR;
-            }
-
-            RxWindow1Delay = LoRaMacParams.ReceiveDelay1 - RADIO_WAKEUP_TIME;
-            RxWindow2Delay = LoRaMacParams.ReceiveDelay2 - RADIO_WAKEUP_TIME;
-
             if( SrvAckRequested == true )
             {
                 SrvAckRequested = false;
@@ -2951,7 +3173,7 @@
             memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
             MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
 
-            if( ( payload != NULL ) && ( payloadSize > 0 ) )
+            if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
             {
                 if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
                 {
@@ -2969,7 +3191,7 @@
             {
                 if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
                 {
-                    payloadSize = MacCommandsBufferIndex;
+                    LoRaMacTxPayloadLen = MacCommandsBufferIndex;
                     payload = MacCommandsBuffer;
                     framePort = 0;
                 }
@@ -2981,23 +3203,21 @@
             {
                 MacCommandsInNextTx = true;
             }
-            MacCommandsBufferIndex = 0;
-
-            if( ( payload != NULL ) && ( payloadSize > 0 ) )
+
+            if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
             {
                 LoRaMacBuffer[pktHeaderLen++] = framePort;
 
                 if( framePort == 0 )
                 {
-                    LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
+                    LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
                 }
                 else
                 {
-                    LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
+                    LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
                 }
-                memcpy1( LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, payloadSize );
             }
-            LoRaMacBufferPktLen = pktHeaderLen + payloadSize;
+            LoRaMacBufferPktLen = pktHeaderLen + LoRaMacTxPayloadLen;
 
             LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
 
@@ -3010,10 +3230,10 @@
 
             break;
         case FRAME_TYPE_PROPRIETARY:
-            if( ( fBuffer != NULL ) && ( fBufferSize > 0 ) )
+            if( ( fBuffer != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
             {
-                memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, fBufferSize );
-                LoRaMacBufferPktLen = pktHeaderLen + fBufferSize;
+                memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, LoRaMacTxPayloadLen );
+                LoRaMacBufferPktLen = pktHeaderLen + LoRaMacTxPayloadLen;
             }
             break;
         default:
@@ -3029,13 +3249,14 @@
     int8_t txPowerIndex = 0;
     int8_t txPower = 0;
 
-    txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower );
+    txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower, Bands[channel.Band].TxMaxPower );
     txPower = TxPowers[txPowerIndex];
 
     MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
     McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
     McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
     McpsConfirm.TxPower = txPowerIndex;
+    McpsConfirm.UpLinkFrequency = channel.Frequency;
 
     Radio.SetChannel( channel.Frequency );
 
@@ -3043,34 +3264,38 @@
     if( LoRaMacParams.ChannelsDatarate == DR_7 )
     { // High Speed FSK channel
         Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 );
+        Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e3 );
         TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
 
     }
     else if( LoRaMacParams.ChannelsDatarate == DR_6 )
     { // High speed LoRa channel
         Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
+        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
         TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
     }
     else
     { // Normal LoRa channel
         Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
+        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
         TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
     }
 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
     Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
     if( LoRaMacParams.ChannelsDatarate >= DR_4 )
     { // High speed LoRa channel BW500 kHz
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
+        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
         TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
     }
     else
     { // Normal LoRa channel
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
+        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
         TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
     }
+#elif defined( USE_BAND_470 )
+    Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
+    Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
+    TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
 #else
     #error "Please define a frequency band in the compiler options."
 #endif
@@ -3083,10 +3308,47 @@
     TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
     TimerStart( &MacStateCheckTimer );
 
+    if( IsLoRaMacNetworkJoined == false )
+    {
+        JoinRequestTrials++;
+    }
+
     // Send now
     Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
 
-    LoRaMacState |= MAC_TX_RUNNING;
+    LoRaMacState |= LORAMAC_TX_RUNNING;
+
+    return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout )
+{
+    int8_t txPowerIndex = 0;
+    int8_t txPower = 0;
+
+    txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower, Bands[Channels[Channel].Band].TxMaxPower );
+    txPower = TxPowers[txPowerIndex];
+
+    // Starts the MAC layer status check timer
+    TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
+    TimerStart( &MacStateCheckTimer );
+
+    Radio.SetTxContinuousWave( Channels[Channel].Frequency, txPower, timeout );
+
+    LoRaMacState |= LORAMAC_TX_RUNNING;
+
+    return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power )
+{
+    Radio.SetTxContinuousWave( frequency, power, timeout );
+
+    // Starts the MAC layer status check timer
+    TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
+    TimerStart( &MacStateCheckTimer );
+
+    LoRaMacState |= LORAMAC_TX_RUNNING;
 
     return LORAMAC_STATUS_OK;
 }
@@ -3100,7 +3362,7 @@
 
     if( ( primitives->MacMcpsConfirm == NULL ) ||
         ( primitives->MacMcpsIndication == NULL ) ||
-        ( primitives->MacMlmeConfirm == NULL ))
+        ( primitives->MacMlmeConfirm == NULL ) )
     {
         return LORAMAC_STATUS_PARAMETER_INVALID;
     }
@@ -3111,9 +3373,10 @@
     LoRaMacFlags.Value = 0;
 
     LoRaMacDeviceClass = CLASS_A;
-    LoRaMacState = MAC_IDLE;
+    LoRaMacState = LORAMAC_IDLE;
 
     JoinRequestTrials = 0;
+    MaxJoinRequestTrials = 1;
     RepeaterSupport = false;
 
     // Reset duty cycle times
@@ -3122,9 +3385,11 @@
 
     // Duty cycle
 #if defined( USE_BAND_433 )
+    DutyCycleOn = true;
+#elif defined( USE_BAND_470 )
     DutyCycleOn = false;
 #elif defined( USE_BAND_780 )
-    DutyCycleOn = false;
+    DutyCycleOn = true;
 #elif defined( USE_BAND_868 )
     DutyCycleOn = true;
 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
@@ -3137,6 +3402,8 @@
     LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
     LoRaMacParamsDefaults.ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
 
+    LoRaMacParamsDefaults.SystemMaxRxError = 10;
+    LoRaMacParamsDefaults.MinRxSymbols = 6;
     LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW;
     LoRaMacParamsDefaults.ReceiveDelay1 = RECEIVE_DELAY1;
     LoRaMacParamsDefaults.ReceiveDelay2 = RECEIVE_DELAY2;
@@ -3151,6 +3418,13 @@
     // Channel mask
 #if defined( USE_BAND_433 )
     LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+#elif defined ( USE_BAND_470 )
+    LoRaMacParamsDefaults.ChannelsMask[0] = 0xFFFF;
+    LoRaMacParamsDefaults.ChannelsMask[1] = 0xFFFF;
+    LoRaMacParamsDefaults.ChannelsMask[2] = 0xFFFF;
+    LoRaMacParamsDefaults.ChannelsMask[3] = 0xFFFF;
+    LoRaMacParamsDefaults.ChannelsMask[4] = 0xFFFF;
+    LoRaMacParamsDefaults.ChannelsMask[5] = 0xFFFF;
 #elif defined( USE_BAND_780 )
     LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
 #elif defined( USE_BAND_868 )
@@ -3188,8 +3462,26 @@
         Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
         Channels[i].Band = 0;
     }
+#elif defined( USE_BAND_470 )
+    // 125 kHz channels
+    for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
+    {
+        Channels[i].Frequency = 470.3e6 + i * 200e3;
+        Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
+        Channels[i].Band = 0;
+    }
 #endif
 
+    // Init parameters which are not set in function ResetMacParameters
+    LoRaMacParams.SystemMaxRxError = LoRaMacParamsDefaults.SystemMaxRxError;
+    LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols;
+    LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow;
+    LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1;
+    LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2;
+    LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1;
+    LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2;
+    LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep;
+
     ResetMacParameters( );
 
     // Initialize timers
@@ -3201,6 +3493,9 @@
     TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
     TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
 
+    // Store the current initialization time
+    LoRaMacInitializationTime = TimerGetCurrentTime( );
+
     // Initialize Radio driver
     RadioEvents.TxDone = OnRadioTxDone;
     RadioEvents.RxDone = OnRadioRxDone;
@@ -3213,7 +3508,7 @@
     srand1( Radio.Random( ) );
 
     PublicNetwork = true;
-    SetPublicNetwork( PublicNetwork );
+    Radio.SetPublicNetwork( PublicNetwork );
     Radio.Sleep( );
 
     return LORAMAC_STATUS_OK;
@@ -3328,6 +3623,16 @@
             mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel;
             break;
         }
+        case MIB_RX2_DEFAULT_CHANNEL:
+        {
+            mibGet->Param.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
+            break;
+        }
+        case MIB_CHANNELS_DEFAULT_MASK:
+        {
+            mibGet->Param.ChannelsDefaultMask = LoRaMacParamsDefaults.ChannelsMask;
+            break;
+        }
         case MIB_CHANNELS_MASK:
         {
             mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask;
@@ -3373,6 +3678,11 @@
             mibGet->Param.ChannelsDatarate = LoRaMacParams.ChannelsDatarate;
             break;
         }
+        case MIB_CHANNELS_DEFAULT_TX_POWER:
+        {
+            mibGet->Param.ChannelsDefaultTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
+            break;
+        }
         case MIB_CHANNELS_TX_POWER:
         {
             mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower;
@@ -3393,6 +3703,16 @@
             mibGet->Param.MulticastList = MulticastChannels;
             break;
         }
+        case MIB_SYSTEM_MAX_RX_ERROR:
+        {
+            mibGet->Param.SystemMaxRxError = LoRaMacParams.SystemMaxRxError;
+            break;
+        }
+        case MIB_MIN_RX_SYMBOLS:
+        {
+            mibGet->Param.MinRxSymbols = LoRaMacParams.MinRxSymbols;
+            break;
+        }
         default:
             status = LORAMAC_STATUS_SERVICE_UNKNOWN;
             break;
@@ -3409,7 +3729,7 @@
     {
         return LORAMAC_STATUS_PARAMETER_INVALID;
     }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+    if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
     {
         return LORAMAC_STATUS_BUSY;
     }
@@ -3489,7 +3809,8 @@
         }
         case MIB_PUBLIC_NETWORK:
         {
-            SetPublicNetwork( mibSet->Param.EnablePublicNetwork );
+            PublicNetwork = mibSet->Param.EnablePublicNetwork;
+            Radio.SetPublicNetwork( PublicNetwork );
             break;
         }
         case MIB_REPEATER_SUPPORT:
@@ -3502,6 +3823,57 @@
             LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel;
             break;
         }
+        case MIB_RX2_DEFAULT_CHANNEL:
+        {
+            LoRaMacParamsDefaults.Rx2Channel = mibSet->Param.Rx2DefaultChannel;
+            break;
+        }
+        case MIB_CHANNELS_DEFAULT_MASK:
+        {
+            if( mibSet->Param.ChannelsDefaultMask )
+            {
+#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+                bool chanMaskState = true;
+
+#if defined( USE_BAND_915_HYBRID )
+                chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsDefaultMask );
+#endif
+                if( chanMaskState == true )
+                {
+                    if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) &&
+                        ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
+                    {
+                        status = LORAMAC_STATUS_PARAMETER_INVALID;
+                    }
+                    else
+                    {
+                        memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
+                                 ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, sizeof( LoRaMacParamsDefaults.ChannelsMask ) );
+                        for ( uint8_t i = 0; i < sizeof( LoRaMacParamsDefaults.ChannelsMask ) / 2; i++ )
+                        {
+                            // Disable channels which are no longer available
+                            ChannelsMaskRemaining[i] &= LoRaMacParamsDefaults.ChannelsMask[i];
+                        }
+                    }
+                }
+                else
+                {
+                    status = LORAMAC_STATUS_PARAMETER_INVALID;
+                }
+#elif defined( USE_BAND_470 )
+                memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
+                         ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, sizeof( LoRaMacParamsDefaults.ChannelsMask ) );
+#else
+                memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
+                         ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, 2 );
+#endif
+            }
+            else
+            {
+                status = LORAMAC_STATUS_PARAMETER_INVALID;
+            }
+            break;
+        }
         case MIB_CHANNELS_MASK:
         {
             if( mibSet->Param.ChannelsMask )
@@ -3514,7 +3886,7 @@
 #endif
                 if( chanMaskState == true )
                 {
-                    if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 6 ) &&
+                    if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) &&
                         ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
                     {
                         status = LORAMAC_STATUS_PARAMETER_INVALID;
@@ -3534,6 +3906,9 @@
                 {
                     status = LORAMAC_STATUS_PARAMETER_INVALID;
                 }
+#elif defined( USE_BAND_470 )
+                memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
+                         ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
 #else
                 memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
                          ( uint8_t* ) mibSet->Param.ChannelsMask, 2 );
@@ -3585,11 +3960,19 @@
         }
         case MIB_CHANNELS_DEFAULT_DATARATE:
         {
+#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
+            if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
+                              DR_0, DR_5 ) )
+            {
+                LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
+            }
+#else
             if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
                               LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
             {
                 LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
             }
+#endif
             else
             {
                 status = LORAMAC_STATUS_PARAMETER_INVALID;
@@ -3609,6 +3992,19 @@
             }
             break;
         }
+        case MIB_CHANNELS_DEFAULT_TX_POWER:
+        {
+            if( ValueInRange( mibSet->Param.ChannelsDefaultTxPower,
+                              LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
+            {
+                LoRaMacParamsDefaults.ChannelsTxPower = mibSet->Param.ChannelsDefaultTxPower;
+            }
+            else
+            {
+                status = LORAMAC_STATUS_PARAMETER_INVALID;
+            }
+            break;
+        }
         case MIB_CHANNELS_TX_POWER:
         {
             if( ValueInRange( mibSet->Param.ChannelsTxPower,
@@ -3632,6 +4028,16 @@
             DownLinkCounter = mibSet->Param.DownLinkCounter;
             break;
         }
+        case MIB_SYSTEM_MAX_RX_ERROR:
+        {
+            LoRaMacParams.SystemMaxRxError = LoRaMacParamsDefaults.SystemMaxRxError = mibSet->Param.SystemMaxRxError;
+            break;
+        }
+        case MIB_MIN_RX_SYMBOLS:
+        {
+            LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols = mibSet->Param.MinRxSymbols;
+            break;
+        }
         default:
             status = LORAMAC_STATUS_SERVICE_UNKNOWN;
             break;
@@ -3642,7 +4048,7 @@
 
 LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
 {
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+#if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
     return LORAMAC_STATUS_PARAMETER_INVALID;
 #else
     bool datarateInvalid = false;
@@ -3655,9 +4061,9 @@
         return LORAMAC_STATUS_PARAMETER_INVALID;
     }
     // Validate if the MAC is in a correct state
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+    if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
     {
-        if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
+        if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
         {
             return LORAMAC_STATUS_BUSY;
         }
@@ -3680,7 +4086,7 @@
             frequencyInvalid = true;
         }
 
-        if( params.DrRange.Fields.Min > LoRaMacParamsDefaults.ChannelsDatarate )
+        if( params.DrRange.Fields.Min > DR_0 )
         {
             datarateInvalid = true;
         }
@@ -3695,7 +4101,11 @@
     if( ( Radio.CheckRfFrequency( params.Frequency ) == true ) && ( params.Frequency > 0 ) && ( frequencyInvalid == false ) )
     {
 #if defined( USE_BAND_868 )
-        if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
+        if( ( params.Frequency >= 863000000 ) && ( params.Frequency < 865000000 ) )
+        {
+            band = BAND_G1_2;
+        }
+        else if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
         {
             band = BAND_G1_0;
         }
@@ -3751,9 +4161,9 @@
 LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
 {
 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+    if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
     {
-        if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
+        if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
         {
             return LORAMAC_STATUS_BUSY;
         }
@@ -3775,7 +4185,7 @@
         }
     }
     return LORAMAC_STATUS_OK;
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) || defined( USE_BAND_470 ) )
     return LORAMAC_STATUS_PARAMETER_INVALID;
 #endif
 }
@@ -3786,7 +4196,7 @@
     {
         return LORAMAC_STATUS_PARAMETER_INVALID;
     }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+    if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
     {
         return LORAMAC_STATUS_BUSY;
     }
@@ -3821,7 +4231,7 @@
     {
         return LORAMAC_STATUS_PARAMETER_INVALID;
     }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+    if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
     {
         return LORAMAC_STATUS_BUSY;
     }
@@ -3863,7 +4273,7 @@
     {
         return LORAMAC_STATUS_PARAMETER_INVALID;
     }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+    if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
     {
         return LORAMAC_STATUS_BUSY;
     }
@@ -3876,33 +4286,52 @@
     {
         case MLME_JOIN:
         {
-            if( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED )
+            if( ( LoRaMacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED )
             {
                 return LORAMAC_STATUS_BUSY;
             }
 
-            MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
             if( ( mlmeRequest->Req.Join.DevEui == NULL ) ||
                 ( mlmeRequest->Req.Join.AppEui == NULL ) ||
-                ( mlmeRequest->Req.Join.AppKey == NULL ) )
+                ( mlmeRequest->Req.Join.AppKey == NULL ) ||
+                ( mlmeRequest->Req.Join.NbTrials == 0 ) )
             {
                 return LORAMAC_STATUS_PARAMETER_INVALID;
             }
 
+#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+            // Enables at least the usage of the 2 datarates.
+            if( mlmeRequest->Req.Join.NbTrials < 2 )
+            {
+                mlmeRequest->Req.Join.NbTrials = 2;
+            }
+#else
+            // Enables at least the usage of all datarates.
+            if( mlmeRequest->Req.Join.NbTrials < 48 )
+            {
+                mlmeRequest->Req.Join.NbTrials = 48;
+            }
+#endif
+
             LoRaMacFlags.Bits.MlmeReq = 1;
+            MlmeConfirm.MlmeRequest = mlmeRequest->Type;
 
             LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
             LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
             LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
-
+            MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials;
+
+            // Reset variable JoinRequestTrials
+            JoinRequestTrials = 0;
+
+            // Setup header information
             macHdr.Value = 0;
             macHdr.Bits.MType  = FRAME_TYPE_JOIN_REQ;
 
             ResetMacParameters( );
 
-            JoinRequestTrials++;
-            LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials );
+            // Add a +1, since we start to count from 0
+            LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials + 1 );
 
             status = Send( &macHdr, 0, NULL, 0 );
             break;
@@ -3916,6 +4345,20 @@
             status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
             break;
         }
+        case MLME_TXCW:
+        {
+            MlmeConfirm.MlmeRequest = mlmeRequest->Type;
+            LoRaMacFlags.Bits.MlmeReq = 1;
+            status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout );
+            break;
+        }
+        case MLME_TXCW_1:
+        {
+            MlmeConfirm.MlmeRequest = mlmeRequest->Type;
+            LoRaMacFlags.Bits.MlmeReq = 1;
+            status = SetTxContinuousWave1( mlmeRequest->Req.TxCw.Timeout, mlmeRequest->Req.TxCw.Frequency, mlmeRequest->Req.TxCw.Power );
+            break;
+        }
         default:
             break;
     }
@@ -3943,8 +4386,8 @@
     {
         return LORAMAC_STATUS_PARAMETER_INVALID;
     }
-    if( ( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING ) ||
-        ( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED ) )
+    if( ( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING ) ||
+        ( ( LoRaMacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED ) )
     {
         return LORAMAC_STATUS_BUSY;
     }
@@ -4037,5 +4480,52 @@
 
 void LoRaMacTestSetDutyCycleOn( bool enable )
 {
+#if ( defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) )
     DutyCycleOn = enable;
+#else
+    DutyCycleOn = false;
+#endif
 }
+
+void LoRaMacTestSetChannel( uint8_t channel )
+{
+    Channel = channel;
+}
+
+static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError )
+{
+    RxConfigParams_t rxConfigParams = { 0, 0, 0, 0 };
+    double tSymbol = 0.0;
+
+    rxConfigParams.Datarate = datarate;
+    switch( Bandwidths[datarate] )
+    {
+        default:
+        case 125000:
+            rxConfigParams.Bandwidth = 0;
+            break;
+        case 250000:
+            rxConfigParams.Bandwidth = 1;
+            break;
+        case 500000:
+            rxConfigParams.Bandwidth = 2;
+            break;
+    }
+
+#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
+    if( datarate == DR_7 )
+    { // FSK
+        tSymbol = ( 1.0 / ( double )Datarates[datarate] ) * 8.0; // 1 symbol equals 1 byte
+    }
+    else
+#endif
+    { // LoRa
+        tSymbol = ( ( double )( 1 << Datarates[datarate] ) / ( double )Bandwidths[datarate] ) * 1e3;
+    }
+
+    rxConfigParams.RxWindowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * LoRaMacParams.MinRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), LoRaMacParams.MinRxSymbols ); // Computed number of symbols
+
+    rxConfigParams.RxOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( rxConfigParams.RxWindowTimeout * tSymbol ) / 2.0 ) - RADIO_WAKEUP_TIME );
+
+    return rxConfigParams;
+}
--- a/LoRaMac.h	Tue Jul 05 13:24:54 2016 +0000
+++ b/LoRaMac.h	Mon Apr 24 09:42:37 2017 +0000
@@ -50,34 +50,34 @@
 #include "LoRaMac-definitions.h"
 
 /*!
- * Beacon interval in us
+ * Beacon interval in ms
  */
-#define BEACON_INTERVAL                             128000000
+#define BEACON_INTERVAL                             128000
 
 /*!
- * Class A&B receive delay 1 in us
+ * Class A&B receive delay 1 in ms
  */
-#define RECEIVE_DELAY1                              1000000
+#define RECEIVE_DELAY1                              1000
 
 /*!
- * Class A&B receive delay 2 in us
+ * Class A&B receive delay 2 in ms
  */
-#define RECEIVE_DELAY2                              2000000
+#define RECEIVE_DELAY2                              2000
 
 /*!
- * Join accept receive delay 1 in us
+ * Join accept receive delay 1 in ms
  */
-#define JOIN_ACCEPT_DELAY1                          5000000
+#define JOIN_ACCEPT_DELAY1                          5000
 
 /*!
- * Join accept receive delay 2 in us
+ * Join accept receive delay 2 in ms
  */
-#define JOIN_ACCEPT_DELAY2                          6000000
+#define JOIN_ACCEPT_DELAY2                          6000
 
 /*!
- * Class A&B maximum receive window delay in us
+ * Class A&B maximum receive window delay in ms
  */
-#define MAX_RX_WINDOW                               3000000
+#define MAX_RX_WINDOW                               3000
 
 /*!
  * Maximum allowed gap for the FCNT field
@@ -99,19 +99,19 @@
  * receiving an acknowledge.
  * AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
  */
-#define ACK_TIMEOUT                                 2000000
+#define ACK_TIMEOUT                                 2000
 
 /*!
  * Random number of seconds after the start of the second reception window without
  * receiving an acknowledge
  * AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
  */
-#define ACK_TIMEOUT_RND                             1000000
+#define ACK_TIMEOUT_RND                             1000
 
 /*!
- * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in us
+ * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in ms
  */
-#define MAC_STATE_CHECK_TIMEOUT                     1000000
+#define MAC_STATE_CHECK_TIMEOUT                     1000
 
 /*!
  * Maximum number of times the MAC layer tries to get an acknowledge.
@@ -140,16 +140,6 @@
 #define LORAMAC_MFR_LEN                             4
 
 /*!
- * Syncword for Private LoRa networks
- */
-#define LORA_MAC_PRIVATE_SYNCWORD                   0x12
-
-/*!
- * Syncword for Public LoRa networks
- */
-#define LORA_MAC_PUBLIC_SYNCWORD                    0x34
-
-/*!
  * LoRaWAN devices classes definition
  */
 typedef enum eDeviceClass
@@ -282,6 +272,17 @@
      */
     int8_t ChannelsDatarate;
     /*!
+     * System overall timing error in milliseconds. 
+     * [-SystemMaxRxError : +SystemMaxRxError]
+     * Default: +/-10 ms
+     */
+    uint32_t SystemMaxRxError;
+    /*!
+     * Minimum required number of symbols to detect an Rx frame
+     * Default: 6 symbols
+     */
+    uint8_t MinRxSymbols;
+    /*!
      * LoRaMac maximum time a reception window stays open
      */
     uint32_t MaxRxWindow;
@@ -564,23 +565,27 @@
      */
     LORAMAC_EVENT_INFO_STATUS_OK = 0,
     /*!
-     * An error occured during the execution of the service
+     * An error occurred during the execution of the service
      */
     LORAMAC_EVENT_INFO_STATUS_ERROR,
     /*!
-     * A Tx timeouit occured
+     * A Tx timeout occurred
      */
     LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT,
     /*!
-     * An Rx timeout occured on receive window 2
+     * An Rx timeout occurred on receive window 2
      */
     LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT,
     /*!
-     * An Rx error occured on receive window 2
+     * An Rx error occurred on receive window 1
+     */
+    LORAMAC_EVENT_INFO_STATUS_RX1_ERROR,
+    /*!
+     * An Rx error occurred on receive window 2
      */
     LORAMAC_EVENT_INFO_STATUS_RX2_ERROR,
     /*!
-     * An error occured in the join procedure
+     * An error occurred in the join procedure
      */
     LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL,
     /*!
@@ -590,11 +595,16 @@
      */
     LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED,
     /*!
+     * The MAC could not retransmit a frame since the MAC decreased the datarate. The
+     * payload size is not applicable for the datarate.
+     */
+    LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR,
+    /*!
      * The node has lost MAX_FCNT_GAP or more frames.
      */
     LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS,
     /*!
-     * An address error occured
+     * An address error occurred
      */
     LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL,
     /*!
@@ -626,6 +636,10 @@
          */
         uint8_t McpsInd         : 1;
         /*!
+         * MCPS-Ind pending. Skip indication to the application layer
+         */
+        uint8_t McpsIndSkip     : 1;
+        /*!
          * MLME-Req pending
          */
         uint8_t MlmeReq         : 1;
@@ -838,6 +852,10 @@
      * The uplink counter value related to the frame
      */
     uint32_t UpLinkCounter;
+    /*!
+     * The uplink frequency related to the frame
+     */
+    uint32_t UpLinkFrequency;
 }McpsConfirm_t;
 
 /*!
@@ -915,6 +933,7 @@
  * --------------------- | :-----: | :--------: | :------: | :-----:
  * \ref MLME_JOIN        | YES     | NO         | NO       | YES
  * \ref MLME_LINK_CHECK  | YES     | NO         | NO       | YES
+ * \ref MLME_TXCW        | YES     | NO         | NO       | YES
  *
  * The following table provides links to the function implementations of the
  * related MLME primitives.
@@ -938,6 +957,18 @@
      * LoRaWAN Specification V1.0.1, chapter 5, table 4
      */
     MLME_LINK_CHECK,
+    /*!
+     * Sets Tx continuous wave mode
+     *
+     * LoRaWAN end-device certification
+     */
+    MLME_TXCW,
+    /*!
+     * Sets Tx continuous wave mode (new LoRa-Alliance CC definition)
+     *
+     * LoRaWAN end-device certification
+     */
+    MLME_TXCW_1,
 }Mlme_t;
 
 /*!
@@ -963,9 +994,32 @@
      * LoRaWAN Specification V1.0.1, chapter 6.2.2
      */
     uint8_t *AppKey;
+    /*!
+     * Number of trials for the join request.
+     */
+    uint8_t NbTrials;
 }MlmeReqJoin_t;
 
 /*!
+ * LoRaMAC MLME-Request for Tx continuous wave mode
+ */
+typedef struct sMlmeReqTxCw
+{
+    /*!
+     * Time in seconds while the radio is kept in continuous wave mode
+     */
+    uint16_t Timeout;
+    /*!
+     * RF frequency to set (Only used with new way)
+     */
+    uint32_t Frequency;
+    /*!
+     * RF output power to set (Only used with new way)
+     */
+    uint8_t Power;
+}MlmeReqTxCw_t;
+
+/*!
  * LoRaMAC MLME-Request structure
  */
 typedef struct sMlmeReq
@@ -984,6 +1038,10 @@
          * MLME-Request parameters for a join request
          */
         MlmeReqJoin_t Join;
+        /*!
+         * MLME-Request parameters for Tx continuous mode request
+         */
+        MlmeReqTxCw_t TxCw;
     }Req;
 }MlmeReq_t;
 
@@ -1013,6 +1071,10 @@
      * Number of gateways which received the last LinkCheckReq
      */
     uint8_t NbGateways;
+    /*!
+     * Provides the number of retransmissions
+     */
+    uint8_t NbRetries;
 }MlmeConfirm_t;
 
 /*!
@@ -1034,6 +1096,7 @@
  * \ref MIB_CHANNELS                 | YES | NO
  * \ref MIB_RX2_CHANNEL              | YES | YES
  * \ref MIB_CHANNELS_MASK            | YES | YES
+ * \ref MIB_CHANNELS_DEFAULT_MASK    | YES | YES
  * \ref MIB_CHANNELS_NB_REP          | YES | YES
  * \ref MIB_MAX_RX_WINDOW_DURATION   | YES | YES
  * \ref MIB_RECEIVE_DELAY_1          | YES | YES
@@ -1043,9 +1106,12 @@
  * \ref MIB_CHANNELS_DATARATE        | YES | YES
  * \ref MIB_CHANNELS_DEFAULT_DATARATE| YES | YES
  * \ref MIB_CHANNELS_TX_POWER        | YES | YES
+ * \ref MIB_CHANNELS_DEFAULT_TX_POWER| YES | YES
  * \ref MIB_UPLINK_COUNTER           | YES | YES
  * \ref MIB_DOWNLINK_COUNTER         | YES | YES
  * \ref MIB_MULTICAST_CHANNEL        | YES | NO
+ * \ref MIB_SYSTEM_MAX_RX_ERROR      | YES | YES
+ * \ref MIB_MIN_RX_SYMBOLS           | YES | YES
  *
  * The following table provides links to the function implementations of the
  * related MIB primitives:
@@ -1132,43 +1198,55 @@
      */
     MIB_RX2_CHANNEL,
     /*!
+     * Set receive window 2 channel
+     *
+     * LoRaWAN Specification V1.0.1, chapter 3.3.2
+     */
+    MIB_RX2_DEFAULT_CHANNEL,
+    /*!
      * LoRaWAN channels mask
      *
      * LoRaWAN Specification V1.0.1, chapter 7
      */
     MIB_CHANNELS_MASK,
     /*!
+     * LoRaWAN default channels mask
+     *
+     * LoRaWAN Specification V1.0.1, chapter 7
+     */
+    MIB_CHANNELS_DEFAULT_MASK,
+    /*!
      * Set the number of repetitions on a channel
      *
      * LoRaWAN Specification V1.0.1, chapter 5.2
      */
     MIB_CHANNELS_NB_REP,
     /*!
-     * Maximum receive window duration in [us]
+     * Maximum receive window duration in [ms]
      *
      * LoRaWAN Specification V1.0.1, chapter 3.3.3
      */
     MIB_MAX_RX_WINDOW_DURATION,
     /*!
-     * Receive delay 1 in [us]
+     * Receive delay 1 in [ms]
      *
      * LoRaWAN Specification V1.0.1, chapter 7
      */
     MIB_RECEIVE_DELAY_1,
     /*!
-     * Receive delay 2 in [us]
+     * Receive delay 2 in [ms]
      *
      * LoRaWAN Specification V1.0.1, chapter 7
      */
     MIB_RECEIVE_DELAY_2,
     /*!
-     * Join accept delay 1 in [us]
+     * Join accept delay 1 in [ms]
      *
      * LoRaWAN Specification V1.0.1, chapter 7
      */
     MIB_JOIN_ACCEPT_DELAY_1,
     /*!
-     * Join accept delay 2 in [us]
+     * Join accept delay 2 in [ms]
      *
      * LoRaWAN Specification V1.0.1, chapter 7
      */
@@ -1208,6 +1286,20 @@
      */
     MIB_CHANNELS_TX_POWER,
     /*!
+     * Transmission power of a channel
+     *
+     * LoRaWAN Specification V1.0.1, chapter 7
+     *
+     * EU868 - [TX_POWER_20_DBM, TX_POWER_14_DBM, TX_POWER_11_DBM,
+     *          TX_POWER_08_DBM, TX_POWER_05_DBM, TX_POWER_02_DBM]
+     *
+     * US915 - [TX_POWER_30_DBM, TX_POWER_28_DBM, TX_POWER_26_DBM,
+     *          TX_POWER_24_DBM, TX_POWER_22_DBM, TX_POWER_20_DBM,
+     *          TX_POWER_18_DBM, TX_POWER_14_DBM, TX_POWER_12_DBM,
+     *          TX_POWER_10_DBM]
+     */
+    MIB_CHANNELS_DEFAULT_TX_POWER,
+    /*!
      * LoRaWAN Up-link counter
      *
      * LoRaWAN Specification V1.0.1, chapter 4.3.1.5
@@ -1225,6 +1317,17 @@
      * NULL, the list is empty.
      */
     MIB_MULTICAST_CHANNEL,
+    /*!
+     * System overall timing error in milliseconds. 
+     * [-SystemMaxRxError : +SystemMaxRxError]
+     * Default: +/-10 ms
+     */
+    MIB_SYSTEM_MAX_RX_ERROR,
+    /*!
+     * Minimum required number of symbols to detect an Rx frame
+     * Default: 6 symbols
+     */
+    MIB_MIN_RX_SYMBOLS,
 }Mib_t;
 
 /*!
@@ -1298,6 +1401,12 @@
      * Related MIB type: \ref MIB_RX2_CHANNEL
      */
     Rx2ChannelParams_t Rx2Channel;
+     /*!
+     * Channel for the receive window 2
+     *
+     * Related MIB type: \ref MIB_RX2_DEFAULT_CHANNEL
+     */
+    Rx2ChannelParams_t Rx2DefaultChannel;
     /*!
      * Channel mask
      *
@@ -1305,6 +1414,12 @@
      */
     uint16_t* ChannelsMask;
     /*!
+     * Default channel mask
+     *
+     * Related MIB type: \ref MIB_CHANNELS_DEFAULT_MASK
+     */
+    uint16_t* ChannelsDefaultMask;
+    /*!
      * Number of frame repetitions
      *
      * Related MIB type: \ref MIB_CHANNELS_NB_REP
@@ -1355,6 +1470,12 @@
     /*!
      * Channels TX power
      *
+     * Related MIB type: \ref MIB_CHANNELS_DEFAULT_TX_POWER
+     */
+    int8_t ChannelsDefaultTxPower;
+    /*!
+     * Channels TX power
+     *
      * Related MIB type: \ref MIB_CHANNELS_TX_POWER
      */
     int8_t ChannelsTxPower;
@@ -1376,6 +1497,18 @@
      * Related MIB type: \ref MIB_MULTICAST_CHANNEL
      */
     MulticastParams_t* MulticastList;
+    /*!
+     * System overall timing error in milliseconds. 
+     *
+     * Related MIB type: \ref MIB_SYSTEM_MAX_RX_ERROR
+     */
+    uint32_t SystemMaxRxError;
+    /*!
+     * Minimum required number of symbols to detect an Rx frame
+     *
+     * Related MIB type: \ref MIB_MIN_RX_SYMBOLS
+     */
+    uint8_t MinRxSymbols;
 }MibParam_t;
 
 /*!
@@ -1447,11 +1580,11 @@
      */
     LORAMAC_STATUS_NO_NETWORK_JOINED,
     /*!
-     * Service not started - playload lenght error
+     * Service not started - payload lenght error
      */
     LORAMAC_STATUS_LENGTH_ERROR,
     /*!
-     * Service not started - playload lenght error
+     * Service not started - payload lenght error
      */
     LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR,
     /*!
--- a/LoRaMacTest.h	Tue Jul 05 13:24:54 2016 +0000
+++ b/LoRaMacTest.h	Mon Apr 24 09:42:37 2017 +0000
@@ -66,6 +66,16 @@
  */
 void LoRaMacTestSetDutyCycleOn( bool enable );
 
+/*!
+ * \brief   Sets the channel index
+ *
+ * \details This is a test function. It shall be used for testing purposes only.
+ *          Changing this attribute may lead to a non-conformance LoRaMac operation.
+ *
+ * \param   [IN] channel - Channel index
+ */
+void LoRaMacTestSetChannel( uint8_t channel );
+
 /*! \} defgroup LORAMACTEST */
 
 #endif // __LORAMACTEST_H__