Fork of Semtech LoRaWAN stack
Fork of LoRaWAN-lib by
Diff: LoRaMac.cpp
- Revision:
- 7:c16969e0f70f
- Parent:
- 6:d7a34ded7c87
- Child:
- 32:26002607de9c
--- a/LoRaMac.cpp Wed May 18 11:19:24 2016 +0000
+++ b/LoRaMac.cpp Tue Jul 05 13:24:54 2016 +0000
@@ -186,10 +186,20 @@
static uint8_t MacCommandsBufferIndex = 0;
/*!
+ * Contains the current MacCommandsBuffer index for MAC commands to repeat
+ */
+static uint8_t MacCommandsBufferToRepeatIndex = 0;
+
+/*!
* Buffer containing the MAC layer commands
*/
static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
+/*!
+ * Buffer containing the MAC layer commands which must be repeated
+ */
+static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
+
#if defined( USE_BAND_433 )
/*!
* Data rates table definition
@@ -324,28 +334,17 @@
{ 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
- { 0xFF , 0xFF , 0xFF , 0xFF },
- { 0xFF , 0xFF , 0xFF , 0xFF },
- { 0xFF , 0xFF , 0xFF , 0xFF },
- { DR_8 , DR_8 , DR_8 , DR_8 },
- { DR_9 , DR_8 , DR_8 , DR_8 },
- { DR_10, DR_9 , DR_8 , DR_8 },
- { DR_11, DR_10, DR_9 , DR_8 },
- { DR_12, DR_11, DR_10, DR_9 },
- { DR_13, DR_12, DR_11, DR_10 },
- { 0xFF , 0xFF , 0xFF , 0xFF },
- { 0xFF , 0xFF , 0xFF , 0xFF },
};
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
-const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 129, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
+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, 129, 242, 242, 0, 0, 0, 33, 103, 222, 222, 222, 222, 0, 0 };
+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
@@ -369,44 +368,35 @@
* Contains the channels which remain to be applied.
*/
static uint16_t ChannelsMaskRemaining[6];
+
+/*!
+ * Defines the first channel for RX window 2 for US band
+ */
+#define LORAMAC_FIRST_RX2_CHANNEL ( (uint32_t) 923.3e6 )
+
+/*!
+ * Defines the last channel for RX window 2 for US band
+ */
+#define LORAMAC_LAST_RX2_CHANNEL ( (uint32_t) 927.5e6 )
+
+/*!
+ * Defines the step width of the channels for RX window 2
+ */
+#define LORAMAC_STEPWIDTH_RX2_CHANNEL ( (uint32_t) 600e3 )
+
#else
#error "Please define a frequency band in the compiler options."
#endif
/*!
- * LoRaMAC 2nd reception window settings
- */
-static Rx2ChannelParams_t Rx2Channel = RX_WND_2_CHANNEL;
-
-/*!
- * Datarate offset between uplink and downlink on first window
+ * LoRaMac parameters
*/
-static uint8_t Rx1DrOffset = 0;
-
-/*!
- * Mask indicating which channels are enabled
- */
-static uint16_t ChannelsMask[6];
+LoRaMacParams_t LoRaMacParams;
/*!
- * Channels Tx output power
- */
-static int8_t ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
-
-/*!
- * Channels datarate
+ * LoRaMac default parameters
*/
-static int8_t ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
-
-/*!
- * Channels default datarate
- */
-static int8_t ChannelsDefaultDatarate = LORAMAC_DEFAULT_DATARATE;
-
-/*!
- * Number of uplink messages repetitions [1:15] (unconfirmed messages only)
- */
-static uint8_t ChannelsNbRep = 1;
+LoRaMacParams_t LoRaMacParamsDefaults;
/*!
* Uplink messages repetitions counter
@@ -436,6 +426,9 @@
*/
static uint8_t Channel;
+/*!
+ * Channel index of the last transmission
+ */
static uint8_t LastTxChannel;
/*!
@@ -490,14 +483,6 @@
static TimerEvent_t RxWindowTimer2;
/*!
- * LoRaMac reception windows delay from end of Tx
- */
-static uint32_t ReceiveDelay1;
-static uint32_t ReceiveDelay2;
-static uint32_t JoinAcceptDelay1;
-static uint32_t JoinAcceptDelay2;
-
-/*!
* LoRaMac reception windows delay
* \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
* join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
@@ -506,11 +491,6 @@
static uint32_t RxWindow2Delay;
/*!
- * LoRaMac maximum time a reception window stays open
- */
-static uint32_t MaxRxWindow;
-
-/*!
* Acknowledge timeout timer. Used for packet retransmissions.
*/
static TimerEvent_t AckTimeoutTimer;
@@ -536,6 +516,11 @@
TimerTime_t TxTimeOnAir = 0;
/*!
+ * Number of trials for the Join Request
+ */
+static uint16_t JoinRequestTrials;
+
+/*!
* Structure to hold an MCPS indication data.
*/
static McpsIndication_t McpsIndication;
@@ -645,6 +630,15 @@
static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
/*!
+ * \brief Verifies if the RX window 2 frequency is in range
+ *
+ * \param [IN] freq window channel frequency
+ *
+ * \retval status Function status [1: OK, 0: Frequency not applicable]
+ */
+static bool Rx2FreqInRange( uint32_t freq );
+
+/*!
* \brief Adds a new MAC command to be sent.
*
* \Remark MAC layer internal function
@@ -664,6 +658,20 @@
static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 );
/*!
+ * \brief Parses the MAC commands which must be repeated.
+ *
+ * \Remark MAC layer internal function
+ *
+ * \param [IN] cmdBufIn Buffer which stores the MAC commands to send
+ * \param [IN] length Length of the input buffer to parse
+ * \param [OUT] cmdBufOut Buffer which stores the MAC commands which must be
+ * repeated.
+ *
+ * \retval Size of the MAC commands to repeat.
+ */
+static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut );
+
+/*!
* \brief Validates if the payload fits into the frame, taking the datarate
* into account.
*
@@ -804,12 +812,27 @@
static LoRaMacStatus_t ScheduleTx( void );
/*
+ * \brief Sets the duty cycle for retransmissions
+ *
+ * \retval Duty cycle
+ */
+static uint16_t RetransmissionDutyCylce( void );
+
+/*
* \brief Calculates the back-off time for the band of a channel.
*
* \param [IN] channel The last Tx channel index
*/
static void CalculateBackOff( uint8_t channel );
+/*
+ * \brief Alternates the datarate of the channel for the join request.
+ *
+ * \param [IN] nbTrials Number of performed join requests.
+ * \retval Datarate to apply
+ */
+static int8_t AlternateDatarate( uint16_t nbTrials );
+
/*!
* \brief LoRaMAC layer prepared frame buffer transmission with channel specification
*
@@ -821,7 +844,10 @@
*/
LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel );
-
+/*!
+ * \brief Resets MAC specific parameters to default
+ */
+static void ResetMacParameters( void );
static void OnRadioTxDone( void )
{
@@ -980,26 +1006,26 @@
LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
// DLSettings
- Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
- Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
+ LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
+ LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
/*
* WARNING: To be removed once Semtech server implementation
* is corrected.
*/
- if( Rx2Channel.Datarate == DR_3 )
+ if( LoRaMacParams.Rx2Channel.Datarate == DR_3 )
{
- Rx2Channel.Datarate = DR_8;
+ LoRaMacParams.Rx2Channel.Datarate = DR_8;
}
#endif
// RxDelay
- ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
- if( ReceiveDelay1 == 0 )
+ LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
+ if( LoRaMacParams.ReceiveDelay1 == 0 )
{
- ReceiveDelay1 = 1;
+ LoRaMacParams.ReceiveDelay1 = 1;
}
- ReceiveDelay1 *= 1e6;
- ReceiveDelay2 = ReceiveDelay1 + 1e6;
+ LoRaMacParams.ReceiveDelay1 *= 1e6;
+ LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6;
#if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
//CFList
@@ -1019,7 +1045,7 @@
#endif
MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
IsLoRaMacNetworkJoined = true;
- ChannelsDatarate = ChannelsDefaultDatarate;
+ LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
}
else
{
@@ -1122,6 +1148,7 @@
McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
AdrAckCounter = 0;
+ MacCommandsBufferToRepeatIndex = 0;
// Update 32 bits downlink counter
if( multicast == 1 )
@@ -1191,11 +1218,6 @@
}
}
- if( fCtrl.Bits.FOptsLen > 0 )
- {
- // Decode Options field MAC commands
- ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
- }
if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
{
port = payload[appPayloadStartIndex++];
@@ -1205,19 +1227,32 @@
if( port == 0 )
{
- LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
- frameLen,
- nwkSKey,
- address,
- DOWN_LINK,
- downLinkCounter,
- LoRaMacRxPayload );
-
- // Decode frame payload MAC commands
- ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
+ if( fCtrl.Bits.FOptsLen == 0 )
+ {
+ LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
+ frameLen,
+ nwkSKey,
+ address,
+ DOWN_LINK,
+ downLinkCounter,
+ LoRaMacRxPayload );
+
+ // Decode frame payload MAC commands
+ ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
+ }
+ else
+ {
+ skipIndication = true;
+ }
}
else
{
+ if( fCtrl.Bits.FOptsLen > 0 )
+ {
+ // Decode Options field MAC commands. Omit the fPort.
+ ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr );
+ }
+
LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
frameLen,
appSKey,
@@ -1234,6 +1269,15 @@
}
}
}
+ else
+ {
+ if( fCtrl.Bits.FOptsLen > 0 )
+ {
+ // Decode Options field MAC commands
+ ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
+ }
+ }
+
if( skipIndication == false )
{
LoRaMacFlags.Bits.McpsInd = 1;
@@ -1370,17 +1414,20 @@
{
if( MlmeConfirm.MlmeRequest == MLME_JOIN )
{
+ // Retransmit only if the answer is not OK
+ ChannelsNbRepCounter = 0;
+
if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
{
+ // Stop retransmission
+ ChannelsNbRepCounter = LoRaMacParams.ChannelsNbRep;
UpLinkCounter = 0;
}
- // Join messages aren't repeated automatically
- ChannelsNbRepCounter = ChannelsNbRep;
}
}
if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
{
- if( ( ChannelsNbRepCounter >= ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
+ if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
{
ChannelsNbRepCounter = 0;
@@ -1426,7 +1473,7 @@
if( ( AckTimeoutRetriesCounter % 2 ) == 1 )
{
- ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
+ LoRaMacParams.ChannelsDatarate = MAX( LoRaMacParams.ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
}
LoRaMacFlags.Bits.MacDone = 0;
// Sends the same frame again
@@ -1436,18 +1483,18 @@
{
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
// Re-enable default channels LC1, LC2, LC3
- ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
+ LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
#elif defined( USE_BAND_915 )
// Re-enable default channels
- ChannelsMask[0] = 0xFFFF;
- ChannelsMask[1] = 0xFFFF;
- ChannelsMask[2] = 0xFFFF;
- ChannelsMask[3] = 0xFFFF;
- ChannelsMask[4] = 0x00FF;
- ChannelsMask[5] = 0x0000;
+ LoRaMacParams.ChannelsMask[0] = 0xFFFF;
+ LoRaMacParams.ChannelsMask[1] = 0xFFFF;
+ LoRaMacParams.ChannelsMask[2] = 0xFFFF;
+ LoRaMacParams.ChannelsMask[3] = 0xFFFF;
+ LoRaMacParams.ChannelsMask[4] = 0x00FF;
+ LoRaMacParams.ChannelsMask[5] = 0x0000;
#elif defined( USE_BAND_915_HYBRID )
// Re-enable default channels
- ReenableChannels( ChannelsMask[4], ChannelsMask );
+ ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
#else
#error "Please define a frequency band in the compiler options."
#endif
@@ -1500,9 +1547,26 @@
static void OnTxDelayedTimerEvent( void )
{
+ LoRaMacHeader_t macHdr;
+ LoRaMacFrameCtrl_t fCtrl;
+
TimerStop( &TxDelayedTimer );
LoRaMacState &= ~MAC_TX_DELAYED;
+ if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
+ {
+ macHdr.Value = 0;
+ macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
+
+ fCtrl.Value = 0;
+ fCtrl.Bits.Adr = AdrCtrlOn;
+
+ /* In case of a join request retransmission, the stack must prepare
+ * the frame again, because the network server keeps track of the random
+ * LoRaMacDevNonce values to prevent reply attacks. */
+ PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 );
+ }
+
ScheduleTx( );
}
@@ -1521,7 +1585,7 @@
}
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- datarate = ChannelsDatarate - Rx1DrOffset;
+ datarate = LoRaMacParams.ChannelsDatarate - LoRaMacParams.Rx1DrOffset;
if( datarate < 0 )
{
datarate = DR_0;
@@ -1543,7 +1607,7 @@
}
RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
- datarate = datarateOffsets[ChannelsDatarate][Rx1DrOffset];
+ datarate = datarateOffsets[LoRaMacParams.ChannelsDatarate][LoRaMacParams.Rx1DrOffset];
if( datarate < 0 )
{
datarate = DR_0;
@@ -1583,7 +1647,7 @@
{// LoRa 500 kHz
bandwidth = 2;
}
- RxWindowSetup( 923.3e6 + ( Channel % 8 ) * 600e3, datarate, bandwidth, symbTimeout, false );
+ RxWindowSetup( LORAMAC_FIRST_RX2_CHANNEL + ( Channel % 8 ) * LORAMAC_STEPWIDTH_RX2_CHANNEL, datarate, bandwidth, symbTimeout, false );
#else
#error "Please define a frequency band in the compiler options."
#endif
@@ -1599,22 +1663,22 @@
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
// For higher datarates, we increase the number of symbols generating a Rx Timeout
- if( ( Rx2Channel.Datarate == DR_3 ) || ( Rx2Channel.Datarate == DR_4 ) )
+ if( ( LoRaMacParams.Rx2Channel.Datarate == DR_3 ) || ( LoRaMacParams.Rx2Channel.Datarate == DR_4 ) )
{ // DR_4, DR_3
symbTimeout = 8;
}
- else if( Rx2Channel.Datarate == DR_5 )
+ else if( LoRaMacParams.Rx2Channel.Datarate == DR_5 )
{
symbTimeout = 10;
}
- else if( Rx2Channel.Datarate == DR_6 )
+ else if( LoRaMacParams.Rx2Channel.Datarate == DR_6 )
{// LoRa 250 kHz
bandwidth = 1;
symbTimeout = 14;
}
#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
// For higher datarates, we increase the number of symbols generating a Rx Timeout
- switch( Rx2Channel.Datarate )
+ switch( LoRaMacParams.Rx2Channel.Datarate )
{
case DR_0: // SF10 - BW125
symbTimeout = 5;
@@ -1644,7 +1708,7 @@
default:
break;
}
- if( Rx2Channel.Datarate >= DR_4 )
+ if( LoRaMacParams.Rx2Channel.Datarate >= DR_4 )
{// LoRa 500 kHz
bandwidth = 2;
}
@@ -1653,11 +1717,11 @@
#endif
if( LoRaMacDeviceClass != CLASS_C )
{
- RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, false );
+ RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, false );
}
else
{
- RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, true );
+ RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, true );
}
}
@@ -1688,17 +1752,17 @@
#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 )
{ // Restore default channels
- memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 8 );
+ memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParams.ChannelsMask, 8 );
}
- if( ( ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) )
+ if( ( LoRaMacParams.ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) )
{ // Make sure, that the channels are activated
- ChannelsMaskRemaining[4] = ChannelsMask[4];
+ ChannelsMaskRemaining[4] = LoRaMacParams.ChannelsMask[4];
}
#else
- if( CountBits( ChannelsMask[0], 16 ) == 0 )
+ if( CountBits( LoRaMacParams.ChannelsMask[0], 16 ) == 0 )
{
// Re-enable default channels, if no channel is enabled
- ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
+ LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
}
#endif
@@ -1738,7 +1802,7 @@
#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
if( ( ChannelsMaskRemaining[k] & ( 1 << j ) ) != 0 )
#else
- if( ( ChannelsMask[k] & ( 1 << j ) ) != 0 )
+ if( ( LoRaMacParams.ChannelsMask[k] & ( 1 << j ) ) != 0 )
#endif
{
if( Channels[i + j].Frequency == 0 )
@@ -1754,8 +1818,8 @@
}
}
#endif
- if( ( ( Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate ) &&
- ( ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false )
+ 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;
}
@@ -1856,7 +1920,7 @@
if( rxContinuous == false )
{
- Radio.Rx( MaxRxWindow );
+ Radio.Rx( LoRaMacParams.MaxRxWindow );
}
else
{
@@ -1865,6 +1929,22 @@
}
}
+static bool Rx2FreqInRange( uint32_t freq )
+{
+#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
+ if( Radio.CheckRfFrequency( freq ) == true )
+#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+ if( ( Radio.CheckRfFrequency( freq ) == true ) &&
+ ( freq >= LORAMAC_FIRST_RX2_CHANNEL ) &&
+ ( freq <= LORAMAC_LAST_RX2_CHANNEL ) &&
+ ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX2_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX2_CHANNEL ) == 0 ) )
+#endif
+ {
+ return true;
+ }
+ return false;
+}
+
static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
{
uint16_t maxN = 0;
@@ -1987,14 +2067,14 @@
{
int8_t resultTxPower = txPower;
#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- if( ( ChannelsDatarate == DR_4 ) ||
- ( ( ChannelsDatarate >= DR_8 ) && ( ChannelsDatarate <= DR_13 ) ) )
+ 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( ChannelsMask ) < 50 )
+ if( CountNbEnabled125kHzChannels( LoRaMacParams.ChannelsMask ) < 50 )
{// Limit tx power to max 21dBm
resultTxPower = MAX( txPower, TX_POWER_20_DBM );
}
@@ -2031,7 +2111,7 @@
static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut )
{
bool adrAckReq = false;
- int8_t datarate = ChannelsDatarate;
+ int8_t datarate = LoRaMacParams.ChannelsDatarate;
if( adrEnabled == true )
{
@@ -2052,7 +2132,7 @@
}
if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) )
{
- if( ( ( AdrAckCounter - ADR_ACK_DELAY ) % ADR_ACK_LIMIT ) == 0 )
+ if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 )
{
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
if( datarate > LORAMAC_TX_MIN_DATARATE )
@@ -2063,9 +2143,8 @@
{
if( updateChannelMask == true )
{
-
// Re-enable default channels LC1, LC2, LC3
- ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
+ LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
}
}
#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
@@ -2083,15 +2162,15 @@
{
#if defined( USE_BAND_915 )
// Re-enable default channels
- ChannelsMask[0] = 0xFFFF;
- ChannelsMask[1] = 0xFFFF;
- ChannelsMask[2] = 0xFFFF;
- ChannelsMask[3] = 0xFFFF;
- ChannelsMask[4] = 0x00FF;
- ChannelsMask[5] = 0x0000;
+ LoRaMacParams.ChannelsMask[0] = 0xFFFF;
+ LoRaMacParams.ChannelsMask[1] = 0xFFFF;
+ LoRaMacParams.ChannelsMask[2] = 0xFFFF;
+ LoRaMacParams.ChannelsMask[3] = 0xFFFF;
+ LoRaMacParams.ChannelsMask[4] = 0x00FF;
+ LoRaMacParams.ChannelsMask[5] = 0x0000;
#else // defined( USE_BAND_915_HYBRID )
// Re-enable default channels
- ReenableChannels( ChannelsMask[4], ChannelsMask );
+ ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
#endif
}
}
@@ -2111,11 +2190,13 @@
static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
{
LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
+ // The maximum buffer length must take MAC commands to re-send into account.
+ uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex;
switch( cmd )
{
case MOTE_MAC_LINK_CHECK_REQ:
- if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ if( MacCommandsBufferIndex < bufLen )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this command
@@ -2123,7 +2204,7 @@
}
break;
case MOTE_MAC_LINK_ADR_ANS:
- if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
+ if( MacCommandsBufferIndex < ( bufLen - 1 ) )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Margin
@@ -2132,7 +2213,7 @@
}
break;
case MOTE_MAC_DUTY_CYCLE_ANS:
- if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ if( MacCommandsBufferIndex < bufLen )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this answer
@@ -2140,7 +2221,7 @@
}
break;
case MOTE_MAC_RX_PARAM_SETUP_ANS:
- if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
+ if( MacCommandsBufferIndex < ( bufLen - 1 ) )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Status: Datarate ACK, Channel ACK
@@ -2149,7 +2230,7 @@
}
break;
case MOTE_MAC_DEV_STATUS_ANS:
- if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 2 ) )
+ if( MacCommandsBufferIndex < ( bufLen - 2 ) )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// 1st byte Battery
@@ -2160,7 +2241,7 @@
}
break;
case MOTE_MAC_NEW_CHANNEL_ANS:
- if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
+ if( MacCommandsBufferIndex < ( bufLen - 1 ) )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Status: Datarate range OK, Channel frequency OK
@@ -2169,7 +2250,7 @@
}
break;
case MOTE_MAC_RX_TIMING_SETUP_ANS:
- if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ if( MacCommandsBufferIndex < bufLen )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this answer
@@ -2186,6 +2267,40 @@
return status;
}
+static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut )
+{
+ uint8_t i = 0;
+ uint8_t cmdCount = 0;
+
+ if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) )
+ {
+ return 0;
+ }
+
+ for( i = 0; i < length; i++ )
+ {
+ switch( cmdBufIn[i] )
+ {
+ case MOTE_MAC_RX_PARAM_SETUP_ANS:
+ {
+ cmdBufOut[cmdCount++] = cmdBufIn[i++];
+ cmdBufOut[cmdCount++] = cmdBufIn[i++];
+ cmdBufOut[cmdCount++] = cmdBufIn[i];
+ break;
+ }
+ case MOTE_MAC_RX_TIMING_SETUP_ANS:
+ {
+ cmdBufOut[cmdCount++] = cmdBufIn[i];
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return cmdCount;
+}
+
static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr )
{
while( macIndex < commandsSize )
@@ -2212,14 +2327,14 @@
// Initialize local copy of the channels mask array
for( i = 0; i < 6; i++ )
{
- channelsMask[i] = ChannelsMask[i];
+ channelsMask[i] = LoRaMacParams.ChannelsMask[i];
}
datarate = payload[macIndex++];
txPower = datarate & 0x0F;
datarate = ( datarate >> 4 ) & 0x0F;
if( ( AdrCtrlOn == false ) &&
- ( ( ChannelsDatarate != datarate ) || ( ChannelsTxPower != txPower ) ) )
+ ( ( 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
@@ -2341,17 +2456,17 @@
}
if( ( status & 0x07 ) == 0x07 )
{
- ChannelsDatarate = datarate;
- ChannelsTxPower = txPower;
-
- ChannelsMask[0] = channelsMask[0];
- ChannelsMask[1] = channelsMask[1];
- ChannelsMask[2] = channelsMask[2];
- ChannelsMask[3] = channelsMask[3];
- ChannelsMask[4] = channelsMask[4];
- ChannelsMask[5] = channelsMask[5];
-
- ChannelsNbRep = nbRep;
+ LoRaMacParams.ChannelsDatarate = datarate;
+ LoRaMacParams.ChannelsTxPower = txPower;
+
+ LoRaMacParams.ChannelsMask[0] = channelsMask[0];
+ LoRaMacParams.ChannelsMask[1] = channelsMask[1];
+ LoRaMacParams.ChannelsMask[2] = channelsMask[2];
+ LoRaMacParams.ChannelsMask[3] = channelsMask[3];
+ LoRaMacParams.ChannelsMask[4] = channelsMask[4];
+ LoRaMacParams.ChannelsMask[5] = channelsMask[5];
+
+ LoRaMacParams.ChannelsNbRep = nbRep;
}
AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
}
@@ -2377,7 +2492,7 @@
freq |= ( uint32_t )payload[macIndex++] << 16;
freq *= 100;
- if( Radio.CheckRfFrequency( freq ) == false )
+ if( Rx2FreqInRange( freq ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -2400,9 +2515,9 @@
if( ( status & 0x07 ) == 0x07 )
{
- Rx2Channel.Datarate = datarate;
- Rx2Channel.Frequency = freq;
- Rx1DrOffset = drOffset;
+ LoRaMacParams.Rx2Channel.Datarate = datarate;
+ LoRaMacParams.Rx2Channel.Frequency = freq;
+ LoRaMacParams.Rx1DrOffset = drOffset;
}
AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
}
@@ -2493,8 +2608,8 @@
{
delay++;
}
- ReceiveDelay1 = delay * 1e6;
- ReceiveDelay2 = ReceiveDelay1 + 1e6;
+ LoRaMacParams.ReceiveDelay1 = delay * 1e6;
+ LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6;
AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
}
break;
@@ -2556,11 +2671,11 @@
while( SetNextChannel( &dutyCycleTimeOff ) == false )
{
// Set the default datarate
- ChannelsDatarate = ChannelsDefaultDatarate;
+ LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
// Re-enable default channels LC1, LC2, LC3
- ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
+ LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
#endif
}
@@ -2581,15 +2696,45 @@
}
}
+static uint16_t RetransmissionDutyCylce( void )
+{
+ uint16_t dutyCycle = 0;
+
+#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
+ TimerTime_t timeElapsed = TimerGetElapsedTime( 0 );
+
+ if( timeElapsed < 3600000000 )
+ {
+ dutyCycle = BACKOFF_DC_1_HOUR;
+ }
+ else if( timeElapsed < ( 3600000000 + 36000000000 ) )
+ {
+ dutyCycle = BACKOFF_DC_10_HOURS;
+ }
+ else
+ {
+ dutyCycle = BACKOFF_DC_24_HOURS;
+ }
+#endif
+ return dutyCycle;
+}
+
static void CalculateBackOff( uint8_t channel )
{
uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
+ uint16_t joinDutyCycle = 0;
+ bool rndTimeOff = false;
if( IsLoRaMacNetworkJoined == false )
{
-#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
- dutyCycle = JOIN_DC;
-#endif
+ joinDutyCycle = RetransmissionDutyCylce( );
+ dutyCycle = MAX( dutyCycle, joinDutyCycle );
+
+ // Make sure to not apply the random back-off to the first TX
+ if( TxTimeOnAir > 0 )
+ {
+ rndTimeOff = true;
+ }
}
// Update Band Time OFF
@@ -2601,10 +2746,126 @@
{
Bands[Channels[channel].Band].TimeOff = 0;
}
+
+ if( rndTimeOff == true )
+ {
+ Bands[Channels[channel].Band].TimeOff = randr( Bands[Channels[channel].Band].TimeOff,
+ Bands[Channels[channel].Band].TimeOff + BACKOFF_RND_OFFSET );
+ }
+
// Update Aggregated Time OFF
AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
}
+static int8_t AlternateDatarate( uint16_t nbTrials )
+{
+ 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( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
+#endif
+
+ if( ( nbTrials & 0x01 ) == 0x01 )
+ {
+ datarate = DR_4;
+ }
+ else
+ {
+ datarate = DR_1;
+ }
+#else
+ if( ( nbTrials % 48 ) == 0 )
+ {
+ datarate = DR_0;
+ }
+ else if( ( nbTrials % 32 ) == 0 )
+ {
+ datarate = DR_1;
+ }
+ else if( ( nbTrials % 24 ) == 0 )
+ {
+ datarate = DR_2;
+ }
+ else if( ( nbTrials % 16 ) == 0 )
+ {
+ datarate = DR_3;
+ }
+ else if( ( nbTrials % 8 ) == 0 )
+ {
+ datarate = DR_4;
+ }
+ else
+ {
+ datarate = DR_5;
+ }
+#endif
+ return datarate;
+}
+
+static void ResetMacParameters( void )
+{
+ IsLoRaMacNetworkJoined = false;
+
+ // Counters
+ UpLinkCounter = 1;
+ DownLinkCounter = 0;
+ AdrAckCounter = 0;
+
+ ChannelsNbRepCounter = 0;
+
+ AckTimeoutRetries = 1;
+ AckTimeoutRetriesCounter = 1;
+ AckTimeoutRetry = false;
+
+ MaxDCycle = 0;
+ AggregatedDCycle = 1;
+
+ MacCommandsBufferIndex = 0;
+ MacCommandsBufferToRepeatIndex = 0;
+
+ IsRxWindowsEnabled = true;
+
+ LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
+ LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
+
+ LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow;
+ LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1;
+ LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2;
+ LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1;
+ LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2;
+
+ LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset;
+ LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep;
+
+ LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
+
+ memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
+
+#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+ memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
+#endif
+
+
+ NodeAckRequested = false;
+ SrvAckRequested = false;
+ MacCommandsInNextTx = false;
+
+ // Reset Multicast downlink counters
+ MulticastParams_t *cur = MulticastChannels;
+ while( cur != NULL )
+ {
+ cur->DownLinkCounter = 0;
+ cur = cur->Next;
+ }
+
+ // Initialize channel index.
+ Channel = LORA_MAX_NB_CHANNELS;
+}
+
LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
{
uint16_t i;
@@ -2628,8 +2889,8 @@
switch( macHdr->Bits.MType )
{
case FRAME_TYPE_JOIN_REQ:
- RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
- RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
+ RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
+ RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
LoRaMacBufferPktLen = pktHeaderLen;
@@ -2660,15 +2921,15 @@
return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet
}
- fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate );
-
- if( ValidatePayloadLength( fBufferSize, ChannelsDatarate, MacCommandsBufferIndex ) == false )
+ fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate );
+
+ if( ValidatePayloadLength( fBufferSize, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false )
{
return LORAMAC_STATUS_LENGTH_ERROR;
}
- RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME;
- RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME;
+ RxWindow1Delay = LoRaMacParams.ReceiveDelay1 - RADIO_WAKEUP_TIME;
+ RxWindow2Delay = LoRaMacParams.ReceiveDelay2 - RADIO_WAKEUP_TIME;
if( SrvAckRequested == true )
{
@@ -2686,6 +2947,10 @@
LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
+ // Copy the MAC commands which must be re-send into the MAC command buffer
+ memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
+ MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
+
if( ( payload != NULL ) && ( payloadSize > 0 ) )
{
if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
@@ -2710,6 +2975,12 @@
}
}
MacCommandsInNextTx = false;
+ // Store MAC commands which must be re-send in case the device does not receive a downlink anymore
+ MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat );
+ if( MacCommandsBufferToRepeatIndex > 0 )
+ {
+ MacCommandsInNextTx = true;
+ }
MacCommandsBufferIndex = 0;
if( ( payload != NULL ) && ( payloadSize > 0 ) )
@@ -2754,29 +3025,29 @@
LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel )
{
- int8_t datarate = Datarates[ChannelsDatarate];
+ int8_t datarate = Datarates[LoRaMacParams.ChannelsDatarate];
int8_t txPowerIndex = 0;
int8_t txPower = 0;
- txPowerIndex = LimitTxPower( ChannelsTxPower );
+ txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower );
txPower = TxPowers[txPowerIndex];
MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- McpsConfirm.Datarate = ChannelsDatarate;
+ McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
McpsConfirm.TxPower = txPowerIndex;
Radio.SetChannel( channel.Frequency );
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- if( ChannelsDatarate == DR_7 )
+ if( LoRaMacParams.ChannelsDatarate == DR_7 )
{ // High Speed FSK channel
Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen );
Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 );
TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
}
- else if( ChannelsDatarate == DR_6 )
+ else if( LoRaMacParams.ChannelsDatarate == DR_6 )
{ // High speed LoRa channel
Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
@@ -2790,7 +3061,7 @@
}
#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
- if( ChannelsDatarate >= DR_4 )
+ if( LoRaMacParams.ChannelsDatarate >= DR_4 )
{ // High speed LoRa channel BW500 kHz
Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
@@ -2840,40 +3111,64 @@
LoRaMacFlags.Value = 0;
LoRaMacDeviceClass = CLASS_A;
-
- UpLinkCounter = 1;
- DownLinkCounter = 0;
- AdrAckCounter = 0;
-
+ LoRaMacState = MAC_IDLE;
+
+ JoinRequestTrials = 0;
RepeaterSupport = false;
- IsRxWindowsEnabled = true;
- IsLoRaMacNetworkJoined = false;
- LoRaMacState = MAC_IDLE;
-
+
+ // Reset duty cycle times
+ AggregatedLastTxDoneTime = 0;
+ AggregatedTimeOff = 0;
+
+ // Duty cycle
#if defined( USE_BAND_433 )
- ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+ DutyCycleOn = false;
#elif defined( USE_BAND_780 )
- ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+ DutyCycleOn = false;
#elif defined( USE_BAND_868 )
- ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+ 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;
+
+ 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_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 )
- ChannelsMask[0] = 0xFFFF;
- ChannelsMask[1] = 0xFFFF;
- ChannelsMask[2] = 0xFFFF;
- ChannelsMask[3] = 0xFFFF;
- ChannelsMask[4] = 0x00FF;
- ChannelsMask[5] = 0x0000;
-
- memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) );
+ 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 )
- ChannelsMask[0] = 0x00FF;
- ChannelsMask[1] = 0x0000;
- ChannelsMask[2] = 0x0000;
- ChannelsMask[3] = 0x0000;
- ChannelsMask[4] = 0x0001;
- ChannelsMask[5] = 0x0000;
-
- memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) );
+ 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
@@ -2895,34 +3190,9 @@
}
#endif
- ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
- ChannelsDefaultDatarate = ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
- ChannelsNbRep = 1;
- ChannelsNbRepCounter = 0;
-
- MaxDCycle = 0;
- AggregatedDCycle = 1;
- AggregatedLastTxDoneTime = 0;
- AggregatedTimeOff = 0;
-
-#if defined( USE_BAND_433 )
- DutyCycleOn = false;
-#elif defined( USE_BAND_780 )
- DutyCycleOn = false;
-#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
-
- MaxRxWindow = MAX_RX_WINDOW;
- ReceiveDelay1 = RECEIVE_DELAY1;
- ReceiveDelay2 = RECEIVE_DELAY2;
- JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
- JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
-
+ ResetMacParameters( );
+
+ // Initialize timers
TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent );
TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
@@ -2942,9 +3212,6 @@
// Random seed initialization
srand1( Radio.Random( ) );
- // Initialize channel index.
- Channel = LORA_MAX_NB_CHANNELS;
-
PublicNetwork = true;
SetPublicNetwork( PublicNetwork );
Radio.Sleep( );
@@ -2954,7 +3221,8 @@
LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
{
- int8_t datarate = ChannelsDefaultDatarate;
+ int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate;
+ uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
if( txInfo == NULL )
{
@@ -2972,9 +3240,9 @@
txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate];
}
- if( txInfo->CurrentPayloadSize >= MacCommandsBufferIndex )
+ if( txInfo->CurrentPayloadSize >= fOptLen )
{
- txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - MacCommandsBufferIndex;
+ txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
}
else
{
@@ -2986,7 +3254,7 @@
return LORAMAC_STATUS_LENGTH_ERROR;
}
- if( ValidatePayloadLength( size, datarate, MacCommandsBufferIndex ) == false )
+ if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
{
return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
}
@@ -3057,57 +3325,57 @@
}
case MIB_RX2_CHANNEL:
{
- mibGet->Param.Rx2Channel = Rx2Channel;
+ mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel;
break;
}
case MIB_CHANNELS_MASK:
{
- mibGet->Param.ChannelsMask = ChannelsMask;
+ mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask;
break;
}
case MIB_CHANNELS_NB_REP:
{
- mibGet->Param.ChannelNbRep = ChannelsNbRep;
+ mibGet->Param.ChannelNbRep = LoRaMacParams.ChannelsNbRep;
break;
}
case MIB_MAX_RX_WINDOW_DURATION:
{
- mibGet->Param.MaxRxWindow = MaxRxWindow;
+ mibGet->Param.MaxRxWindow = LoRaMacParams.MaxRxWindow;
break;
}
case MIB_RECEIVE_DELAY_1:
{
- mibGet->Param.ReceiveDelay1 = ReceiveDelay1;
+ mibGet->Param.ReceiveDelay1 = LoRaMacParams.ReceiveDelay1;
break;
}
case MIB_RECEIVE_DELAY_2:
{
- mibGet->Param.ReceiveDelay2 = ReceiveDelay2;
+ mibGet->Param.ReceiveDelay2 = LoRaMacParams.ReceiveDelay2;
break;
}
case MIB_JOIN_ACCEPT_DELAY_1:
{
- mibGet->Param.JoinAcceptDelay1 = JoinAcceptDelay1;
+ mibGet->Param.JoinAcceptDelay1 = LoRaMacParams.JoinAcceptDelay1;
break;
}
case MIB_JOIN_ACCEPT_DELAY_2:
{
- mibGet->Param.JoinAcceptDelay2 = JoinAcceptDelay2;
+ mibGet->Param.JoinAcceptDelay2 = LoRaMacParams.JoinAcceptDelay2;
break;
}
case MIB_CHANNELS_DEFAULT_DATARATE:
{
- mibGet->Param.ChannelsDefaultDatarate = ChannelsDefaultDatarate;
+ mibGet->Param.ChannelsDefaultDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
break;
}
case MIB_CHANNELS_DATARATE:
{
- mibGet->Param.ChannelsDatarate = ChannelsDatarate;
+ mibGet->Param.ChannelsDatarate = LoRaMacParams.ChannelsDatarate;
break;
}
case MIB_CHANNELS_TX_POWER:
{
- mibGet->Param.ChannelsTxPower = ChannelsTxPower;
+ mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower;
break;
}
case MIB_UPLINK_COUNTER:
@@ -3231,7 +3499,7 @@
}
case MIB_RX2_CHANNEL:
{
- Rx2Channel = mibSet->Param.Rx2Channel;
+ LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel;
break;
}
case MIB_CHANNELS_MASK:
@@ -3253,12 +3521,12 @@
}
else
{
- memcpy1( ( uint8_t* ) ChannelsMask,
- ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( ChannelsMask ) );
- for ( uint8_t i = 0; i < sizeof( ChannelsMask ) / 2; i++ )
+ 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] &= ChannelsMask[i];
+ ChannelsMaskRemaining[i] &= LoRaMacParams.ChannelsMask[i];
}
}
}
@@ -3267,7 +3535,7 @@
status = LORAMAC_STATUS_PARAMETER_INVALID;
}
#else
- memcpy1( ( uint8_t* ) ChannelsMask,
+ memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
( uint8_t* ) mibSet->Param.ChannelsMask, 2 );
#endif
}
@@ -3282,7 +3550,7 @@
if( ( mibSet->Param.ChannelNbRep >= 1 ) &&
( mibSet->Param.ChannelNbRep <= 15 ) )
{
- ChannelsNbRep = mibSet->Param.ChannelNbRep;
+ LoRaMacParams.ChannelsNbRep = mibSet->Param.ChannelNbRep;
}
else
{
@@ -3292,27 +3560,27 @@
}
case MIB_MAX_RX_WINDOW_DURATION:
{
- MaxRxWindow = mibSet->Param.MaxRxWindow;
+ LoRaMacParams.MaxRxWindow = mibSet->Param.MaxRxWindow;
break;
}
case MIB_RECEIVE_DELAY_1:
{
- ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
+ LoRaMacParams.ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
break;
}
case MIB_RECEIVE_DELAY_2:
{
- ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
+ LoRaMacParams.ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
break;
}
case MIB_JOIN_ACCEPT_DELAY_1:
{
- JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
+ LoRaMacParams.JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
break;
}
case MIB_JOIN_ACCEPT_DELAY_2:
{
- JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
+ LoRaMacParams.JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
break;
}
case MIB_CHANNELS_DEFAULT_DATARATE:
@@ -3320,7 +3588,7 @@
if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
{
- ChannelsDefaultDatarate = mibSet->Param.ChannelsDefaultDatarate;
+ LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
}
else
{
@@ -3333,7 +3601,7 @@
if( ValueInRange( mibSet->Param.ChannelsDatarate,
LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
{
- ChannelsDatarate = mibSet->Param.ChannelsDatarate;
+ LoRaMacParams.ChannelsDatarate = mibSet->Param.ChannelsDatarate;
}
else
{
@@ -3346,7 +3614,7 @@
if( ValueInRange( mibSet->Param.ChannelsTxPower,
LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
{
- ChannelsTxPower = mibSet->Param.ChannelsTxPower;
+ LoRaMacParams.ChannelsTxPower = mibSet->Param.ChannelsTxPower;
}
else
{
@@ -3412,7 +3680,7 @@
frequencyInvalid = true;
}
- if( params.DrRange.Fields.Min > ChannelsDefaultDatarate )
+ if( params.DrRange.Fields.Min > LoRaMacParamsDefaults.ChannelsDatarate )
{
datarateInvalid = true;
}
@@ -3474,7 +3742,7 @@
// Every parameter is valid, activate the channel
Channels[id] = params;
Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ LoRaMacParams.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
#endif
@@ -3501,7 +3769,7 @@
Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 };
// Disable the channel as it doesn't exist anymore
- if( DisableChannelInMask( id, ChannelsMask ) == false )
+ if( DisableChannelInMask( id, LoRaMacParams.ChannelsMask ) == false )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
@@ -3631,28 +3899,10 @@
macHdr.Value = 0;
macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
- IsLoRaMacNetworkJoined = false;
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-#if defined( USE_BAND_915 )
- // Re-enable 500 kHz default channels
- ChannelsMask[4] = 0x00FF;
-#else // defined( USE_BAND_915_HYBRID )
- // Re-enable 500 kHz default channels
- ChannelsMask[4] = 0x0001;
-#endif
-
- static uint8_t drSwitch = 0;
-
- if( ( ++drSwitch & 0x01 ) == 0x01 )
- {
- ChannelsDatarate = DR_0;
- }
- else
- {
- ChannelsDatarate = DR_4;
- }
-#endif
+ ResetMacParameters( );
+
+ JoinRequestTrials++;
+ LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials );
status = Send( &macHdr, 0, NULL, 0 );
break;
@@ -3751,7 +4001,7 @@
{
if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true )
{
- ChannelsDatarate = datarate;
+ LoRaMacParams.ChannelsDatarate = datarate;
}
else
{


