Fork of Semtech LoRaWAN stack
Fork of LoRaWAN-lib by
Revision 32:26002607de9c, committed 2017-04-24
- Comitter:
- mluis
- Date:
- Mon Apr 24 09:42:37 2017 +0000
- Parent:
- 7:c16969e0f70f
- Child:
- 33: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
--- 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__
