LoRaWAN MAC layer implementation
Dependents: LoRaWAN-demo-72_tjm LoRaWAN-demo-72_jlc LoRaWAN-demo-elmo frdm_LoRa_Connect_Woodstream_Demo_tjm ... more
LoRAWAN-lib is a port of the GitHub LoRaMac-node 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 7:c16969e0f70f, committed 2016-07-05
- Comitter:
- mluis
- Date:
- Tue Jul 05 13:24:54 2016 +0000
- Parent:
- 6:d7a34ded7c87
- Child:
- 8:26002607de9c
- Commit message:
- Synchronized with https://github.com/Lora-net/LoRaMac-node git revision 7a4aec588de628d864c364e9469ae45105fdbe26
Changed in this revision
--- a/LoRaMac-api-v3.h Wed May 18 11:19:24 2016 +0000 +++ b/LoRaMac-api-v3.h Tue Jul 05 13:24:54 2016 +0000 @@ -33,7 +33,6 @@ // Includes board dependent definitions such as channels frequencies #include "LoRaMac.h" -#include "LoRaMac-board.h" /*! * Beacon interval in us
--- a/LoRaMac-board.h Wed May 18 11:19:24 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,508 +0,0 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - (C)2013 Semtech - -Description: LoRa MAC layer board dependent definitions - -License: Revised BSD License, see LICENSE.TXT file include in the project - -Maintainer: Miguel Luis and Gregory Cristian -*/ -#ifndef __LORAMAC_BOARD_H__ -#define __LORAMAC_BOARD_H__ - -/*! - * Returns individual channel mask - * - * \param[IN] channelIndex Channel index 1 based - * \retval channelMask - */ -#define LC( channelIndex ) ( uint16_t )( 1 << ( channelIndex - 1 ) ) - -#if defined( USE_BAND_433 ) - -/*! - * LoRaMac maximum number of channels - */ -#define LORA_MAX_NB_CHANNELS 16 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_TX_MIN_DATARATE DR_0 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_TX_MAX_DATARATE DR_7 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_RX_MIN_DATARATE DR_0 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_RX_MAX_DATARATE DR_7 - -/*! - * 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 5 - -/*! - * Minimal Tx output power that can be used by the node - */ -#define LORAMAC_MIN_TX_POWER TX_POWER_M5_DBM - -/*! - * Minimal Tx output power that can be used by the node - */ -#define LORAMAC_MAX_TX_POWER TX_POWER_10_DBM - -/*! - * Default Tx output power used by the node - */ -#define LORAMAC_DEFAULT_TX_POWER TX_POWER_10_DBM - -/*! - * LoRaMac TxPower definition - */ -#define TX_POWER_10_DBM 0 -#define TX_POWER_07_DBM 1 -#define TX_POWER_04_DBM 2 -#define TX_POWER_01_DBM 3 -#define TX_POWER_M2_DBM 4 -#define TX_POWER_M5_DBM 5 - -/*! - * 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 -#define DR_6 6 // SF7 - BW250 -#define DR_7 7 // FSK - -/*! - * Second reception window channel definition. - */ -// Channel = { Frequency [Hz], Datarate } -#define RX_WND_2_CHANNEL { 434665000, DR_0 } - -/*! - * LoRaMac maximum number of bands - */ -#define LORA_MAX_NB_BANDS 1 - -// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } -#define BAND0 { 100, TX_POWER_10_DBM, 0, 0 } // 1.0 % - -/*! - * LoRaMac default channels - */ -// Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } -#define LC1 { 433175000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } -#define LC2 { 433375000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } -#define LC3 { 433575000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } - -/*! - * LoRaMac duty cycle for the join procedure - */ -#define JOIN_DC 1000 - -/*! - * LoRaMac channels which are allowed for the join procedure - */ -#define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) ) - -#elif defined( USE_BAND_780 ) - -/*! - * LoRaMac maximum number of channels - */ -#define LORA_MAX_NB_CHANNELS 16 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_TX_MIN_DATARATE DR_0 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_TX_MAX_DATARATE DR_7 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_RX_MIN_DATARATE DR_0 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_RX_MAX_DATARATE DR_7 - -/*! - * 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 5 - -/*! - * Minimal Tx output power that can be used by the node - */ -#define LORAMAC_MIN_TX_POWER TX_POWER_M5_DBM - -/*! - * Minimal Tx output power that can be used by the node - */ -#define LORAMAC_MAX_TX_POWER TX_POWER_10_DBM - -/*! - * Default Tx output power used by the node - */ -#define LORAMAC_DEFAULT_TX_POWER TX_POWER_10_DBM - -/*! - * LoRaMac TxPower definition - */ -#define TX_POWER_10_DBM 0 -#define TX_POWER_07_DBM 1 -#define TX_POWER_04_DBM 2 -#define TX_POWER_01_DBM 3 -#define TX_POWER_M2_DBM 4 -#define TX_POWER_M5_DBM 5 - -/*! - * 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 -#define DR_6 6 // SF7 - BW250 -#define DR_7 7 // FSK - -/*! - * Second reception window channel definition. - */ -// Channel = { Frequency [Hz], Datarate } -#define RX_WND_2_CHANNEL { 786000000, DR_0 } - -/*! - * LoRaMac maximum number of bands - */ -#define LORA_MAX_NB_BANDS 1 - -// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } -#define BAND0 { 100, TX_POWER_10_DBM, 0, 0 } // 1.0 % - -/*! - * LoRaMac default channels - */ -// Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } -#define LC1 { 779500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } -#define LC2 { 779700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } -#define LC3 { 779900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } - -/*! - * LoRaMac duty cycle for the join procedure - */ -#define JOIN_DC 1000 - -/*! - * LoRaMac channels which are allowed for the join procedure - */ -#define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) ) - -#elif defined( USE_BAND_868 ) - -/*! - * LoRaMac maximum number of channels - */ -#define LORA_MAX_NB_CHANNELS 16 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_TX_MIN_DATARATE DR_0 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_TX_MAX_DATARATE DR_7 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_RX_MIN_DATARATE DR_0 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_RX_MAX_DATARATE DR_7 - -/*! - * 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 5 - -/*! - * Minimal Tx output power that can be used by the node - */ -#define LORAMAC_MIN_TX_POWER TX_POWER_02_DBM - -/*! - * Minimal Tx output power that can be used by the node - */ -#define LORAMAC_MAX_TX_POWER TX_POWER_20_DBM - -/*! - * Default Tx output power used by the node - */ -#define LORAMAC_DEFAULT_TX_POWER TX_POWER_14_DBM - -/*! - * LoRaMac TxPower definition - */ -#define TX_POWER_20_DBM 0 -#define TX_POWER_14_DBM 1 -#define TX_POWER_11_DBM 2 -#define TX_POWER_08_DBM 3 -#define TX_POWER_05_DBM 4 -#define TX_POWER_02_DBM 5 - -/*! - * 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 -#define DR_6 6 // SF7 - BW250 -#define DR_7 7 // FSK - -/*! - * Second reception window channel definition. - */ -// Channel = { Frequency [Hz], Datarate } -#define RX_WND_2_CHANNEL { 869525000, DR_0 } - -/*! - * LoRaMac maximum number of bands - */ -#define LORA_MAX_NB_BANDS 5 - -/*! - * LoRaMac EU868 default bands - */ -typedef enum -{ - BAND_G1_0, - BAND_G1_1, - BAND_G1_2, - BAND_G1_3, - BAND_G1_4, -}BandId_t; - -// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } -#define BAND0 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % -#define BAND1 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % -#define BAND2 { 1000, TX_POWER_14_DBM, 0, 0 } // 0.1 % -#define BAND3 { 10 , TX_POWER_14_DBM, 0, 0 } // 10.0 % -#define BAND4 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % - -/*! - * LoRaMac default channels - */ -// Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } -#define LC1 { 868100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 } -#define LC2 { 868300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 } -#define LC3 { 868500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 } - -/*! - * LoRaMac duty cycle for the join procedure - */ -#define JOIN_DC 1000 - -/*! - * LoRaMac channels which are allowed for the join procedure - */ -#define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) ) - -#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - -/*! - * LoRaMac maximum number of channels - */ -#define LORA_MAX_NB_CHANNELS 72 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_TX_MIN_DATARATE DR_0 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_TX_MAX_DATARATE DR_4 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_RX_MIN_DATARATE DR_8 - -/*! - * Minimal datarate that can be used by the node - */ -#define LORAMAC_RX_MAX_DATARATE DR_13 - -/*! - * 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_10_DBM - -/*! - * Minimal Tx output power that can be used by the node - */ -#define LORAMAC_MAX_TX_POWER TX_POWER_30_DBM - -/*! - * Default Tx output power used by the node - */ -#define LORAMAC_DEFAULT_TX_POWER TX_POWER_20_DBM - -/*! - * LoRaMac TxPower definition - */ -#define TX_POWER_30_DBM 0 -#define TX_POWER_28_DBM 1 -#define TX_POWER_26_DBM 2 -#define TX_POWER_24_DBM 3 -#define TX_POWER_22_DBM 4 -#define TX_POWER_20_DBM 5 -#define TX_POWER_18_DBM 6 -#define TX_POWER_16_DBM 7 -#define TX_POWER_14_DBM 8 -#define TX_POWER_12_DBM 9 -#define TX_POWER_10_DBM 10 - -/*! - * LoRaMac datarates definition - */ -#define DR_0 0 // SF10 - BW125 | -#define DR_1 1 // SF9 - BW125 | -#define DR_2 2 // SF8 - BW125 +-> Up link -#define DR_3 3 // SF7 - BW125 | -#define DR_4 4 // SF8 - BW500 | -#define DR_5 5 // RFU -#define DR_6 6 // RFU -#define DR_7 7 // RFU -#define DR_8 8 // SF12 - BW500 | -#define DR_9 9 // SF11 - BW500 | -#define DR_10 10 // SF10 - BW500 | -#define DR_11 11 // SF9 - BW500 | -#define DR_12 12 // SF8 - BW500 +-> Down link -#define DR_13 13 // SF7 - BW500 | -#define DR_14 14 // RFU | -#define DR_15 15 // RFU | - -/*! - * Second reception window channel definition. - */ -// Channel = { Frequency [Hz], Datarate } -#define RX_WND_2_CHANNEL { 923300000, DR_8 } - -/*! - * LoRaMac maximum number of bands - */ -#define LORA_MAX_NB_BANDS 1 - -// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } -#define BAND0 { 1, TX_POWER_20_DBM, 0, 0 } // 100.0 % - -/*! - * LoRaMac default channels - */ -// Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } -/* - * US band channels are initialized using a loop in LoRaMacInit function - * \code - * // 125 kHz channels - * for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ ) - * { - * Channels[i].Frequency = 902.3e6 + i * 200e3; - * Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0; - * Channels[i].Band = 0; - * } - * // 500 kHz channels - * for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ ) - * { - * Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6; - * Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4; - * Channels[i].Band = 0; - * } - * \endcode - */ -#else - #error "Please define a frequency band in the compiler options." -#endif - -#endif // __LORAMAC_BOARD_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LoRaMac-definitions.h Tue Jul 05 13:24:54 2016 +0000 @@ -0,0 +1,522 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: LoRa MAC layer global definitions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __LORAMAC_BOARD_H__ +#define __LORAMAC_BOARD_H__ + +/*! + * Returns individual channel mask + * + * \param[IN] channelIndex Channel index 1 based + * \retval channelMask + */ +#define LC( channelIndex ) ( uint16_t )( 1 << ( channelIndex - 1 ) ) + +#if defined( USE_BAND_433 ) + +/*! + * LoRaMac maximum number of channels + */ +#define LORA_MAX_NB_CHANNELS 16 + +/*! + * 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_7 + +/*! + * 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_7 + +/*! + * 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 5 + +/*! + * Minimal Tx output power that can be used by the node + */ +#define LORAMAC_MIN_TX_POWER TX_POWER_M5_DBM + +/*! + * Maximal Tx output power that can be used by the node + */ +#define LORAMAC_MAX_TX_POWER TX_POWER_10_DBM + +/*! + * Default Tx output power used by the node + */ +#define LORAMAC_DEFAULT_TX_POWER TX_POWER_10_DBM + +/*! + * LoRaMac TxPower definition + */ +#define TX_POWER_10_DBM 0 +#define TX_POWER_07_DBM 1 +#define TX_POWER_04_DBM 2 +#define TX_POWER_01_DBM 3 +#define TX_POWER_M2_DBM 4 +#define TX_POWER_M5_DBM 5 + +/*! + * 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 +#define DR_6 6 // SF7 - BW250 +#define DR_7 7 // FSK + +/*! + * Second reception window channel definition. + */ +// Channel = { Frequency [Hz], Datarate } +#define RX_WND_2_CHANNEL { 434665000, DR_0 } + +/*! + * LoRaMac maximum number of bands + */ +#define LORA_MAX_NB_BANDS 1 + +// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } +#define BAND0 { 100, TX_POWER_10_DBM, 0, 0 } // 1.0 % + +/*! + * LoRaMac default channels + */ +// Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } +#define LC1 { 433175000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC2 { 433375000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#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_780 ) + +/*! + * LoRaMac maximum number of channels + */ +#define LORA_MAX_NB_CHANNELS 16 + +/*! + * 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_7 + +/*! + * 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_7 + +/*! + * 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 5 + +/*! + * Minimal Tx output power that can be used by the node + */ +#define LORAMAC_MIN_TX_POWER TX_POWER_M5_DBM + +/*! + * Maximal Tx output power that can be used by the node + */ +#define LORAMAC_MAX_TX_POWER TX_POWER_10_DBM + +/*! + * Default Tx output power used by the node + */ +#define LORAMAC_DEFAULT_TX_POWER TX_POWER_10_DBM + +/*! + * LoRaMac TxPower definition + */ +#define TX_POWER_10_DBM 0 +#define TX_POWER_07_DBM 1 +#define TX_POWER_04_DBM 2 +#define TX_POWER_01_DBM 3 +#define TX_POWER_M2_DBM 4 +#define TX_POWER_M5_DBM 5 + +/*! + * 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 +#define DR_6 6 // SF7 - BW250 +#define DR_7 7 // FSK + +/*! + * Second reception window channel definition. + */ +// Channel = { Frequency [Hz], Datarate } +#define RX_WND_2_CHANNEL { 786000000, DR_0 } + +/*! + * LoRaMac maximum number of bands + */ +#define LORA_MAX_NB_BANDS 1 + +// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } +#define BAND0 { 100, TX_POWER_10_DBM, 0, 0 } // 1.0 % + +/*! + * LoRaMac default channels + */ +// Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } +#define LC1 { 779500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#define LC2 { 779700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } +#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 ) ) + +#elif defined( USE_BAND_868 ) + +/*! + * LoRaMac maximum number of channels + */ +#define LORA_MAX_NB_CHANNELS 16 + +/*! + * 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_7 + +/*! + * 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_7 + +/*! + * 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 5 + +/*! + * Minimal Tx output power that can be used by the node + */ +#define LORAMAC_MIN_TX_POWER TX_POWER_02_DBM + +/*! + * Maximal Tx output power that can be used by the node + */ +#define LORAMAC_MAX_TX_POWER TX_POWER_20_DBM + +/*! + * Default Tx output power used by the node + */ +#define LORAMAC_DEFAULT_TX_POWER TX_POWER_14_DBM + +/*! + * LoRaMac TxPower definition + */ +#define TX_POWER_20_DBM 0 +#define TX_POWER_14_DBM 1 +#define TX_POWER_11_DBM 2 +#define TX_POWER_08_DBM 3 +#define TX_POWER_05_DBM 4 +#define TX_POWER_02_DBM 5 + +/*! + * 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 +#define DR_6 6 // SF7 - BW250 +#define DR_7 7 // FSK + +/*! + * Second reception window channel definition. + */ +// Channel = { Frequency [Hz], Datarate } +#define RX_WND_2_CHANNEL { 869525000, DR_0 } + +/*! + * LoRaMac maximum number of bands + */ +#define LORA_MAX_NB_BANDS 5 + +/*! + * LoRaMac EU868 default bands + */ +typedef enum +{ + BAND_G1_0, + BAND_G1_1, + BAND_G1_2, + BAND_G1_3, + BAND_G1_4, +}BandId_t; + +// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } +#define BAND0 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % +#define BAND1 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % +#define BAND2 { 1000, TX_POWER_14_DBM, 0, 0 } // 0.1 % +#define BAND3 { 10 , TX_POWER_14_DBM, 0, 0 } // 10.0 % +#define BAND4 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % + +/*! + * LoRaMac default channels + */ +// Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } +#define LC1 { 868100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 } +#define LC2 { 868300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 } +#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 ) ) + +#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) + +/*! + * LoRaMac maximum number of channels + */ +#define LORA_MAX_NB_CHANNELS 72 + +/*! + * 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_4 + +/*! + * Minimal datarate that can be used by the node + */ +#define LORAMAC_RX_MIN_DATARATE DR_8 + +/*! + * Maximal datarate that can be used by the node + */ +#define LORAMAC_RX_MAX_DATARATE DR_13 + +/*! + * 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_10_DBM + +/*! + * Maximal Tx output power that can be used by the node + */ +#define LORAMAC_MAX_TX_POWER TX_POWER_30_DBM + +/*! + * Default Tx output power used by the node + */ +#define LORAMAC_DEFAULT_TX_POWER TX_POWER_20_DBM + +/*! + * LoRaMac TxPower definition + */ +#define TX_POWER_30_DBM 0 +#define TX_POWER_28_DBM 1 +#define TX_POWER_26_DBM 2 +#define TX_POWER_24_DBM 3 +#define TX_POWER_22_DBM 4 +#define TX_POWER_20_DBM 5 +#define TX_POWER_18_DBM 6 +#define TX_POWER_16_DBM 7 +#define TX_POWER_14_DBM 8 +#define TX_POWER_12_DBM 9 +#define TX_POWER_10_DBM 10 + +/*! + * LoRaMac datarates definition + */ +#define DR_0 0 // SF10 - BW125 | +#define DR_1 1 // SF9 - BW125 | +#define DR_2 2 // SF8 - BW125 +-> Up link +#define DR_3 3 // SF7 - BW125 | +#define DR_4 4 // SF8 - BW500 | +#define DR_5 5 // RFU +#define DR_6 6 // RFU +#define DR_7 7 // RFU +#define DR_8 8 // SF12 - BW500 | +#define DR_9 9 // SF11 - BW500 | +#define DR_10 10 // SF10 - BW500 | +#define DR_11 11 // SF9 - BW500 | +#define DR_12 12 // SF8 - BW500 +-> Down link +#define DR_13 13 // SF7 - BW500 | +#define DR_14 14 // RFU | +#define DR_15 15 // RFU | + +/*! + * Second reception window channel definition. + */ +// Channel = { Frequency [Hz], Datarate } +#define RX_WND_2_CHANNEL { 923300000, DR_8 } + +/*! + * LoRaMac maximum number of bands + */ +#define LORA_MAX_NB_BANDS 1 + +// Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } +#define BAND0 { 1, TX_POWER_20_DBM, 0, 0 } // 100.0 % + +#define BACKOFF_RND_OFFSET 600000 + +/*! + * LoRaMac default channels + */ +// Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } +/* + * US band channels are initialized using a loop in LoRaMacInit function + * \code + * // 125 kHz channels + * for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ ) + * { + * Channels[i].Frequency = 902.3e6 + i * 200e3; + * Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0; + * Channels[i].Band = 0; + * } + * // 500 kHz channels + * for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ ) + * { + * Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6; + * Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4; + * Channels[i].Band = 0; + * } + * \endcode + */ +#else + #error "Please define a frequency band in the compiler options." +#endif + +#endif // __LORAMAC_BOARD_H__
--- a/LoRaMac.cpp Wed May 18 11:19:24 2016 +0000 +++ b/LoRaMac.cpp Tue Jul 05 13:24:54 2016 +0000 @@ -186,10 +186,20 @@ static uint8_t MacCommandsBufferIndex = 0; /*! + * Contains the current MacCommandsBuffer index for MAC commands to repeat + */ +static uint8_t MacCommandsBufferToRepeatIndex = 0; + +/*! * Buffer containing the MAC layer commands */ static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH]; +/*! + * Buffer containing the MAC layer commands which must be repeated + */ +static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH]; + #if defined( USE_BAND_433 ) /*! * Data rates table definition @@ -324,28 +334,17 @@ { DR_12, DR_11, DR_10, DR_9 }, // DR_2 { DR_13, DR_12, DR_11, DR_10 }, // DR_3 { DR_13, DR_13, DR_12, DR_11 }, // DR_4 - { 0xFF , 0xFF , 0xFF , 0xFF }, - { 0xFF , 0xFF , 0xFF , 0xFF }, - { 0xFF , 0xFF , 0xFF , 0xFF }, - { DR_8 , DR_8 , DR_8 , DR_8 }, - { DR_9 , DR_8 , DR_8 , DR_8 }, - { DR_10, DR_9 , DR_8 , DR_8 }, - { DR_11, DR_10, DR_9 , DR_8 }, - { DR_12, DR_11, DR_10, DR_9 }, - { DR_13, DR_12, DR_11, DR_10 }, - { 0xFF , 0xFF , 0xFF , 0xFF }, - { 0xFF , 0xFF , 0xFF , 0xFF }, }; /*! * Maximum payload with respect to the datarate index. Cannot operate with repeater. */ -const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 129, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 }; +const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 }; /*! * Maximum payload with respect to the datarate index. Can operate with repeater. */ -const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 129, 242, 242, 0, 0, 0, 33, 103, 222, 222, 222, 222, 0, 0 }; +const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 }; /*! * Tx output powers table definition @@ -369,44 +368,35 @@ * Contains the channels which remain to be applied. */ static uint16_t ChannelsMaskRemaining[6]; + +/*! + * Defines the first channel for RX window 2 for US band + */ +#define LORAMAC_FIRST_RX2_CHANNEL ( (uint32_t) 923.3e6 ) + +/*! + * Defines the last channel for RX window 2 for US band + */ +#define LORAMAC_LAST_RX2_CHANNEL ( (uint32_t) 927.5e6 ) + +/*! + * Defines the step width of the channels for RX window 2 + */ +#define LORAMAC_STEPWIDTH_RX2_CHANNEL ( (uint32_t) 600e3 ) + #else #error "Please define a frequency band in the compiler options." #endif /*! - * LoRaMAC 2nd reception window settings - */ -static Rx2ChannelParams_t Rx2Channel = RX_WND_2_CHANNEL; - -/*! - * Datarate offset between uplink and downlink on first window + * LoRaMac parameters */ -static uint8_t Rx1DrOffset = 0; - -/*! - * Mask indicating which channels are enabled - */ -static uint16_t ChannelsMask[6]; +LoRaMacParams_t LoRaMacParams; /*! - * Channels Tx output power - */ -static int8_t ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; - -/*! - * Channels datarate + * LoRaMac default parameters */ -static int8_t ChannelsDatarate = LORAMAC_DEFAULT_DATARATE; - -/*! - * Channels default datarate - */ -static int8_t ChannelsDefaultDatarate = LORAMAC_DEFAULT_DATARATE; - -/*! - * Number of uplink messages repetitions [1:15] (unconfirmed messages only) - */ -static uint8_t ChannelsNbRep = 1; +LoRaMacParams_t LoRaMacParamsDefaults; /*! * Uplink messages repetitions counter @@ -436,6 +426,9 @@ */ static uint8_t Channel; +/*! + * Channel index of the last transmission + */ static uint8_t LastTxChannel; /*! @@ -490,14 +483,6 @@ static TimerEvent_t RxWindowTimer2; /*! - * LoRaMac reception windows delay from end of Tx - */ -static uint32_t ReceiveDelay1; -static uint32_t ReceiveDelay2; -static uint32_t JoinAcceptDelay1; -static uint32_t JoinAcceptDelay2; - -/*! * LoRaMac reception windows delay * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME @@ -506,11 +491,6 @@ static uint32_t RxWindow2Delay; /*! - * LoRaMac maximum time a reception window stays open - */ -static uint32_t MaxRxWindow; - -/*! * Acknowledge timeout timer. Used for packet retransmissions. */ static TimerEvent_t AckTimeoutTimer; @@ -536,6 +516,11 @@ TimerTime_t TxTimeOnAir = 0; /*! + * Number of trials for the Join Request + */ +static uint16_t JoinRequestTrials; + +/*! * Structure to hold an MCPS indication data. */ static McpsIndication_t McpsIndication; @@ -645,6 +630,15 @@ static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous ); /*! + * \brief Verifies if the RX window 2 frequency is in range + * + * \param [IN] freq window channel frequency + * + * \retval status Function status [1: OK, 0: Frequency not applicable] + */ +static bool Rx2FreqInRange( uint32_t freq ); + +/*! * \brief Adds a new MAC command to be sent. * * \Remark MAC layer internal function @@ -664,6 +658,20 @@ static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ); /*! + * \brief Parses the MAC commands which must be repeated. + * + * \Remark MAC layer internal function + * + * \param [IN] cmdBufIn Buffer which stores the MAC commands to send + * \param [IN] length Length of the input buffer to parse + * \param [OUT] cmdBufOut Buffer which stores the MAC commands which must be + * repeated. + * + * \retval Size of the MAC commands to repeat. + */ +static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ); + +/*! * \brief Validates if the payload fits into the frame, taking the datarate * into account. * @@ -804,12 +812,27 @@ static LoRaMacStatus_t ScheduleTx( void ); /* + * \brief Sets the duty cycle for retransmissions + * + * \retval Duty cycle + */ +static uint16_t RetransmissionDutyCylce( void ); + +/* * \brief Calculates the back-off time for the band of a channel. * * \param [IN] channel The last Tx channel index */ static void CalculateBackOff( uint8_t channel ); +/* + * \brief Alternates the datarate of the channel for the join request. + * + * \param [IN] nbTrials Number of performed join requests. + * \retval Datarate to apply + */ +static int8_t AlternateDatarate( uint16_t nbTrials ); + /*! * \brief LoRaMAC layer prepared frame buffer transmission with channel specification * @@ -821,7 +844,10 @@ */ LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel ); - +/*! + * \brief Resets MAC specific parameters to default + */ +static void ResetMacParameters( void ); static void OnRadioTxDone( void ) { @@ -980,26 +1006,26 @@ LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 ); // DLSettings - Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07; - Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F; + LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07; + LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F; #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) /* * WARNING: To be removed once Semtech server implementation * is corrected. */ - if( Rx2Channel.Datarate == DR_3 ) + if( LoRaMacParams.Rx2Channel.Datarate == DR_3 ) { - Rx2Channel.Datarate = DR_8; + LoRaMacParams.Rx2Channel.Datarate = DR_8; } #endif // RxDelay - ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F ); - if( ReceiveDelay1 == 0 ) + LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F ); + if( LoRaMacParams.ReceiveDelay1 == 0 ) { - ReceiveDelay1 = 1; + LoRaMacParams.ReceiveDelay1 = 1; } - ReceiveDelay1 *= 1e6; - ReceiveDelay2 = ReceiveDelay1 + 1e6; + LoRaMacParams.ReceiveDelay1 *= 1e6; + LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6; #if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) //CFList @@ -1019,7 +1045,7 @@ #endif MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; IsLoRaMacNetworkJoined = true; - ChannelsDatarate = ChannelsDefaultDatarate; + LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate; } else { @@ -1122,6 +1148,7 @@ McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; AdrAckCounter = 0; + MacCommandsBufferToRepeatIndex = 0; // Update 32 bits downlink counter if( multicast == 1 ) @@ -1191,11 +1218,6 @@ } } - if( fCtrl.Bits.FOptsLen > 0 ) - { - // Decode Options field MAC commands - ProcessMacCommands( payload, 8, appPayloadStartIndex, snr ); - } if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 ) { port = payload[appPayloadStartIndex++]; @@ -1205,19 +1227,32 @@ if( port == 0 ) { - LoRaMacPayloadDecrypt( payload + appPayloadStartIndex, - frameLen, - nwkSKey, - address, - DOWN_LINK, - downLinkCounter, - LoRaMacRxPayload ); - - // Decode frame payload MAC commands - ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr ); + if( fCtrl.Bits.FOptsLen == 0 ) + { + LoRaMacPayloadDecrypt( payload + appPayloadStartIndex, + frameLen, + nwkSKey, + address, + DOWN_LINK, + downLinkCounter, + LoRaMacRxPayload ); + + // Decode frame payload MAC commands + ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr ); + } + else + { + skipIndication = true; + } } else { + if( fCtrl.Bits.FOptsLen > 0 ) + { + // Decode Options field MAC commands. Omit the fPort. + ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr ); + } + LoRaMacPayloadDecrypt( payload + appPayloadStartIndex, frameLen, appSKey, @@ -1234,6 +1269,15 @@ } } } + else + { + if( fCtrl.Bits.FOptsLen > 0 ) + { + // Decode Options field MAC commands + ProcessMacCommands( payload, 8, appPayloadStartIndex, snr ); + } + } + if( skipIndication == false ) { LoRaMacFlags.Bits.McpsInd = 1; @@ -1370,17 +1414,20 @@ { if( MlmeConfirm.MlmeRequest == MLME_JOIN ) { + // Retransmit only if the answer is not OK + ChannelsNbRepCounter = 0; + if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK ) { + // Stop retransmission + ChannelsNbRepCounter = LoRaMacParams.ChannelsNbRep; UpLinkCounter = 0; } - // Join messages aren't repeated automatically - ChannelsNbRepCounter = ChannelsNbRep; } } if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) ) { - if( ( ChannelsNbRepCounter >= ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) ) + if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) ) { ChannelsNbRepCounter = 0; @@ -1426,7 +1473,7 @@ if( ( AckTimeoutRetriesCounter % 2 ) == 1 ) { - ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE ); + LoRaMacParams.ChannelsDatarate = MAX( LoRaMacParams.ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE ); } LoRaMacFlags.Bits.MacDone = 0; // Sends the same frame again @@ -1436,18 +1483,18 @@ { #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) // Re-enable default channels LC1, LC2, LC3 - ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); #elif defined( USE_BAND_915 ) // Re-enable default channels - ChannelsMask[0] = 0xFFFF; - ChannelsMask[1] = 0xFFFF; - ChannelsMask[2] = 0xFFFF; - ChannelsMask[3] = 0xFFFF; - ChannelsMask[4] = 0x00FF; - ChannelsMask[5] = 0x0000; + LoRaMacParams.ChannelsMask[0] = 0xFFFF; + LoRaMacParams.ChannelsMask[1] = 0xFFFF; + LoRaMacParams.ChannelsMask[2] = 0xFFFF; + LoRaMacParams.ChannelsMask[3] = 0xFFFF; + LoRaMacParams.ChannelsMask[4] = 0x00FF; + LoRaMacParams.ChannelsMask[5] = 0x0000; #elif defined( USE_BAND_915_HYBRID ) // Re-enable default channels - ReenableChannels( ChannelsMask[4], ChannelsMask ); + ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask ); #else #error "Please define a frequency band in the compiler options." #endif @@ -1500,9 +1547,26 @@ static void OnTxDelayedTimerEvent( void ) { + LoRaMacHeader_t macHdr; + LoRaMacFrameCtrl_t fCtrl; + TimerStop( &TxDelayedTimer ); LoRaMacState &= ~MAC_TX_DELAYED; + if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) ) + { + macHdr.Value = 0; + macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; + + fCtrl.Value = 0; + fCtrl.Bits.Adr = AdrCtrlOn; + + /* In case of a join request retransmission, the stack must prepare + * the frame again, because the network server keeps track of the random + * LoRaMacDevNonce values to prevent reply attacks. */ + PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 ); + } + ScheduleTx( ); } @@ -1521,7 +1585,7 @@ } #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) - datarate = ChannelsDatarate - Rx1DrOffset; + datarate = LoRaMacParams.ChannelsDatarate - LoRaMacParams.Rx1DrOffset; if( datarate < 0 ) { datarate = DR_0; @@ -1543,7 +1607,7 @@ } RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false ); #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) - datarate = datarateOffsets[ChannelsDatarate][Rx1DrOffset]; + datarate = datarateOffsets[LoRaMacParams.ChannelsDatarate][LoRaMacParams.Rx1DrOffset]; if( datarate < 0 ) { datarate = DR_0; @@ -1583,7 +1647,7 @@ {// LoRa 500 kHz bandwidth = 2; } - RxWindowSetup( 923.3e6 + ( Channel % 8 ) * 600e3, datarate, bandwidth, symbTimeout, false ); + RxWindowSetup( LORAMAC_FIRST_RX2_CHANNEL + ( Channel % 8 ) * LORAMAC_STEPWIDTH_RX2_CHANNEL, datarate, bandwidth, symbTimeout, false ); #else #error "Please define a frequency band in the compiler options." #endif @@ -1599,22 +1663,22 @@ #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) // For higher datarates, we increase the number of symbols generating a Rx Timeout - if( ( Rx2Channel.Datarate == DR_3 ) || ( Rx2Channel.Datarate == DR_4 ) ) + if( ( LoRaMacParams.Rx2Channel.Datarate == DR_3 ) || ( LoRaMacParams.Rx2Channel.Datarate == DR_4 ) ) { // DR_4, DR_3 symbTimeout = 8; } - else if( Rx2Channel.Datarate == DR_5 ) + else if( LoRaMacParams.Rx2Channel.Datarate == DR_5 ) { symbTimeout = 10; } - else if( Rx2Channel.Datarate == DR_6 ) + else if( LoRaMacParams.Rx2Channel.Datarate == DR_6 ) {// LoRa 250 kHz bandwidth = 1; symbTimeout = 14; } #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) // For higher datarates, we increase the number of symbols generating a Rx Timeout - switch( Rx2Channel.Datarate ) + switch( LoRaMacParams.Rx2Channel.Datarate ) { case DR_0: // SF10 - BW125 symbTimeout = 5; @@ -1644,7 +1708,7 @@ default: break; } - if( Rx2Channel.Datarate >= DR_4 ) + if( LoRaMacParams.Rx2Channel.Datarate >= DR_4 ) {// LoRa 500 kHz bandwidth = 2; } @@ -1653,11 +1717,11 @@ #endif if( LoRaMacDeviceClass != CLASS_C ) { - RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, false ); + RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, false ); } else { - RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, true ); + RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, true ); } } @@ -1688,17 +1752,17 @@ #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 ) { // Restore default channels - memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 8 ); + memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParams.ChannelsMask, 8 ); } - if( ( ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) ) + if( ( LoRaMacParams.ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) ) { // Make sure, that the channels are activated - ChannelsMaskRemaining[4] = ChannelsMask[4]; + ChannelsMaskRemaining[4] = LoRaMacParams.ChannelsMask[4]; } #else - if( CountBits( ChannelsMask[0], 16 ) == 0 ) + if( CountBits( LoRaMacParams.ChannelsMask[0], 16 ) == 0 ) { // Re-enable default channels, if no channel is enabled - ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); } #endif @@ -1738,7 +1802,7 @@ #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) if( ( ChannelsMaskRemaining[k] & ( 1 << j ) ) != 0 ) #else - if( ( ChannelsMask[k] & ( 1 << j ) ) != 0 ) + if( ( LoRaMacParams.ChannelsMask[k] & ( 1 << j ) ) != 0 ) #endif { if( Channels[i + j].Frequency == 0 ) @@ -1754,8 +1818,8 @@ } } #endif - if( ( ( Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate ) && - ( ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false ) + if( ( ( Channels[i + j].DrRange.Fields.Min <= LoRaMacParams.ChannelsDatarate ) && + ( LoRaMacParams.ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false ) { // Check if the current channel selection supports the given datarate continue; } @@ -1856,7 +1920,7 @@ if( rxContinuous == false ) { - Radio.Rx( MaxRxWindow ); + Radio.Rx( LoRaMacParams.MaxRxWindow ); } else { @@ -1865,6 +1929,22 @@ } } +static bool Rx2FreqInRange( uint32_t freq ) +{ +#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) + if( Radio.CheckRfFrequency( freq ) == true ) +#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) + if( ( Radio.CheckRfFrequency( freq ) == true ) && + ( freq >= LORAMAC_FIRST_RX2_CHANNEL ) && + ( freq <= LORAMAC_LAST_RX2_CHANNEL ) && + ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX2_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX2_CHANNEL ) == 0 ) ) +#endif + { + return true; + } + return false; +} + static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen ) { uint16_t maxN = 0; @@ -1987,14 +2067,14 @@ { int8_t resultTxPower = txPower; #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - if( ( ChannelsDatarate == DR_4 ) || - ( ( ChannelsDatarate >= DR_8 ) && ( ChannelsDatarate <= DR_13 ) ) ) + if( ( LoRaMacParams.ChannelsDatarate == DR_4 ) || + ( ( LoRaMacParams.ChannelsDatarate >= DR_8 ) && ( LoRaMacParams.ChannelsDatarate <= DR_13 ) ) ) {// Limit tx power to max 26dBm resultTxPower = MAX( txPower, TX_POWER_26_DBM ); } else { - if( CountNbEnabled125kHzChannels( ChannelsMask ) < 50 ) + if( CountNbEnabled125kHzChannels( LoRaMacParams.ChannelsMask ) < 50 ) {// Limit tx power to max 21dBm resultTxPower = MAX( txPower, TX_POWER_20_DBM ); } @@ -2031,7 +2111,7 @@ static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut ) { bool adrAckReq = false; - int8_t datarate = ChannelsDatarate; + int8_t datarate = LoRaMacParams.ChannelsDatarate; if( adrEnabled == true ) { @@ -2052,7 +2132,7 @@ } if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) ) { - if( ( ( AdrAckCounter - ADR_ACK_DELAY ) % ADR_ACK_LIMIT ) == 0 ) + if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 ) { #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) if( datarate > LORAMAC_TX_MIN_DATARATE ) @@ -2063,9 +2143,8 @@ { if( updateChannelMask == true ) { - // Re-enable default channels LC1, LC2, LC3 - ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); } } #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) @@ -2083,15 +2162,15 @@ { #if defined( USE_BAND_915 ) // Re-enable default channels - ChannelsMask[0] = 0xFFFF; - ChannelsMask[1] = 0xFFFF; - ChannelsMask[2] = 0xFFFF; - ChannelsMask[3] = 0xFFFF; - ChannelsMask[4] = 0x00FF; - ChannelsMask[5] = 0x0000; + LoRaMacParams.ChannelsMask[0] = 0xFFFF; + LoRaMacParams.ChannelsMask[1] = 0xFFFF; + LoRaMacParams.ChannelsMask[2] = 0xFFFF; + LoRaMacParams.ChannelsMask[3] = 0xFFFF; + LoRaMacParams.ChannelsMask[4] = 0x00FF; + LoRaMacParams.ChannelsMask[5] = 0x0000; #else // defined( USE_BAND_915_HYBRID ) // Re-enable default channels - ReenableChannels( ChannelsMask[4], ChannelsMask ); + ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask ); #endif } } @@ -2111,11 +2190,13 @@ static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ) { LoRaMacStatus_t status = LORAMAC_STATUS_BUSY; + // The maximum buffer length must take MAC commands to re-send into account. + uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex; switch( cmd ) { case MOTE_MAC_LINK_CHECK_REQ: - if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH ) + if( MacCommandsBufferIndex < bufLen ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // No payload for this command @@ -2123,7 +2204,7 @@ } break; case MOTE_MAC_LINK_ADR_ANS: - if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) ) + if( MacCommandsBufferIndex < ( bufLen - 1 ) ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // Margin @@ -2132,7 +2213,7 @@ } break; case MOTE_MAC_DUTY_CYCLE_ANS: - if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH ) + if( MacCommandsBufferIndex < bufLen ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // No payload for this answer @@ -2140,7 +2221,7 @@ } break; case MOTE_MAC_RX_PARAM_SETUP_ANS: - if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) ) + if( MacCommandsBufferIndex < ( bufLen - 1 ) ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // Status: Datarate ACK, Channel ACK @@ -2149,7 +2230,7 @@ } break; case MOTE_MAC_DEV_STATUS_ANS: - if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 2 ) ) + if( MacCommandsBufferIndex < ( bufLen - 2 ) ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // 1st byte Battery @@ -2160,7 +2241,7 @@ } break; case MOTE_MAC_NEW_CHANNEL_ANS: - if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) ) + if( MacCommandsBufferIndex < ( bufLen - 1 ) ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // Status: Datarate range OK, Channel frequency OK @@ -2169,7 +2250,7 @@ } break; case MOTE_MAC_RX_TIMING_SETUP_ANS: - if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH ) + if( MacCommandsBufferIndex < bufLen ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // No payload for this answer @@ -2186,6 +2267,40 @@ return status; } +static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ) +{ + uint8_t i = 0; + uint8_t cmdCount = 0; + + if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) ) + { + return 0; + } + + for( i = 0; i < length; i++ ) + { + switch( cmdBufIn[i] ) + { + case MOTE_MAC_RX_PARAM_SETUP_ANS: + { + cmdBufOut[cmdCount++] = cmdBufIn[i++]; + cmdBufOut[cmdCount++] = cmdBufIn[i++]; + cmdBufOut[cmdCount++] = cmdBufIn[i]; + break; + } + case MOTE_MAC_RX_TIMING_SETUP_ANS: + { + cmdBufOut[cmdCount++] = cmdBufIn[i]; + break; + } + default: + break; + } + } + + return cmdCount; +} + static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr ) { while( macIndex < commandsSize ) @@ -2212,14 +2327,14 @@ // Initialize local copy of the channels mask array for( i = 0; i < 6; i++ ) { - channelsMask[i] = ChannelsMask[i]; + channelsMask[i] = LoRaMacParams.ChannelsMask[i]; } datarate = payload[macIndex++]; txPower = datarate & 0x0F; datarate = ( datarate >> 4 ) & 0x0F; if( ( AdrCtrlOn == false ) && - ( ( ChannelsDatarate != datarate ) || ( ChannelsTxPower != txPower ) ) ) + ( ( LoRaMacParams.ChannelsDatarate != datarate ) || ( LoRaMacParams.ChannelsTxPower != txPower ) ) ) { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower // Answer the server with fail status // Power ACK = 0 @@ -2341,17 +2456,17 @@ } if( ( status & 0x07 ) == 0x07 ) { - ChannelsDatarate = datarate; - ChannelsTxPower = txPower; - - ChannelsMask[0] = channelsMask[0]; - ChannelsMask[1] = channelsMask[1]; - ChannelsMask[2] = channelsMask[2]; - ChannelsMask[3] = channelsMask[3]; - ChannelsMask[4] = channelsMask[4]; - ChannelsMask[5] = channelsMask[5]; - - ChannelsNbRep = nbRep; + LoRaMacParams.ChannelsDatarate = datarate; + LoRaMacParams.ChannelsTxPower = txPower; + + LoRaMacParams.ChannelsMask[0] = channelsMask[0]; + LoRaMacParams.ChannelsMask[1] = channelsMask[1]; + LoRaMacParams.ChannelsMask[2] = channelsMask[2]; + LoRaMacParams.ChannelsMask[3] = channelsMask[3]; + LoRaMacParams.ChannelsMask[4] = channelsMask[4]; + LoRaMacParams.ChannelsMask[5] = channelsMask[5]; + + LoRaMacParams.ChannelsNbRep = nbRep; } AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 ); } @@ -2377,7 +2492,7 @@ freq |= ( uint32_t )payload[macIndex++] << 16; freq *= 100; - if( Radio.CheckRfFrequency( freq ) == false ) + if( Rx2FreqInRange( freq ) == false ) { status &= 0xFE; // Channel frequency KO } @@ -2400,9 +2515,9 @@ if( ( status & 0x07 ) == 0x07 ) { - Rx2Channel.Datarate = datarate; - Rx2Channel.Frequency = freq; - Rx1DrOffset = drOffset; + LoRaMacParams.Rx2Channel.Datarate = datarate; + LoRaMacParams.Rx2Channel.Frequency = freq; + LoRaMacParams.Rx1DrOffset = drOffset; } AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 ); } @@ -2493,8 +2608,8 @@ { delay++; } - ReceiveDelay1 = delay * 1e6; - ReceiveDelay2 = ReceiveDelay1 + 1e6; + LoRaMacParams.ReceiveDelay1 = delay * 1e6; + LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6; AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 ); } break; @@ -2556,11 +2671,11 @@ while( SetNextChannel( &dutyCycleTimeOff ) == false ) { // Set the default datarate - ChannelsDatarate = ChannelsDefaultDatarate; + LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate; #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) // Re-enable default channels LC1, LC2, LC3 - ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); #endif } @@ -2581,15 +2696,45 @@ } } +static uint16_t RetransmissionDutyCylce( void ) +{ + uint16_t dutyCycle = 0; + +#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) + TimerTime_t timeElapsed = TimerGetElapsedTime( 0 ); + + if( timeElapsed < 3600000000 ) + { + dutyCycle = BACKOFF_DC_1_HOUR; + } + else if( timeElapsed < ( 3600000000 + 36000000000 ) ) + { + dutyCycle = BACKOFF_DC_10_HOURS; + } + else + { + dutyCycle = BACKOFF_DC_24_HOURS; + } +#endif + return dutyCycle; +} + static void CalculateBackOff( uint8_t channel ) { uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle; + uint16_t joinDutyCycle = 0; + bool rndTimeOff = false; if( IsLoRaMacNetworkJoined == false ) { -#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) - dutyCycle = JOIN_DC; -#endif + joinDutyCycle = RetransmissionDutyCylce( ); + dutyCycle = MAX( dutyCycle, joinDutyCycle ); + + // Make sure to not apply the random back-off to the first TX + if( TxTimeOnAir > 0 ) + { + rndTimeOff = true; + } } // Update Band Time OFF @@ -2601,10 +2746,126 @@ { Bands[Channels[channel].Band].TimeOff = 0; } + + if( rndTimeOff == true ) + { + Bands[Channels[channel].Band].TimeOff = randr( Bands[Channels[channel].Band].TimeOff, + Bands[Channels[channel].Band].TimeOff + BACKOFF_RND_OFFSET ); + } + // Update Aggregated Time OFF AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir ); } +static int8_t AlternateDatarate( uint16_t nbTrials ) +{ + int8_t datarate = LORAMAC_TX_MIN_DATARATE; +#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) +#if defined( USE_BAND_915 ) + // Re-enable 500 kHz default channels + LoRaMacParams.ChannelsMask[4] = 0x00FF; +#else // defined( USE_BAND_915_HYBRID ) + // Re-enable 500 kHz default channels + ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask ); +#endif + + if( ( nbTrials & 0x01 ) == 0x01 ) + { + datarate = DR_4; + } + else + { + datarate = DR_1; + } +#else + if( ( nbTrials % 48 ) == 0 ) + { + datarate = DR_0; + } + else if( ( nbTrials % 32 ) == 0 ) + { + datarate = DR_1; + } + else if( ( nbTrials % 24 ) == 0 ) + { + datarate = DR_2; + } + else if( ( nbTrials % 16 ) == 0 ) + { + datarate = DR_3; + } + else if( ( nbTrials % 8 ) == 0 ) + { + datarate = DR_4; + } + else + { + datarate = DR_5; + } +#endif + return datarate; +} + +static void ResetMacParameters( void ) +{ + IsLoRaMacNetworkJoined = false; + + // Counters + UpLinkCounter = 1; + DownLinkCounter = 0; + AdrAckCounter = 0; + + ChannelsNbRepCounter = 0; + + AckTimeoutRetries = 1; + AckTimeoutRetriesCounter = 1; + AckTimeoutRetry = false; + + MaxDCycle = 0; + AggregatedDCycle = 1; + + MacCommandsBufferIndex = 0; + MacCommandsBufferToRepeatIndex = 0; + + IsRxWindowsEnabled = true; + + LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower; + LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate; + + LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow; + LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1; + LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2; + LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1; + LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2; + + LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset; + LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep; + + LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel; + + memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); + +#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) + memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); +#endif + + + NodeAckRequested = false; + SrvAckRequested = false; + MacCommandsInNextTx = false; + + // Reset Multicast downlink counters + MulticastParams_t *cur = MulticastChannels; + while( cur != NULL ) + { + cur->DownLinkCounter = 0; + cur = cur->Next; + } + + // Initialize channel index. + Channel = LORA_MAX_NB_CHANNELS; +} + LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) { uint16_t i; @@ -2628,8 +2889,8 @@ switch( macHdr->Bits.MType ) { case FRAME_TYPE_JOIN_REQ: - RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME; - RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME; + RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 - RADIO_WAKEUP_TIME; + RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 - RADIO_WAKEUP_TIME; LoRaMacBufferPktLen = pktHeaderLen; @@ -2660,15 +2921,15 @@ return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet } - fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate ); - - if( ValidatePayloadLength( fBufferSize, ChannelsDatarate, MacCommandsBufferIndex ) == false ) + fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate ); + + if( ValidatePayloadLength( fBufferSize, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false ) { return LORAMAC_STATUS_LENGTH_ERROR; } - RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME; - RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME; + RxWindow1Delay = LoRaMacParams.ReceiveDelay1 - RADIO_WAKEUP_TIME; + RxWindow2Delay = LoRaMacParams.ReceiveDelay2 - RADIO_WAKEUP_TIME; if( SrvAckRequested == true ) { @@ -2686,6 +2947,10 @@ LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF; LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF; + // Copy the MAC commands which must be re-send into the MAC command buffer + memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex ); + MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex; + if( ( payload != NULL ) && ( payloadSize > 0 ) ) { if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) ) @@ -2710,6 +2975,12 @@ } } MacCommandsInNextTx = false; + // Store MAC commands which must be re-send in case the device does not receive a downlink anymore + MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat ); + if( MacCommandsBufferToRepeatIndex > 0 ) + { + MacCommandsInNextTx = true; + } MacCommandsBufferIndex = 0; if( ( payload != NULL ) && ( payloadSize > 0 ) ) @@ -2754,29 +3025,29 @@ LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel ) { - int8_t datarate = Datarates[ChannelsDatarate]; + int8_t datarate = Datarates[LoRaMacParams.ChannelsDatarate]; int8_t txPowerIndex = 0; int8_t txPower = 0; - txPowerIndex = LimitTxPower( ChannelsTxPower ); + txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower ); txPower = TxPowers[txPowerIndex]; MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR; McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR; - McpsConfirm.Datarate = ChannelsDatarate; + McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate; McpsConfirm.TxPower = txPowerIndex; Radio.SetChannel( channel.Frequency ); #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) - if( ChannelsDatarate == DR_7 ) + if( LoRaMacParams.ChannelsDatarate == DR_7 ) { // High Speed FSK channel Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen ); Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 ); TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen ); } - else if( ChannelsDatarate == DR_6 ) + else if( LoRaMacParams.ChannelsDatarate == DR_6 ) { // High speed LoRa channel Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen ); Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 ); @@ -2790,7 +3061,7 @@ } #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen ); - if( ChannelsDatarate >= DR_4 ) + if( LoRaMacParams.ChannelsDatarate >= DR_4 ) { // High speed LoRa channel BW500 kHz Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 ); TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen ); @@ -2840,40 +3111,64 @@ LoRaMacFlags.Value = 0; LoRaMacDeviceClass = CLASS_A; - - UpLinkCounter = 1; - DownLinkCounter = 0; - AdrAckCounter = 0; - + LoRaMacState = MAC_IDLE; + + JoinRequestTrials = 0; RepeaterSupport = false; - IsRxWindowsEnabled = true; - IsLoRaMacNetworkJoined = false; - LoRaMacState = MAC_IDLE; - + + // Reset duty cycle times + AggregatedLastTxDoneTime = 0; + AggregatedTimeOff = 0; + + // Duty cycle #if defined( USE_BAND_433 ) - ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); + DutyCycleOn = false; #elif defined( USE_BAND_780 ) - ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); + DutyCycleOn = false; #elif defined( USE_BAND_868 ) - ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); + DutyCycleOn = true; +#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) + DutyCycleOn = false; +#else + #error "Please define a frequency band in the compiler options." +#endif + + // Reset to defaults + LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; + LoRaMacParamsDefaults.ChannelsDatarate = LORAMAC_DEFAULT_DATARATE; + + LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW; + LoRaMacParamsDefaults.ReceiveDelay1 = RECEIVE_DELAY1; + LoRaMacParamsDefaults.ReceiveDelay2 = RECEIVE_DELAY2; + LoRaMacParamsDefaults.JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1; + LoRaMacParamsDefaults.JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2; + + LoRaMacParamsDefaults.ChannelsNbRep = 1; + LoRaMacParamsDefaults.Rx1DrOffset = 0; + + LoRaMacParamsDefaults.Rx2Channel = ( Rx2ChannelParams_t )RX_WND_2_CHANNEL; + + // Channel mask +#if defined( USE_BAND_433 ) + LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); +#elif defined( USE_BAND_780 ) + LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); +#elif defined( USE_BAND_868 ) + LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); #elif defined( USE_BAND_915 ) - ChannelsMask[0] = 0xFFFF; - ChannelsMask[1] = 0xFFFF; - ChannelsMask[2] = 0xFFFF; - ChannelsMask[3] = 0xFFFF; - ChannelsMask[4] = 0x00FF; - ChannelsMask[5] = 0x0000; - - memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) ); + LoRaMacParamsDefaults.ChannelsMask[0] = 0xFFFF; + LoRaMacParamsDefaults.ChannelsMask[1] = 0xFFFF; + LoRaMacParamsDefaults.ChannelsMask[2] = 0xFFFF; + LoRaMacParamsDefaults.ChannelsMask[3] = 0xFFFF; + LoRaMacParamsDefaults.ChannelsMask[4] = 0x00FF; + LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000; #elif defined( USE_BAND_915_HYBRID ) - ChannelsMask[0] = 0x00FF; - ChannelsMask[1] = 0x0000; - ChannelsMask[2] = 0x0000; - ChannelsMask[3] = 0x0000; - ChannelsMask[4] = 0x0001; - ChannelsMask[5] = 0x0000; - - memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) ); + LoRaMacParamsDefaults.ChannelsMask[0] = 0x00FF; + LoRaMacParamsDefaults.ChannelsMask[1] = 0x0000; + LoRaMacParamsDefaults.ChannelsMask[2] = 0x0000; + LoRaMacParamsDefaults.ChannelsMask[3] = 0x0000; + LoRaMacParamsDefaults.ChannelsMask[4] = 0x0001; + LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000; #else #error "Please define a frequency band in the compiler options." #endif @@ -2895,34 +3190,9 @@ } #endif - ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; - ChannelsDefaultDatarate = ChannelsDatarate = LORAMAC_DEFAULT_DATARATE; - ChannelsNbRep = 1; - ChannelsNbRepCounter = 0; - - MaxDCycle = 0; - AggregatedDCycle = 1; - AggregatedLastTxDoneTime = 0; - AggregatedTimeOff = 0; - -#if defined( USE_BAND_433 ) - DutyCycleOn = false; -#elif defined( USE_BAND_780 ) - DutyCycleOn = false; -#elif defined( USE_BAND_868 ) - DutyCycleOn = true; -#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - DutyCycleOn = false; -#else - #error "Please define a frequency band in the compiler options." -#endif - - MaxRxWindow = MAX_RX_WINDOW; - ReceiveDelay1 = RECEIVE_DELAY1; - ReceiveDelay2 = RECEIVE_DELAY2; - JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1; - JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2; - + ResetMacParameters( ); + + // Initialize timers TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent ); TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT ); @@ -2942,9 +3212,6 @@ // Random seed initialization srand1( Radio.Random( ) ); - // Initialize channel index. - Channel = LORA_MAX_NB_CHANNELS; - PublicNetwork = true; SetPublicNetwork( PublicNetwork ); Radio.Sleep( ); @@ -2954,7 +3221,8 @@ LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo ) { - int8_t datarate = ChannelsDefaultDatarate; + int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate; + uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex; if( txInfo == NULL ) { @@ -2972,9 +3240,9 @@ txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate]; } - if( txInfo->CurrentPayloadSize >= MacCommandsBufferIndex ) + if( txInfo->CurrentPayloadSize >= fOptLen ) { - txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - MacCommandsBufferIndex; + txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen; } else { @@ -2986,7 +3254,7 @@ return LORAMAC_STATUS_LENGTH_ERROR; } - if( ValidatePayloadLength( size, datarate, MacCommandsBufferIndex ) == false ) + if( ValidatePayloadLength( size, datarate, fOptLen ) == false ) { return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR; } @@ -3057,57 +3325,57 @@ } case MIB_RX2_CHANNEL: { - mibGet->Param.Rx2Channel = Rx2Channel; + mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel; break; } case MIB_CHANNELS_MASK: { - mibGet->Param.ChannelsMask = ChannelsMask; + mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask; break; } case MIB_CHANNELS_NB_REP: { - mibGet->Param.ChannelNbRep = ChannelsNbRep; + mibGet->Param.ChannelNbRep = LoRaMacParams.ChannelsNbRep; break; } case MIB_MAX_RX_WINDOW_DURATION: { - mibGet->Param.MaxRxWindow = MaxRxWindow; + mibGet->Param.MaxRxWindow = LoRaMacParams.MaxRxWindow; break; } case MIB_RECEIVE_DELAY_1: { - mibGet->Param.ReceiveDelay1 = ReceiveDelay1; + mibGet->Param.ReceiveDelay1 = LoRaMacParams.ReceiveDelay1; break; } case MIB_RECEIVE_DELAY_2: { - mibGet->Param.ReceiveDelay2 = ReceiveDelay2; + mibGet->Param.ReceiveDelay2 = LoRaMacParams.ReceiveDelay2; break; } case MIB_JOIN_ACCEPT_DELAY_1: { - mibGet->Param.JoinAcceptDelay1 = JoinAcceptDelay1; + mibGet->Param.JoinAcceptDelay1 = LoRaMacParams.JoinAcceptDelay1; break; } case MIB_JOIN_ACCEPT_DELAY_2: { - mibGet->Param.JoinAcceptDelay2 = JoinAcceptDelay2; + mibGet->Param.JoinAcceptDelay2 = LoRaMacParams.JoinAcceptDelay2; break; } case MIB_CHANNELS_DEFAULT_DATARATE: { - mibGet->Param.ChannelsDefaultDatarate = ChannelsDefaultDatarate; + mibGet->Param.ChannelsDefaultDatarate = LoRaMacParamsDefaults.ChannelsDatarate; break; } case MIB_CHANNELS_DATARATE: { - mibGet->Param.ChannelsDatarate = ChannelsDatarate; + mibGet->Param.ChannelsDatarate = LoRaMacParams.ChannelsDatarate; break; } case MIB_CHANNELS_TX_POWER: { - mibGet->Param.ChannelsTxPower = ChannelsTxPower; + mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower; break; } case MIB_UPLINK_COUNTER: @@ -3231,7 +3499,7 @@ } case MIB_RX2_CHANNEL: { - Rx2Channel = mibSet->Param.Rx2Channel; + LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel; break; } case MIB_CHANNELS_MASK: @@ -3253,12 +3521,12 @@ } else { - memcpy1( ( uint8_t* ) ChannelsMask, - ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( ChannelsMask ) ); - for ( uint8_t i = 0; i < sizeof( ChannelsMask ) / 2; i++ ) + memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, + ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); + for ( uint8_t i = 0; i < sizeof( LoRaMacParams.ChannelsMask ) / 2; i++ ) { // Disable channels which are no longer available - ChannelsMaskRemaining[i] &= ChannelsMask[i]; + ChannelsMaskRemaining[i] &= LoRaMacParams.ChannelsMask[i]; } } } @@ -3267,7 +3535,7 @@ status = LORAMAC_STATUS_PARAMETER_INVALID; } #else - memcpy1( ( uint8_t* ) ChannelsMask, + memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) mibSet->Param.ChannelsMask, 2 ); #endif } @@ -3282,7 +3550,7 @@ if( ( mibSet->Param.ChannelNbRep >= 1 ) && ( mibSet->Param.ChannelNbRep <= 15 ) ) { - ChannelsNbRep = mibSet->Param.ChannelNbRep; + LoRaMacParams.ChannelsNbRep = mibSet->Param.ChannelNbRep; } else { @@ -3292,27 +3560,27 @@ } case MIB_MAX_RX_WINDOW_DURATION: { - MaxRxWindow = mibSet->Param.MaxRxWindow; + LoRaMacParams.MaxRxWindow = mibSet->Param.MaxRxWindow; break; } case MIB_RECEIVE_DELAY_1: { - ReceiveDelay1 = mibSet->Param.ReceiveDelay1; + LoRaMacParams.ReceiveDelay1 = mibSet->Param.ReceiveDelay1; break; } case MIB_RECEIVE_DELAY_2: { - ReceiveDelay2 = mibSet->Param.ReceiveDelay2; + LoRaMacParams.ReceiveDelay2 = mibSet->Param.ReceiveDelay2; break; } case MIB_JOIN_ACCEPT_DELAY_1: { - JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1; + LoRaMacParams.JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1; break; } case MIB_JOIN_ACCEPT_DELAY_2: { - JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2; + LoRaMacParams.JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2; break; } case MIB_CHANNELS_DEFAULT_DATARATE: @@ -3320,7 +3588,7 @@ if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) ) { - ChannelsDefaultDatarate = mibSet->Param.ChannelsDefaultDatarate; + LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate; } else { @@ -3333,7 +3601,7 @@ if( ValueInRange( mibSet->Param.ChannelsDatarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) ) { - ChannelsDatarate = mibSet->Param.ChannelsDatarate; + LoRaMacParams.ChannelsDatarate = mibSet->Param.ChannelsDatarate; } else { @@ -3346,7 +3614,7 @@ if( ValueInRange( mibSet->Param.ChannelsTxPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) ) { - ChannelsTxPower = mibSet->Param.ChannelsTxPower; + LoRaMacParams.ChannelsTxPower = mibSet->Param.ChannelsTxPower; } else { @@ -3412,7 +3680,7 @@ frequencyInvalid = true; } - if( params.DrRange.Fields.Min > ChannelsDefaultDatarate ) + if( params.DrRange.Fields.Min > LoRaMacParamsDefaults.ChannelsDatarate ) { datarateInvalid = true; } @@ -3474,7 +3742,7 @@ // Every parameter is valid, activate the channel Channels[id] = params; Channels[id].Band = band; - ChannelsMask[0] |= ( 1 << id ); + LoRaMacParams.ChannelsMask[0] |= ( 1 << id ); return LORAMAC_STATUS_OK; #endif @@ -3501,7 +3769,7 @@ Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 }; // Disable the channel as it doesn't exist anymore - if( DisableChannelInMask( id, ChannelsMask ) == false ) + if( DisableChannelInMask( id, LoRaMacParams.ChannelsMask ) == false ) { return LORAMAC_STATUS_PARAMETER_INVALID; } @@ -3631,28 +3899,10 @@ macHdr.Value = 0; macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; - IsLoRaMacNetworkJoined = false; - -#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) -#if defined( USE_BAND_915 ) - // Re-enable 500 kHz default channels - ChannelsMask[4] = 0x00FF; -#else // defined( USE_BAND_915_HYBRID ) - // Re-enable 500 kHz default channels - ChannelsMask[4] = 0x0001; -#endif - - static uint8_t drSwitch = 0; - - if( ( ++drSwitch & 0x01 ) == 0x01 ) - { - ChannelsDatarate = DR_0; - } - else - { - ChannelsDatarate = DR_4; - } -#endif + ResetMacParameters( ); + + JoinRequestTrials++; + LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials ); status = Send( &macHdr, 0, NULL, 0 ); break; @@ -3751,7 +4001,7 @@ { if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true ) { - ChannelsDatarate = datarate; + LoRaMacParams.ChannelsDatarate = datarate; } else {
--- a/LoRaMac.h Wed May 18 11:19:24 2016 +0000 +++ b/LoRaMac.h Tue Jul 05 13:24:54 2016 +0000 @@ -47,7 +47,7 @@ #define __LORAMAC_H__ // Includes board dependent definitions such as channels frequencies -#include "LoRaMac-board.h" +#include "LoRaMac-definitions.h" /*! * Beacon interval in us @@ -149,11 +149,6 @@ */ #define LORA_MAC_PUBLIC_SYNCWORD 0x34 - /*! - * LoRaMac internal state - */ -//uint32_t LoRaMacState; - /*! * LoRaWAN devices classes definition */ @@ -162,19 +157,19 @@ /*! * LoRaWAN device class A * - * LoRaWAN Specification V1.0, chapter 3ff + * LoRaWAN Specification V1.0.1, chapter 3ff */ CLASS_A, /*! * LoRaWAN device class B * - * LoRaWAN Specification V1.0, chapter 8ff + * LoRaWAN Specification V1.0.1, chapter 8ff */ CLASS_B, /*! * LoRaWAN device class C * - * LoRaWAN Specification V1.0, chapter 17ff + * LoRaWAN Specification V1.0.1, chapter 17ff */ CLASS_C, }DeviceClass_t; @@ -274,6 +269,57 @@ }Rx2ChannelParams_t; /*! + * Global MAC layer parameters + */ +typedef struct sLoRaMacParams +{ + /*! + * Channels TX power + */ + int8_t ChannelsTxPower; + /*! + * Channels data rate + */ + int8_t ChannelsDatarate; + /*! + * LoRaMac maximum time a reception window stays open + */ + uint32_t MaxRxWindow; + /*! + * Receive delay 1 + */ + uint32_t ReceiveDelay1; + /*! + * Receive delay 2 + */ + uint32_t ReceiveDelay2; + /*! + * Join accept delay 1 + */ + uint32_t JoinAcceptDelay1; + /*! + * Join accept delay 1 + */ + uint32_t JoinAcceptDelay2; + /*! + * Number of uplink messages repetitions [1:15] (unconfirmed messages only) + */ + uint8_t ChannelsNbRep; + /*! + * Datarate offset between uplink and downlink on first window + */ + uint8_t Rx1DrOffset; + /*! + * LoRaMAC 2nd reception window settings + */ + Rx2ChannelParams_t Rx2Channel; + /*! + * Mask indicating which channels are enabled + */ + uint16_t ChannelsMask[6]; +}LoRaMacParams_t; + +/*! * LoRaMAC multicast channel parameter */ typedef struct sMulticastParams @@ -303,7 +349,7 @@ /*! * LoRaMAC frame types * - * LoRaWAN Specification V1.0, chapter 4.2.1, table 1 + * LoRaWAN Specification V1.0.1, chapter 4.2.1, table 1 */ typedef enum eLoRaMacFrameType { @@ -344,7 +390,7 @@ /*! * LoRaMAC mote MAC commands * - * LoRaWAN Specification V1.0, chapter 5, table 4 + * LoRaWAN Specification V1.0.1, chapter 5, table 4 */ typedef enum eLoRaMacMoteCmd { @@ -381,7 +427,7 @@ /*! * LoRaMAC server MAC commands * - * LoRaWAN Specification V1.0, chapter 5, table 4 + * LoRaWAN Specification V1.0.1 chapter 5, table 4 */ typedef enum eLoRaMacSrvCmd { @@ -441,7 +487,7 @@ /*! * LoRaMAC header field definition (MHDR field) * - * LoRaWAN Specification V1.0, chapter 4.2 + * LoRaWAN Specification V1.0.1, chapter 4.2 */ typedef union uLoRaMacHeader { @@ -472,7 +518,7 @@ /*! * LoRaMAC frame control field definition (FCtrl) * - * LoRaWAN Specification V1.0, chapter 4.3.1 + * LoRaWAN Specification V1.0.1, chapter 4.3.1 */ typedef union uLoRaMacFrameCtrl { @@ -642,7 +688,7 @@ * Frame port field. Must be set if the payload is not empty. Use the * application specific frame port values: [1...223] * - * LoRaWAN Specification V1.0, chapter 4.3.2 + * LoRaWAN Specification V1.0.1, chapter 4.3.2 */ uint8_t fPort; /*! @@ -668,7 +714,7 @@ * Frame port field. Must be set if the payload is not empty. Use the * application specific frame port values: [1...223] * - * LoRaWAN Specification V1.0, chapter 4.3.2 + * LoRaWAN Specification V1.0.1, chapter 4.3.2 */ uint8_t fPort; /*! @@ -686,7 +732,7 @@ /*! * Number of trials to transmit the frame, if the LoRaMAC layer did not * receive an acknowledgment. The MAC performs a datarate adaptation, - * according to the LoRaWAN Specification V1.0, chapter 18.4, according + * according to the LoRaWAN Specification V1.0.1, chapter 19.4, according * to the following table: * * Transmission nb | Data Rate @@ -883,13 +929,13 @@ /*! * Initiates the Over-the-Air activation * - * LoRaWAN Specification V1.0, chapter 6.2 + * LoRaWAN Specification V1.0.1, chapter 6.2 */ MLME_JOIN, /*! * LinkCheckReq - Connectivity validation * - * LoRaWAN Specification V1.0, chapter 5, table 4 + * LoRaWAN Specification V1.0.1, chapter 5, table 4 */ MLME_LINK_CHECK, }Mlme_t; @@ -902,19 +948,19 @@ /*! * Globally unique end-device identifier * - * LoRaWAN Specification V1.0, chapter 6.2.1 + * LoRaWAN Specification V1.0.1, chapter 6.2.1 */ uint8_t *DevEui; /*! * Application identifier * - * LoRaWAN Specification V1.0, chapter 6.1.2 + * LoRaWAN Specification V1.0.1, chapter 6.1.2 */ uint8_t *AppEui; /*! * AES-128 application key * - * LoRaWAN Specification V1.0, chapter 6.2.2 + * LoRaWAN Specification V1.0.1, chapter 6.2.2 */ uint8_t *AppKey; }MlmeReqJoin_t; @@ -1014,19 +1060,19 @@ /*! * LoRaWAN device class * - * LoRaWAN Specification V1.0 + * LoRaWAN Specification V1.0.1 */ MIB_DEVICE_CLASS, /*! * LoRaWAN Network joined attribute * - * LoRaWAN Specification V1.0 + * LoRaWAN Specification V1.0.1 */ MIB_NETWORK_JOINED, /*! * Adaptive data rate * - * LoRaWAN Specification V1.0, chapter 4.3.1.1 + * LoRaWAN Specification V1.0.1, chapter 4.3.1.1 * * [true: ADR enabled, false: ADR disabled] */ @@ -1034,31 +1080,31 @@ /*! * Network identifier * - * LoRaWAN Specification V1.0, chapter 6.2.5 + * LoRaWAN Specification V1.0.1, chapter 6.1.1 */ MIB_NET_ID, /*! * End-device address * - * LoRaWAN Specification V1.0, chapter 6.1.2 + * LoRaWAN Specification V1.0.1, chapter 6.1.1 */ MIB_DEV_ADDR, /*! * Network session key * - * LoRaWAN Specification V1.0, chapter 6.1.3 + * LoRaWAN Specification V1.0.1, chapter 6.1.3 */ MIB_NWK_SKEY, /*! * Application session key * - * LoRaWAN Specification V1.0, chapter 6.1.4 + * LoRaWAN Specification V1.0.1, chapter 6.1.4 */ MIB_APP_SKEY, /*! * Set the network type to public or private * - * LoRaWAN Specification V1.0, chapter 7 + * LoRaWAN Specification V1.0.1, chapter 7 * * [true: public network, false: private network] */ @@ -1066,7 +1112,7 @@ /*! * Support the operation with repeaters * - * LoRaWAN Specification V1.0, chapter 7 + * LoRaWAN Specification V1.0.1, chapter 7 * * [true: repeater support enabled, false: repeater support disabled] */ @@ -1076,61 +1122,61 @@ * pointer which references the first entry of the channel list. The * list is of size LORA_MAX_NB_CHANNELS * - * LoRaWAN Specification V1.0, chapter 7 + * LoRaWAN Specification V1.0.1, chapter 7 */ MIB_CHANNELS, /*! * Set receive window 2 channel * - * LoRaWAN Specification V1.0, chapter 3.3.2 + * LoRaWAN Specification V1.0.1, chapter 3.3.2 */ MIB_RX2_CHANNEL, /*! * LoRaWAN channels mask * - * LoRaWAN Specification V1.0, chapter 5.2 + * LoRaWAN Specification V1.0.1, chapter 7 */ MIB_CHANNELS_MASK, /*! * Set the number of repetitions on a channel * - * LoRaWAN Specification V1.0, chapter 5.2 + * LoRaWAN Specification V1.0.1, chapter 5.2 */ MIB_CHANNELS_NB_REP, /*! * Maximum receive window duration in [us] * - * LoRaWAN Specification V1.0, chapter 3.3.3 + * LoRaWAN Specification V1.0.1, chapter 3.3.3 */ MIB_MAX_RX_WINDOW_DURATION, /*! * Receive delay 1 in [us] * - * LoRaWAN Specification V1.0, chapter 6 + * LoRaWAN Specification V1.0.1, chapter 7 */ MIB_RECEIVE_DELAY_1, /*! * Receive delay 2 in [us] * - * LoRaWAN Specification V1.0, chapter 6 + * LoRaWAN Specification V1.0.1, chapter 7 */ MIB_RECEIVE_DELAY_2, /*! * Join accept delay 1 in [us] * - * LoRaWAN Specification V1.0, chapter 6 + * LoRaWAN Specification V1.0.1, chapter 7 */ MIB_JOIN_ACCEPT_DELAY_1, /*! * Join accept delay 2 in [us] * - * LoRaWAN Specification V1.0, chapter 6 + * LoRaWAN Specification V1.0.1, chapter 7 */ MIB_JOIN_ACCEPT_DELAY_2, /*! * Default Data rate of a channel * - * LoRaWAN Specification V1.0, chapter 7 + * LoRaWAN Specification V1.0.1, chapter 7 * * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7] * @@ -1140,7 +1186,7 @@ /*! * Data rate of a channel * - * LoRaWAN Specification V1.0, chapter 7 + * LoRaWAN Specification V1.0.1, chapter 7 * * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7] * @@ -1150,7 +1196,7 @@ /*! * Transmission power of a channel * - * LoRaWAN Specification V1.0, chapter 7 + * 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] @@ -1164,13 +1210,13 @@ /*! * LoRaWAN Up-link counter * - * LoRaWAN Specification V1.0, chapter 4.3.1.5 + * LoRaWAN Specification V1.0.1, chapter 4.3.1.5 */ MIB_UPLINK_COUNTER, /*! * LoRaWAN Down-link counter * - * LoRaWAN Specification V1.0, chapter 4.3.1.5 + * LoRaWAN Specification V1.0.1, chapter 4.3.1.5 */ MIB_DOWNLINK_COUNTER, /*!