for publishing
Fork of LoRaWAN-lib_publishing_testing_UART_bug by
Revision 8:26002607de9c, committed 2017-04-24
- Comitter:
- mluis
- Date:
- Mon Apr 24 09:42:37 2017 +0000
- Parent:
- 7:c16969e0f70f
- Child:
- 9:db4900d60c37
- Child:
- 11:0cbf861e53f8
- 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__