Fork of Semtech LoRaWAN stack
Fork of LoRaWAN-lib by
Diff: LoRaMac.cpp
- Revision:
- 32:26002607de9c
- Parent:
- 7:c16969e0f70f
- Child:
- 33:db4900d60c37
--- a/LoRaMac.cpp Tue Jul 05 13:24:54 2016 +0000
+++ b/LoRaMac.cpp Mon Apr 24 09:42:37 2017 +0000
@@ -17,6 +17,7 @@
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
*/
+#include <math.h>
#include "board.h"
#include "LoRaMacCrypto.h"
@@ -41,6 +42,21 @@
#define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
/*!
+ * LoRaMac duty cycle for the back-off procedure during the first hour.
+ */
+#define BACKOFF_DC_1_HOUR 100
+
+/*!
+ * LoRaMac duty cycle for the back-off procedure during the next 10 hours.
+ */
+#define BACKOFF_DC_10_HOURS 1000
+
+/*!
+ * LoRaMac duty cycle for the back-off procedure during the next 24 hours.
+ */
+#define BACKOFF_DC_24_HOURS 10000
+
+/*!
* Device IEEE EUI
*/
static uint8_t *LoRaMacDevEui;
@@ -120,16 +136,20 @@
static uint16_t LoRaMacBufferPktLen = 0;
/*!
+ * Length of the payload in LoRaMacBuffer
+ */
+static uint8_t LoRaMacTxPayloadLen = 0;
+
+/*!
* Buffer containing the upper layer data.
*/
-static uint8_t LoRaMacPayload[LORAMAC_PHY_MAXPAYLOAD];
static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];
/*!
* LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
* Only the 16 LSB bits are sent
*/
-static uint32_t UpLinkCounter = 1;
+static uint32_t UpLinkCounter = 0;
/*!
* LoRaMAC frame counter. Each time a packet is received the counter is incremented.
@@ -207,19 +227,24 @@
const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 250e3, 0 };
+
+/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
-const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
+const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
+const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* Tx output powers table definition
*/
-const int8_t TxPowers[] = { 20, 14, 11, 8, 5, 2 };
+const int8_t TxPowers[] = { 10, 7, 4, 1, -2, -5 };
/*!
* LoRaMac bands
@@ -238,6 +263,61 @@
LC2,
LC3,
};
+#elif defined( USE_BAND_470 )
+
+/*!
+ * Data rates table definition
+ */
+const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7 };
+
+/*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3 };
+
+/*!
+ * Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ */
+const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 222, 222 };
+
+/*!
+ * Maximum payload with respect to the datarate index. Can operate with repeater.
+ */
+const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222 };
+
+/*!
+ * Tx output powers table definition
+ */
+const int8_t TxPowers[] = { 17, 16, 14, 12, 10, 7, 5, 2 };
+
+/*!
+ * LoRaMac bands
+ */
+static Band_t Bands[LORA_MAX_NB_BANDS] =
+{
+ BAND0,
+};
+
+/*!
+ * LoRaMAC channels
+ */
+static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS];
+
+/*!
+ * Defines the first channel for RX window 1 for CN470 band
+ */
+#define LORAMAC_FIRST_RX1_CHANNEL ( (uint32_t) 500.3e6 )
+
+/*!
+ * Defines the last channel for RX window 1 for CN470 band
+ */
+#define LORAMAC_LAST_RX1_CHANNEL ( (uint32_t) 509.7e6 )
+
+/*!
+ * Defines the step width of the channels for RX window 1
+ */
+#define LORAMAC_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 200e3 )
+
#elif defined( USE_BAND_780 )
/*!
* Data rates table definition
@@ -245,19 +325,24 @@
const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 250e3, 0 };
+
+/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
-const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
+const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
*/
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
+const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
/*!
* Tx output powers table definition
*/
-const int8_t TxPowers[] = { 20, 14, 11, 8, 5, 2 };
+const int8_t TxPowers[] = { 10, 7, 4, 1, -2, -5 };
/*!
* LoRaMac bands
@@ -283,6 +368,11 @@
const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
/*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 125e3, 125e3, 250e3, 0 };
+
+/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
@@ -325,9 +415,14 @@
const uint8_t Datarates[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
/*!
+ * Bandwidths table definition in Hz
+ */
+const uint32_t Bandwidths[] = { 125e3, 125e3, 125e3, 125e3, 500e3, 0, 0, 0, 500e3, 500e3, 500e3, 500e3, 500e3, 500e3, 0, 0 };
+
+/*!
* Up/Down link data rates offset definition
*/
-const int8_t datarateOffsets[16][4] =
+const int8_t DatarateOffsets[5][4] =
{
{ DR_10, DR_9 , DR_8 , DR_8 }, // DR_0
{ DR_11, DR_10, DR_9 , DR_8 }, // DR_1
@@ -370,19 +465,19 @@
static uint16_t ChannelsMaskRemaining[6];
/*!
- * Defines the first channel for RX window 2 for US band
+ * Defines the first channel for RX window 1 for US band
*/
-#define LORAMAC_FIRST_RX2_CHANNEL ( (uint32_t) 923.3e6 )
+#define LORAMAC_FIRST_RX1_CHANNEL ( (uint32_t) 923.3e6 )
/*!
- * Defines the last channel for RX window 2 for US band
+ * Defines the last channel for RX window 1 for US band
*/
-#define LORAMAC_LAST_RX2_CHANNEL ( (uint32_t) 927.5e6 )
+#define LORAMAC_LAST_RX1_CHANNEL ( (uint32_t) 927.5e6 )
/*!
- * Defines the step width of the channels for RX window 2
+ * Defines the step width of the channels for RX window 1
*/
-#define LORAMAC_STEPWIDTH_RX2_CHANNEL ( (uint32_t) 600e3 )
+#define LORAMAC_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600e3 )
#else
#error "Please define a frequency band in the compiler options."
@@ -427,29 +522,31 @@
static uint8_t Channel;
/*!
- * Channel index of the last transmission
+ * Stores the time at LoRaMac initialization.
+ *
+ * \remark Used for the BACKOFF_DC computation.
*/
-static uint8_t LastTxChannel;
+static TimerTime_t LoRaMacInitializationTime = 0;
/*!
* LoRaMac internal states
*/
enum eLoRaMacState
{
- MAC_IDLE = 0x00000000,
- MAC_TX_RUNNING = 0x00000001,
- MAC_RX = 0x00000002,
- MAC_ACK_REQ = 0x00000004,
- MAC_ACK_RETRY = 0x00000008,
- MAC_TX_DELAYED = 0x00000010,
- MAC_TX_CONFIG = 0x00000020,
- MAC_RX_ABORT = 0x00000040,
+ LORAMAC_IDLE = 0x00000000,
+ LORAMAC_TX_RUNNING = 0x00000001,
+ LORAMAC_RX = 0x00000002,
+ LORAMAC_ACK_REQ = 0x00000004,
+ LORAMAC_ACK_RETRY = 0x00000008,
+ LORAMAC_TX_DELAYED = 0x00000010,
+ LORAMAC_TX_CONFIG = 0x00000020,
+ LORAMAC_RX_ABORT = 0x00000040,
};
/*!
* LoRaMac internal state
*/
-uint32_t LoRaMacState = MAC_IDLE;
+uint32_t LoRaMacState = LORAMAC_IDLE;
/*!
* LoRaMac timer used to check the LoRaMacState (runs every second)
@@ -491,6 +588,22 @@
static uint32_t RxWindow2Delay;
/*!
+ * Rx window parameters
+ */
+typedef struct
+{
+ int8_t Datarate;
+ uint8_t Bandwidth;
+ uint32_t RxWindowTimeout;
+ int32_t RxOffset;
+}RxConfigParams_t;
+
+/*!
+ * Rx windows params
+ */
+static RxConfigParams_t RxWindowsParams[2];
+
+/*!
* Acknowledge timeout timer. Used for packet retransmissions.
*/
static TimerEvent_t AckTimeoutTimer;
@@ -518,7 +631,12 @@
/*!
* Number of trials for the Join Request
*/
-static uint16_t JoinRequestTrials;
+static uint8_t JoinRequestTrials;
+
+/*!
+ * Maximum number of trials for the Join Request
+ */
+static uint8_t MaxJoinRequestTrials;
/*!
* Structure to hold an MCPS indication data.
@@ -613,21 +731,16 @@
static bool SetNextChannel( TimerTime_t* time );
/*!
- * \brief Sets the network to public or private. Updates the sync byte.
- *
- * \param [IN] enable if true, it enables a public network
- */
-static void SetPublicNetwork( bool enable );
-
-/*!
* \brief Initializes and opens the reception window
*
* \param [IN] freq window channel frequency
* \param [IN] datarate window channel datarate
* \param [IN] bandwidth window channel bandwidth
* \param [IN] timeout window channel timeout
+ *
+ * \retval status Operation status [true: Success, false: Fail]
*/
-static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
+static bool RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
/*!
* \brief Verifies if the RX window 2 frequency is in range
@@ -717,7 +830,7 @@
* \param [IN] mask Block definition to set.
* \param [OUT] channelsMask Pointer to the first element of the channel mask
*/
-static void ReenableChannels( uint16_t mask, uint16_t* channelMask );
+static void ReenableChannels( uint16_t mask, uint16_t* channelsMask );
/*!
* \brief Validates the correctness of the channel mask for US915, hybrid mode.
@@ -726,17 +839,30 @@
*
* \retval [true: channel mask correct, false: channel mask not correct]
*/
-static bool ValidateChannelMask( uint16_t* channelMask );
+static bool ValidateChannelMask( uint16_t* channelsMask );
#endif
#endif
/*!
+ * \brief Validates the correctness of the datarate against the enable channels.
+ *
+ * \param [IN] datarate Datarate to be check
+ * \param [IN] channelsMask Pointer to the first element of the channel mask
+ *
+ * \retval [true: datarate can be used, false: datarate can not be used]
+ */
+static bool ValidateDatarate( int8_t datarate, uint16_t* channelsMask );
+
+/*!
* \brief Limits the Tx power according to the number of enabled channels
*
+ * \param [IN] txPower txPower to limit
+ * \param [IN] maxBandTxPower Maximum band allowed TxPower
+ *
* \retval Returns the maximum valid tx power
*/
-static int8_t LimitTxPower( int8_t txPower );
+static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower );
/*!
* \brief Verifies, if a value is in a given range.
@@ -812,11 +938,11 @@
static LoRaMacStatus_t ScheduleTx( void );
/*
- * \brief Sets the duty cycle for retransmissions
+ * \brief Sets the duty cycle for the join procedure.
*
* \retval Duty cycle
*/
-static uint16_t RetransmissionDutyCylce( void );
+static uint16_t JoinDutyCycle( void );
/*
* \brief Calculates the back-off time for the band of a channel.
@@ -845,13 +971,86 @@
LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel );
/*!
+ * \brief Sets the radio in continuous transmission mode
+ *
+ * \remark Uses the radio parameters set on the previous transmission.
+ *
+ * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
+ * \retval status Status of the operation.
+ */
+LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout );
+
+/*!
+ * \brief Sets the radio in continuous transmission mode
+ *
+ * \remark Uses the radio parameters set on the previous transmission.
+ *
+ * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
+ * \param [IN] frequency RF frequency to be set.
+ * \param [IN] power RF ouptput power to be set.
+ * \retval status Status of the operation.
+ */
+LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power );
+
+/*!
* \brief Resets MAC specific parameters to default
*/
static void ResetMacParameters( void );
+/*
+ * Rx window precise timing
+ *
+ * For more details please consult the following document, chapter 3.1.2.
+ * http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
+ * or
+ * http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
+ *
+ * Downlink start: T = Tx + 1s (+/- 20 us)
+ * |
+ * TRxEarly | TRxLate
+ * | | |
+ * | | +---+---+---+---+---+---+---+---+
+ * | | | Latest Rx window |
+ * | | +---+---+---+---+---+---+---+---+
+ * | | |
+ * +---+---+---+---+---+---+---+---+
+ * | Earliest Rx window |
+ * +---+---+---+---+---+---+---+---+
+ * |
+ * +---+---+---+---+---+---+---+---+
+ *Downlink preamble 8 symbols | | | | | | | | |
+ * +---+---+---+---+---+---+---+---+
+ *
+ * Worst case Rx window timings
+ *
+ * TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
+ * TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
+ *
+ * TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
+ *
+ * RxOffset = ( TRxLate + TRxEarly ) / 2
+ *
+ * RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
+ * RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
+ *
+ * Minimal value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol
+ */
+/*!
+ * Computes the Rx window parameters.
+ *
+ * \param [IN] datarate Rx window datarate to be used
+ * \param [IN] rxError Maximum timing error of the receiver. in milliseconds
+ * The receiver will turn on in a [-rxError : +rxError] ms
+ * interval around RxOffset
+ *
+ * \retval rxConfigParams Returns a RxConfigParams_t structure.
+ */
+static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError );
+
static void OnRadioTxDone( void )
{
TimerTime_t curTime = TimerGetCurrentTime( );
+
if( LoRaMacDeviceClass != CLASS_C )
{
Radio.Sleep( );
@@ -861,13 +1060,7 @@
OnRxWindow2TimerEvent( );
}
- // Store last Tx channel
- LastTxChannel = Channel;
- // Update last tx done time for the current channel
- Bands[Channels[LastTxChannel].Band].LastTxDoneTime = curTime;
- // Update Aggregated last tx done time
- AggregatedLastTxDoneTime = curTime;
-
+ // Setup timers
if( IsRxWindowsEnabled == true )
{
TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
@@ -896,6 +1089,13 @@
LoRaMacFlags.Bits.MacDone = 1;
}
+ // Update last tx done time for the current channel
+ Bands[Channels[Channel].Band].LastTxDoneTime = curTime;
+ // Update Aggregated last tx done time
+ AggregatedLastTxDoneTime = curTime;
+ // Update Backoff
+ CalculateBackOff( Channel );
+
if( NodeAckRequested == false )
{
McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
@@ -905,23 +1105,18 @@
static void PrepareRxDoneAbort( void )
{
- LoRaMacState |= MAC_RX_ABORT;
+ LoRaMacState |= LORAMAC_RX_ABORT;
if( NodeAckRequested )
{
OnAckTimeoutTimerEvent( );
}
- if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
- {
- OnRxWindow2TimerEvent( );
- }
-
LoRaMacFlags.Bits.McpsInd = 1;
LoRaMacFlags.Bits.MacDone = 1;
// Trig OnMacCheckTimerEvent call as soon as possible
- TimerSetValue( &MacStateCheckTimer, 1000 );
+ TimerSetValue( &MacStateCheckTimer, 1 );
TimerStart( &MacStateCheckTimer );
}
@@ -966,10 +1161,7 @@
McpsIndication.DownLinkCounter = 0;
McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
- if( LoRaMacDeviceClass != CLASS_C )
- {
- Radio.Sleep( );
- }
+ Radio.Sleep( );
TimerStop( &RxWindowTimer2 );
macHdr.Value = payload[pktHeaderLen++];
@@ -979,7 +1171,9 @@
case FRAME_TYPE_JOIN_ACCEPT:
if( IsLoRaMacNetworkJoined == true )
{
- break;
+ McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ PrepareRxDoneAbort( );
+ return;
}
LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
@@ -1008,24 +1202,15 @@
// DLSettings
LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
- /*
- * WARNING: To be removed once Semtech server implementation
- * is corrected.
- */
- if( LoRaMacParams.Rx2Channel.Datarate == DR_3 )
- {
- LoRaMacParams.Rx2Channel.Datarate = DR_8;
- }
-#endif
+
// RxDelay
LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
if( LoRaMacParams.ReceiveDelay1 == 0 )
{
LoRaMacParams.ReceiveDelay1 = 1;
}
- LoRaMacParams.ReceiveDelay1 *= 1e6;
- LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6;
+ LoRaMacParams.ReceiveDelay1 *= 1e3;
+ LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e3;
#if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
//CFList
@@ -1034,13 +1219,20 @@
ChannelParams_t param;
param.DrRange.Value = ( DR_5 << 4 ) | DR_0;
- LoRaMacState |= MAC_TX_CONFIG;
+ LoRaMacState |= LORAMAC_TX_CONFIG;
for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 )
{
param.Frequency = ( ( uint32_t )LoRaMacRxPayload[13 + j] | ( ( uint32_t )LoRaMacRxPayload[14 + j] << 8 ) | ( ( uint32_t )LoRaMacRxPayload[15 + j] << 16 ) ) * 100;
- LoRaMacChannelAdd( i, param );
+ if( param.Frequency != 0 )
+ {
+ LoRaMacChannelAdd( i, param );
+ }
+ else
+ {
+ LoRaMacChannelRemove( i );
+ }
}
- LoRaMacState &= ~MAC_TX_CONFIG;
+ LoRaMacState &= ~LORAMAC_TX_CONFIG;
}
#endif
MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
@@ -1176,6 +1368,10 @@
( DownLinkCounter != 0 ) )
{
// Duplicated confirmed downlink. Skip indication.
+ // In this case, the MAC layer shall accept the MAC commands
+ // which are included in the downlink retransmission.
+ // It should not provide the same frame to the application
+ // layer again.
skipIndication = true;
}
}
@@ -1196,28 +1392,23 @@
DownLinkCounter = downLinkCounter;
}
- // Check if the frame is an acknowledgement
- if( fCtrl.Bits.Ack == 1 )
+ // This must be done before parsing the payload and the MAC commands.
+ // We need to reset the MacCommandsBufferIndex here, since we need
+ // to take retransmissions and repititions into account. Error cases
+ // will be handled in function OnMacStateCheckTimerEvent.
+ if( McpsConfirm.McpsRequest == MCPS_CONFIRMED )
{
- McpsConfirm.AckReceived = true;
- McpsIndication.AckReceived = true;
-
- // Stop the AckTimeout timer as no more retransmissions
- // are needed.
- TimerStop( &AckTimeoutTimer );
+ if( fCtrl.Bits.Ack == 1 )
+ {// Reset MacCommandsBufferIndex when we have received an ACK.
+ MacCommandsBufferIndex = 0;
+ }
}
else
- {
- McpsConfirm.AckReceived = false;
-
- if( AckTimeoutRetriesCounter > AckTimeoutRetries )
- {
- // Stop the AckTimeout timer as no more retransmissions
- // are needed.
- TimerStop( &AckTimeoutTimer );
- }
+ {// Reset the variable if we have received any valid frame.
+ MacCommandsBufferIndex = 0;
}
+ // Process payload and MAC commands
if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
{
port = payload[appPayloadStartIndex++];
@@ -1227,6 +1418,7 @@
if( port == 0 )
{
+ // Only allow frames which do not have fOpts
if( fCtrl.Bits.FOptsLen == 0 )
{
LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
@@ -1280,8 +1472,32 @@
if( skipIndication == false )
{
- LoRaMacFlags.Bits.McpsInd = 1;
+ // Check if the frame is an acknowledgement
+ if( fCtrl.Bits.Ack == 1 )
+ {
+ McpsConfirm.AckReceived = true;
+ McpsIndication.AckReceived = true;
+
+ // Stop the AckTimeout timer as no more retransmissions
+ // are needed.
+ TimerStop( &AckTimeoutTimer );
+ }
+ else
+ {
+ McpsConfirm.AckReceived = false;
+
+ if( AckTimeoutRetriesCounter > AckTimeoutRetries )
+ {
+ // Stop the AckTimeout timer as no more retransmissions
+ // are needed.
+ TimerStop( &AckTimeoutTimer );
+ }
+ }
}
+ // Provide always an indication, skip the callback to the user application,
+ // in case of a confirmed downlink retransmission.
+ LoRaMacFlags.Bits.McpsInd = 1;
+ LoRaMacFlags.Bits.McpsIndSkip = skipIndication;
}
else
{
@@ -1309,15 +1525,10 @@
PrepareRxDoneAbort( );
break;
}
-
- if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
- {
- OnRxWindow2TimerEvent( );
- }
LoRaMacFlags.Bits.MacDone = 1;
// Trig OnMacCheckTimerEvent call as soon as possible
- TimerSetValue( &MacStateCheckTimer, 1000 );
+ TimerSetValue( &MacStateCheckTimer, 1 );
TimerStart( &MacStateCheckTimer );
}
@@ -1348,7 +1559,20 @@
OnRxWindow2TimerEvent( );
}
- if( RxSlot == 1 )
+ if( RxSlot == 0 )
+ {
+ if( NodeAckRequested == true )
+ {
+ McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
+ }
+ MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
+
+ if( TimerGetElapsedTime( AggregatedLastTxDoneTime ) >= RxWindow2Delay )
+ {
+ LoRaMacFlags.Bits.MacDone = 1;
+ }
+ }
+ else
{
if( NodeAckRequested == true )
{
@@ -1388,10 +1612,10 @@
if( LoRaMacFlags.Bits.MacDone == 1 )
{
- if( ( LoRaMacState & MAC_RX_ABORT ) == MAC_RX_ABORT )
+ if( ( LoRaMacState & LORAMAC_RX_ABORT ) == LORAMAC_RX_ABORT )
{
- LoRaMacState &= ~MAC_RX_ABORT;
- LoRaMacState &= ~MAC_TX_RUNNING;
+ LoRaMacState &= ~LORAMAC_RX_ABORT;
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
}
if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
@@ -1400,7 +1624,8 @@
( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) )
{
// Stop transmit cycle due to tx timeout.
- LoRaMacState &= ~MAC_TX_RUNNING;
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
+ MacCommandsBufferIndex = 0;
McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
McpsConfirm.AckReceived = false;
McpsConfirm.TxTimeOnAir = 0;
@@ -1410,46 +1635,64 @@
if( ( NodeAckRequested == false ) && ( txTimeout == false ) )
{
- if( LoRaMacFlags.Bits.MlmeReq == 1 )
- {
- if( MlmeConfirm.MlmeRequest == MLME_JOIN )
- {
- // Retransmit only if the answer is not OK
- ChannelsNbRepCounter = 0;
-
- if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
- {
- // Stop retransmission
- ChannelsNbRepCounter = LoRaMacParams.ChannelsNbRep;
- UpLinkCounter = 0;
- }
- }
- }
if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
{
- if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
- {
- ChannelsNbRepCounter = 0;
-
- AdrAckCounter++;
- if( IsUpLinkCounterFixed == false )
+ if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
+ {// Procedure for the join request
+ MlmeConfirm.NbRetries = JoinRequestTrials;
+
+ if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
+ {// Node joined successfully
+ UpLinkCounter = 0;
+ ChannelsNbRepCounter = 0;
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
+ }
+ else
{
- UpLinkCounter++;
+ if( JoinRequestTrials >= MaxJoinRequestTrials )
+ {
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
+ }
+ else
+ {
+ LoRaMacFlags.Bits.MacDone = 0;
+ // Sends the same frame again
+ OnTxDelayedTimerEvent( );
+ }
}
-
- LoRaMacState &= ~MAC_TX_RUNNING;
}
else
- {
- LoRaMacFlags.Bits.MacDone = 0;
- // Sends the same frame again
- ScheduleTx( );
+ {// Procedure for all other frames
+ if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
+ {
+ if( LoRaMacFlags.Bits.McpsInd == 0 )
+ { // Maximum repititions without downlink. Reset MacCommandsBufferIndex. Increase ADR Ack counter.
+ // Only process the case when the MAC did not receive a downlink.
+ MacCommandsBufferIndex = 0;
+ AdrAckCounter++;
+ }
+
+ ChannelsNbRepCounter = 0;
+
+ if( IsUpLinkCounterFixed == false )
+ {
+ UpLinkCounter++;
+ }
+
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
+ }
+ else
+ {
+ LoRaMacFlags.Bits.MacDone = 0;
+ // Sends the same frame again
+ OnTxDelayedTimerEvent( );
+ }
}
}
}
if( LoRaMacFlags.Bits.McpsInd == 1 )
- {
+ {// Procedure if we received a frame
if( ( McpsConfirm.AckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) )
{
AckTimeoutRetry = false;
@@ -1460,12 +1703,12 @@
}
McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
- LoRaMacState &= ~MAC_TX_RUNNING;
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
}
}
- if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & MAC_TX_DELAYED ) == 0 ) )
- {
+ if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & LORAMAC_TX_DELAYED ) == 0 ) )
+ {// Retransmissions procedure for confirmed uplinks
AckTimeoutRetry = false;
if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) )
{
@@ -1475,31 +1718,48 @@
{
LoRaMacParams.ChannelsDatarate = MAX( LoRaMacParams.ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
}
- LoRaMacFlags.Bits.MacDone = 0;
- // Sends the same frame again
- ScheduleTx( );
+ // Try to send the frame again
+ if( ScheduleTx( ) == LORAMAC_STATUS_OK )
+ {
+ LoRaMacFlags.Bits.MacDone = 0;
+ }
+ else
+ {
+ // The DR is not applicable for the payload size
+ McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR;
+
+ MacCommandsBufferIndex = 0;
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
+ NodeAckRequested = false;
+ McpsConfirm.AckReceived = false;
+ McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
+ McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
+ if( IsUpLinkCounterFixed == false )
+ {
+ UpLinkCounter++;
+ }
+ }
}
else
{
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
// Re-enable default channels LC1, LC2, LC3
LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
+#elif defined( USE_BAND_470 )
+ // Re-enable default channels
+ memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
#elif defined( USE_BAND_915 )
// Re-enable default channels
- LoRaMacParams.ChannelsMask[0] = 0xFFFF;
- LoRaMacParams.ChannelsMask[1] = 0xFFFF;
- LoRaMacParams.ChannelsMask[2] = 0xFFFF;
- LoRaMacParams.ChannelsMask[3] = 0xFFFF;
- LoRaMacParams.ChannelsMask[4] = 0x00FF;
- LoRaMacParams.ChannelsMask[5] = 0x0000;
+ memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
#elif defined( USE_BAND_915_HYBRID )
// Re-enable default channels
- ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
+ ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
#else
#error "Please define a frequency band in the compiler options."
#endif
- LoRaMacState &= ~MAC_TX_RUNNING;
-
+ LoRaMacState &= ~LORAMAC_TX_RUNNING;
+
+ MacCommandsBufferIndex = 0;
NodeAckRequested = false;
McpsConfirm.AckReceived = false;
McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
@@ -1511,11 +1771,11 @@
}
}
// Handle reception for Class B and Class C
- if( ( LoRaMacState & MAC_RX ) == MAC_RX )
+ if( ( LoRaMacState & LORAMAC_RX ) == LORAMAC_RX )
{
- LoRaMacState &= ~MAC_RX;
+ LoRaMacState &= ~LORAMAC_RX;
}
- if( LoRaMacState == MAC_IDLE )
+ if( LoRaMacState == LORAMAC_IDLE )
{
if( LoRaMacFlags.Bits.McpsReq == 1 )
{
@@ -1529,6 +1789,7 @@
LoRaMacFlags.Bits.MlmeReq = 0;
}
+ // Procedure done. Reset variables.
LoRaMacFlags.Bits.MacDone = 0;
}
else
@@ -1540,7 +1801,15 @@
if( LoRaMacFlags.Bits.McpsInd == 1 )
{
- LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
+ if( LoRaMacDeviceClass == CLASS_C )
+ {// Activate RX2 window for Class C
+ OnRxWindow2TimerEvent( );
+ }
+ if( LoRaMacFlags.Bits.McpsIndSkip == 0 )
+ {
+ LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
+ }
+ LoRaMacFlags.Bits.McpsIndSkip = 0;
LoRaMacFlags.Bits.McpsInd = 0;
}
}
@@ -1551,17 +1820,21 @@
LoRaMacFrameCtrl_t fCtrl;
TimerStop( &TxDelayedTimer );
- LoRaMacState &= ~MAC_TX_DELAYED;
+ LoRaMacState &= ~LORAMAC_TX_DELAYED;
if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
{
+ ResetMacParameters( );
+ // Add a +1, since we start to count from 0
+ LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials + 1 );
+
macHdr.Value = 0;
macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
fCtrl.Value = 0;
fCtrl.Bits.Adr = AdrCtrlOn;
- /* In case of a join request retransmission, the stack must prepare
+ /* In case of join request retransmissions, the stack must prepare
* the frame again, because the network server keeps track of the random
* LoRaMacDevNonce values to prevent reply attacks. */
PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 );
@@ -1572,10 +1845,6 @@
static void OnRxWindow1TimerEvent( void )
{
- uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
- int8_t datarate = 0;
- uint32_t bandwidth = 0; // LoRa 125 kHz
-
TimerStop( &RxWindowTimer1 );
RxSlot = 0;
@@ -1585,69 +1854,11 @@
}
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- datarate = LoRaMacParams.ChannelsDatarate - LoRaMacParams.Rx1DrOffset;
- if( datarate < 0 )
- {
- datarate = DR_0;
- }
-
- // For higher datarates, we increase the number of symbols generating a Rx Timeout
- if( ( datarate == DR_3 ) || ( datarate == DR_4 ) )
- { // DR_4, DR_3
- symbTimeout = 8;
- }
- else if( datarate == DR_5 )
- {
- symbTimeout = 10;
- }
- else if( datarate == DR_6 )
- {// LoRa 250 kHz
- bandwidth = 1;
- symbTimeout = 14;
- }
- RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
+ RxWindowSetup( Channels[Channel].Frequency, RxWindowsParams[0].Datarate, RxWindowsParams[0].Bandwidth, RxWindowsParams[0].RxWindowTimeout, false );
+#elif defined( USE_BAND_470 )
+ RxWindowSetup( LORAMAC_FIRST_RX1_CHANNEL + ( Channel % 48 ) * LORAMAC_STEPWIDTH_RX1_CHANNEL, RxWindowsParams[0].Datarate, RxWindowsParams[0].Bandwidth, RxWindowsParams[0].RxWindowTimeout, false );
#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
- datarate = datarateOffsets[LoRaMacParams.ChannelsDatarate][LoRaMacParams.Rx1DrOffset];
- if( datarate < 0 )
- {
- datarate = DR_0;
- }
- // For higher datarates, we increase the number of symbols generating a Rx Timeout
- switch( datarate )
- {
- case DR_0: // SF10 - BW125
- symbTimeout = 5;
- break;
-
- case DR_1: // SF9 - BW125
- case DR_2: // SF8 - BW125
- case DR_8: // SF12 - BW500
- case DR_9: // SF11 - BW500
- case DR_10: // SF10 - BW500
- symbTimeout = 8;
- break;
-
- case DR_3: // SF7 - BW125
- case DR_11: // SF9 - BW500
- symbTimeout = 10;
- break;
-
- case DR_4: // SF8 - BW500
- case DR_12: // SF8 - BW500
- symbTimeout = 14;
- break;
-
- case DR_13: // SF7 - BW500
- symbTimeout = 16;
- break;
- default:
- break;
- }
- if( datarate >= DR_4 )
- {// LoRa 500 kHz
- bandwidth = 2;
- }
- RxWindowSetup( LORAMAC_FIRST_RX2_CHANNEL + ( Channel % 8 ) * LORAMAC_STEPWIDTH_RX2_CHANNEL, datarate, bandwidth, symbTimeout, false );
+ RxWindowSetup( LORAMAC_FIRST_RX1_CHANNEL + ( Channel % 8 ) * LORAMAC_STEPWIDTH_RX1_CHANNEL, RxWindowsParams[0].Datarate, RxWindowsParams[0].Bandwidth, RxWindowsParams[0].RxWindowTimeout, false );
#else
#error "Please define a frequency band in the compiler options."
#endif
@@ -1655,73 +1866,17 @@
static void OnRxWindow2TimerEvent( void )
{
- uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
- uint32_t bandwidth = 0; // LoRa 125 kHz
+ bool rxContinuousMode = false;
TimerStop( &RxWindowTimer2 );
- RxSlot = 1;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- // For higher datarates, we increase the number of symbols generating a Rx Timeout
- if( ( LoRaMacParams.Rx2Channel.Datarate == DR_3 ) || ( LoRaMacParams.Rx2Channel.Datarate == DR_4 ) )
- { // DR_4, DR_3
- symbTimeout = 8;
- }
- else if( LoRaMacParams.Rx2Channel.Datarate == DR_5 )
- {
- symbTimeout = 10;
- }
- else if( LoRaMacParams.Rx2Channel.Datarate == DR_6 )
- {// LoRa 250 kHz
- bandwidth = 1;
- symbTimeout = 14;
- }
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
- // For higher datarates, we increase the number of symbols generating a Rx Timeout
- switch( LoRaMacParams.Rx2Channel.Datarate )
+
+ if( LoRaMacDeviceClass == CLASS_C )
{
- case DR_0: // SF10 - BW125
- symbTimeout = 5;
- break;
-
- case DR_1: // SF9 - BW125
- case DR_2: // SF8 - BW125
- case DR_8: // SF12 - BW500
- case DR_9: // SF11 - BW500
- case DR_10: // SF10 - BW500
- symbTimeout = 8;
- break;
-
- case DR_3: // SF7 - BW125
- case DR_11: // SF9 - BW500
- symbTimeout = 10;
- break;
-
- case DR_4: // SF8 - BW500
- case DR_12: // SF8 - BW500
- symbTimeout = 14;
- break;
-
- case DR_13: // SF7 - BW500
- symbTimeout = 16;
- break;
- default:
- break;
+ rxContinuousMode = true;
}
- if( LoRaMacParams.Rx2Channel.Datarate >= DR_4 )
- {// LoRa 500 kHz
- bandwidth = 2;
- }
-#else
- #error "Please define a frequency band in the compiler options."
-#endif
- if( LoRaMacDeviceClass != CLASS_C )
+ if( RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, RxWindowsParams[1].Datarate, RxWindowsParams[1].Bandwidth, RxWindowsParams[1].RxWindowTimeout, rxContinuousMode ) == true )
{
- RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, false );
- }
- else
- {
- RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, true );
+ RxSlot = 1;
}
}
@@ -1732,7 +1887,7 @@
if( NodeAckRequested == true )
{
AckTimeoutRetry = true;
- LoRaMacState &= ~MAC_ACK_REQ;
+ LoRaMacState &= ~LORAMAC_ACK_REQ;
}
if( LoRaMacDeviceClass == CLASS_C )
{
@@ -1758,6 +1913,16 @@
{ // Make sure, that the channels are activated
ChannelsMaskRemaining[4] = LoRaMacParams.ChannelsMask[4];
}
+#elif defined( USE_BAND_470 )
+ if( ( CountBits( LoRaMacParams.ChannelsMask[0], 16 ) == 0 ) &&
+ ( CountBits( LoRaMacParams.ChannelsMask[1], 16 ) == 0 ) &&
+ ( CountBits( LoRaMacParams.ChannelsMask[2], 16 ) == 0 ) &&
+ ( CountBits( LoRaMacParams.ChannelsMask[3], 16 ) == 0 ) &&
+ ( CountBits( LoRaMacParams.ChannelsMask[4], 16 ) == 0 ) &&
+ ( CountBits( LoRaMacParams.ChannelsMask[5], 16 ) == 0 ) )
+ {
+ memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
+ }
#else
if( CountBits( LoRaMacParams.ChannelsMask[0], 16 ) == 0 )
{
@@ -1774,7 +1939,7 @@
// Update bands Time OFF
for( uint8_t i = 0; i < LORA_MAX_NB_BANDS; i++ )
{
- if( DutyCycleOn == true )
+ if( ( IsLoRaMacNetworkJoined == false ) || ( DutyCycleOn == true ) )
{
if( Bands[i].TimeOff <= TimerGetElapsedTime( Bands[i].LastTxDoneTime ) )
{
@@ -1782,15 +1947,15 @@
}
if( Bands[i].TimeOff != 0 )
{
- nextTxDelay = MIN( Bands[i].TimeOff -
- TimerGetElapsedTime( Bands[i].LastTxDoneTime ),
- nextTxDelay );
+ nextTxDelay = MIN( Bands[i].TimeOff - TimerGetElapsedTime( Bands[i].LastTxDoneTime ), nextTxDelay );
}
}
else
{
- nextTxDelay = 0;
- Bands[i].TimeOff = 0;
+ if( DutyCycleOn == false )
+ {
+ Bands[i].TimeOff = 0;
+ }
}
}
@@ -1865,23 +2030,7 @@
}
}
-static void SetPublicNetwork( bool enable )
-{
- PublicNetwork = enable;
- Radio.SetModem( MODEM_LORA );
- if( PublicNetwork == true )
- {
- // Change LoRa modem SyncWord
- Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD );
- }
- else
- {
- // Change LoRa modem SyncWord
- Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD );
- }
-}
-
-static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
+static bool RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
{
uint8_t downlinkDatarate = Datarates[datarate];
RadioModems_t modem;
@@ -1897,14 +2046,14 @@
if( datarate == DR_7 )
{
modem = MODEM_FSK;
- Radio.SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, rxContinuous );
+ Radio.SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, timeout, false, 0, true, 0, 0, false, rxContinuous );
}
else
{
modem = MODEM_LORA;
Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
}
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+#elif defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
modem = MODEM_LORA;
Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
#endif
@@ -1926,18 +2075,20 @@
{
Radio.Rx( 0 ); // Continuous mode
}
+ return true;
}
+ return false;
}
static bool Rx2FreqInRange( uint32_t freq )
{
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
if( Radio.CheckRfFrequency( freq ) == true )
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+#elif defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
if( ( Radio.CheckRfFrequency( freq ) == true ) &&
- ( freq >= LORAMAC_FIRST_RX2_CHANNEL ) &&
- ( freq <= LORAMAC_LAST_RX2_CHANNEL ) &&
- ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX2_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX2_CHANNEL ) == 0 ) )
+ ( freq >= LORAMAC_FIRST_RX1_CHANNEL ) &&
+ ( freq <= LORAMAC_LAST_RX1_CHANNEL ) &&
+ ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX1_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX1_CHANNEL ) == 0 ) )
#endif
{
return true;
@@ -1999,27 +2150,27 @@
}
#if defined( USE_BAND_915_HYBRID )
-static void ReenableChannels( uint16_t mask, uint16_t* channelMask )
+static void ReenableChannels( uint16_t mask, uint16_t* channelsMask )
{
uint16_t blockMask = mask;
for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
{
- channelMask[i] = 0;
+ channelsMask[i] = 0;
if( ( blockMask & ( 1 << j ) ) != 0 )
{
- channelMask[i] |= 0x00FF;
+ channelsMask[i] |= 0x00FF;
}
if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
{
- channelMask[i] |= 0xFF00;
+ channelsMask[i] |= 0xFF00;
}
}
- channelMask[4] = blockMask;
- channelMask[5] = 0x0000;
+ channelsMask[4] = blockMask;
+ channelsMask[5] = 0x0000;
}
-static bool ValidateChannelMask( uint16_t* channelMask )
+static bool ValidateChannelMask( uint16_t* channelsMask )
{
bool chanMaskState = false;
uint16_t block1 = 0;
@@ -2028,20 +2179,20 @@
for( uint8_t i = 0; i < 4; i++ )
{
- block1 = channelMask[i] & 0x00FF;
- block2 = channelMask[i] & 0xFF00;
+ block1 = channelsMask[i] & 0x00FF;
+ block2 = channelsMask[i] & 0xFF00;
if( ( CountBits( block1, 16 ) > 5 ) && ( chanMaskState == false ) )
{
- channelMask[i] &= block1;
- channelMask[4] = 1 << ( i * 2 );
+ channelsMask[i] &= block1;
+ channelsMask[4] = 1 << ( i * 2 );
chanMaskState = true;
index = i;
}
else if( ( CountBits( block2, 16 ) > 5 ) && ( chanMaskState == false ) )
{
- channelMask[i] &= block2;
- channelMask[4] = 1 << ( i * 2 + 1 );
+ channelsMask[i] &= block2;
+ channelsMask[4] = 1 << ( i * 2 + 1 );
chanMaskState = true;
index = i;
}
@@ -2054,7 +2205,7 @@
{
if( i != index )
{
- channelMask[i] = 0;
+ channelsMask[i] = 0;
}
}
}
@@ -2063,9 +2214,36 @@
#endif
#endif
-static int8_t LimitTxPower( int8_t txPower )
+static bool ValidateDatarate( int8_t datarate, uint16_t* channelsMask )
+{
+ if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false )
+ {
+ return false;
+ }
+ for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
+ {
+ for( uint8_t j = 0; j < 16; j++ )
+ {
+ if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) )
+ {// Check datarate validity for enabled channels
+ if( ValueInRange( datarate, Channels[i + j].DrRange.Fields.Min, Channels[i + j].DrRange.Fields.Max ) == true )
+ {
+ // At least 1 channel has been found we can return OK.
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower )
{
int8_t resultTxPower = txPower;
+
+ // Limit tx power to the band max
+ resultTxPower = MAX( txPower, maxBandTxPower );
+
#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
if( ( LoRaMacParams.ChannelsDatarate == DR_4 ) ||
( ( LoRaMacParams.ChannelsDatarate >= DR_8 ) && ( LoRaMacParams.ChannelsDatarate <= DR_13 ) ) )
@@ -2125,6 +2303,7 @@
if( AdrAckCounter >= ADR_ACK_LIMIT )
{
adrAckReq = true;
+ LoRaMacParams.ChannelsTxPower = LORAMAC_MAX_TX_POWER;
}
else
{
@@ -2132,7 +2311,7 @@
}
if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) )
{
- if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 )
+ if( ( AdrAckCounter % ADR_ACK_DELAY ) == 1 )
{
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
if( datarate > LORAMAC_TX_MIN_DATARATE )
@@ -2147,6 +2326,19 @@
LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
}
}
+#elif defined( USE_BAND_470 )
+ if( datarate > LORAMAC_TX_MIN_DATARATE )
+ {
+ datarate--;
+ }
+ if( datarate == LORAMAC_TX_MIN_DATARATE )
+ {
+ if( updateChannelMask == true )
+ {
+ // Re-enable default channels
+ memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
+ }
+ }
#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
if( ( datarate > LORAMAC_TX_MIN_DATARATE ) && ( datarate == DR_8 ) )
{
@@ -2162,15 +2354,10 @@
{
#if defined( USE_BAND_915 )
// Re-enable default channels
- LoRaMacParams.ChannelsMask[0] = 0xFFFF;
- LoRaMacParams.ChannelsMask[1] = 0xFFFF;
- LoRaMacParams.ChannelsMask[2] = 0xFFFF;
- LoRaMacParams.ChannelsMask[3] = 0xFFFF;
- LoRaMacParams.ChannelsMask[4] = 0x00FF;
- LoRaMacParams.ChannelsMask[5] = 0x0000;
+ memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
#else // defined( USE_BAND_915_HYBRID )
// Re-enable default channels
- ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
+ ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
#endif
}
}
@@ -2281,10 +2468,10 @@
{
switch( cmdBufIn[i] )
{
+ // STICKY
case MOTE_MAC_RX_PARAM_SETUP_ANS:
{
cmdBufOut[cmdCount++] = cmdBufIn[i++];
- cmdBufOut[cmdCount++] = cmdBufIn[i++];
cmdBufOut[cmdCount++] = cmdBufIn[i];
break;
}
@@ -2293,6 +2480,23 @@
cmdBufOut[cmdCount++] = cmdBufIn[i];
break;
}
+ // NON-STICKY
+ case MOTE_MAC_DEV_STATUS_ANS:
+ { // 2 bytes payload
+ i += 2;
+ break;
+ }
+ case MOTE_MAC_LINK_ADR_ANS:
+ case MOTE_MAC_NEW_CHANNEL_ANS:
+ { // 1 byte payload
+ i++;
+ break;
+ }
+ case MOTE_MAC_DUTY_CYCLE_ANS:
+ case MOTE_MAC_LINK_CHECK_REQ:
+ { // 0 byte payload
+ break;
+ }
default:
break;
}
@@ -2387,11 +2591,11 @@
}
channelsMask[0] = chMask;
}
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+#elif defined( USE_BAND_470 )
if( chMaskCntl == 6 )
{
// Enable all 125 kHz channels
- for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
+ for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
{
for( uint8_t j = 0; j < 16; j++ )
{
@@ -2404,15 +2608,6 @@
}
else if( chMaskCntl == 7 )
{
- // Disable all 125 kHz channels
- channelsMask[0] = 0x0000;
- channelsMask[1] = 0x0000;
- channelsMask[2] = 0x0000;
- channelsMask[3] = 0x0000;
- }
- else if( chMaskCntl == 5 )
- {
- // RFU
status &= 0xFE; // Channel mask KO
}
else
@@ -2426,8 +2621,39 @@
}
}
channelsMask[chMaskCntl] = chMask;
-
- if( CountNbEnabled125kHzChannels( channelsMask ) < 6 )
+ }
+#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+ if( chMaskCntl == 6 )
+ {
+ // Enable all 125 kHz channels
+ channelsMask[0] = 0xFFFF;
+ channelsMask[1] = 0xFFFF;
+ channelsMask[2] = 0xFFFF;
+ channelsMask[3] = 0xFFFF;
+ // Apply chMask to channels 64 to 71
+ channelsMask[4] = chMask;
+ }
+ else if( chMaskCntl == 7 )
+ {
+ // Disable all 125 kHz channels
+ channelsMask[0] = 0x0000;
+ channelsMask[1] = 0x0000;
+ channelsMask[2] = 0x0000;
+ channelsMask[3] = 0x0000;
+ // Apply chMask to channels 64 to 71
+ channelsMask[4] = chMask;
+ }
+ else if( chMaskCntl == 5 )
+ {
+ // RFU
+ status &= 0xFE; // Channel mask KO
+ }
+ else
+ {
+ channelsMask[chMaskCntl] = chMask;
+
+ // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
+ if( ( datarate < DR_4 ) && ( CountNbEnabled125kHzChannels( channelsMask ) < 2 ) )
{
status &= 0xFE; // Channel mask KO
}
@@ -2442,7 +2668,7 @@
#else
#error "Please define a frequency band in the compiler options."
#endif
- if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false )
+ if( ValidateDatarate( datarate, channelsMask ) == false )
{
status &= 0xFD; // Datarate KO
}
@@ -2459,14 +2685,18 @@
LoRaMacParams.ChannelsDatarate = datarate;
LoRaMacParams.ChannelsTxPower = txPower;
- LoRaMacParams.ChannelsMask[0] = channelsMask[0];
- LoRaMacParams.ChannelsMask[1] = channelsMask[1];
- LoRaMacParams.ChannelsMask[2] = channelsMask[2];
- LoRaMacParams.ChannelsMask[3] = channelsMask[3];
- LoRaMacParams.ChannelsMask[4] = channelsMask[4];
- LoRaMacParams.ChannelsMask[5] = channelsMask[5];
+ memcpy1( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )channelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
LoRaMacParams.ChannelsNbRep = nbRep;
+#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+ // Reset ChannelsMaskRemaining to the new ChannelsMask
+ ChannelsMaskRemaining[0] &= channelsMask[0];
+ ChannelsMaskRemaining[1] &= channelsMask[1];
+ ChannelsMaskRemaining[2] &= channelsMask[2];
+ ChannelsMaskRemaining[3] &= channelsMask[3];
+ ChannelsMaskRemaining[4] = channelsMask[4];
+ ChannelsMaskRemaining[5] = channelsMask[5];
+#endif
}
AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
}
@@ -2536,7 +2766,7 @@
{
uint8_t status = 0x03;
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+#if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
status &= 0xFC; // Channel frequency and datarate KO
macIndex += 5;
#else
@@ -2550,7 +2780,7 @@
chParam.Frequency *= 100;
chParam.DrRange.Value = payload[macIndex++];
- LoRaMacState |= MAC_TX_CONFIG;
+ LoRaMacState |= LORAMAC_TX_CONFIG;
if( chParam.Frequency == 0 )
{
if( channelIndex < 3 )
@@ -2595,7 +2825,7 @@
}
}
}
- LoRaMacState &= ~MAC_TX_CONFIG;
+ LoRaMacState &= ~LORAMAC_TX_CONFIG;
#endif
AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
}
@@ -2608,8 +2838,8 @@
{
delay++;
}
- LoRaMacParams.ReceiveDelay1 = delay * 1e6;
- LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6;
+ LoRaMacParams.ReceiveDelay1 = delay * 1e3;
+ LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e3;
AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
}
break;
@@ -2651,7 +2881,7 @@
return status;
}
-static LoRaMacStatus_t ScheduleTx( )
+static LoRaMacStatus_t ScheduleTx( void )
{
TimerTime_t dutyCycleTimeOff = 0;
@@ -2665,8 +2895,6 @@
AggregatedTimeOff = 0;
}
- CalculateBackOff( LastTxChannel );
-
// Select channel
while( SetNextChannel( &dutyCycleTimeOff ) == false )
{
@@ -2679,6 +2907,30 @@
#endif
}
+ // Compute Rx1 windows parameters
+#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+ RxWindowsParams[0] = ComputeRxWindowParameters( DatarateOffsets[LoRaMacParams.ChannelsDatarate][LoRaMacParams.Rx1DrOffset], LoRaMacParams.SystemMaxRxError );
+#else
+ RxWindowsParams[0] = ComputeRxWindowParameters( MAX( DR_0, LoRaMacParams.ChannelsDatarate - LoRaMacParams.Rx1DrOffset ), LoRaMacParams.SystemMaxRxError );
+#endif
+ // Compute Rx2 windows parameters
+ RxWindowsParams[1] = ComputeRxWindowParameters( LoRaMacParams.Rx2Channel.Datarate, LoRaMacParams.SystemMaxRxError );
+
+ if( IsLoRaMacNetworkJoined == false )
+ {
+ RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 + RxWindowsParams[0].RxOffset;
+ RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 + RxWindowsParams[1].RxOffset;
+ }
+ else
+ {
+ if( ValidatePayloadLength( LoRaMacTxPayloadLen, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false )
+ {
+ return LORAMAC_STATUS_LENGTH_ERROR;
+ }
+ RxWindow1Delay = LoRaMacParams.ReceiveDelay1 + RxWindowsParams[0].RxOffset;
+ RxWindow2Delay = LoRaMacParams.ReceiveDelay2 + RxWindowsParams[1].RxOffset;
+ }
+
// Schedule transmission of frame
if( dutyCycleTimeOff == 0 )
{
@@ -2688,7 +2940,7 @@
else
{
// Send later - prepare timer
- LoRaMacState |= MAC_TX_DELAYED;
+ LoRaMacState |= LORAMAC_TX_DELAYED;
TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
TimerStart( &TxDelayedTimer );
@@ -2696,18 +2948,16 @@
}
}
-static uint16_t RetransmissionDutyCylce( void )
+static uint16_t JoinDutyCycle( void )
{
uint16_t dutyCycle = 0;
-
-#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
- TimerTime_t timeElapsed = TimerGetElapsedTime( 0 );
-
- if( timeElapsed < 3600000000 )
+ TimerTime_t timeElapsed = TimerGetElapsedTime( LoRaMacInitializationTime );
+
+ if( timeElapsed < 3600e3 )
{
dutyCycle = BACKOFF_DC_1_HOUR;
}
- else if( timeElapsed < ( 3600000000 + 36000000000 ) )
+ else if( timeElapsed < ( 3600e3 + 36000e3 ) )
{
dutyCycle = BACKOFF_DC_10_HOURS;
}
@@ -2715,7 +2965,6 @@
{
dutyCycle = BACKOFF_DC_24_HOURS;
}
-#endif
return dutyCycle;
}
@@ -2723,34 +2972,25 @@
{
uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
uint16_t joinDutyCycle = 0;
- bool rndTimeOff = false;
+
+ // Reset time-off to initial value.
+ Bands[Channels[channel].Band].TimeOff = 0;
if( IsLoRaMacNetworkJoined == false )
{
- joinDutyCycle = RetransmissionDutyCylce( );
+ // The node has not joined yet. Apply join duty cycle to all regions.
+ joinDutyCycle = JoinDutyCycle( );
dutyCycle = MAX( dutyCycle, joinDutyCycle );
- // Make sure to not apply the random back-off to the first TX
- if( TxTimeOnAir > 0 )
- {
- rndTimeOff = true;
- }
- }
-
- // Update Band Time OFF
- if( DutyCycleOn == true )
- {
+ // Update Band time-off.
Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
}
else
{
- Bands[Channels[channel].Band].TimeOff = 0;
- }
-
- if( rndTimeOff == true )
- {
- Bands[Channels[channel].Band].TimeOff = randr( Bands[Channels[channel].Band].TimeOff,
- Bands[Channels[channel].Band].TimeOff + BACKOFF_RND_OFFSET );
+ if( DutyCycleOn == true )
+ {
+ Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
+ }
}
// Update Aggregated Time OFF
@@ -2766,7 +3006,7 @@
LoRaMacParams.ChannelsMask[4] = 0x00FF;
#else // defined( USE_BAND_915_HYBRID )
// Re-enable 500 kHz default channels
- ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
+ ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
#endif
if( ( nbTrials & 0x01 ) == 0x01 )
@@ -2775,7 +3015,7 @@
}
else
{
- datarate = DR_1;
+ datarate = DR_0;
}
#else
if( ( nbTrials % 48 ) == 0 )
@@ -2811,7 +3051,7 @@
IsLoRaMacNetworkJoined = false;
// Counters
- UpLinkCounter = 1;
+ UpLinkCounter = 0;
DownLinkCounter = 0;
AdrAckCounter = 0;
@@ -2832,15 +3072,7 @@
LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
- LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow;
- LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1;
- LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2;
- LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1;
- LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2;
-
LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset;
- LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep;
-
LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
@@ -2872,7 +3104,6 @@
uint8_t pktHeaderLen = 0;
uint32_t mic = 0;
const void* payload = fBuffer;
- uint8_t payloadSize = fBufferSize;
uint8_t framePort = fPort;
LoRaMacBufferPktLen = 0;
@@ -2884,14 +3115,13 @@
fBufferSize = 0;
}
+ LoRaMacTxPayloadLen = fBufferSize;
+
LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
switch( macHdr->Bits.MType )
{
case FRAME_TYPE_JOIN_REQ:
- RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
- RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
-
LoRaMacBufferPktLen = pktHeaderLen;
memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
@@ -2914,7 +3144,7 @@
break;
case FRAME_TYPE_DATA_CONFIRMED_UP:
NodeAckRequested = true;
- //Intentional falltrough
+ //Intentional fallthrough
case FRAME_TYPE_DATA_UNCONFIRMED_UP:
if( IsLoRaMacNetworkJoined == false )
{
@@ -2923,14 +3153,6 @@
fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate );
- if( ValidatePayloadLength( fBufferSize, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false )
- {
- return LORAMAC_STATUS_LENGTH_ERROR;
- }
-
- RxWindow1Delay = LoRaMacParams.ReceiveDelay1 - RADIO_WAKEUP_TIME;
- RxWindow2Delay = LoRaMacParams.ReceiveDelay2 - RADIO_WAKEUP_TIME;
-
if( SrvAckRequested == true )
{
SrvAckRequested = false;
@@ -2951,7 +3173,7 @@
memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
- if( ( payload != NULL ) && ( payloadSize > 0 ) )
+ if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
{
if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
{
@@ -2969,7 +3191,7 @@
{
if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
{
- payloadSize = MacCommandsBufferIndex;
+ LoRaMacTxPayloadLen = MacCommandsBufferIndex;
payload = MacCommandsBuffer;
framePort = 0;
}
@@ -2981,23 +3203,21 @@
{
MacCommandsInNextTx = true;
}
- MacCommandsBufferIndex = 0;
-
- if( ( payload != NULL ) && ( payloadSize > 0 ) )
+
+ if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
{
LoRaMacBuffer[pktHeaderLen++] = framePort;
if( framePort == 0 )
{
- LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
+ LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
}
else
{
- LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
+ LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
}
- memcpy1( LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, payloadSize );
}
- LoRaMacBufferPktLen = pktHeaderLen + payloadSize;
+ LoRaMacBufferPktLen = pktHeaderLen + LoRaMacTxPayloadLen;
LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
@@ -3010,10 +3230,10 @@
break;
case FRAME_TYPE_PROPRIETARY:
- if( ( fBuffer != NULL ) && ( fBufferSize > 0 ) )
+ if( ( fBuffer != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
{
- memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, fBufferSize );
- LoRaMacBufferPktLen = pktHeaderLen + fBufferSize;
+ memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, LoRaMacTxPayloadLen );
+ LoRaMacBufferPktLen = pktHeaderLen + LoRaMacTxPayloadLen;
}
break;
default:
@@ -3029,13 +3249,14 @@
int8_t txPowerIndex = 0;
int8_t txPower = 0;
- txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower );
+ txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower, Bands[channel.Band].TxMaxPower );
txPower = TxPowers[txPowerIndex];
MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
McpsConfirm.TxPower = txPowerIndex;
+ McpsConfirm.UpLinkFrequency = channel.Frequency;
Radio.SetChannel( channel.Frequency );
@@ -3043,34 +3264,38 @@
if( LoRaMacParams.ChannelsDatarate == DR_7 )
{ // High Speed FSK channel
Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen );
- Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 );
+ Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e3 );
TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
}
else if( LoRaMacParams.ChannelsDatarate == DR_6 )
{ // High speed LoRa channel
Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
- Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
+ Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
}
else
{ // Normal LoRa channel
Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
- Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
+ Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
}
#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
if( LoRaMacParams.ChannelsDatarate >= DR_4 )
{ // High speed LoRa channel BW500 kHz
- Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
+ Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
}
else
{ // Normal LoRa channel
- Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
+ Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
}
+#elif defined( USE_BAND_470 )
+ Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
+ Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
+ TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
#else
#error "Please define a frequency band in the compiler options."
#endif
@@ -3083,10 +3308,47 @@
TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
TimerStart( &MacStateCheckTimer );
+ if( IsLoRaMacNetworkJoined == false )
+ {
+ JoinRequestTrials++;
+ }
+
// Send now
Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
- LoRaMacState |= MAC_TX_RUNNING;
+ LoRaMacState |= LORAMAC_TX_RUNNING;
+
+ return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout )
+{
+ int8_t txPowerIndex = 0;
+ int8_t txPower = 0;
+
+ txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower, Bands[Channels[Channel].Band].TxMaxPower );
+ txPower = TxPowers[txPowerIndex];
+
+ // Starts the MAC layer status check timer
+ TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
+ TimerStart( &MacStateCheckTimer );
+
+ Radio.SetTxContinuousWave( Channels[Channel].Frequency, txPower, timeout );
+
+ LoRaMacState |= LORAMAC_TX_RUNNING;
+
+ return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power )
+{
+ Radio.SetTxContinuousWave( frequency, power, timeout );
+
+ // Starts the MAC layer status check timer
+ TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
+ TimerStart( &MacStateCheckTimer );
+
+ LoRaMacState |= LORAMAC_TX_RUNNING;
return LORAMAC_STATUS_OK;
}
@@ -3100,7 +3362,7 @@
if( ( primitives->MacMcpsConfirm == NULL ) ||
( primitives->MacMcpsIndication == NULL ) ||
- ( primitives->MacMlmeConfirm == NULL ))
+ ( primitives->MacMlmeConfirm == NULL ) )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
@@ -3111,9 +3373,10 @@
LoRaMacFlags.Value = 0;
LoRaMacDeviceClass = CLASS_A;
- LoRaMacState = MAC_IDLE;
+ LoRaMacState = LORAMAC_IDLE;
JoinRequestTrials = 0;
+ MaxJoinRequestTrials = 1;
RepeaterSupport = false;
// Reset duty cycle times
@@ -3122,9 +3385,11 @@
// Duty cycle
#if defined( USE_BAND_433 )
+ DutyCycleOn = true;
+#elif defined( USE_BAND_470 )
DutyCycleOn = false;
#elif defined( USE_BAND_780 )
- DutyCycleOn = false;
+ DutyCycleOn = true;
#elif defined( USE_BAND_868 )
DutyCycleOn = true;
#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
@@ -3137,6 +3402,8 @@
LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
LoRaMacParamsDefaults.ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
+ LoRaMacParamsDefaults.SystemMaxRxError = 10;
+ LoRaMacParamsDefaults.MinRxSymbols = 6;
LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW;
LoRaMacParamsDefaults.ReceiveDelay1 = RECEIVE_DELAY1;
LoRaMacParamsDefaults.ReceiveDelay2 = RECEIVE_DELAY2;
@@ -3151,6 +3418,13 @@
// Channel mask
#if defined( USE_BAND_433 )
LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+#elif defined ( USE_BAND_470 )
+ LoRaMacParamsDefaults.ChannelsMask[0] = 0xFFFF;
+ LoRaMacParamsDefaults.ChannelsMask[1] = 0xFFFF;
+ LoRaMacParamsDefaults.ChannelsMask[2] = 0xFFFF;
+ LoRaMacParamsDefaults.ChannelsMask[3] = 0xFFFF;
+ LoRaMacParamsDefaults.ChannelsMask[4] = 0xFFFF;
+ LoRaMacParamsDefaults.ChannelsMask[5] = 0xFFFF;
#elif defined( USE_BAND_780 )
LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
#elif defined( USE_BAND_868 )
@@ -3188,8 +3462,26 @@
Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
Channels[i].Band = 0;
}
+#elif defined( USE_BAND_470 )
+ // 125 kHz channels
+ for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
+ {
+ Channels[i].Frequency = 470.3e6 + i * 200e3;
+ Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
+ Channels[i].Band = 0;
+ }
#endif
+ // Init parameters which are not set in function ResetMacParameters
+ LoRaMacParams.SystemMaxRxError = LoRaMacParamsDefaults.SystemMaxRxError;
+ LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols;
+ LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow;
+ LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1;
+ LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2;
+ LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1;
+ LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2;
+ LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep;
+
ResetMacParameters( );
// Initialize timers
@@ -3201,6 +3493,9 @@
TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
+ // Store the current initialization time
+ LoRaMacInitializationTime = TimerGetCurrentTime( );
+
// Initialize Radio driver
RadioEvents.TxDone = OnRadioTxDone;
RadioEvents.RxDone = OnRadioRxDone;
@@ -3213,7 +3508,7 @@
srand1( Radio.Random( ) );
PublicNetwork = true;
- SetPublicNetwork( PublicNetwork );
+ Radio.SetPublicNetwork( PublicNetwork );
Radio.Sleep( );
return LORAMAC_STATUS_OK;
@@ -3328,6 +3623,16 @@
mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel;
break;
}
+ case MIB_RX2_DEFAULT_CHANNEL:
+ {
+ mibGet->Param.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
+ break;
+ }
+ case MIB_CHANNELS_DEFAULT_MASK:
+ {
+ mibGet->Param.ChannelsDefaultMask = LoRaMacParamsDefaults.ChannelsMask;
+ break;
+ }
case MIB_CHANNELS_MASK:
{
mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask;
@@ -3373,6 +3678,11 @@
mibGet->Param.ChannelsDatarate = LoRaMacParams.ChannelsDatarate;
break;
}
+ case MIB_CHANNELS_DEFAULT_TX_POWER:
+ {
+ mibGet->Param.ChannelsDefaultTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
+ break;
+ }
case MIB_CHANNELS_TX_POWER:
{
mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower;
@@ -3393,6 +3703,16 @@
mibGet->Param.MulticastList = MulticastChannels;
break;
}
+ case MIB_SYSTEM_MAX_RX_ERROR:
+ {
+ mibGet->Param.SystemMaxRxError = LoRaMacParams.SystemMaxRxError;
+ break;
+ }
+ case MIB_MIN_RX_SYMBOLS:
+ {
+ mibGet->Param.MinRxSymbols = LoRaMacParams.MinRxSymbols;
+ break;
+ }
default:
status = LORAMAC_STATUS_SERVICE_UNKNOWN;
break;
@@ -3409,7 +3729,7 @@
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+ if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
return LORAMAC_STATUS_BUSY;
}
@@ -3489,7 +3809,8 @@
}
case MIB_PUBLIC_NETWORK:
{
- SetPublicNetwork( mibSet->Param.EnablePublicNetwork );
+ PublicNetwork = mibSet->Param.EnablePublicNetwork;
+ Radio.SetPublicNetwork( PublicNetwork );
break;
}
case MIB_REPEATER_SUPPORT:
@@ -3502,6 +3823,57 @@
LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel;
break;
}
+ case MIB_RX2_DEFAULT_CHANNEL:
+ {
+ LoRaMacParamsDefaults.Rx2Channel = mibSet->Param.Rx2DefaultChannel;
+ break;
+ }
+ case MIB_CHANNELS_DEFAULT_MASK:
+ {
+ if( mibSet->Param.ChannelsDefaultMask )
+ {
+#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+ bool chanMaskState = true;
+
+#if defined( USE_BAND_915_HYBRID )
+ chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsDefaultMask );
+#endif
+ if( chanMaskState == true )
+ {
+ if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) &&
+ ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ else
+ {
+ memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
+ ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, sizeof( LoRaMacParamsDefaults.ChannelsMask ) );
+ for ( uint8_t i = 0; i < sizeof( LoRaMacParamsDefaults.ChannelsMask ) / 2; i++ )
+ {
+ // Disable channels which are no longer available
+ ChannelsMaskRemaining[i] &= LoRaMacParamsDefaults.ChannelsMask[i];
+ }
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+#elif defined( USE_BAND_470 )
+ memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
+ ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, sizeof( LoRaMacParamsDefaults.ChannelsMask ) );
+#else
+ memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
+ ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, 2 );
+#endif
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
case MIB_CHANNELS_MASK:
{
if( mibSet->Param.ChannelsMask )
@@ -3514,7 +3886,7 @@
#endif
if( chanMaskState == true )
{
- if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 6 ) &&
+ if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) &&
( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
{
status = LORAMAC_STATUS_PARAMETER_INVALID;
@@ -3534,6 +3906,9 @@
{
status = LORAMAC_STATUS_PARAMETER_INVALID;
}
+#elif defined( USE_BAND_470 )
+ memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
+ ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
#else
memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
( uint8_t* ) mibSet->Param.ChannelsMask, 2 );
@@ -3585,11 +3960,19 @@
}
case MIB_CHANNELS_DEFAULT_DATARATE:
{
+#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
+ if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
+ DR_0, DR_5 ) )
+ {
+ LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
+ }
+#else
if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
{
LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
}
+#endif
else
{
status = LORAMAC_STATUS_PARAMETER_INVALID;
@@ -3609,6 +3992,19 @@
}
break;
}
+ case MIB_CHANNELS_DEFAULT_TX_POWER:
+ {
+ if( ValueInRange( mibSet->Param.ChannelsDefaultTxPower,
+ LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
+ {
+ LoRaMacParamsDefaults.ChannelsTxPower = mibSet->Param.ChannelsDefaultTxPower;
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
case MIB_CHANNELS_TX_POWER:
{
if( ValueInRange( mibSet->Param.ChannelsTxPower,
@@ -3632,6 +4028,16 @@
DownLinkCounter = mibSet->Param.DownLinkCounter;
break;
}
+ case MIB_SYSTEM_MAX_RX_ERROR:
+ {
+ LoRaMacParams.SystemMaxRxError = LoRaMacParamsDefaults.SystemMaxRxError = mibSet->Param.SystemMaxRxError;
+ break;
+ }
+ case MIB_MIN_RX_SYMBOLS:
+ {
+ LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols = mibSet->Param.MinRxSymbols;
+ break;
+ }
default:
status = LORAMAC_STATUS_SERVICE_UNKNOWN;
break;
@@ -3642,7 +4048,7 @@
LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
{
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+#if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
return LORAMAC_STATUS_PARAMETER_INVALID;
#else
bool datarateInvalid = false;
@@ -3655,9 +4061,9 @@
return LORAMAC_STATUS_PARAMETER_INVALID;
}
// Validate if the MAC is in a correct state
- if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+ if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
- if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
+ if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
{
return LORAMAC_STATUS_BUSY;
}
@@ -3680,7 +4086,7 @@
frequencyInvalid = true;
}
- if( params.DrRange.Fields.Min > LoRaMacParamsDefaults.ChannelsDatarate )
+ if( params.DrRange.Fields.Min > DR_0 )
{
datarateInvalid = true;
}
@@ -3695,7 +4101,11 @@
if( ( Radio.CheckRfFrequency( params.Frequency ) == true ) && ( params.Frequency > 0 ) && ( frequencyInvalid == false ) )
{
#if defined( USE_BAND_868 )
- if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
+ if( ( params.Frequency >= 863000000 ) && ( params.Frequency < 865000000 ) )
+ {
+ band = BAND_G1_2;
+ }
+ else if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
{
band = BAND_G1_0;
}
@@ -3751,9 +4161,9 @@
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
{
#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
- if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+ if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
- if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
+ if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
{
return LORAMAC_STATUS_BUSY;
}
@@ -3775,7 +4185,7 @@
}
}
return LORAMAC_STATUS_OK;
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) || defined( USE_BAND_470 ) )
return LORAMAC_STATUS_PARAMETER_INVALID;
#endif
}
@@ -3786,7 +4196,7 @@
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+ if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
return LORAMAC_STATUS_BUSY;
}
@@ -3821,7 +4231,7 @@
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+ if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
return LORAMAC_STATUS_BUSY;
}
@@ -3863,7 +4273,7 @@
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
+ if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
return LORAMAC_STATUS_BUSY;
}
@@ -3876,33 +4286,52 @@
{
case MLME_JOIN:
{
- if( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED )
+ if( ( LoRaMacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED )
{
return LORAMAC_STATUS_BUSY;
}
- MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
if( ( mlmeRequest->Req.Join.DevEui == NULL ) ||
( mlmeRequest->Req.Join.AppEui == NULL ) ||
- ( mlmeRequest->Req.Join.AppKey == NULL ) )
+ ( mlmeRequest->Req.Join.AppKey == NULL ) ||
+ ( mlmeRequest->Req.Join.NbTrials == 0 ) )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
+#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
+ // Enables at least the usage of the 2 datarates.
+ if( mlmeRequest->Req.Join.NbTrials < 2 )
+ {
+ mlmeRequest->Req.Join.NbTrials = 2;
+ }
+#else
+ // Enables at least the usage of all datarates.
+ if( mlmeRequest->Req.Join.NbTrials < 48 )
+ {
+ mlmeRequest->Req.Join.NbTrials = 48;
+ }
+#endif
+
LoRaMacFlags.Bits.MlmeReq = 1;
+ MlmeConfirm.MlmeRequest = mlmeRequest->Type;
LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
-
+ MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials;
+
+ // Reset variable JoinRequestTrials
+ JoinRequestTrials = 0;
+
+ // Setup header information
macHdr.Value = 0;
macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
ResetMacParameters( );
- JoinRequestTrials++;
- LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials );
+ // Add a +1, since we start to count from 0
+ LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials + 1 );
status = Send( &macHdr, 0, NULL, 0 );
break;
@@ -3916,6 +4345,20 @@
status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
break;
}
+ case MLME_TXCW:
+ {
+ MlmeConfirm.MlmeRequest = mlmeRequest->Type;
+ LoRaMacFlags.Bits.MlmeReq = 1;
+ status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout );
+ break;
+ }
+ case MLME_TXCW_1:
+ {
+ MlmeConfirm.MlmeRequest = mlmeRequest->Type;
+ LoRaMacFlags.Bits.MlmeReq = 1;
+ status = SetTxContinuousWave1( mlmeRequest->Req.TxCw.Timeout, mlmeRequest->Req.TxCw.Frequency, mlmeRequest->Req.TxCw.Power );
+ break;
+ }
default:
break;
}
@@ -3943,8 +4386,8 @@
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING ) ||
- ( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED ) )
+ if( ( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING ) ||
+ ( ( LoRaMacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED ) )
{
return LORAMAC_STATUS_BUSY;
}
@@ -4037,5 +4480,52 @@
void LoRaMacTestSetDutyCycleOn( bool enable )
{
+#if ( defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) )
DutyCycleOn = enable;
+#else
+ DutyCycleOn = false;
+#endif
}
+
+void LoRaMacTestSetChannel( uint8_t channel )
+{
+ Channel = channel;
+}
+
+static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError )
+{
+ RxConfigParams_t rxConfigParams = { 0, 0, 0, 0 };
+ double tSymbol = 0.0;
+
+ rxConfigParams.Datarate = datarate;
+ switch( Bandwidths[datarate] )
+ {
+ default:
+ case 125000:
+ rxConfigParams.Bandwidth = 0;
+ break;
+ case 250000:
+ rxConfigParams.Bandwidth = 1;
+ break;
+ case 500000:
+ rxConfigParams.Bandwidth = 2;
+ break;
+ }
+
+#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
+ if( datarate == DR_7 )
+ { // FSK
+ tSymbol = ( 1.0 / ( double )Datarates[datarate] ) * 8.0; // 1 symbol equals 1 byte
+ }
+ else
+#endif
+ { // LoRa
+ tSymbol = ( ( double )( 1 << Datarates[datarate] ) / ( double )Bandwidths[datarate] ) * 1e3;
+ }
+
+ rxConfigParams.RxWindowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * LoRaMacParams.MinRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), LoRaMacParams.MinRxSymbols ); // Computed number of symbols
+
+ rxConfigParams.RxOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( rxConfigParams.RxWindowTimeout * tSymbol ) / 2.0 ) - RADIO_WAKEUP_TIME );
+
+ return rxConfigParams;
+}


