Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
LoRAWAN-lib is a port of the GitHub LoRaMac-node develop branch LoRaWAN MAC layer implementation.
This library depends on the SX1276Lib or SX1272Lib radio drivers depending on the used mbed component shield.
This library depends also on some cryptographic helper functions as well as helper functions for the timers management. These can be found on the example projects under the system directory.
The example projects are:
The LoRaWAN specification specifies different ISM bands operating parameters. These are all implemented under the LoRaMac-board.h file.
In order to select which band to use, please change line 24 of board.h file provided on the examples projects as follows:
EU868
board.h
#define USE_BAND_868
US915
board.h
#define USE_BAND_915
US915 - Hybrid
board.h
#define USE_BAND_915_HYBRID
CN780
board.h
#define USE_BAND_780
EU433
board.h
#define USE_BAND_433
Revision 2:76f59096e3a7, committed 2017-04-24
- Comitter:
- mluis
- Date:
- Mon Apr 24 14:11:47 2017 +0000
- Parent:
- 1:4820e04b066c
- Commit message:
- WARNING: API timings changed from micro-seconds to milliseconds; Synchronized with https://github.com/Lora-net/LoRaMac-node git revision c82a25f9c5cc746dc2be1f8ed7f76c3707975ab2; ;
Changed in this revision
--- a/LoRaMac-definitions.h Tue Jul 05 15:12:50 2016 +0000
+++ b/LoRaMac-definitions.h Mon Apr 24 14:11:47 2017 +0000
@@ -103,6 +103,13 @@
#define DR_7 7 // FSK
/*!
+ * Verification of default datarate
+ */
+#if ( LORAMAC_DEFAULT_DATARATE > DR_5 )
+#error "A default DR higher than DR_5 may lead to connectivity loss."
+#endif
+
+/*!
* Second reception window channel definition.
*/
// Channel = { Frequency [Hz], Datarate }
@@ -125,19 +132,104 @@
#define LC3 { 433575000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
- * LoRaMac duty cycle for the back-off procedure
- */
-#define BACKOFF_DC_1_HOUR 100
-#define BACKOFF_DC_10_HOURS 1000
-#define BACKOFF_DC_24_HOURS 10000
-
-#define BACKOFF_RND_OFFSET 600000
-
-/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
+#elif defined( USE_BAND_470 )
+
+/*!
+ * LoRaMac maximum number of channels
+ */
+#define LORA_MAX_NB_CHANNELS 96
+
+/*!
+ * Minimal datarate that can be used by the node
+ */
+#define LORAMAC_TX_MIN_DATARATE DR_0
+
+/*!
+ * Maximal datarate that can be used by the node
+ */
+#define LORAMAC_TX_MAX_DATARATE DR_5
+
+/*!
+ * Minimal datarate that can be used by the node
+ */
+#define LORAMAC_RX_MIN_DATARATE DR_0
+
+/*!
+ * Maximal datarate that can be used by the node
+ */
+#define LORAMAC_RX_MAX_DATARATE DR_5
+
+/*!
+ * Default datarate used by the node
+ */
+#define LORAMAC_DEFAULT_DATARATE DR_0
+
+/*!
+ * Minimal Rx1 receive datarate offset
+ */
+#define LORAMAC_MIN_RX1_DR_OFFSET 0
+
+/*!
+ * Maximal Rx1 receive datarate offset
+ */
+#define LORAMAC_MAX_RX1_DR_OFFSET 3
+
+/*!
+ * Minimal Tx output power that can be used by the node
+ */
+#define LORAMAC_MIN_TX_POWER TX_POWER_2_DBM
+
+/*!
+ * Maximal Tx output power that can be used by the node
+ */
+#define LORAMAC_MAX_TX_POWER TX_POWER_17_DBM
+
+/*!
+ * Default Tx output power used by the node
+ */
+#define LORAMAC_DEFAULT_TX_POWER TX_POWER_14_DBM
+
+/*!
+ * LoRaMac TxPower definition
+ */
+#define TX_POWER_17_DBM 0
+#define TX_POWER_16_DBM 1
+#define TX_POWER_14_DBM 2
+#define TX_POWER_12_DBM 3
+#define TX_POWER_10_DBM 4
+#define TX_POWER_7_DBM 5
+#define TX_POWER_5_DBM 6
+#define TX_POWER_2_DBM 7
+
+
+/*!
+ * LoRaMac datarates definition
+ */
+#define DR_0 0 // SF12 - BW125 |
+#define DR_1 1 // SF11 - BW125 |
+#define DR_2 2 // SF10 - BW125 |
+#define DR_3 3 // SF9 - BW125 |
+#define DR_4 4 // SF8 - BW125 |
+#define DR_5 5 // SF7 - BW125 |
+
+/*!
+ * Second reception window channel definition.
+ */
+// Channel = { Frequency [Hz], Datarate }
+#define RX_WND_2_CHANNEL { 505300000, DR_0 }
+
+/*!
+ * LoRaMac maximum number of bands
+ */
+#define LORA_MAX_NB_BANDS 1
+
+// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+#define BAND0 { 1, TX_POWER_17_DBM, 0, 0 } // 100.0 %
+
#elif defined( USE_BAND_780 )
/*!
@@ -218,6 +310,13 @@
#define DR_7 7 // FSK
/*!
+ * Verification of default datarate
+ */
+#if ( LORAMAC_DEFAULT_DATARATE > DR_5 )
+#error "A default DR higher than DR_5 may lead to connectivity loss."
+#endif
+
+/*!
* Second reception window channel definition.
*/
// Channel = { Frequency [Hz], Datarate }
@@ -240,15 +339,6 @@
#define LC3 { 779900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
/*!
- * LoRaMac duty cycle for the back-off procedure
- */
-#define BACKOFF_DC_1_HOUR 100
-#define BACKOFF_DC_10_HOURS 1000
-#define BACKOFF_DC_24_HOURS 10000
-
-#define BACKOFF_RND_OFFSET 600000
-
-/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
@@ -333,6 +423,13 @@
#define DR_7 7 // FSK
/*!
+ * Verification of default datarate
+ */
+#if ( LORAMAC_DEFAULT_DATARATE > DR_5 )
+#error "A default DR higher than DR_5 may lead to connectivity loss."
+#endif
+
+/*!
* Second reception window channel definition.
*/
// Channel = { Frequency [Hz], Datarate }
@@ -371,15 +468,6 @@
#define LC3 { 868500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
/*!
- * LoRaMac duty cycle for the back-off procedure
- */
-#define BACKOFF_DC_1_HOUR 100
-#define BACKOFF_DC_10_HOURS 1000
-#define BACKOFF_DC_24_HOURS 10000
-
-#define BACKOFF_RND_OFFSET 600000
-
-/*!
* LoRaMac channels which are allowed for the join procedure
*/
#define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
@@ -490,8 +578,6 @@
// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
#define BAND0 { 1, TX_POWER_20_DBM, 0, 0 } // 100.0 %
-#define BACKOFF_RND_OFFSET 600000
-
/*!
* LoRaMac default channels
*/
--- a/LoRaMac.cpp Tue Jul 05 15:12:50 2016 +0000
+++ b/LoRaMac.cpp Mon Apr 24 14:11:47 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,24 +1105,22 @@
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 );
+#if defined( USE_RADIO_DEBUG ) && defined( USE_DEBUG_PINS )
+ GpioWrite( &DbgPin5, 0 );
+#endif
}
static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
@@ -966,10 +1164,7 @@
McpsIndication.DownLinkCounter = 0;
McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
- if( LoRaMacDeviceClass != CLASS_C )
- {
- Radio.Sleep( );
- }
+ Radio.Sleep( );
TimerStop( &RxWindowTimer2 );
macHdr.Value = payload[pktHeaderLen++];
@@ -979,7 +1174,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 +1205,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 +1222,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;
@@ -1138,6 +1333,9 @@
if( isMicOk == true )
{
+#if defined( USE_RADIO_DEBUG ) && defined( USE_DEBUG_PINS )
+ GpioWrite( &DbgPin5, 1 );
+#endif
McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
McpsIndication.Multicast = multicast;
McpsIndication.FramePending = fCtrl.Bits.FPending;
@@ -1176,6 +1374,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 +1398,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 +1424,7 @@
if( port == 0 )
{
+ // Only allow frames which do not have fOpts
if( fCtrl.Bits.FOptsLen == 0 )
{
LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
@@ -1280,8 +1478,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,16 +1531,14 @@
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 );
+#if defined( USE_RADIO_DEBUG ) && defined( USE_DEBUG_PINS )
+ GpioWrite( &DbgPin5, 0 );
+#endif
}
static void OnRadioTxTimeout( void )
@@ -1348,7 +1568,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 +1621,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 +1633,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 +1644,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 +1712,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 +1727,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 +1780,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 +1798,7 @@
LoRaMacFlags.Bits.MlmeReq = 0;
}
+ // Procedure done. Reset variables.
LoRaMacFlags.Bits.MacDone = 0;
}
else
@@ -1540,7 +1810,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 +1829,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 +1854,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 +1863,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 +1875,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 +1896,7 @@
if( NodeAckRequested == true )
{
AckTimeoutRetry = true;
- LoRaMacState &= ~MAC_ACK_REQ;
+ LoRaMacState &= ~LORAMAC_ACK_REQ;
}
if( LoRaMacDeviceClass == CLASS_C )
{
@@ -1758,6 +1922,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 +1948,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 +1956,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 +2039,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 +2055,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 +2084,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 +2159,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 +2188,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 +2214,7 @@
{
if( i != index )
{
- channelMask[i] = 0;
+ channelsMask[i] = 0;
}
}
}
@@ -2063,9 +2223,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 +2312,7 @@
if( AdrAckCounter >= ADR_ACK_LIMIT )
{
adrAckReq = true;
+ LoRaMacParams.ChannelsTxPower = LORAMAC_MAX_TX_POWER;
}
else
{
@@ -2132,7 +2320,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 +2335,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 +2363,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 +2477,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 +2489,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 +2600,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 +2617,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 +2630,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 +2677,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 +2694,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 +2775,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 +2789,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 +2834,7 @@
}
}
}
- LoRaMacState &= ~MAC_TX_CONFIG;
+ LoRaMacState &= ~LORAMAC_TX_CONFIG;
#endif
AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
}
@@ -2608,8 +2847,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 +2890,7 @@
return status;
}
-static LoRaMacStatus_t ScheduleTx( )
+static LoRaMacStatus_t ScheduleTx( void )
{
TimerTime_t dutyCycleTimeOff = 0;
@@ -2665,8 +2904,6 @@
AggregatedTimeOff = 0;
}
- CalculateBackOff( LastTxChannel );
-
// Select channel
while( SetNextChannel( &dutyCycleTimeOff ) == false )
{
@@ -2679,6 +2916,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 +2949,7 @@
else
{
// Send later - prepare timer
- LoRaMacState |= MAC_TX_DELAYED;
+ LoRaMacState |= LORAMAC_TX_DELAYED;
TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
TimerStart( &TxDelayedTimer );
@@ -2696,18 +2957,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 +2974,6 @@
{
dutyCycle = BACKOFF_DC_24_HOURS;
}
-#endif
return dutyCycle;
}
@@ -2723,34 +2981,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 +3015,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 +3024,7 @@
}
else
{
- datarate = DR_1;
+ datarate = DR_0;
}
#else
if( ( nbTrials % 48 ) == 0 )
@@ -2811,7 +3060,7 @@
IsLoRaMacNetworkJoined = false;
// Counters
- UpLinkCounter = 1;
+ UpLinkCounter = 0;
DownLinkCounter = 0;
AdrAckCounter = 0;
@@ -2832,15 +3081,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 +3113,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 +3124,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 +3153,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 +3162,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 +3182,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 +3200,7 @@
{
if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
{
- payloadSize = MacCommandsBufferIndex;
+ LoRaMacTxPayloadLen = MacCommandsBufferIndex;
payload = MacCommandsBuffer;
framePort = 0;
}
@@ -2981,23 +3212,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 +3239,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 +3258,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 +3273,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 +3317,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 +3371,7 @@
if( ( primitives->MacMcpsConfirm == NULL ) ||
( primitives->MacMcpsIndication == NULL ) ||
- ( primitives->MacMlmeConfirm == NULL ))
+ ( primitives->MacMlmeConfirm == NULL ) )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
@@ -3111,9 +3382,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 +3394,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 +3411,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 +3427,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 +3471,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 +3502,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 +3517,7 @@
srand1( Radio.Random( ) );
PublicNetwork = true;
- SetPublicNetwork( PublicNetwork );
+ Radio.SetPublicNetwork( PublicNetwork );
Radio.Sleep( );
return LORAMAC_STATUS_OK;
@@ -3328,6 +3632,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 +3687,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 +3712,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 +3738,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 +3818,8 @@
}
case MIB_PUBLIC_NETWORK:
{
- SetPublicNetwork( mibSet->Param.EnablePublicNetwork );
+ PublicNetwork = mibSet->Param.EnablePublicNetwork;
+ Radio.SetPublicNetwork( PublicNetwork );
break;
}
case MIB_REPEATER_SUPPORT:
@@ -3502,6 +3832,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 +3895,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 +3915,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 +3969,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 +4001,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 +4037,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 +4057,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 +4070,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 +4095,7 @@
frequencyInvalid = true;
}
- if( params.DrRange.Fields.Min > LoRaMacParamsDefaults.ChannelsDatarate )
+ if( params.DrRange.Fields.Min > DR_0 )
{
datarateInvalid = true;
}
@@ -3695,7 +4110,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 +4170,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 +4194,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 +4205,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 +4240,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 +4282,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 +4295,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 +4354,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 +4395,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 +4489,52 @@
void LoRaMacTestSetDutyCycleOn( bool enable )
{
+#if ( defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) )
DutyCycleOn = enable;
+#else
+ DutyCycleOn = false;
+#endif
}
+
+void LoRaMacTestSetChannel( uint8_t channel )
+{
+ Channel = channel;
+}
+
+static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError )
+{
+ RxConfigParams_t rxConfigParams = { 0, 0, 0, 0 };
+ double tSymbol = 0.0;
+
+ rxConfigParams.Datarate = datarate;
+ switch( Bandwidths[datarate] )
+ {
+ default:
+ case 125000:
+ rxConfigParams.Bandwidth = 0;
+ break;
+ case 250000:
+ rxConfigParams.Bandwidth = 1;
+ break;
+ case 500000:
+ rxConfigParams.Bandwidth = 2;
+ break;
+ }
+
+#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
+ if( datarate == DR_7 )
+ { // FSK
+ tSymbol = ( 1.0 / ( double )Datarates[datarate] ) * 8.0; // 1 symbol equals 1 byte
+ }
+ else
+#endif
+ { // LoRa
+ tSymbol = ( ( double )( 1 << Datarates[datarate] ) / ( double )Bandwidths[datarate] ) * 1e3;
+ }
+
+ rxConfigParams.RxWindowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * LoRaMacParams.MinRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), LoRaMacParams.MinRxSymbols ); // Computed number of symbols
+
+ rxConfigParams.RxOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( rxConfigParams.RxWindowTimeout * tSymbol ) / 2.0 ) - RADIO_WAKEUP_TIME );
+
+ return rxConfigParams;
+}
--- a/LoRaMac.h Tue Jul 05 15:12:50 2016 +0000
+++ b/LoRaMac.h Mon Apr 24 14:11:47 2017 +0000
@@ -50,34 +50,34 @@
#include "LoRaMac-definitions.h"
/*!
- * Beacon interval in us
+ * Beacon interval in ms
*/
-#define BEACON_INTERVAL 128000000
+#define BEACON_INTERVAL 128000
/*!
- * Class A&B receive delay 1 in us
+ * Class A&B receive delay 1 in ms
*/
-#define RECEIVE_DELAY1 1000000
+#define RECEIVE_DELAY1 1000
/*!
- * Class A&B receive delay 2 in us
+ * Class A&B receive delay 2 in ms
*/
-#define RECEIVE_DELAY2 2000000
+#define RECEIVE_DELAY2 2000
/*!
- * Join accept receive delay 1 in us
+ * Join accept receive delay 1 in ms
*/
-#define JOIN_ACCEPT_DELAY1 5000000
+#define JOIN_ACCEPT_DELAY1 5000
/*!
- * Join accept receive delay 2 in us
+ * Join accept receive delay 2 in ms
*/
-#define JOIN_ACCEPT_DELAY2 6000000
+#define JOIN_ACCEPT_DELAY2 6000
/*!
- * Class A&B maximum receive window delay in us
+ * Class A&B maximum receive window delay in ms
*/
-#define MAX_RX_WINDOW 3000000
+#define MAX_RX_WINDOW 3000
/*!
* Maximum allowed gap for the FCNT field
@@ -99,19 +99,19 @@
* receiving an acknowledge.
* AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
*/
-#define ACK_TIMEOUT 2000000
+#define ACK_TIMEOUT 2000
/*!
* Random number of seconds after the start of the second reception window without
* receiving an acknowledge
* AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
*/
-#define ACK_TIMEOUT_RND 1000000
+#define ACK_TIMEOUT_RND 1000
/*!
- * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in us
+ * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in ms
*/
-#define MAC_STATE_CHECK_TIMEOUT 1000000
+#define MAC_STATE_CHECK_TIMEOUT 1000
/*!
* Maximum number of times the MAC layer tries to get an acknowledge.
@@ -140,16 +140,6 @@
#define LORAMAC_MFR_LEN 4
/*!
- * Syncword for Private LoRa networks
- */
-#define LORA_MAC_PRIVATE_SYNCWORD 0x12
-
-/*!
- * Syncword for Public LoRa networks
- */
-#define LORA_MAC_PUBLIC_SYNCWORD 0x34
-
-/*!
* LoRaWAN devices classes definition
*/
typedef enum eDeviceClass
@@ -282,6 +272,17 @@
*/
int8_t ChannelsDatarate;
/*!
+ * System overall timing error in milliseconds.
+ * [-SystemMaxRxError : +SystemMaxRxError]
+ * Default: +/-10 ms
+ */
+ uint32_t SystemMaxRxError;
+ /*!
+ * Minimum required number of symbols to detect an Rx frame
+ * Default: 6 symbols
+ */
+ uint8_t MinRxSymbols;
+ /*!
* LoRaMac maximum time a reception window stays open
*/
uint32_t MaxRxWindow;
@@ -564,23 +565,27 @@
*/
LORAMAC_EVENT_INFO_STATUS_OK = 0,
/*!
- * An error occured during the execution of the service
+ * An error occurred during the execution of the service
*/
LORAMAC_EVENT_INFO_STATUS_ERROR,
/*!
- * A Tx timeouit occured
+ * A Tx timeout occurred
*/
LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT,
/*!
- * An Rx timeout occured on receive window 2
+ * An Rx timeout occurred on receive window 2
*/
LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT,
/*!
- * An Rx error occured on receive window 2
+ * An Rx error occurred on receive window 1
+ */
+ LORAMAC_EVENT_INFO_STATUS_RX1_ERROR,
+ /*!
+ * An Rx error occurred on receive window 2
*/
LORAMAC_EVENT_INFO_STATUS_RX2_ERROR,
/*!
- * An error occured in the join procedure
+ * An error occurred in the join procedure
*/
LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL,
/*!
@@ -590,11 +595,16 @@
*/
LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED,
/*!
+ * The MAC could not retransmit a frame since the MAC decreased the datarate. The
+ * payload size is not applicable for the datarate.
+ */
+ LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR,
+ /*!
* The node has lost MAX_FCNT_GAP or more frames.
*/
LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS,
/*!
- * An address error occured
+ * An address error occurred
*/
LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL,
/*!
@@ -626,6 +636,10 @@
*/
uint8_t McpsInd : 1;
/*!
+ * MCPS-Ind pending. Skip indication to the application layer
+ */
+ uint8_t McpsIndSkip : 1;
+ /*!
* MLME-Req pending
*/
uint8_t MlmeReq : 1;
@@ -838,6 +852,10 @@
* The uplink counter value related to the frame
*/
uint32_t UpLinkCounter;
+ /*!
+ * The uplink frequency related to the frame
+ */
+ uint32_t UpLinkFrequency;
}McpsConfirm_t;
/*!
@@ -915,6 +933,7 @@
* --------------------- | :-----: | :--------: | :------: | :-----:
* \ref MLME_JOIN | YES | NO | NO | YES
* \ref MLME_LINK_CHECK | YES | NO | NO | YES
+ * \ref MLME_TXCW | YES | NO | NO | YES
*
* The following table provides links to the function implementations of the
* related MLME primitives.
@@ -938,6 +957,18 @@
* LoRaWAN Specification V1.0.1, chapter 5, table 4
*/
MLME_LINK_CHECK,
+ /*!
+ * Sets Tx continuous wave mode
+ *
+ * LoRaWAN end-device certification
+ */
+ MLME_TXCW,
+ /*!
+ * Sets Tx continuous wave mode (new LoRa-Alliance CC definition)
+ *
+ * LoRaWAN end-device certification
+ */
+ MLME_TXCW_1,
}Mlme_t;
/*!
@@ -963,9 +994,32 @@
* LoRaWAN Specification V1.0.1, chapter 6.2.2
*/
uint8_t *AppKey;
+ /*!
+ * Number of trials for the join request.
+ */
+ uint8_t NbTrials;
}MlmeReqJoin_t;
/*!
+ * LoRaMAC MLME-Request for Tx continuous wave mode
+ */
+typedef struct sMlmeReqTxCw
+{
+ /*!
+ * Time in seconds while the radio is kept in continuous wave mode
+ */
+ uint16_t Timeout;
+ /*!
+ * RF frequency to set (Only used with new way)
+ */
+ uint32_t Frequency;
+ /*!
+ * RF output power to set (Only used with new way)
+ */
+ uint8_t Power;
+}MlmeReqTxCw_t;
+
+/*!
* LoRaMAC MLME-Request structure
*/
typedef struct sMlmeReq
@@ -984,6 +1038,10 @@
* MLME-Request parameters for a join request
*/
MlmeReqJoin_t Join;
+ /*!
+ * MLME-Request parameters for Tx continuous mode request
+ */
+ MlmeReqTxCw_t TxCw;
}Req;
}MlmeReq_t;
@@ -1013,6 +1071,10 @@
* Number of gateways which received the last LinkCheckReq
*/
uint8_t NbGateways;
+ /*!
+ * Provides the number of retransmissions
+ */
+ uint8_t NbRetries;
}MlmeConfirm_t;
/*!
@@ -1034,6 +1096,7 @@
* \ref MIB_CHANNELS | YES | NO
* \ref MIB_RX2_CHANNEL | YES | YES
* \ref MIB_CHANNELS_MASK | YES | YES
+ * \ref MIB_CHANNELS_DEFAULT_MASK | YES | YES
* \ref MIB_CHANNELS_NB_REP | YES | YES
* \ref MIB_MAX_RX_WINDOW_DURATION | YES | YES
* \ref MIB_RECEIVE_DELAY_1 | YES | YES
@@ -1043,9 +1106,12 @@
* \ref MIB_CHANNELS_DATARATE | YES | YES
* \ref MIB_CHANNELS_DEFAULT_DATARATE| YES | YES
* \ref MIB_CHANNELS_TX_POWER | YES | YES
+ * \ref MIB_CHANNELS_DEFAULT_TX_POWER| YES | YES
* \ref MIB_UPLINK_COUNTER | YES | YES
* \ref MIB_DOWNLINK_COUNTER | YES | YES
* \ref MIB_MULTICAST_CHANNEL | YES | NO
+ * \ref MIB_SYSTEM_MAX_RX_ERROR | YES | YES
+ * \ref MIB_MIN_RX_SYMBOLS | YES | YES
*
* The following table provides links to the function implementations of the
* related MIB primitives:
@@ -1132,43 +1198,55 @@
*/
MIB_RX2_CHANNEL,
/*!
+ * Set receive window 2 channel
+ *
+ * LoRaWAN Specification V1.0.1, chapter 3.3.2
+ */
+ MIB_RX2_DEFAULT_CHANNEL,
+ /*!
* LoRaWAN channels mask
*
* LoRaWAN Specification V1.0.1, chapter 7
*/
MIB_CHANNELS_MASK,
/*!
+ * LoRaWAN default channels mask
+ *
+ * LoRaWAN Specification V1.0.1, chapter 7
+ */
+ MIB_CHANNELS_DEFAULT_MASK,
+ /*!
* Set the number of repetitions on a channel
*
* LoRaWAN Specification V1.0.1, chapter 5.2
*/
MIB_CHANNELS_NB_REP,
/*!
- * Maximum receive window duration in [us]
+ * Maximum receive window duration in [ms]
*
* LoRaWAN Specification V1.0.1, chapter 3.3.3
*/
MIB_MAX_RX_WINDOW_DURATION,
/*!
- * Receive delay 1 in [us]
+ * Receive delay 1 in [ms]
*
* LoRaWAN Specification V1.0.1, chapter 7
*/
MIB_RECEIVE_DELAY_1,
/*!
- * Receive delay 2 in [us]
+ * Receive delay 2 in [ms]
*
* LoRaWAN Specification V1.0.1, chapter 7
*/
MIB_RECEIVE_DELAY_2,
/*!
- * Join accept delay 1 in [us]
+ * Join accept delay 1 in [ms]
*
* LoRaWAN Specification V1.0.1, chapter 7
*/
MIB_JOIN_ACCEPT_DELAY_1,
/*!
- * Join accept delay 2 in [us]
+ * Join accept delay 2 in [ms]
*
* LoRaWAN Specification V1.0.1, chapter 7
*/
@@ -1208,6 +1286,20 @@
*/
MIB_CHANNELS_TX_POWER,
/*!
+ * Transmission power of a channel
+ *
+ * LoRaWAN Specification V1.0.1, chapter 7
+ *
+ * EU868 - [TX_POWER_20_DBM, TX_POWER_14_DBM, TX_POWER_11_DBM,
+ * TX_POWER_08_DBM, TX_POWER_05_DBM, TX_POWER_02_DBM]
+ *
+ * US915 - [TX_POWER_30_DBM, TX_POWER_28_DBM, TX_POWER_26_DBM,
+ * TX_POWER_24_DBM, TX_POWER_22_DBM, TX_POWER_20_DBM,
+ * TX_POWER_18_DBM, TX_POWER_14_DBM, TX_POWER_12_DBM,
+ * TX_POWER_10_DBM]
+ */
+ MIB_CHANNELS_DEFAULT_TX_POWER,
+ /*!
* LoRaWAN Up-link counter
*
* LoRaWAN Specification V1.0.1, chapter 4.3.1.5
@@ -1225,6 +1317,17 @@
* NULL, the list is empty.
*/
MIB_MULTICAST_CHANNEL,
+ /*!
+ * System overall timing error in milliseconds.
+ * [-SystemMaxRxError : +SystemMaxRxError]
+ * Default: +/-10 ms
+ */
+ MIB_SYSTEM_MAX_RX_ERROR,
+ /*!
+ * Minimum required number of symbols to detect an Rx frame
+ * Default: 6 symbols
+ */
+ MIB_MIN_RX_SYMBOLS,
}Mib_t;
/*!
@@ -1298,6 +1401,12 @@
* Related MIB type: \ref MIB_RX2_CHANNEL
*/
Rx2ChannelParams_t Rx2Channel;
+ /*!
+ * Channel for the receive window 2
+ *
+ * Related MIB type: \ref MIB_RX2_DEFAULT_CHANNEL
+ */
+ Rx2ChannelParams_t Rx2DefaultChannel;
/*!
* Channel mask
*
@@ -1305,6 +1414,12 @@
*/
uint16_t* ChannelsMask;
/*!
+ * Default channel mask
+ *
+ * Related MIB type: \ref MIB_CHANNELS_DEFAULT_MASK
+ */
+ uint16_t* ChannelsDefaultMask;
+ /*!
* Number of frame repetitions
*
* Related MIB type: \ref MIB_CHANNELS_NB_REP
@@ -1355,6 +1470,12 @@
/*!
* Channels TX power
*
+ * Related MIB type: \ref MIB_CHANNELS_DEFAULT_TX_POWER
+ */
+ int8_t ChannelsDefaultTxPower;
+ /*!
+ * Channels TX power
+ *
* Related MIB type: \ref MIB_CHANNELS_TX_POWER
*/
int8_t ChannelsTxPower;
@@ -1376,6 +1497,18 @@
* Related MIB type: \ref MIB_MULTICAST_CHANNEL
*/
MulticastParams_t* MulticastList;
+ /*!
+ * System overall timing error in milliseconds.
+ *
+ * Related MIB type: \ref MIB_SYSTEM_MAX_RX_ERROR
+ */
+ uint32_t SystemMaxRxError;
+ /*!
+ * Minimum required number of symbols to detect an Rx frame
+ *
+ * Related MIB type: \ref MIB_MIN_RX_SYMBOLS
+ */
+ uint8_t MinRxSymbols;
}MibParam_t;
/*!
@@ -1447,11 +1580,11 @@
*/
LORAMAC_STATUS_NO_NETWORK_JOINED,
/*!
- * Service not started - playload lenght error
+ * Service not started - payload lenght error
*/
LORAMAC_STATUS_LENGTH_ERROR,
/*!
- * Service not started - playload lenght error
+ * Service not started - payload lenght error
*/
LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR,
/*!
--- a/LoRaMacTest.h Tue Jul 05 15:12:50 2016 +0000 +++ b/LoRaMacTest.h Mon Apr 24 14:11:47 2017 +0000 @@ -66,6 +66,16 @@ */ void LoRaMacTestSetDutyCycleOn( bool enable ); +/*! + * \brief Sets the channel index + * + * \details This is a test function. It shall be used for testing purposes only. + * Changing this attribute may lead to a non-conformance LoRaMac operation. + * + * \param [IN] channel - Channel index + */ +void LoRaMacTestSetChannel( uint8_t channel ); + /*! \} defgroup LORAMACTEST */ #endif // __LORAMACTEST_H__