Fork of Semtech LoRaWAN stack
Fork of LoRaWAN-lib by
Diff: LoRaMac.cpp
- Branch:
- class_b
- Revision:
- 38:182ba91524e4
- Parent:
- 34:1ac668ce2b15
- Child:
- 39:ca51084123b8
--- a/LoRaMac.cpp Tue Aug 08 19:27:17 2017 -0400
+++ b/LoRaMac.cpp Wed Aug 09 16:20:21 2017 -0400
@@ -15,15 +15,18 @@
License: Revised BSD License, see LICENSE.TXT file include in the project
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
+Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
*/
-#include <math.h>
#include "board.h"
+#include "LoRaMac.h"
+#include "LoRaMacClassB.h"
+#include "region/Region.h"
#include "LoRaMacCrypto.h"
-#include "LoRaMac.h"
#include "LoRaMacTest.h"
+
+
/*!
* Maximum PHY layer payload size
*/
@@ -32,14 +35,12 @@
/*!
* Maximum MAC commands buffer size
*/
-#define LORA_MAC_COMMAND_MAX_LENGTH 15
+#define LORA_MAC_COMMAND_MAX_LENGTH 128
/*!
- * FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
- * in RxWindowSetup function.
- * Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater + LORA_MAC_FRMPAYLOAD_OVERHEAD
+ * Maximum length of the fOpts field
*/
-#define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
+#define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH 15
/*!
* LoRaMac duty cycle for the back-off procedure during the first hour.
@@ -57,6 +58,11 @@
#define BACKOFF_DC_24_HOURS 10000
/*!
+ * LoRaMac region.
+ */
+static LoRaMacRegion_t LoRaMacRegion;
+
+/*!
* Device IEEE EUI
*/
static uint8_t *LoRaMacDevEui;
@@ -121,11 +127,6 @@
static bool PublicNetwork;
/*!
- * Indicates if the node supports repeaters
- */
-static bool RepeaterSupport;
-
-/*!
* Buffer containing the data to be sent or received.
*/
static uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD];
@@ -220,269 +221,6 @@
*/
static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
-#if defined( USE_BAND_433 )
-/*!
- * Data rates table definition
- */
-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 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
-
-/*!
- * Tx output powers table definition
- */
-const int8_t TxPowers[] = { 10, 7, 4, 1, -2, -5 };
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
- BAND0,
-};
-
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
- LC1,
- 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
- */
-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 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
-
-/*!
- * Tx output powers table definition
- */
-const int8_t TxPowers[] = { 10, 7, 4, 1, -2, -5 };
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
- BAND0,
-};
-
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
- LC1,
- LC2,
- LC3,
-};
-#elif defined( USE_BAND_868 )
-/*!
- * Data rates table definition
- */
-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 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-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 };
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
- BAND0,
- BAND1,
- BAND2,
- BAND3,
- BAND4,
-};
-
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
- LC1,
- LC2,
- LC3,
-};
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-/*!
- * Data rates table definition
- */
-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[5][4] =
-{
- { DR_10, DR_9 , DR_8 , DR_8 }, // DR_0
- { DR_11, DR_10, DR_9 , DR_8 }, // DR_1
- { DR_12, DR_11, DR_10, DR_9 }, // DR_2
- { DR_13, DR_12, DR_11, DR_10 }, // DR_3
- { DR_13, DR_13, DR_12, DR_11 }, // DR_4
-};
-
-/*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
-
-/*!
- * Tx output powers table definition
- */
-const int8_t TxPowers[] = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 };
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
- BAND0,
-};
-
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS];
-
-/*!
- * Contains the channels which remain to be applied.
- */
-static uint16_t ChannelsMaskRemaining[6];
-
-/*!
- * Defines the first channel for RX window 1 for US band
- */
-#define LORAMAC_FIRST_RX1_CHANNEL ( (uint32_t) 923.3e6 )
-
-/*!
- * Defines the last channel for RX window 1 for US band
- */
-#define LORAMAC_LAST_RX1_CHANNEL ( (uint32_t) 927.5e6 )
-
-/*!
- * Defines the step width of the channels for RX window 1
- */
-#define LORAMAC_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600e3 )
-
-#else
- #error "Please define a frequency band in the compiler options."
-#endif
-
/*!
* LoRaMac parameters
*/
@@ -522,6 +260,16 @@
static uint8_t Channel;
/*!
+ * Current channel index
+ */
+static uint8_t LastTxChannel;
+
+/*!
+ * Set to true, if the last uplink was a join request
+ */
+static bool LastTxIsJoinRequest;
+
+/*!
* Stores the time at LoRaMac initialization.
*
* \remark Used for the BACKOFF_DC computation.
@@ -588,20 +336,10 @@
static uint32_t RxWindow2Delay;
/*!
- * Rx window parameters
+ * LoRaMac Rx windows configuration
*/
-typedef struct
-{
- int8_t Datarate;
- uint8_t Bandwidth;
- uint32_t RxWindowTimeout;
- int32_t RxOffset;
-}RxConfigParams_t;
-
-/*!
- * Rx windows params
- */
-static RxConfigParams_t RxWindowsParams[2];
+static RxConfigParams_t RxWindow1Config;
+static RxConfigParams_t RxWindow2Config;
/*!
* Acknowledge timeout timer. Used for packet retransmissions.
@@ -649,11 +387,26 @@
static McpsConfirm_t McpsConfirm;
/*!
+ * Structure to hold MLME indication data.
+ */
+static MlmeIndication_t MlmeIndication;
+
+/*!
* Structure to hold MLME confirm data.
*/
static MlmeConfirm_t MlmeConfirm;
/*!
+ * MlmeConfirm queue data structure
+ */
+static MlmeConfirmQueue_t MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN];
+
+/*!
+ * Counts the number of MlmeConfirms to process
+ */
+static uint8_t MlmeConfirmQueueCnt;
+
+/*!
* Holds the current rx window slot
*/
static uint8_t RxSlot = 0;
@@ -720,36 +473,19 @@
static void OnAckTimeoutTimerEvent( void );
/*!
- * \brief Searches and set the next random available channel
- *
- * \param [OUT] Time to wait for the next transmission according to the duty
- * cycle.
- *
- * \retval status Function status [1: OK, 0: Unable to find a channel on the
- * current datarate]
- */
-static bool SetNextChannel( TimerTime_t* time );
-
-/*!
* \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]
+ * \param [IN] rxContinuous Set to true, if the RX is in continuous mode
+ * \param [IN] maxRxWindow Maximum RX window timeout
*/
-static bool RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
+static void RxWindowSetup( bool rxContinuous, uint32_t maxRxWindow );
/*!
- * \brief Verifies if the RX window 2 frequency is in range
- *
- * \param [IN] freq window channel frequency
+ * \brief Switches the device class
*
- * \retval status Function status [1: OK, 0: Frequency not applicable]
+ * \param [IN] deviceClass Device class to switch to
*/
-static bool Rx2FreqInRange( uint32_t freq );
+static LoRaMacStatus_t SwitchClass( DeviceClass_t deviceClass );
/*!
* \brief Adds a new MAC command to be sent.
@@ -803,105 +539,6 @@
static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );
/*!
- * \brief Counts the number of bits in a mask.
- *
- * \param [IN] mask A mask from which the function counts the active bits.
- * \param [IN] nbBits The number of bits to check.
- *
- * \retval Number of enabled bits in the mask.
- */
-static uint8_t CountBits( uint16_t mask, uint8_t nbBits );
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-/*!
- * \brief Counts the number of enabled 125 kHz channels in the channel mask.
- * This function can only be applied to US915 band.
- *
- * \param [IN] channelsMask Pointer to the first element of the channel mask
- *
- * \retval Number of enabled channels in the channel mask
- */
-static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask );
-
-#if defined( USE_BAND_915_HYBRID )
-/*!
- * \brief Validates the correctness of the channel mask for US915, hybrid mode.
- *
- * \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* channelsMask );
-
-/*!
- * \brief Validates the correctness of the channel mask for US915, hybrid mode.
- *
- * \param [IN] channelsMask Pointer to the first element of the channel mask
- *
- * \retval [true: channel mask correct, false: channel mask not correct]
- */
-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, int8_t maxBandTxPower );
-
-/*!
- * \brief Verifies, if a value is in a given range.
- *
- * \param value Value to verify, if it is in range
- *
- * \param min Minimum possible value
- *
- * \param max Maximum possible value
- *
- * \retval Returns the maximum valid tx power
- */
-static bool ValueInRange( int8_t value, int8_t min, int8_t max );
-
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off
- *
- * \param [IN] adrEnabled Specify whether ADR is on or off
- *
- * \param [IN] updateChannelMask Set to true, if the channel masks shall be updated
- *
- * \param [OUT] datarateOut Reports the datarate which will be used next
- *
- * \retval Returns the state of ADR ack request
- */
-static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut );
-
-/*!
- * \brief Disables channel in a specified channel mask
- *
- * \param [IN] id - Id of the channel
- *
- * \param [IN] mask - Pointer to the channel mask to edit
- *
- * \retval [true, if disable was successful, false if not]
- */
-static bool DisableChannelInMask( uint8_t id, uint16_t* mask );
-
-/*!
* \brief Decodes MAC commands in the fOpts field and in the payload
*/
static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr );
@@ -938,13 +575,6 @@
static LoRaMacStatus_t ScheduleTx( void );
/*
- * \brief Sets the duty cycle for the join procedure.
- *
- * \retval Duty cycle
- */
-static uint16_t JoinDutyCycle( void );
-
-/*
* \brief Calculates the back-off time for the band of a channel.
*
* \param [IN] channel The last Tx channel index
@@ -952,12 +582,21 @@
static void CalculateBackOff( uint8_t channel );
/*
- * \brief Alternates the datarate of the channel for the join request.
+ * \brief Gets the index of the confirm queue of a specific MLME-request
*
- * \param [IN] nbTrials Number of performed join requests.
- * \retval Datarate to apply
+ * \param [IN] queue MLME-Confirm queue pointer
+ * \param [IN] req MLME-Request to validate
+ * \retval Index of the MLME-Confirm. 0xFF is no entry found.
*/
-static int8_t AlternateDatarate( uint16_t nbTrials );
+static uint8_t GetMlmeConfirmIndex( MlmeConfirmQueue_t* queue, Mlme_t req );
+
+/*
+ * \brief Sets the status of all MLME requests in the queue to the provided status
+ *
+ * \param [IN] queue MLME-Confirm queue pointer
+ * \param [IN] status MLME-Status to set
+ */
+static void SetEveryMlmeConfirmStatus( MlmeConfirmQueue_t* queue, LoRaMacEventInfoStatus_t status );
/*!
* \brief LoRaMAC layer prepared frame buffer transmission with channel specification
@@ -965,10 +604,10 @@
* \remark PrepareFrame must be called at least once before calling this
* function.
*
- * \param [IN] channel Channel parameters
- * \retval status Status of the operation.
+ * \param [IN] channel Channel to transmit on
+ * \retval Time delay Returns a time which shall delay the next TX.
*/
-LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel );
+TimerTime_t SendFrameOnChannel( uint8_t channel );
/*!
* \brief Sets the radio in continuous transmission mode
@@ -987,7 +626,7 @@
*
* \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.
+ * \param [IN] power RF output power to be set.
* \retval status Status of the operation.
*/
LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power );
@@ -997,58 +636,11 @@
*/
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 )
{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ SetBandTxDoneParams_t txDone;
TimerTime_t curTime = TimerGetCurrentTime( );
if( LoRaMacDeviceClass != CLASS_C )
@@ -1072,15 +664,16 @@
}
if( ( LoRaMacDeviceClass == CLASS_C ) || ( NodeAckRequested == true ) )
{
- TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + ACK_TIMEOUT +
- randr( -ACK_TIMEOUT_RND, ACK_TIMEOUT_RND ) );
+ getPhy.Attribute = PHY_ACK_TIMEOUT;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + phyParam.Value );
TimerStart( &AckTimeoutTimer );
}
}
else
{
McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
+ SetEveryMlmeConfirmStatus( MlmeConfirmQueue, LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT );
if( LoRaMacFlags.Value == 0 )
{
@@ -1089,12 +682,25 @@
LoRaMacFlags.Bits.MacDone = 1;
}
+ // Verify if the last uplink was a join request
+ if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
+ {
+ LastTxIsJoinRequest = true;
+ }
+ else
+ {
+ LastTxIsJoinRequest = false;
+ }
+
+ // Store last Tx channel
+ LastTxChannel = Channel;
// Update last tx done time for the current channel
- Bands[Channels[Channel].Band].LastTxDoneTime = curTime;
+ txDone.Channel = Channel;
+ txDone.Joined = IsLoRaMacNetworkJoined;
+ txDone.LastTxDoneTime = curTime;
+ RegionSetBandTxDone( LoRaMacRegion, &txDone );
// Update Aggregated last tx done time
AggregatedLastTxDoneTime = curTime;
- // Update Backoff
- CalculateBackOff( Channel );
if( NodeAckRequested == false )
{
@@ -1124,8 +730,13 @@
{
LoRaMacHeader_t macHdr;
LoRaMacFrameCtrl_t fCtrl;
+ ApplyCFListParams_t applyCFList;
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
bool skipIndication = false;
+ uint8_t index = 0;
+
uint8_t pktHeaderLen = 0;
uint32_t address = 0;
uint8_t appPayloadStartIndex = 0;
@@ -1164,6 +775,21 @@
Radio.Sleep( );
TimerStop( &RxWindowTimer2 );
+ // This function must be called even if we are not in class b mode yet.
+ if( LoRaMacClassBRxBeacon( payload, size ) == true )
+ {
+ return;
+ }
+ // Check if we expect a ping slot.
+ if( LoRaMacDeviceClass == CLASS_B )
+ {
+ if( LoRaMacClassBIsPingExpected( ) == true )
+ {
+ LoRaMacClassBSetPingSlotState( PINGSLOT_STATE_SET_TIMER );
+ LoRaMacClassBPingSlotTimerEvent( );
+ }
+ }
+
macHdr.Value = payload[pktHeaderLen++];
switch( macHdr.Bits.MType )
@@ -1186,72 +812,80 @@
micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16 );
micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24 );
- if( micRx == mic )
+ index = GetMlmeConfirmIndex( MlmeConfirmQueue, MLME_JOIN );
+ if( index < LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
{
- LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
-
- LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
- LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
- LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );
-
- LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
- LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
- LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
- LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
-
- // DLSettings
- LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
- LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
-
- // RxDelay
- LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
- if( LoRaMacParams.ReceiveDelay1 == 0 )
+ if( micRx == mic )
{
- LoRaMacParams.ReceiveDelay1 = 1;
+ LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
+
+ LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
+ LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
+ LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );
+
+ LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
+ LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
+ LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
+ LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
+
+ // DLSettings
+ LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
+ LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
+
+ // RxDelay
+ LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
+ if( LoRaMacParams.ReceiveDelay1 == 0 )
+ {
+ LoRaMacParams.ReceiveDelay1 = 1;
+ }
+ LoRaMacParams.ReceiveDelay1 *= 1000;
+ LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1000;
+
+ // Apply CF list
+ applyCFList.Payload = &LoRaMacRxPayload[13];
+ // Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC
+ applyCFList.Size = size - 17;
+
+ RegionApplyCFList( LoRaMacRegion, &applyCFList );
+
+ MlmeConfirmQueue[index].Status = LORAMAC_EVENT_INFO_STATUS_OK;
+ IsLoRaMacNetworkJoined = true;
+ LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
}
- LoRaMacParams.ReceiveDelay1 *= 1e3;
- LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e3;
-
-#if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
- //CFList
- if( ( size - 1 ) > 16 )
+ else
{
- ChannelParams_t param;
- param.DrRange.Value = ( DR_5 << 4 ) | DR_0;
-
- 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;
- if( param.Frequency != 0 )
- {
- LoRaMacChannelAdd( i, param );
- }
- else
- {
- LoRaMacChannelRemove( i );
- }
- }
- LoRaMacState &= ~LORAMAC_TX_CONFIG;
+ MlmeConfirmQueue[index].Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
}
-#endif
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- IsLoRaMacNetworkJoined = true;
- LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
- }
- else
- {
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
}
break;
case FRAME_TYPE_DATA_CONFIRMED_DOWN:
case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
{
+ // Check if the received payload size is valid
+ getPhy.UplinkDwellTime = LoRaMacParams.DownlinkDwellTime;
+ getPhy.Datarate = McpsIndication.RxDatarate;
+ getPhy.Attribute = PHY_MAX_PAYLOAD;
+
+ // Get the maximum payload length
+ if( LoRaMacParams.RepeaterSupport == true )
+ {
+ getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
+ }
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ if( (uint32_t)MAX( (int16_t)0, ( int16_t )( ( int16_t )size - ( int16_t )LORA_MAC_FRMPAYLOAD_OVERHEAD ) ) > phyParam.Value )
+ {
+ McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ PrepareRxDoneAbort( );
+ return;
+ }
+
address = payload[pktHeaderLen++];
address |= ( (uint32_t)payload[pktHeaderLen++] << 8 );
address |= ( (uint32_t)payload[pktHeaderLen++] << 16 );
address |= ( (uint32_t)payload[pktHeaderLen++] << 24 );
+ fCtrl.Value = payload[pktHeaderLen++];
+
if( address != LoRaMacDevAddr )
{
curMulticastParams = MulticastChannels;
@@ -1274,6 +908,15 @@
PrepareRxDoneAbort( );
return;
}
+ if( ( macHdr.Bits.MType != FRAME_TYPE_DATA_UNCONFIRMED_DOWN ) ||
+ ( fCtrl.Bits.Ack == 1 ) ||
+ ( fCtrl.Bits.AdrAckReq == 1 ) )
+ {
+ // Wrong multicast message format. Refer to chapter 11.2.2 of the specification
+ McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MULTICAST_FAIL;
+ PrepareRxDoneAbort( );
+ return;
+ }
}
else
{
@@ -1283,8 +926,6 @@
downLinkCounter = DownLinkCounter;
}
- fCtrl.Value = payload[pktHeaderLen++];
-
sequenceCounter = ( uint16_t )payload[pktHeaderLen++];
sequenceCounter |= ( uint16_t )payload[pktHeaderLen++] << 8;
@@ -1320,7 +961,9 @@
}
// Check for a the maximum allowed counter difference
- if( sequenceCounterDiff >= MAX_FCNT_GAP )
+ getPhy.Attribute = PHY_MAX_FCNT_GAP;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ if( sequenceCounterDiff >= phyParam.Value )
{
McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
McpsIndication.DownLinkCounter = downLinkCounter;
@@ -1394,7 +1037,7 @@
// 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
+ // to take retransmissions and repetitions into account. Error cases
// will be handled in function OnMacStateCheckTimerEvent.
if( McpsConfirm.McpsRequest == MCPS_CONFIRMED )
{
@@ -1418,8 +1061,7 @@
if( port == 0 )
{
- // Only allow frames which do not have fOpts
- if( fCtrl.Bits.FOptsLen == 0 )
+ if( ( fCtrl.Bits.FOptsLen == 0 ) && ( multicast == 0 ) )
{
LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
frameLen,
@@ -1439,7 +1081,7 @@
}
else
{
- if( fCtrl.Bits.FOptsLen > 0 )
+ if( ( fCtrl.Bits.FOptsLen > 0 ) && ( multicast == 0 ) )
{
// Decode Options field MAC commands. Omit the fPort.
ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr );
@@ -1544,12 +1186,14 @@
}
McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
+ SetEveryMlmeConfirmStatus( MlmeConfirmQueue, LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT );
LoRaMacFlags.Bits.MacDone = 1;
}
static void OnRadioRxError( void )
{
+ bool classBRx = false;
+
if( LoRaMacDeviceClass != CLASS_C )
{
Radio.Sleep( );
@@ -1559,32 +1203,52 @@
OnRxWindow2TimerEvent( );
}
- if( RxSlot == 0 )
+ if( LoRaMacDeviceClass == CLASS_B )
{
- if( NodeAckRequested == true )
+ if( LoRaMacClassBIsBeaconExpected( ) == true )
+ {
+ LoRaMacClassBSetBeaconState( BEACON_STATE_TIMEOUT );
+ LoRaMacClassBBeaconTimerEvent( );
+ classBRx = true;
+ }
+ if( LoRaMacClassBIsPingExpected( ) == true )
{
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
+ LoRaMacClassBSetPingSlotState( PINGSLOT_STATE_SET_TIMER );
+ LoRaMacClassBPingSlotTimerEvent( );
+ classBRx = true;
}
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
-
- if( TimerGetElapsedTime( AggregatedLastTxDoneTime ) >= RxWindow2Delay )
+ }
+
+ if( classBRx == false )
+ {
+ if( RxSlot == 0 )
{
+ if( NodeAckRequested == true )
+ {
+ McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
+ }
+ SetEveryMlmeConfirmStatus( MlmeConfirmQueue, LORAMAC_EVENT_INFO_STATUS_RX1_ERROR );
+ if( TimerGetElapsedTime( AggregatedLastTxDoneTime ) >= RxWindow2Delay )
+ {
+ LoRaMacFlags.Bits.MacDone = 1;
+ }
+ }
+ else
+ {
+ if( NodeAckRequested == true )
+ {
+ McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
+ }
+ SetEveryMlmeConfirmStatus( MlmeConfirmQueue, LORAMAC_EVENT_INFO_STATUS_RX2_ERROR );
LoRaMacFlags.Bits.MacDone = 1;
}
}
- else
- {
- if( NodeAckRequested == true )
- {
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
- }
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
- LoRaMacFlags.Bits.MacDone = 1;
- }
}
static void OnRadioRxTimeout( void )
{
+ bool classBRx = false;
+
if( LoRaMacDeviceClass != CLASS_C )
{
Radio.Sleep( );
@@ -1594,21 +1258,64 @@
OnRxWindow2TimerEvent( );
}
- if( RxSlot == 1 )
+ if( LoRaMacDeviceClass == CLASS_B )
{
- if( NodeAckRequested == true )
+ if( LoRaMacClassBIsBeaconExpected( ) == true )
+ {
+ LoRaMacClassBSetBeaconState( BEACON_STATE_TIMEOUT );
+ LoRaMacClassBBeaconTimerEvent( );
+ classBRx = true;
+ }
+
+ if( LoRaMacClassBIsPingExpected( ) == true )
+ {
+ LoRaMacClassBSetPingSlotState( PINGSLOT_STATE_SET_TIMER );
+ LoRaMacClassBPingSlotTimerEvent( );
+ classBRx = true;
+ }
+ }
+
+ if( classBRx == false )
+ {
+ if( RxSlot == 0 )
{
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
+ if( NodeAckRequested == true )
+ {
+ McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT;
+ }
+ SetEveryMlmeConfirmStatus( MlmeConfirmQueue, LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT );
+
+ if( TimerGetElapsedTime( AggregatedLastTxDoneTime ) >= RxWindow2Delay )
+ {
+ LoRaMacFlags.Bits.MacDone = 1;
+ }
}
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
- LoRaMacFlags.Bits.MacDone = 1;
+ else
+ {
+ if( NodeAckRequested == true )
+ {
+ McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
+ }
+ SetEveryMlmeConfirmStatus( MlmeConfirmQueue, LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT );
+
+ if( LoRaMacDeviceClass != CLASS_C )
+ {
+ LoRaMacFlags.Bits.MacDone = 1;
+ }
+ }
}
}
static void OnMacStateCheckTimerEvent( void )
{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ uint8_t index = 0;
+ bool noTx = false;
+ uint8_t i, j = 0;
+
+
TimerStop( &MacStateCheckTimer );
- bool txTimeout = false;
if( LoRaMacFlags.Bits.MacDone == 1 )
{
@@ -1620,6 +1327,9 @@
if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
{
+ // Get a status of any request and check if we have a TX timeout
+ MlmeConfirm.Status = MlmeConfirmQueue[0].Status;
+
if( ( McpsConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) ||
( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) )
{
@@ -1629,19 +1339,30 @@
McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
McpsConfirm.AckReceived = false;
McpsConfirm.TxTimeOnAir = 0;
- txTimeout = true;
+ noTx = true;
+ }
+
+ index = GetMlmeConfirmIndex( MlmeConfirmQueue, MLME_BEACON_ACQUISITION );
+ if( ( index < LORA_MAC_MLME_CONFIRM_QUEUE_LEN ) && ( LoRaMacFlags.Bits.McpsReq == 0 ) )
+ {
+ if( LoRaMacFlags.Bits.MlmeReq == 1 )
+ {
+ noTx = true;
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
+ }
}
}
- if( ( NodeAckRequested == false ) && ( txTimeout == false ) )
+ if( ( NodeAckRequested == false ) && ( noTx == false ) )
{
if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
{
- if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
+ index = GetMlmeConfirmIndex( MlmeConfirmQueue, MLME_JOIN );
+ if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( index < LORA_MAC_MLME_CONFIRM_QUEUE_LEN ) )
{// Procedure for the join request
MlmeConfirm.NbRetries = JoinRequestTrials;
- if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
+ if( MlmeConfirmQueue[index].Status == LORAMAC_EVENT_INFO_STATUS_OK )
{// Node joined successfully
UpLinkCounter = 0;
ChannelsNbRepCounter = 0;
@@ -1666,7 +1387,7 @@
if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
{
if( LoRaMacFlags.Bits.McpsInd == 0 )
- { // Maximum repititions without downlink. Reset MacCommandsBufferIndex. Increase ADR Ack counter.
+ { // Maximum repetitions without downlink. Reset MacCommandsBufferIndex. Increase ADR Ack counter.
// Only process the case when the MAC did not receive a downlink.
MacCommandsBufferIndex = 0;
AdrAckCounter++;
@@ -1716,7 +1437,11 @@
if( ( AckTimeoutRetriesCounter % 2 ) == 1 )
{
- LoRaMacParams.ChannelsDatarate = MAX( LoRaMacParams.ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
+ getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
+ getPhy.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ getPhy.Datarate = LoRaMacParams.ChannelsDatarate;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParams.ChannelsDatarate = phyParam.Value;
}
// Try to send the frame again
if( ScheduleTx( ) == LORAMAC_STATUS_OK )
@@ -1742,21 +1467,8 @@
}
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
- memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
-#elif defined( USE_BAND_915_HYBRID )
- // Re-enable default channels
- ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
-#else
- #error "Please define a frequency band in the compiler options."
-#endif
+ RegionInitDefaults( LoRaMacRegion, INIT_TYPE_RESTORE );
+
LoRaMacState &= ~LORAMAC_TX_RUNNING;
MacCommandsBufferIndex = 0;
@@ -1785,12 +1497,44 @@
if( LoRaMacFlags.Bits.MlmeReq == 1 )
{
- LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm );
- LoRaMacFlags.Bits.MlmeReq = 0;
+ j = MlmeConfirmQueueCnt;
+ for( i = 0; i < MlmeConfirmQueueCnt; i++ )
+ {
+ if( MlmeConfirmQueue[i].MlmeRequest == MLME_BEACON_ACQUISITION )
+ {
+ if( LoRaMacClassBIsAcquisitionPending( ) == true )
+ {
+ MlmeConfirmQueue[0].MlmeRequest = MLME_BEACON_ACQUISITION;
+ MlmeConfirmQueue[0].Status = MlmeConfirmQueue[i].Status;
+ continue;
+ }
+ }
+ j--;
+ MlmeConfirm.Status = MlmeConfirmQueue[i].Status;
+ MlmeConfirm.MlmeRequest = MlmeConfirmQueue[i].MlmeRequest;
+ LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm );
+ }
+ MlmeConfirmQueueCnt = j;
+
+ if( MlmeConfirmQueueCnt == 0 )
+ {
+ LoRaMacFlags.Bits.MlmeReq = 0;
+ }
+ }
+
+ if( LoRaMacFlags.Bits.MlmeInd == 1 )
+ {
+ LoRaMacPrimitives->MacMlmeIndication( &MlmeIndication );
+ LoRaMacFlags.Bits.MlmeInd = 0;
}
// Procedure done. Reset variables.
LoRaMacFlags.Bits.MacDone = 0;
+
+ if( LoRaMacDeviceClass == CLASS_B )
+ {
+ LoRaMacClassBResumeBeaconing( );
+ }
}
else
{
@@ -1818,15 +1562,20 @@
{
LoRaMacHeader_t macHdr;
LoRaMacFrameCtrl_t fCtrl;
+ AlternateDrParams_t altDr;
+ uint8_t index = 0;
TimerStop( &TxDelayedTimer );
LoRaMacState &= ~LORAMAC_TX_DELAYED;
- if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
+ index = GetMlmeConfirmIndex( MlmeConfirmQueue, MLME_JOIN );
+
+ if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( index < LORA_MAC_MLME_CONFIRM_QUEUE_LEN ) )
{
ResetMacParameters( );
- // Add a +1, since we start to count from 0
- LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials + 1 );
+
+ altDr.NbTrials = JoinRequestTrials + 1;
+ LoRaMacParams.ChannelsDatarate = RegionAlternateDr( LoRaMacRegion, &altDr );
macHdr.Value = 0;
macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
@@ -1848,35 +1597,45 @@
TimerStop( &RxWindowTimer1 );
RxSlot = 0;
+ RxWindow1Config.Channel = Channel;
+ RxWindow1Config.DrOffset = LoRaMacParams.Rx1DrOffset;
+ RxWindow1Config.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
+ RxWindow1Config.RepeaterSupport = LoRaMacParams.RepeaterSupport;
+ RxWindow1Config.RxContinuous = false;
+ RxWindow1Config.Window = RxSlot;
+
if( LoRaMacDeviceClass == CLASS_C )
{
Radio.Standby( );
}
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- 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 ) )
- 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
+ RegionRxConfig( LoRaMacRegion, &RxWindow1Config, ( int8_t* )&McpsIndication.RxDatarate );
+ RxWindowSetup( RxWindow1Config.RxContinuous, LoRaMacParams.MaxRxWindow );
}
static void OnRxWindow2TimerEvent( void )
{
- bool rxContinuousMode = false;
-
TimerStop( &RxWindowTimer2 );
- if( LoRaMacDeviceClass == CLASS_C )
+ RxWindow2Config.Channel = Channel;
+ RxWindow2Config.Frequency = LoRaMacParams.Rx2Channel.Frequency;
+ RxWindow2Config.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
+ RxWindow2Config.RepeaterSupport = LoRaMacParams.RepeaterSupport;
+ RxWindow2Config.Window = 1;
+
+ if( LoRaMacDeviceClass != CLASS_C )
{
- rxContinuousMode = true;
+ RxWindow2Config.RxContinuous = false;
+ }
+ else
+ {
+ RxWindow2Config.RxContinuous = true;
}
- if( RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, RxWindowsParams[1].Datarate, RxWindowsParams[1].Bandwidth, RxWindowsParams[1].RxWindowTimeout, rxContinuousMode ) == true )
+
+ if( RegionRxConfig( LoRaMacRegion, &RxWindow2Config, ( int8_t* )&McpsIndication.RxDatarate ) == true )
{
- RxSlot = 1;
+ RxWindowSetup( RxWindow2Config.RxContinuous, LoRaMacParams.MaxRxWindow );
+ RxSlot = RxWindow2Config.Window;
}
}
@@ -1895,221 +1654,93 @@
}
}
-static bool SetNextChannel( TimerTime_t* time )
+static void RxWindowSetup( bool rxContinuous, uint32_t maxRxWindow )
{
- uint8_t nbEnabledChannels = 0;
- uint8_t delayTx = 0;
- uint8_t enabledChannels[LORA_MAX_NB_CHANNELS];
- TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
-
- memset1( enabledChannels, 0, LORA_MAX_NB_CHANNELS );
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 )
- { // Restore default channels
- memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParams.ChannelsMask, 8 );
- }
- if( ( LoRaMacParams.ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) )
- { // 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 )
- {
- // Re-enable default channels, if no channel is enabled
- LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
- }
-#endif
-
- // Update Aggregated duty cycle
- if( AggregatedTimeOff <= TimerGetElapsedTime( AggregatedLastTxDoneTime ) )
+ if( rxContinuous == false )
{
- AggregatedTimeOff = 0;
-
- // Update bands Time OFF
- for( uint8_t i = 0; i < LORA_MAX_NB_BANDS; i++ )
- {
- if( ( IsLoRaMacNetworkJoined == false ) || ( DutyCycleOn == true ) )
- {
- if( Bands[i].TimeOff <= TimerGetElapsedTime( Bands[i].LastTxDoneTime ) )
- {
- Bands[i].TimeOff = 0;
- }
- if( Bands[i].TimeOff != 0 )
- {
- nextTxDelay = MIN( Bands[i].TimeOff - TimerGetElapsedTime( Bands[i].LastTxDoneTime ), nextTxDelay );
- }
- }
- else
- {
- if( DutyCycleOn == false )
- {
- Bands[i].TimeOff = 0;
- }
- }
- }
-
- // Search how many channels are enabled
- for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
- {
- for( uint8_t j = 0; j < 16; j++ )
- {
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- if( ( ChannelsMaskRemaining[k] & ( 1 << j ) ) != 0 )
-#else
- if( ( LoRaMacParams.ChannelsMask[k] & ( 1 << j ) ) != 0 )
-#endif
- {
- if( Channels[i + j].Frequency == 0 )
- { // Check if the channel is enabled
- continue;
- }
-#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
- if( IsLoRaMacNetworkJoined == false )
- {
- if( ( JOIN_CHANNELS & ( 1 << j ) ) == 0 )
- {
- continue;
- }
- }
-#endif
- if( ( ( Channels[i + j].DrRange.Fields.Min <= LoRaMacParams.ChannelsDatarate ) &&
- ( LoRaMacParams.ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false )
- { // Check if the current channel selection supports the given datarate
- continue;
- }
- if( Bands[Channels[i + j].Band].TimeOff > 0 )
- { // Check if the band is available for transmission
- delayTx++;
- continue;
- }
- enabledChannels[nbEnabledChannels++] = i + j;
- }
- }
- }
+ Radio.Rx( maxRxWindow );
}
else
{
- delayTx++;
- nextTxDelay = AggregatedTimeOff - TimerGetElapsedTime( AggregatedLastTxDoneTime );
- }
-
- if( nbEnabledChannels > 0 )
- {
- Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- if( Channel < ( LORA_MAX_NB_CHANNELS - 8 ) )
- {
- DisableChannelInMask( Channel, ChannelsMaskRemaining );
- }
-#endif
- *time = 0;
- return true;
- }
- else
- {
- if( delayTx > 0 )
- {
- // Delay transmission due to AggregatedTimeOff or to a band time off
- *time = nextTxDelay;
- return true;
- }
- // Datarate not supported by any channel
- *time = 0;
- return false;
+ Radio.Rx( 0 ); // Continuous mode
}
}
-static bool RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
+static LoRaMacStatus_t SwitchClass( DeviceClass_t deviceClass )
{
- uint8_t downlinkDatarate = Datarates[datarate];
- RadioModems_t modem;
-
- if( Radio.GetStatus( ) == RF_IDLE )
+ LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
+
+ switch( LoRaMacDeviceClass )
{
- Radio.SetChannel( freq );
-
- // Store downlink datarate
- McpsIndication.RxDatarate = ( uint8_t ) datarate;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- if( datarate == DR_7 )
+ case CLASS_A:
{
- modem = MODEM_FSK;
- 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_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
-
- if( RepeaterSupport == true )
- {
- Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRepeater[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
+ if( deviceClass == CLASS_B )
+ {
+ status = LoRaMacClassBSwitchClass( deviceClass );
+ if( status == LORAMAC_STATUS_OK )
+ {
+ LoRaMacDeviceClass = deviceClass;
+ }
+ }
+
+ if( deviceClass == CLASS_C )
+ {
+ LoRaMacDeviceClass = deviceClass;
+
+ // Set the NodeAckRequested indicator to default
+ NodeAckRequested = false;
+ OnRxWindow2TimerEvent( );
+
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
}
- else
+ case CLASS_B:
{
- Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
+ status = LoRaMacClassBSwitchClass( deviceClass );
+ if( status == LORAMAC_STATUS_OK )
+ {
+ LoRaMacDeviceClass = deviceClass;
+ }
+ break;
}
-
- if( rxContinuous == false )
+ case CLASS_C:
{
- Radio.Rx( LoRaMacParams.MaxRxWindow );
+ if( deviceClass == CLASS_A )
+ {
+ LoRaMacDeviceClass = deviceClass;
+
+ // Set the radio into sleep to setup a defined state
+ Radio.Sleep( );
+
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
}
- else
- {
- 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_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- if( ( Radio.CheckRfFrequency( freq ) == true ) &&
- ( 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;
- }
- return false;
+
+ return status;
}
static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
uint16_t maxN = 0;
uint16_t payloadSize = 0;
+ // Setup PHY request
+ getPhy.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ getPhy.Datarate = datarate;
+ getPhy.Attribute = PHY_MAX_PAYLOAD;
+
// Get the maximum payload length
- if( RepeaterSupport == true )
+ if( LoRaMacParams.RepeaterSupport == true )
{
- maxN = MaxPayloadOfDatarateRepeater[datarate];
+ getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
}
- else
- {
- maxN = MaxPayloadOfDatarate[datarate];
- }
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ maxN = phyParam.Value;
// Calculate the resulting payload size
payloadSize = ( lenN + fOptsLen );
@@ -2122,258 +1753,6 @@
return false;
}
-static uint8_t CountBits( uint16_t mask, uint8_t nbBits )
-{
- uint8_t nbActiveBits = 0;
-
- for( uint8_t j = 0; j < nbBits; j++ )
- {
- if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
- {
- nbActiveBits++;
- }
- }
- return nbActiveBits;
-}
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask )
-{
- uint8_t nb125kHzChannels = 0;
-
- for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
- {
- nb125kHzChannels += CountBits( channelsMask[k], 16 );
- }
-
- return nb125kHzChannels;
-}
-
-#if defined( USE_BAND_915_HYBRID )
-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 )
- {
- channelsMask[i] = 0;
- if( ( blockMask & ( 1 << j ) ) != 0 )
- {
- channelsMask[i] |= 0x00FF;
- }
- if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
- {
- channelsMask[i] |= 0xFF00;
- }
- }
- channelsMask[4] = blockMask;
- channelsMask[5] = 0x0000;
-}
-
-static bool ValidateChannelMask( uint16_t* channelsMask )
-{
- bool chanMaskState = false;
- uint16_t block1 = 0;
- uint16_t block2 = 0;
- uint8_t index = 0;
-
- for( uint8_t i = 0; i < 4; i++ )
- {
- block1 = channelsMask[i] & 0x00FF;
- block2 = channelsMask[i] & 0xFF00;
-
- if( ( CountBits( block1, 16 ) > 5 ) && ( chanMaskState == false ) )
- {
- channelsMask[i] &= block1;
- channelsMask[4] = 1 << ( i * 2 );
- chanMaskState = true;
- index = i;
- }
- else if( ( CountBits( block2, 16 ) > 5 ) && ( chanMaskState == false ) )
- {
- channelsMask[i] &= block2;
- channelsMask[4] = 1 << ( i * 2 + 1 );
- chanMaskState = true;
- index = i;
- }
- }
-
- // Do only change the channel mask, if we have found a valid block.
- if( chanMaskState == true )
- {
- for( uint8_t i = 0; i < 4; i++ )
- {
- if( i != index )
- {
- channelsMask[i] = 0;
- }
- }
- }
- return chanMaskState;
-}
-#endif
-#endif
-
-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 ) ) )
- {// Limit tx power to max 26dBm
- resultTxPower = MAX( txPower, TX_POWER_26_DBM );
- }
- else
- {
- if( CountNbEnabled125kHzChannels( LoRaMacParams.ChannelsMask ) < 50 )
- {// Limit tx power to max 21dBm
- resultTxPower = MAX( txPower, TX_POWER_20_DBM );
- }
- }
-#endif
- return resultTxPower;
-}
-
-static bool ValueInRange( int8_t value, int8_t min, int8_t max )
-{
- if( ( value >= min ) && ( value <= max ) )
- {
- return true;
- }
- return false;
-}
-
-static bool DisableChannelInMask( uint8_t id, uint16_t* mask )
-{
- uint8_t index = 0;
- index = id / 16;
-
- if( ( index > 4 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
- {
- return false;
- }
-
- // Deactivate channel
- mask[index] &= ~( 1 << ( id % 16 ) );
-
- return true;
-}
-
-static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut )
-{
- bool adrAckReq = false;
- int8_t datarate = LoRaMacParams.ChannelsDatarate;
-
- if( adrEnabled == true )
- {
- if( datarate == LORAMAC_TX_MIN_DATARATE )
- {
- AdrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( AdrAckCounter >= ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- LoRaMacParams.ChannelsTxPower = LORAMAC_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) )
- {
- 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 )
- {
- datarate--;
- }
- if( datarate == LORAMAC_TX_MIN_DATARATE )
- {
- if( updateChannelMask == true )
- {
- // Re-enable default channels LC1, LC2, LC3
- 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 ) )
- {
- datarate = DR_4;
- }
- else if( datarate > LORAMAC_TX_MIN_DATARATE )
- {
- datarate--;
- }
- if( datarate == LORAMAC_TX_MIN_DATARATE )
- {
- if( updateChannelMask == true )
- {
-#if defined( USE_BAND_915 )
- // Re-enable default channels
- memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
-#else // defined( USE_BAND_915_HYBRID )
- // Re-enable default channels
- ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
-#endif
- }
- }
-#else
-#error "Please define a frequency band in the compiler options."
-#endif
- }
- }
- }
- }
-
- *datarateOut = datarate;
-
- return adrAckReq;
-}
-
static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
{
LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
@@ -2444,6 +1823,57 @@
status = LORAMAC_STATUS_OK;
}
break;
+ case MOTE_MAC_TX_PARAM_SETUP_ANS:
+ if( MacCommandsBufferIndex < bufLen )
+ {
+ MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+ // No payload for this answer
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
+ case MOTE_MAC_DL_CHANNEL_ANS:
+ if( MacCommandsBufferIndex < bufLen )
+ {
+ MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+ // Status: Uplink frequency exists, Channel frequency OK
+ MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
+ case MOTE_MAC_PING_SLOT_INFO_REQ:
+ if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
+ {
+ MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+ // Status: Periodicity and Datarate
+ MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
+ case MOTE_MAC_PING_SLOT_FREQ_ANS:
+ if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ {
+ MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+ // Status: Datarate range OK, Channel frequency OK
+ MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
+ case MOTE_MAC_BEACON_TIMING_REQ:
+ if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ {
+ MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+ // No payload for this answer
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
+ case MOTE_MAC_BEACON_FREQ_ANS:
+ if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ {
+ MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+ // No payload for this answer
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
default:
return LORAMAC_STATUS_SERVICE_UNKNOWN;
}
@@ -2469,14 +1899,15 @@
switch( cmdBufIn[i] )
{
// STICKY
+ case MOTE_MAC_DL_CHANNEL_ANS:
case MOTE_MAC_RX_PARAM_SETUP_ANS:
- {
+ { // 1 byte payload
cmdBufOut[cmdCount++] = cmdBufIn[i++];
cmdBufOut[cmdCount++] = cmdBufIn[i];
break;
}
case MOTE_MAC_RX_TIMING_SETUP_ANS:
- {
+ { // 0 byte payload
cmdBufOut[cmdCount++] = cmdBufIn[i];
break;
}
@@ -2492,6 +1923,7 @@
i++;
break;
}
+ case MOTE_MAC_TX_PARAM_SETUP_ANS:
case MOTE_MAC_DUTY_CYCLE_ANS:
case MOTE_MAC_LINK_CHECK_REQ:
{ // 0 byte payload
@@ -2507,198 +1939,58 @@
static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr )
{
+ uint8_t status = 0;
+ uint8_t index = 0;
+
while( macIndex < commandsSize )
{
// Decode Frame MAC commands
switch( payload[macIndex++] )
{
case SRV_MAC_LINK_CHECK_ANS:
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- MlmeConfirm.DemodMargin = payload[macIndex++];
- MlmeConfirm.NbGateways = payload[macIndex++];
+ index = GetMlmeConfirmIndex( MlmeConfirmQueue, MLME_LINK_CHECK );
+ if( index < LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
+ {
+ MlmeConfirmQueue[index].Status = LORAMAC_EVENT_INFO_STATUS_OK;
+ MlmeConfirm.DemodMargin = payload[macIndex++];
+ MlmeConfirm.NbGateways = payload[macIndex++];
+ }
break;
case SRV_MAC_LINK_ADR_REQ:
{
- uint8_t i;
- uint8_t status = 0x07;
- uint16_t chMask;
- int8_t txPower = 0;
- int8_t datarate = 0;
- uint8_t nbRep = 0;
- uint8_t chMaskCntl = 0;
- uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
-
- // Initialize local copy of the channels mask array
- for( i = 0; i < 6; i++ )
- {
- channelsMask[i] = LoRaMacParams.ChannelsMask[i];
- }
- datarate = payload[macIndex++];
- txPower = datarate & 0x0F;
- datarate = ( datarate >> 4 ) & 0x0F;
-
- if( ( AdrCtrlOn == false ) &&
- ( ( LoRaMacParams.ChannelsDatarate != datarate ) || ( LoRaMacParams.ChannelsTxPower != txPower ) ) )
- { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower
- // Answer the server with fail status
- // Power ACK = 0
- // Data rate ACK = 0
- // Channel mask = 0
- AddMacCommand( MOTE_MAC_LINK_ADR_ANS, 0, 0 );
- macIndex += 3; // Skip over the remaining bytes of the request
- break;
- }
- chMask = ( uint16_t )payload[macIndex++];
- chMask |= ( uint16_t )payload[macIndex++] << 8;
-
- nbRep = payload[macIndex++];
- chMaskCntl = ( nbRep >> 4 ) & 0x07;
- nbRep &= 0x0F;
- if( nbRep == 0 )
- {
- nbRep = 1;
- }
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- if( ( chMaskCntl == 0 ) && ( chMask == 0 ) )
- {
- status &= 0xFE; // Channel mask KO
- }
- else if( ( ( chMaskCntl >= 1 ) && ( chMaskCntl <= 5 )) ||
- ( chMaskCntl >= 7 ) )
- {
- // RFU
- status &= 0xFE; // Channel mask KO
- }
- else
- {
- for( i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
- {
- if( chMaskCntl == 6 )
- {
- if( Channels[i].Frequency != 0 )
- {
- chMask |= 1 << i;
- }
- }
- else
- {
- if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[i].Frequency == 0 ) )
- {// Trying to enable an undefined channel
- status &= 0xFE; // Channel mask KO
- }
- }
- }
- channelsMask[0] = chMask;
- }
-#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; i += 16, k++ )
- {
- for( uint8_t j = 0; j < 16; j++ )
- {
- if( Channels[i + j].Frequency != 0 )
- {
- channelsMask[k] |= 1 << j;
- }
- }
- }
- }
- else if( chMaskCntl == 7 )
- {
- status &= 0xFE; // Channel mask KO
- }
- else
- {
- for( uint8_t i = 0; i < 16; i++ )
- {
- if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[chMaskCntl * 16 + i].Frequency == 0 ) )
- {// Trying to enable an undefined channel
- status &= 0xFE; // Channel mask KO
- }
- }
- channelsMask[chMaskCntl] = chMask;
- }
-#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
- }
-
-#if defined( USE_BAND_915_HYBRID )
- if( ValidateChannelMask( channelsMask ) == false )
- {
- status &= 0xFE; // Channel mask KO
- }
-#endif
- }
-#else
- #error "Please define a frequency band in the compiler options."
-#endif
- if( ValidateDatarate( datarate, channelsMask ) == false )
- {
- status &= 0xFD; // Datarate KO
- }
-
- //
- // Remark MaxTxPower = 0 and MinTxPower = 5
- //
- if( ValueInRange( txPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) == false )
- {
- status &= 0xFB; // TxPower KO
- }
+ LinkAdrReqParams_t linkAdrReq;
+ int8_t linkAdrDatarate = DR_0;
+ int8_t linkAdrTxPower = TX_POWER_0;
+ uint8_t linkAdrNbRep = 0;
+ uint8_t linkAdrNbBytesParsed = 0;
+
+ // Fill parameter structure
+ linkAdrReq.Payload = &payload[macIndex - 1];
+ linkAdrReq.PayloadSize = commandsSize - ( macIndex - 1 );
+ linkAdrReq.AdrEnabled = AdrCtrlOn;
+ linkAdrReq.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ linkAdrReq.CurrentDatarate = LoRaMacParams.ChannelsDatarate;
+ linkAdrReq.CurrentTxPower = LoRaMacParams.ChannelsTxPower;
+ linkAdrReq.CurrentNbRep = LoRaMacParams.ChannelsNbRep;
+
+ // Process the ADR requests
+ status = RegionLinkAdrReq( LoRaMacRegion, &linkAdrReq, &linkAdrDatarate,
+ &linkAdrTxPower, &linkAdrNbRep, &linkAdrNbBytesParsed );
+
if( ( status & 0x07 ) == 0x07 )
{
- LoRaMacParams.ChannelsDatarate = datarate;
- LoRaMacParams.ChannelsTxPower = txPower;
-
- 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
+ LoRaMacParams.ChannelsDatarate = linkAdrDatarate;
+ LoRaMacParams.ChannelsTxPower = linkAdrTxPower;
+ LoRaMacParams.ChannelsNbRep = linkAdrNbRep;
}
- AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
+
+ // Add the answers to the buffer
+ for( uint8_t i = 0; i < ( linkAdrNbBytesParsed / 5 ); i++ )
+ {
+ AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
+ }
+ // Update MAC index
+ macIndex += linkAdrNbBytesParsed - 1;
}
break;
case SRV_MAC_DUTY_CYCLE_REQ:
@@ -2708,46 +2000,26 @@
break;
case SRV_MAC_RX_PARAM_SETUP_REQ:
{
- uint8_t status = 0x07;
- int8_t datarate = 0;
- int8_t drOffset = 0;
- uint32_t freq = 0;
-
- drOffset = ( payload[macIndex] >> 4 ) & 0x07;
- datarate = payload[macIndex] & 0x0F;
+ RxParamSetupReqParams_t rxParamSetupReq;
+ status = 0x07;
+
+ rxParamSetupReq.DrOffset = ( payload[macIndex] >> 4 ) & 0x07;
+ rxParamSetupReq.Datarate = payload[macIndex] & 0x0F;
macIndex++;
- freq = ( uint32_t )payload[macIndex++];
- freq |= ( uint32_t )payload[macIndex++] << 8;
- freq |= ( uint32_t )payload[macIndex++] << 16;
- freq *= 100;
-
- if( Rx2FreqInRange( freq ) == false )
- {
- status &= 0xFE; // Channel frequency KO
- }
-
- if( ValueInRange( datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE ) == false )
- {
- status &= 0xFD; // Datarate KO
- }
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
- if( ( ValueInRange( datarate, DR_5, DR_7 ) == true ) ||
- ( datarate > DR_13 ) )
- {
- status &= 0xFD; // Datarate KO
- }
-#endif
- if( ValueInRange( drOffset, LORAMAC_MIN_RX1_DR_OFFSET, LORAMAC_MAX_RX1_DR_OFFSET ) == false )
- {
- status &= 0xFB; // Rx1DrOffset range KO
- }
+ rxParamSetupReq.Frequency = ( uint32_t )payload[macIndex++];
+ rxParamSetupReq.Frequency |= ( uint32_t )payload[macIndex++] << 8;
+ rxParamSetupReq.Frequency |= ( uint32_t )payload[macIndex++] << 16;
+ rxParamSetupReq.Frequency *= 100;
+
+ // Perform request on region
+ status = RegionRxParamSetupReq( LoRaMacRegion, &rxParamSetupReq );
if( ( status & 0x07 ) == 0x07 )
{
- LoRaMacParams.Rx2Channel.Datarate = datarate;
- LoRaMacParams.Rx2Channel.Frequency = freq;
- LoRaMacParams.Rx1DrOffset = drOffset;
+ LoRaMacParams.Rx2Channel.Datarate = rxParamSetupReq.Datarate;
+ LoRaMacParams.Rx2Channel.Frequency = rxParamSetupReq.Frequency;
+ LoRaMacParams.Rx1DrOffset = rxParamSetupReq.DrOffset;
}
AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
}
@@ -2764,69 +2036,22 @@
}
case SRV_MAC_NEW_CHANNEL_REQ:
{
- uint8_t status = 0x03;
-
-#if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- status &= 0xFC; // Channel frequency and datarate KO
- macIndex += 5;
-#else
- int8_t channelIndex = 0;
+ NewChannelReqParams_t newChannelReq;
ChannelParams_t chParam;
-
- channelIndex = payload[macIndex++];
+ status = 0x03;
+
+ newChannelReq.ChannelId = payload[macIndex++];
+ newChannelReq.NewChannel = &chParam;
+
chParam.Frequency = ( uint32_t )payload[macIndex++];
chParam.Frequency |= ( uint32_t )payload[macIndex++] << 8;
chParam.Frequency |= ( uint32_t )payload[macIndex++] << 16;
chParam.Frequency *= 100;
+ chParam.Rx1Frequency = 0;
chParam.DrRange.Value = payload[macIndex++];
- LoRaMacState |= LORAMAC_TX_CONFIG;
- if( chParam.Frequency == 0 )
- {
- if( channelIndex < 3 )
- {
- status &= 0xFC;
- }
- else
- {
- if( LoRaMacChannelRemove( channelIndex ) != LORAMAC_STATUS_OK )
- {
- status &= 0xFC;
- }
- }
- }
- else
- {
- switch( LoRaMacChannelAdd( channelIndex, chParam ) )
- {
- case LORAMAC_STATUS_OK:
- {
- break;
- }
- case LORAMAC_STATUS_FREQUENCY_INVALID:
- {
- status &= 0xFE;
- break;
- }
- case LORAMAC_STATUS_DATARATE_INVALID:
- {
- status &= 0xFD;
- break;
- }
- case LORAMAC_STATUS_FREQ_AND_DR_INVALID:
- {
- status &= 0xFC;
- break;
- }
- default:
- {
- status &= 0xFC;
- break;
- }
- }
- }
- LoRaMacState &= ~LORAMAC_TX_CONFIG;
-#endif
+ status = RegionNewChannelReq( LoRaMacRegion, &newChannelReq );
+
AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
}
break;
@@ -2838,11 +2063,109 @@
{
delay++;
}
- LoRaMacParams.ReceiveDelay1 = delay * 1e3;
- LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e3;
+ LoRaMacParams.ReceiveDelay1 = delay * 1000;
+ LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1000;
AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
}
break;
+ case SRV_MAC_TX_PARAM_SETUP_REQ:
+ {
+ TxParamSetupReqParams_t txParamSetupReq;
+ uint8_t eirpDwellTime = payload[macIndex++];
+
+ txParamSetupReq.UplinkDwellTime = 0;
+ txParamSetupReq.DownlinkDwellTime = 0;
+
+ if( ( eirpDwellTime & 0x20 ) == 0x20 )
+ {
+ txParamSetupReq.DownlinkDwellTime = 1;
+ }
+ if( ( eirpDwellTime & 0x10 ) == 0x10 )
+ {
+ txParamSetupReq.UplinkDwellTime = 1;
+ }
+ txParamSetupReq.MaxEirp = eirpDwellTime & 0x0F;
+
+ // Check the status for correctness
+ if( RegionTxParamSetupReq( LoRaMacRegion, &txParamSetupReq ) != -1 )
+ {
+ // Accept command
+ LoRaMacParams.UplinkDwellTime = txParamSetupReq.UplinkDwellTime;
+ LoRaMacParams.DownlinkDwellTime = txParamSetupReq.DownlinkDwellTime;
+ LoRaMacParams.MaxEirp = LoRaMacMaxEirpTable[txParamSetupReq.MaxEirp];
+ // Add command response
+ AddMacCommand( MOTE_MAC_TX_PARAM_SETUP_ANS, 0, 0 );
+ }
+ }
+ break;
+ case SRV_MAC_DL_CHANNEL_REQ:
+ {
+ DlChannelReqParams_t dlChannelReq;
+ status = 0x03;
+
+ dlChannelReq.ChannelId = payload[macIndex++];
+ dlChannelReq.Rx1Frequency = ( uint32_t )payload[macIndex++];
+ dlChannelReq.Rx1Frequency |= ( uint32_t )payload[macIndex++] << 8;
+ dlChannelReq.Rx1Frequency |= ( uint32_t )payload[macIndex++] << 16;
+ dlChannelReq.Rx1Frequency *= 100;
+
+ status = RegionDlChannelReq( LoRaMacRegion, &dlChannelReq );
+
+ AddMacCommand( MOTE_MAC_DL_CHANNEL_ANS, status, 0 );
+ }
+ break;
+ case SRV_MAC_PING_SLOT_INFO_ANS:
+ {
+ LoRaMacClassBPingSlotInfoAns( );
+ }
+ break;
+ case SRV_MAC_PING_SLOT_CHANNEL_REQ:
+ {
+ uint8_t status = 0x03;
+ uint32_t frequency = 0;
+ uint8_t datarate;
+
+ frequency = ( uint32_t )payload[macIndex++];
+ frequency |= ( uint32_t )payload[macIndex++] << 8;
+ frequency |= ( uint32_t )payload[macIndex++] << 16;
+ frequency *= 100;
+ datarate = payload[macIndex++] & 0x0F;
+
+ status = LoRaMacClassBPingSlotChannelReq( datarate, frequency );
+ AddMacCommand( MOTE_MAC_PING_SLOT_FREQ_ANS, status, 0 );
+ }
+ break;
+ case SRV_MAC_BEACON_TIMING_ANS:
+ {
+ uint16_t beaconTimingDelay = 0;
+ uint8_t beaconTimingChannel = 0;
+
+ beaconTimingDelay = ( uint16_t )payload[macIndex++];
+ beaconTimingDelay |= ( uint16_t )payload[macIndex++] << 8;
+ beaconTimingChannel = payload[macIndex++];
+
+ LoRaMacClassBBeaconTimingAns( beaconTimingDelay, beaconTimingChannel );
+ }
+ break;
+ case SRV_MAC_BEACON_FREQ_REQ:
+ {
+ uint32_t frequency = 0;
+
+ frequency = ( uint32_t )payload[macIndex++];
+ frequency |= ( uint32_t )payload[macIndex++] << 8;
+ frequency |= ( uint32_t )payload[macIndex++] << 16;
+ frequency *= 100;
+
+ if( LoRaMacClassBBeaconFreqReq( frequency ) == true )
+ {
+ AddMacCommand( MOTE_MAC_BEACON_FREQ_ANS, 1, 0 );
+ }
+ else
+ {
+ AddMacCommand( MOTE_MAC_BEACON_FREQ_ANS, 0, 0 );
+ }
+ }
+ break;
default:
// Unknown command. ABORT MAC commands processing
return;
@@ -2857,7 +2180,14 @@
fCtrl.Value = 0;
fCtrl.Bits.FOptsLen = 0;
- fCtrl.Bits.FPending = 0;
+ if( LoRaMacDeviceClass == CLASS_B )
+ {
+ fCtrl.Bits.FPending = 1;
+ }
+ else
+ {
+ fCtrl.Bits.FPending = 0;
+ }
fCtrl.Bits.Ack = false;
fCtrl.Bits.AdrAckReq = false;
fCtrl.Bits.Adr = AdrCtrlOn;
@@ -2884,6 +2214,9 @@
static LoRaMacStatus_t ScheduleTx( void )
{
TimerTime_t dutyCycleTimeOff = 0;
+ TimerTime_t mutexTimeLock = 0;
+ TimerTime_t timeOff = 0;
+ NextChanParams_t nextChan;
// Check if the device is off
if( MaxDCycle == 255 )
@@ -2895,31 +2228,41 @@
AggregatedTimeOff = 0;
}
+ // Update Backoff
+ CalculateBackOff( LastTxChannel );
+
+ nextChan.AggrTimeOff = AggregatedTimeOff;
+ nextChan.Datarate = LoRaMacParams.ChannelsDatarate;
+ nextChan.DutyCycleEnabled = DutyCycleOn;
+ nextChan.Joined = IsLoRaMacNetworkJoined;
+ nextChan.LastAggrTx = AggregatedLastTxDoneTime;
+
// Select channel
- while( SetNextChannel( &dutyCycleTimeOff ) == false )
+ while( RegionNextChannel( LoRaMacRegion, &nextChan, &Channel, &dutyCycleTimeOff, &AggregatedTimeOff ) == false )
{
// Set the default datarate
LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
-
-#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 ) );
-#endif
+ // Update datarate in the function parameters
+ nextChan.Datarate = LoRaMacParams.ChannelsDatarate;
}
// 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
+ RegionComputeRxWindowParameters( LoRaMacRegion,
+ RegionApplyDrOffset( LoRaMacRegion, LoRaMacParams.DownlinkDwellTime, LoRaMacParams.ChannelsDatarate, LoRaMacParams.Rx1DrOffset ),
+ LoRaMacParams.MinRxSymbols,
+ LoRaMacParams.SystemMaxRxError,
+ &RxWindow1Config );
// Compute Rx2 windows parameters
- RxWindowsParams[1] = ComputeRxWindowParameters( LoRaMacParams.Rx2Channel.Datarate, LoRaMacParams.SystemMaxRxError );
+ RegionComputeRxWindowParameters( LoRaMacRegion,
+ LoRaMacParams.Rx2Channel.Datarate,
+ LoRaMacParams.MinRxSymbols,
+ LoRaMacParams.SystemMaxRxError,
+ &RxWindow2Config );
if( IsLoRaMacNetworkJoined == false )
{
- RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 + RxWindowsParams[0].RxOffset;
- RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 + RxWindowsParams[1].RxOffset;
+ RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 + RxWindow1Config.WindowOffset;
+ RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 + RxWindow2Config.WindowOffset;
}
else
{
@@ -2927,123 +2270,68 @@
{
return LORAMAC_STATUS_LENGTH_ERROR;
}
- RxWindow1Delay = LoRaMacParams.ReceiveDelay1 + RxWindowsParams[0].RxOffset;
- RxWindow2Delay = LoRaMacParams.ReceiveDelay2 + RxWindowsParams[1].RxOffset;
+ RxWindow1Delay = LoRaMacParams.ReceiveDelay1 + RxWindow1Config.WindowOffset;
+ RxWindow2Delay = LoRaMacParams.ReceiveDelay2 + RxWindow2Config.WindowOffset;
}
// Schedule transmission of frame
if( dutyCycleTimeOff == 0 )
{
// Try to send now
- return SendFrameOnChannel( Channels[Channel] );
+ mutexTimeLock = SendFrameOnChannel( Channel );
}
- else
+
+ timeOff = MAX( dutyCycleTimeOff, mutexTimeLock );
+
+ if( timeOff > 0 )
{
// Send later - prepare timer
LoRaMacState |= LORAMAC_TX_DELAYED;
- TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
+ TimerSetValue( &TxDelayedTimer, timeOff );
TimerStart( &TxDelayedTimer );
-
- return LORAMAC_STATUS_OK;
}
-}
-
-static uint16_t JoinDutyCycle( void )
-{
- uint16_t dutyCycle = 0;
- TimerTime_t timeElapsed = TimerGetElapsedTime( LoRaMacInitializationTime );
-
- if( timeElapsed < 3600e3 )
- {
- dutyCycle = BACKOFF_DC_1_HOUR;
- }
- else if( timeElapsed < ( 3600e3 + 36000e3 ) )
- {
- dutyCycle = BACKOFF_DC_10_HOURS;
- }
- else
- {
- dutyCycle = BACKOFF_DC_24_HOURS;
- }
- return dutyCycle;
+ return LORAMAC_STATUS_OK;
}
static void CalculateBackOff( uint8_t channel )
{
- uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
- uint16_t joinDutyCycle = 0;
-
- // Reset time-off to initial value.
- Bands[Channels[channel].Band].TimeOff = 0;
-
- if( IsLoRaMacNetworkJoined == false )
- {
- // The node has not joined yet. Apply join duty cycle to all regions.
- joinDutyCycle = JoinDutyCycle( );
- dutyCycle = MAX( dutyCycle, joinDutyCycle );
-
- // Update Band time-off.
- Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
- }
- else
- {
- if( DutyCycleOn == true )
- {
- Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
- }
- }
-
- // Update Aggregated Time OFF
+ CalcBackOffParams_t calcBackOff;
+
+ calcBackOff.Joined = IsLoRaMacNetworkJoined;
+ calcBackOff.DutyCycleEnabled = DutyCycleOn;
+ calcBackOff.Channel = channel;
+ calcBackOff.ElapsedTime = TimerGetElapsedTime( LoRaMacInitializationTime );
+ calcBackOff.TxTimeOnAir = TxTimeOnAir;
+ calcBackOff.LastTxIsJoinRequest = LastTxIsJoinRequest;
+
+ // Update regional back-off
+ RegionCalcBackOff( LoRaMacRegion, &calcBackOff );
+
+ // Update aggregated time-off
AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
}
-static int8_t AlternateDatarate( uint16_t nbTrials )
+static uint8_t GetMlmeConfirmIndex( MlmeConfirmQueue_t* queue, Mlme_t req )
{
- int8_t datarate = LORAMAC_TX_MIN_DATARATE;
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-#if defined( USE_BAND_915 )
- // Re-enable 500 kHz default channels
- LoRaMacParams.ChannelsMask[4] = 0x00FF;
-#else // defined( USE_BAND_915_HYBRID )
- // Re-enable 500 kHz default channels
- ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
-#endif
-
- if( ( nbTrials & 0x01 ) == 0x01 )
- {
- datarate = DR_4;
- }
- else
- {
- datarate = DR_0;
- }
-#else
- if( ( nbTrials % 48 ) == 0 )
+ for( uint8_t i = 0; i < MlmeConfirmQueueCnt; i++ )
{
- datarate = DR_0;
- }
- else if( ( nbTrials % 32 ) == 0 )
- {
- datarate = DR_1;
+ if( queue->MlmeRequest == req )
+ {
+ return i;
+ }
+ queue++;
}
- else if( ( nbTrials % 24 ) == 0 )
- {
- datarate = DR_2;
- }
- else if( ( nbTrials % 16 ) == 0 )
+
+ // Out of band
+ return LORA_MAC_MLME_CONFIRM_QUEUE_LEN;
+}
+
+static void SetEveryMlmeConfirmStatus( MlmeConfirmQueue_t* queue, LoRaMacEventInfoStatus_t status )
+{
+ for( uint8_t i = 0; i < MlmeConfirmQueueCnt; i++ )
{
- datarate = DR_3;
- }
- else if( ( nbTrials % 8 ) == 0 )
- {
- datarate = DR_4;
+ queue[i].Status = status;
}
- else
- {
- datarate = DR_5;
- }
-#endif
- return datarate;
}
static void ResetMacParameters( void )
@@ -3071,16 +2359,12 @@
LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
-
LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset;
LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
-
- memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
-#endif
-
+ LoRaMacParams.UplinkDwellTime = LoRaMacParamsDefaults.UplinkDwellTime;
+ LoRaMacParams.DownlinkDwellTime = LoRaMacParamsDefaults.DownlinkDwellTime;
+ LoRaMacParams.MaxEirp = LoRaMacParamsDefaults.MaxEirp;
+ LoRaMacParams.AntennaGain = LoRaMacParamsDefaults.AntennaGain;
NodeAckRequested = false;
SrvAckRequested = false;
@@ -3095,11 +2379,13 @@
}
// Initialize channel index.
- Channel = LORA_MAX_NB_CHANNELS;
+ Channel = 0;
+ LastTxChannel = Channel;
}
LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
{
+ AdrNextParams_t adrNext;
uint16_t i;
uint8_t pktHeaderLen = 0;
uint32_t mic = 0;
@@ -3151,8 +2437,17 @@
return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet
}
- fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate );
-
+ // Adr next request
+ adrNext.UpdateChanMask = true;
+ adrNext.AdrEnabled = fCtrl->Bits.Adr;
+ adrNext.AdrAckCounter = AdrAckCounter;
+ adrNext.Datarate = LoRaMacParams.ChannelsDatarate;
+ adrNext.TxPower = LoRaMacParams.ChannelsTxPower;
+ adrNext.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+
+ fCtrl->Bits.AdrAckReq = RegionAdrNext( LoRaMacRegion, &adrNext,
+ &LoRaMacParams.ChannelsDatarate, &LoRaMacParams.ChannelsTxPower, &AdrAckCounter );
+
if( SrvAckRequested == true )
{
SrvAckRequested = false;
@@ -3175,21 +2470,30 @@
if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
{
- if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
+ if( MacCommandsInNextTx == true )
{
- fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
-
- // Update FCtrl field with new value of OptionsLength
- LoRaMacBuffer[0x05] = fCtrl->Value;
- for( i = 0; i < MacCommandsBufferIndex; i++ )
+ if( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH )
{
- LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
+ fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
+
+ // Update FCtrl field with new value of OptionsLength
+ LoRaMacBuffer[0x05] = fCtrl->Value;
+ for( i = 0; i < MacCommandsBufferIndex; i++ )
+ {
+ LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
+ }
+ }
+ else
+ {
+ LoRaMacTxPayloadLen = MacCommandsBufferIndex;
+ payload = MacCommandsBuffer;
+ framePort = 0;
}
}
}
else
{
- if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
+ if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx == true ) )
{
LoRaMacTxPayloadLen = MacCommandsBufferIndex;
payload = MacCommandsBuffer;
@@ -3210,6 +2514,8 @@
if( framePort == 0 )
{
+ // Reset buffer index as the mac commands are being sent on port 0
+ MacCommandsBufferIndex = 0;
LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
}
else
@@ -3243,67 +2549,55 @@
return LORAMAC_STATUS_OK;
}
-LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel )
+TimerTime_t SendFrameOnChannel( uint8_t channel )
{
- int8_t datarate = Datarates[LoRaMacParams.ChannelsDatarate];
- int8_t txPowerIndex = 0;
+ TxConfigParams_t txConfig;
int8_t txPower = 0;
- txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower, Bands[channel.Band].TxMaxPower );
- txPower = TxPowers[txPowerIndex];
-
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ txConfig.Channel = channel;
+ txConfig.Datarate = LoRaMacParams.ChannelsDatarate;
+ txConfig.TxPower = LoRaMacParams.ChannelsTxPower;
+ txConfig.MaxEirp = LoRaMacParams.MaxEirp;
+ txConfig.AntennaGain = LoRaMacParams.AntennaGain;
+ txConfig.PktLen = LoRaMacBufferPktLen;
+
+ if( LoRaMacDeviceClass == CLASS_B )
+ {
+ if( LoRaMacClassBIsBeaconExpected( ) == true )
+ {
+ return LoRaMacClassBGetBeaconReservedTime( );
+ }
+ if( LoRaMacClassBIsPingExpected( ) == true )
+ {
+ return LoRaMacClassBGetPingSlotWinTime( );
+ }
+ }
+ RegionTxConfig( LoRaMacRegion, &txConfig, &txPower, &TxTimeOnAir );
+
+ SetEveryMlmeConfirmStatus( MlmeConfirmQueue, 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 );
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- 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, 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, 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, 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, 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, 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
+ McpsConfirm.TxPower = txPower;
// Store the time on air
McpsConfirm.TxTimeOnAir = TxTimeOnAir;
MlmeConfirm.TxTimeOnAir = TxTimeOnAir;
+ if( ( LoRaMacDeviceClass == CLASS_B ) || ( LoRaMacClassBIsBeaconModeActive( ) == true ) )
+ {
+ TimerTime_t collisionTime = LoRaMacClassBIsUplinkCollision( TxTimeOnAir );
+
+ if( collisionTime > 0 )
+ {
+ return collisionTime;
+ }
+ }
+
+ if( LoRaMacDeviceClass == CLASS_B )
+ {
+ LoRaMacClassBHaltBeaconing( );
+ }
+
// Starts the MAC layer status check timer
TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
TimerStart( &MacStateCheckTimer );
@@ -3313,28 +2607,33 @@
JoinRequestTrials++;
}
+ LoRaMacState |= LORAMAC_TX_RUNNING;
+
// Send now
Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
LoRaMacState |= LORAMAC_TX_RUNNING;
- return LORAMAC_STATUS_OK;
+ return 0;
}
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];
+ ContinuousWaveParams_t continuousWave;
+
+ continuousWave.Channel = Channel;
+ continuousWave.Datarate = LoRaMacParams.ChannelsDatarate;
+ continuousWave.TxPower = LoRaMacParams.ChannelsTxPower;
+ continuousWave.MaxEirp = LoRaMacParams.MaxEirp;
+ continuousWave.AntennaGain = LoRaMacParams.AntennaGain;
+ continuousWave.Timeout = timeout;
+
+ RegionSetContinuousWave( LoRaMacRegion, &continuousWave );
// 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;
@@ -3353,8 +2652,13 @@
return LORAMAC_STATUS_OK;
}
-LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks )
+LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks, LoRaMacRegion_t region )
{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ LoRaMacClassBCallback_t classBCallbacks;
+ LoRaMacClassBParams_t classBParams;
+
if( primitives == NULL )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
@@ -3362,13 +2666,20 @@
if( ( primitives->MacMcpsConfirm == NULL ) ||
( primitives->MacMcpsIndication == NULL ) ||
- ( primitives->MacMlmeConfirm == NULL ) )
+ ( primitives->MacMlmeConfirm == NULL ) ||
+ ( primitives->MacMlmeIndication == NULL ) )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
+ // Verify if the region is supported
+ if( RegionIsActive( region ) == false )
+ {
+ return LORAMAC_STATUS_REGION_NOT_SUPPORTED;
+ }
LoRaMacPrimitives = primitives;
LoRaMacCallbacks = callbacks;
+ LoRaMacRegion = region;
LoRaMacFlags.Value = 0;
@@ -3377,102 +2688,80 @@
JoinRequestTrials = 0;
MaxJoinRequestTrials = 1;
- RepeaterSupport = false;
// Reset duty cycle times
AggregatedLastTxDoneTime = 0;
AggregatedTimeOff = 0;
- // Duty cycle
-#if defined( USE_BAND_433 )
- DutyCycleOn = true;
-#elif defined( USE_BAND_470 )
- DutyCycleOn = false;
-#elif defined( USE_BAND_780 )
- DutyCycleOn = true;
-#elif defined( USE_BAND_868 )
- DutyCycleOn = true;
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- DutyCycleOn = false;
-#else
- #error "Please define a frequency band in the compiler options."
-#endif
-
// Reset to defaults
- LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
- LoRaMacParamsDefaults.ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
-
+ getPhy.Attribute = PHY_DUTY_CYCLE;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ DutyCycleOn = ( bool ) phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_TX_POWER;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.ChannelsTxPower = phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_TX_DR;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.ChannelsDatarate = phyParam.Value;
+
+ getPhy.Attribute = PHY_MAX_RX_WINDOW;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.MaxRxWindow = phyParam.Value;
+
+ getPhy.Attribute = PHY_RECEIVE_DELAY1;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.ReceiveDelay1 = phyParam.Value;
+
+ getPhy.Attribute = PHY_RECEIVE_DELAY2;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.ReceiveDelay2 = phyParam.Value;
+
+ getPhy.Attribute = PHY_JOIN_ACCEPT_DELAY1;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.JoinAcceptDelay1 = phyParam.Value;
+
+ getPhy.Attribute = PHY_JOIN_ACCEPT_DELAY2;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.JoinAcceptDelay2 = phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_DR1_OFFSET;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.Rx1DrOffset = phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_RX2_FREQUENCY;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.Rx2Channel.Frequency = phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_RX2_DR;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.Rx2Channel.Datarate = phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_UPLINK_DWELL_TIME;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.UplinkDwellTime = phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_DOWNLINK_DWELL_TIME;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.DownlinkDwellTime = phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_MAX_EIRP;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.MaxEirp = phyParam.fValue;
+
+ getPhy.Attribute = PHY_DEF_ANTENNA_GAIN;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ LoRaMacParamsDefaults.AntennaGain = phyParam.fValue;
+
+ RegionInitDefaults( LoRaMacRegion, INIT_TYPE_INIT );
+
+ // Init parameters which are not set in function ResetMacParameters
+ LoRaMacParams.RepeaterSupport = false;
+ LoRaMacParamsDefaults.ChannelsNbRep = 1;
LoRaMacParamsDefaults.SystemMaxRxError = 10;
LoRaMacParamsDefaults.MinRxSymbols = 6;
- LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW;
- LoRaMacParamsDefaults.ReceiveDelay1 = RECEIVE_DELAY1;
- LoRaMacParamsDefaults.ReceiveDelay2 = RECEIVE_DELAY2;
- LoRaMacParamsDefaults.JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
- LoRaMacParamsDefaults.JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
-
- LoRaMacParamsDefaults.ChannelsNbRep = 1;
- LoRaMacParamsDefaults.Rx1DrOffset = 0;
-
- LoRaMacParamsDefaults.Rx2Channel = ( Rx2ChannelParams_t )RX_WND_2_CHANNEL;
-
- // 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 )
- LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
-#elif defined( USE_BAND_915 )
- LoRaMacParamsDefaults.ChannelsMask[0] = 0xFFFF;
- LoRaMacParamsDefaults.ChannelsMask[1] = 0xFFFF;
- LoRaMacParamsDefaults.ChannelsMask[2] = 0xFFFF;
- LoRaMacParamsDefaults.ChannelsMask[3] = 0xFFFF;
- LoRaMacParamsDefaults.ChannelsMask[4] = 0x00FF;
- LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000;
-#elif defined( USE_BAND_915_HYBRID )
- LoRaMacParamsDefaults.ChannelsMask[0] = 0x00FF;
- LoRaMacParamsDefaults.ChannelsMask[1] = 0x0000;
- LoRaMacParamsDefaults.ChannelsMask[2] = 0x0000;
- LoRaMacParamsDefaults.ChannelsMask[3] = 0x0000;
- LoRaMacParamsDefaults.ChannelsMask[4] = 0x0001;
- LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000;
-#else
- #error "Please define a frequency band in the compiler options."
-#endif
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- // 125 kHz channels
- for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ )
- {
- Channels[i].Frequency = 902.3e6 + i * 200e3;
- Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
- Channels[i].Band = 0;
- }
- // 500 kHz channels
- for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ )
- {
- Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6;
- 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;
@@ -3511,12 +2800,39 @@
Radio.SetPublicNetwork( PublicNetwork );
Radio.Sleep( );
+ // Initialize class b
+ // Apply callback
+ classBCallbacks.GetTemperatureLevel = NULL;
+ if( callbacks != NULL )
+ {
+ classBCallbacks.GetTemperatureLevel = callbacks->GetTemperatureLevel;
+ }
+ classBCallbacks.GetMlmeConfrimIndex = GetMlmeConfirmIndex;
+
+ // Must all be static. Don't use local references.
+ classBParams.MlmeIndication = &MlmeIndication;
+ classBParams.McpsIndication = &McpsIndication;
+ classBParams.MlmeConfirm = &MlmeConfirm;
+ classBParams.LoRaMacFlags = &LoRaMacFlags;
+ classBParams.LoRaMacDevAddr = &LoRaMacDevAddr;
+ classBParams.MlmeConfirmQueue = MlmeConfirmQueue;
+ classBParams.LoRaMacRegion = &LoRaMacRegion;
+ classBParams.MacStateCheckTimer = &MacStateCheckTimer;
+ classBParams.LoRaMacParams = &LoRaMacParams;
+ classBParams.MulticastChannels = MulticastChannels;
+
+ LoRaMacClassBInit( &classBParams, &classBCallbacks );
+
return LORAMAC_STATUS_OK;
}
LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
{
+ AdrNextParams_t adrNext;
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate;
+ int8_t txPower = LoRaMacParamsDefaults.ChannelsTxPower;
uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
if( txInfo == NULL )
@@ -3524,42 +2840,59 @@
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- AdrNextDr( AdrCtrlOn, false, &datarate );
-
- if( RepeaterSupport == true )
+ // Setup ADR request
+ adrNext.UpdateChanMask = false;
+ adrNext.AdrEnabled = AdrCtrlOn;
+ adrNext.AdrAckCounter = AdrAckCounter;
+ adrNext.Datarate = LoRaMacParams.ChannelsDatarate;
+ adrNext.TxPower = LoRaMacParams.ChannelsTxPower;
+ adrNext.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+
+ // We call the function for information purposes only. We don't want to
+ // apply the datarate, the tx power and the ADR ack counter.
+ RegionAdrNext( LoRaMacRegion, &adrNext, &datarate, &txPower, &AdrAckCounter );
+
+ // Setup PHY request
+ getPhy.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ getPhy.Datarate = datarate;
+ getPhy.Attribute = PHY_MAX_PAYLOAD;
+
+ // Change request in case repeater is supported
+ if( LoRaMacParams.RepeaterSupport == true )
{
- txInfo->CurrentPayloadSize = MaxPayloadOfDatarateRepeater[datarate];
+ getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
}
- else
- {
- txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate];
- }
-
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ txInfo->CurrentPayloadSize = phyParam.Value;
+
+ // Verify if the fOpts fit into the maximum payload
if( txInfo->CurrentPayloadSize >= fOptLen )
{
txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
}
else
{
- return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
+ txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize;
+ // The fOpts don't fit into the maximum payload. Omit the MAC commands to
+ // ensure that another uplink is possible.
+ fOptLen = 0;
+ MacCommandsBufferIndex = 0;
+ MacCommandsBufferToRepeatIndex = 0;
}
- if( ValidatePayloadLength( size, datarate, 0 ) == false )
+ // Verify if the fOpts and the payload fit into the maximum payload
+ if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
{
return LORAMAC_STATUS_LENGTH_ERROR;
}
-
- if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
- {
- return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
- }
-
return LORAMAC_STATUS_OK;
}
LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
{
LoRaMacStatus_t status = LORAMAC_STATUS_OK;
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
if( mibGet == NULL )
{
@@ -3610,12 +2943,15 @@
}
case MIB_REPEATER_SUPPORT:
{
- mibGet->Param.EnableRepeaterSupport = RepeaterSupport;
+ mibGet->Param.EnableRepeaterSupport = LoRaMacParams.RepeaterSupport;
break;
}
case MIB_CHANNELS:
{
- mibGet->Param.ChannelList = Channels;
+ getPhy.Attribute = PHY_CHANNELS;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+
+ mibGet->Param.ChannelList = phyParam.Channels;
break;
}
case MIB_RX2_CHANNEL:
@@ -3630,12 +2966,18 @@
}
case MIB_CHANNELS_DEFAULT_MASK:
{
- mibGet->Param.ChannelsDefaultMask = LoRaMacParamsDefaults.ChannelsMask;
+ getPhy.Attribute = PHY_CHANNELS_DEFAULT_MASK;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+
+ mibGet->Param.ChannelsDefaultMask = phyParam.ChannelsMask;
break;
}
case MIB_CHANNELS_MASK:
{
- mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask;
+ getPhy.Attribute = PHY_CHANNELS_MASK;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+
+ mibGet->Param.ChannelsMask = phyParam.ChannelsMask;
break;
}
case MIB_CHANNELS_NB_REP:
@@ -3713,17 +3055,32 @@
mibGet->Param.MinRxSymbols = LoRaMacParams.MinRxSymbols;
break;
}
- default:
- status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+ case MIB_ANTENNA_GAIN:
+ {
+ mibGet->Param.AntennaGain = LoRaMacParams.AntennaGain;
break;
+ }
+ default:
+ {
+ if( LoRaMacDeviceClass == CLASS_B )
+ {
+ status = LoRaMacClassBMibGetRequestConfirm( mibGet );
+ }
+ else
+ {
+ status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+ }
+ break;
+ }
}
-
return status;
}
LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
{
LoRaMacStatus_t status = LORAMAC_STATUS_OK;
+ ChanMaskSetParams_t chanMaskSet;
+ VerifyParams_t verify;
if( mibSet == NULL )
{
@@ -3738,27 +3095,7 @@
{
case MIB_DEVICE_CLASS:
{
- LoRaMacDeviceClass = mibSet->Param.Class;
- switch( LoRaMacDeviceClass )
- {
- case CLASS_A:
- {
- // Set the radio into sleep to setup a defined state
- Radio.Sleep( );
- break;
- }
- case CLASS_B:
- {
- break;
- }
- case CLASS_C:
- {
- // Set the NodeAckRequested indicator to default
- NodeAckRequested = false;
- OnRxWindow2TimerEvent( );
- break;
- }
- }
+ status = SwitchClass( mibSet->Param.Class );
break;
}
case MIB_NETWORK_JOINED:
@@ -3815,58 +3152,44 @@
}
case MIB_REPEATER_SUPPORT:
{
- RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
+ LoRaMacParams.RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
break;
}
case MIB_RX2_CHANNEL:
{
- 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 )
+ verify.DatarateParams.Datarate = mibSet->Param.Rx2Channel.Datarate;
+ verify.DatarateParams.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_RX_DR ) == true )
{
-#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 )
+ LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel;
+
+ if( ( LoRaMacDeviceClass == CLASS_C ) && ( IsLoRaMacNetworkJoined == true ) )
{
- if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) &&
- ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
+ // Compute Rx2 windows parameters
+ RegionComputeRxWindowParameters( LoRaMacRegion,
+ LoRaMacParams.Rx2Channel.Datarate,
+ LoRaMacParams.MinRxSymbols,
+ LoRaMacParams.SystemMaxRxError,
+ &RxWindow2Config );
+
+ RxWindow2Config.Channel = Channel;
+ RxWindow2Config.Frequency = LoRaMacParams.Rx2Channel.Frequency;
+ RxWindow2Config.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
+ RxWindow2Config.RepeaterSupport = LoRaMacParams.RepeaterSupport;
+ RxWindow2Config.Window = 1;
+ RxWindow2Config.RxContinuous = true;
+
+ if( RegionRxConfig( LoRaMacRegion, &RxWindow2Config, ( int8_t* )&McpsIndication.RxDatarate ) == true )
+ {
+ RxWindowSetup( RxWindow2Config.RxContinuous, LoRaMacParams.MaxRxWindow );
+ RxSlot = RxWindow2Config.Window;
+ }
+ else
{
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
{
@@ -3874,47 +3197,38 @@
}
break;
}
+ case MIB_RX2_DEFAULT_CHANNEL:
+ {
+ verify.DatarateParams.Datarate = mibSet->Param.Rx2Channel.Datarate;
+ verify.DatarateParams.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_RX_DR ) == true )
+ {
+ LoRaMacParamsDefaults.Rx2Channel = mibSet->Param.Rx2DefaultChannel;
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_CHANNELS_DEFAULT_MASK:
+ {
+ chanMaskSet.ChannelsMaskIn = mibSet->Param.ChannelsMask;
+ chanMaskSet.ChannelsMaskType = CHANNELS_DEFAULT_MASK;
+
+ if( RegionChanMaskSet( LoRaMacRegion, &chanMaskSet ) == false )
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
case MIB_CHANNELS_MASK:
{
- if( mibSet->Param.ChannelsMask )
- {
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- bool chanMaskState = true;
-
-#if defined( USE_BAND_915_HYBRID )
- chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsMask );
-#endif
- if( chanMaskState == true )
- {
- if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) &&
- ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- else
- {
- memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
- ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
- for ( uint8_t i = 0; i < sizeof( LoRaMacParams.ChannelsMask ) / 2; i++ )
- {
- // Disable channels which are no longer available
- ChannelsMaskRemaining[i] &= LoRaMacParams.ChannelsMask[i];
- }
- }
- }
- else
- {
- 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 );
-#endif
- }
- else
+ chanMaskSet.ChannelsMaskIn = mibSet->Param.ChannelsMask;
+ chanMaskSet.ChannelsMaskType = CHANNELS_MASK;
+
+ if( RegionChanMaskSet( LoRaMacRegion, &chanMaskSet ) == false )
{
status = LORAMAC_STATUS_PARAMETER_INVALID;
}
@@ -3960,19 +3274,12 @@
}
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 ) )
+ verify.DatarateParams.Datarate = mibSet->Param.ChannelsDefaultDatarate;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_DEF_TX_DR ) == true )
{
- LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
+ LoRaMacParamsDefaults.ChannelsDatarate = verify.DatarateParams.Datarate;
}
-#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;
@@ -3981,10 +3288,11 @@
}
case MIB_CHANNELS_DATARATE:
{
- if( ValueInRange( mibSet->Param.ChannelsDatarate,
- LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
+ verify.DatarateParams.Datarate = mibSet->Param.ChannelsDatarate;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_TX_DR ) == true )
{
- LoRaMacParams.ChannelsDatarate = mibSet->Param.ChannelsDatarate;
+ LoRaMacParams.ChannelsDatarate = verify.DatarateParams.Datarate;
}
else
{
@@ -3994,10 +3302,11 @@
}
case MIB_CHANNELS_DEFAULT_TX_POWER:
{
- if( ValueInRange( mibSet->Param.ChannelsDefaultTxPower,
- LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
+ verify.TxPower = mibSet->Param.ChannelsDefaultTxPower;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_DEF_TX_POWER ) == true )
{
- LoRaMacParamsDefaults.ChannelsTxPower = mibSet->Param.ChannelsDefaultTxPower;
+ LoRaMacParamsDefaults.ChannelsTxPower = verify.TxPower;
}
else
{
@@ -4007,10 +3316,11 @@
}
case MIB_CHANNELS_TX_POWER:
{
- if( ValueInRange( mibSet->Param.ChannelsTxPower,
- LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
+ verify.TxPower = mibSet->Param.ChannelsTxPower;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_TX_POWER ) == true )
{
- LoRaMacParams.ChannelsTxPower = mibSet->Param.ChannelsTxPower;
+ LoRaMacParams.ChannelsTxPower = verify.TxPower;
}
else
{
@@ -4038,9 +3348,23 @@
LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols = mibSet->Param.MinRxSymbols;
break;
}
+ case MIB_ANTENNA_GAIN:
+ {
+ LoRaMacParams.AntennaGain = mibSet->Param.AntennaGain;
+ break;
+ }
default:
- status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+ {
+ if( LoRaMacDeviceClass == CLASS_B )
+ {
+ status = LoRaMacMibClassBSetRequestConfirm( mibSet );
+ }
+ else
+ {
+ status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+ }
break;
+ }
}
return status;
@@ -4048,18 +3372,8 @@
LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
{
-#if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- return LORAMAC_STATUS_PARAMETER_INVALID;
-#else
- bool datarateInvalid = false;
- bool frequencyInvalid = false;
- uint8_t band = 0;
-
- // The id must not exceed LORA_MAX_NB_CHANNELS
- if( id >= LORA_MAX_NB_CHANNELS )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
+ ChannelAddParams_t channelAdd;
+
// Validate if the MAC is in a correct state
if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
@@ -4068,99 +3382,17 @@
return LORAMAC_STATUS_BUSY;
}
}
- // Validate the datarate
- if( ( params.DrRange.Fields.Min > params.DrRange.Fields.Max ) ||
- ( ValueInRange( params.DrRange.Fields.Min, LORAMAC_TX_MIN_DATARATE,
- LORAMAC_TX_MAX_DATARATE ) == false ) ||
- ( ValueInRange( params.DrRange.Fields.Max, LORAMAC_TX_MIN_DATARATE,
- LORAMAC_TX_MAX_DATARATE ) == false ) )
- {
- datarateInvalid = true;
- }
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- if( id < 3 )
- {
- if( params.Frequency != Channels[id].Frequency )
- {
- frequencyInvalid = true;
- }
-
- if( params.DrRange.Fields.Min > DR_0 )
- {
- datarateInvalid = true;
- }
- if( ValueInRange( params.DrRange.Fields.Max, DR_5, LORAMAC_TX_MAX_DATARATE ) == false )
- {
- datarateInvalid = true;
- }
- }
-#endif
-
- // Validate the frequency
- if( ( Radio.CheckRfFrequency( params.Frequency ) == true ) && ( params.Frequency > 0 ) && ( frequencyInvalid == false ) )
- {
-#if defined( USE_BAND_868 )
- if( ( params.Frequency >= 863000000 ) && ( params.Frequency < 865000000 ) )
- {
- band = BAND_G1_2;
- }
- else if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
- {
- band = BAND_G1_0;
- }
- else if( ( params.Frequency > 868000000 ) && ( params.Frequency <= 868600000 ) )
- {
- band = BAND_G1_1;
- }
- else if( ( params.Frequency >= 868700000 ) && ( params.Frequency <= 869200000 ) )
- {
- band = BAND_G1_2;
- }
- else if( ( params.Frequency >= 869400000 ) && ( params.Frequency <= 869650000 ) )
- {
- band = BAND_G1_3;
- }
- else if( ( params.Frequency >= 869700000 ) && ( params.Frequency <= 870000000 ) )
- {
- band = BAND_G1_4;
- }
- else
- {
- frequencyInvalid = true;
- }
-#endif
- }
- else
- {
- frequencyInvalid = true;
- }
-
- if( ( datarateInvalid == true ) && ( frequencyInvalid == true ) )
- {
- return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
- }
- if( datarateInvalid == true )
- {
- return LORAMAC_STATUS_DATARATE_INVALID;
- }
- if( frequencyInvalid == true )
- {
- return LORAMAC_STATUS_FREQUENCY_INVALID;
- }
-
- // Every parameter is valid, activate the channel
- Channels[id] = params;
- Channels[id].Band = band;
- LoRaMacParams.ChannelsMask[0] |= ( 1 << id );
-
- return LORAMAC_STATUS_OK;
-#endif
+
+ channelAdd.NewChannel = ¶ms;
+ channelAdd.ChannelId = id;
+
+ return RegionChannelAdd( LoRaMacRegion, &channelAdd );
}
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
{
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
+ ChannelRemoveParams_t channelRemove;
+
if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
@@ -4169,25 +3401,13 @@
}
}
- if( ( id < 3 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
+ channelRemove.ChannelId = id;
+
+ if( RegionChannelsRemove( LoRaMacRegion, &channelRemove ) == false )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- else
- {
- // Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 };
-
- // Disable the channel as it doesn't exist anymore
- if( DisableChannelInMask( id, LoRaMacParams.ChannelsMask ) == false )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- }
return LORAMAC_STATUS_OK;
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) || defined( USE_BAND_470 ) )
- return LORAMAC_STATUS_PARAMETER_INVALID;
-#endif
}
LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam )
@@ -4203,6 +3423,7 @@
// Reset downlink counter
channelParam->DownLinkCounter = 0;
+ channelParam->Next = NULL;
if( MulticastChannels == NULL )
{
@@ -4268,6 +3489,10 @@
{
LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
LoRaMacHeader_t macHdr;
+ AlternateDrParams_t altDr;
+ VerifyParams_t verify;
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
if( mlmeRequest == NULL )
{
@@ -4277,11 +3502,18 @@
{
return LORAMAC_STATUS_BUSY;
}
-
- memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) );
-
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-
+ if( LORA_MAC_MLME_CONFIRM_QUEUE_LEN <= MlmeConfirmQueueCnt )
+ {
+ return LORAMAC_STATUS_BUSY;
+ }
+
+ // Reset the confirm queue if it is empty
+ if( MlmeConfirmQueueCnt == 0 )
+ {
+ memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) );
+ }
+
+ // Switch requests
switch( mlmeRequest->Type )
{
case MLME_JOIN:
@@ -4299,22 +3531,21 @@
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 )
+ // Apply the request
+ LoRaMacFlags.Bits.MlmeReq = 1;
+ MlmeConfirmQueue[MlmeConfirmQueueCnt].MlmeRequest = mlmeRequest->Type;
+ MlmeConfirmQueueCnt++;
+
+ // Verify the parameter NbTrials for the join procedure
+ verify.NbJoinTrials = mlmeRequest->Req.Join.NbTrials;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_NB_JOIN_TRIALS ) == false )
{
- mlmeRequest->Req.Join.NbTrials = 2;
+ // Value not supported, get default
+ getPhy.Attribute = PHY_DEF_NB_JOIN_TRIALS;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ mlmeRequest->Req.Join.NbTrials = ( uint8_t ) phyParam.Value;
}
-#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;
@@ -4330,33 +3561,85 @@
ResetMacParameters( );
- // Add a +1, since we start to count from 0
- LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials + 1 );
+ altDr.NbTrials = JoinRequestTrials + 1;
+
+ LoRaMacParams.ChannelsDatarate = RegionAlternateDr( LoRaMacRegion, &altDr );
status = Send( &macHdr, 0, NULL, 0 );
break;
}
case MLME_LINK_CHECK:
{
+ // Apply the request
LoRaMacFlags.Bits.MlmeReq = 1;
+ MlmeConfirmQueue[MlmeConfirmQueueCnt].MlmeRequest = mlmeRequest->Type;
+ MlmeConfirmQueueCnt++;
+
// LoRaMac will send this command piggy-pack
- MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
break;
}
case MLME_TXCW:
{
- MlmeConfirm.MlmeRequest = mlmeRequest->Type;
+ // Apply the request
LoRaMacFlags.Bits.MlmeReq = 1;
+ MlmeConfirmQueue[MlmeConfirmQueueCnt].MlmeRequest = mlmeRequest->Type;
+ MlmeConfirmQueueCnt++;
status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout );
break;
}
case MLME_TXCW_1:
{
- MlmeConfirm.MlmeRequest = mlmeRequest->Type;
+ // Apply the request
+ LoRaMacFlags.Bits.MlmeReq = 1;
+ MlmeConfirmQueue[MlmeConfirmQueueCnt].MlmeRequest = mlmeRequest->Type;
+ MlmeConfirmQueueCnt++;
+ status = SetTxContinuousWave1( mlmeRequest->Req.TxCw.Timeout, mlmeRequest->Req.TxCw.Frequency, mlmeRequest->Req.TxCw.Power );
+ break;
+ }
+ case MLME_PING_SLOT_INFO:
+ {
+ uint8_t value = mlmeRequest->Req.PingSlotInfo.PingSlot.Value;
+
+ // Apply the request
+ LoRaMacFlags.Bits.MlmeReq = 1;
+ MlmeConfirmQueue[MlmeConfirmQueueCnt].MlmeRequest = mlmeRequest->Type;
+ MlmeConfirmQueueCnt++;
+ // LoRaMac will send this command piggy-pack
+ LoRaMacClassBSetPingSlotInfo( mlmeRequest->Req.PingSlotInfo.PingSlot.Fields.Periodicity );
+
+ status = AddMacCommand( MOTE_MAC_PING_SLOT_INFO_REQ, value, 0 );
+ break;
+ }
+ case MLME_BEACON_TIMING:
+ {
+ // Apply the request
LoRaMacFlags.Bits.MlmeReq = 1;
- status = SetTxContinuousWave1( mlmeRequest->Req.TxCw.Timeout, mlmeRequest->Req.TxCw.Frequency, mlmeRequest->Req.TxCw.Power );
+ MlmeConfirmQueue[MlmeConfirmQueueCnt].MlmeRequest = mlmeRequest->Type;
+ MlmeConfirmQueueCnt++;
+ // LoRaMac will send this command piggy-pack
+ status = AddMacCommand( MOTE_MAC_BEACON_TIMING_REQ, 0, 0 );
+ break;
+ }
+ case MLME_BEACON_ACQUISITION:
+ {
+ // Apply the request
+ LoRaMacFlags.Bits.MlmeReq = 1;
+ MlmeConfirmQueue[MlmeConfirmQueueCnt].MlmeRequest = mlmeRequest->Type;
+ MlmeConfirmQueueCnt++;
+
+ if( ( LoRaMacClassBIsAcquisitionPending( ) == false ) && ( LoRaMacClassBIsAcquisitionTimerSet( ) == false ) )
+ {
+ // Start class B algorithm
+ LoRaMacClassBSetBeaconState( BEACON_STATE_ACQUISITION );
+ LoRaMacClassBBeaconTimerEvent( );
+
+ status = LORAMAC_STATUS_OK;
+ }
+ else
+ {
+ status = LORAMAC_STATUS_BUSY;
+ }
break;
}
default:
@@ -4366,7 +3649,11 @@
if( status != LORAMAC_STATUS_OK )
{
NodeAckRequested = false;
- LoRaMacFlags.Bits.MlmeReq = 0;
+ MlmeConfirmQueueCnt--;
+ if( MlmeConfirmQueueCnt == 0 )
+ {
+ LoRaMacFlags.Bits.MlmeReq = 0;
+ }
}
return status;
@@ -4374,8 +3661,11 @@
LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
LoRaMacHeader_t macHdr;
+ VerifyParams_t verify;
uint8_t fPort = 0;
void *fBuffer;
uint16_t fBufferSize;
@@ -4396,6 +3686,9 @@
memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) );
McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ // AckTimeoutRetriesCounter must be reset every time a new request (unconfirmed or confirmed) is performed.
+ AckTimeoutRetriesCounter = 1;
+
switch( mcpsRequest->Type )
{
case MCPS_UNCONFIRMED:
@@ -4413,7 +3706,6 @@
case MCPS_CONFIRMED:
{
readyToSend = true;
- AckTimeoutRetriesCounter = 1;
AckTimeoutRetries = mcpsRequest->Req.Confirmed.NbTrials;
macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
@@ -4438,13 +3730,24 @@
break;
}
+ // Get the minimum possible datarate
+ getPhy.Attribute = PHY_MIN_TX_DR;
+ getPhy.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ // Apply the minimum possible datarate.
+ // Some regions have limitations for the minimum datarate.
+ datarate = MAX( datarate, phyParam.Value );
+
if( readyToSend == true )
{
if( AdrCtrlOn == false )
{
- if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true )
+ verify.DatarateParams.Datarate = datarate;
+ verify.DatarateParams.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_TX_DR ) == true )
{
- LoRaMacParams.ChannelsDatarate = datarate;
+ LoRaMacParams.ChannelsDatarate = verify.DatarateParams.Datarate;
}
else
{
@@ -4480,52 +3783,17 @@
void LoRaMacTestSetDutyCycleOn( bool enable )
{
-#if ( defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) )
- DutyCycleOn = enable;
-#else
- DutyCycleOn = false;
-#endif
+ VerifyParams_t verify;
+
+ verify.DutyCycle = enable;
+
+ if( RegionVerify( LoRaMacRegion, &verify, PHY_DUTY_CYCLE ) == true )
+ {
+ DutyCycleOn = enable;
+ }
}
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;
-}
