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:

  1. LoRaWAN-demo-72
  2. LoRaWAN-demo-76
  3. LoRaWAN-demo-NAMote72

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
Committer:
mluis
Date:
Tue Jul 05 13:24:54 2016 +0000
Revision:
7:c16969e0f70f
Parent:
6:d7a34ded7c87
Child:
8:26002607de9c
Synchronized with https://github.com/Lora-net/LoRaMac-node git revision 7a4aec588de628d864c364e9469ae45105fdbe26

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mluis 0:91d1a7783bb9 1 /*
mluis 0:91d1a7783bb9 2 / _____) _ | |
mluis 0:91d1a7783bb9 3 ( (____ _____ ____ _| |_ _____ ____| |__
mluis 0:91d1a7783bb9 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
mluis 0:91d1a7783bb9 5 _____) ) ____| | | || |_| ____( (___| | | |
mluis 0:91d1a7783bb9 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
mluis 0:91d1a7783bb9 7 (C)2013 Semtech
mluis 2:14a5d6ad92d5 8 ___ _____ _ ___ _ _____ ___ ___ ___ ___
mluis 2:14a5d6ad92d5 9 / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
mluis 2:14a5d6ad92d5 10 \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
mluis 2:14a5d6ad92d5 11 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
mluis 2:14a5d6ad92d5 12 embedded.connectivity.solutions===============
mluis 0:91d1a7783bb9 13
mluis 0:91d1a7783bb9 14 Description: LoRa MAC layer implementation
mluis 0:91d1a7783bb9 15
mluis 0:91d1a7783bb9 16 License: Revised BSD License, see LICENSE.TXT file include in the project
mluis 0:91d1a7783bb9 17
mluis 2:14a5d6ad92d5 18 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
mluis 0:91d1a7783bb9 19 */
mluis 0:91d1a7783bb9 20 #include "board.h"
mluis 0:91d1a7783bb9 21
mluis 0:91d1a7783bb9 22 #include "LoRaMacCrypto.h"
mluis 0:91d1a7783bb9 23 #include "LoRaMac.h"
mluis 2:14a5d6ad92d5 24 #include "LoRaMacTest.h"
mluis 0:91d1a7783bb9 25
mluis 0:91d1a7783bb9 26 /*!
mluis 0:91d1a7783bb9 27 * Maximum PHY layer payload size
mluis 0:91d1a7783bb9 28 */
mluis 1:91e4e6c60d1e 29 #define LORAMAC_PHY_MAXPAYLOAD 255
mluis 1:91e4e6c60d1e 30
mluis 1:91e4e6c60d1e 31 /*!
mluis 1:91e4e6c60d1e 32 * Maximum MAC commands buffer size
mluis 1:91e4e6c60d1e 33 */
mluis 1:91e4e6c60d1e 34 #define LORA_MAC_COMMAND_MAX_LENGTH 15
mluis 0:91d1a7783bb9 35
mluis 0:91d1a7783bb9 36 /*!
mluis 4:37c12dbc8dc7 37 * FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
mluis 4:37c12dbc8dc7 38 * in RxWindowSetup function.
mluis 4:37c12dbc8dc7 39 * Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater + LORA_MAC_FRMPAYLOAD_OVERHEAD
mluis 4:37c12dbc8dc7 40 */
mluis 4:37c12dbc8dc7 41 #define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
mluis 4:37c12dbc8dc7 42
mluis 4:37c12dbc8dc7 43 /*!
mluis 0:91d1a7783bb9 44 * Device IEEE EUI
mluis 0:91d1a7783bb9 45 */
mluis 0:91d1a7783bb9 46 static uint8_t *LoRaMacDevEui;
mluis 0:91d1a7783bb9 47
mluis 0:91d1a7783bb9 48 /*!
mluis 0:91d1a7783bb9 49 * Application IEEE EUI
mluis 0:91d1a7783bb9 50 */
mluis 0:91d1a7783bb9 51 static uint8_t *LoRaMacAppEui;
mluis 0:91d1a7783bb9 52
mluis 0:91d1a7783bb9 53 /*!
mluis 0:91d1a7783bb9 54 * AES encryption/decryption cipher application key
mluis 0:91d1a7783bb9 55 */
mluis 0:91d1a7783bb9 56 static uint8_t *LoRaMacAppKey;
mluis 0:91d1a7783bb9 57
mluis 0:91d1a7783bb9 58 /*!
mluis 0:91d1a7783bb9 59 * AES encryption/decryption cipher network session key
mluis 0:91d1a7783bb9 60 */
mluis 0:91d1a7783bb9 61 static uint8_t LoRaMacNwkSKey[] =
mluis 0:91d1a7783bb9 62 {
mluis 0:91d1a7783bb9 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mluis 0:91d1a7783bb9 64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:91d1a7783bb9 65 };
mluis 0:91d1a7783bb9 66
mluis 0:91d1a7783bb9 67 /*!
mluis 0:91d1a7783bb9 68 * AES encryption/decryption cipher application session key
mluis 0:91d1a7783bb9 69 */
mluis 0:91d1a7783bb9 70 static uint8_t LoRaMacAppSKey[] =
mluis 0:91d1a7783bb9 71 {
mluis 0:91d1a7783bb9 72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mluis 0:91d1a7783bb9 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:91d1a7783bb9 74 };
mluis 0:91d1a7783bb9 75
mluis 0:91d1a7783bb9 76 /*!
mluis 0:91d1a7783bb9 77 * Device nonce is a random value extracted by issuing a sequence of RSSI
mluis 0:91d1a7783bb9 78 * measurements
mluis 0:91d1a7783bb9 79 */
mluis 0:91d1a7783bb9 80 static uint16_t LoRaMacDevNonce;
mluis 0:91d1a7783bb9 81
mluis 0:91d1a7783bb9 82 /*!
mluis 0:91d1a7783bb9 83 * Network ID ( 3 bytes )
mluis 0:91d1a7783bb9 84 */
mluis 0:91d1a7783bb9 85 static uint32_t LoRaMacNetID;
mluis 0:91d1a7783bb9 86
mluis 0:91d1a7783bb9 87 /*!
mluis 0:91d1a7783bb9 88 * Mote Address
mluis 0:91d1a7783bb9 89 */
mluis 0:91d1a7783bb9 90 static uint32_t LoRaMacDevAddr;
mluis 0:91d1a7783bb9 91
mluis 0:91d1a7783bb9 92 /*!
mluis 2:14a5d6ad92d5 93 * Multicast channels linked list
mluis 0:91d1a7783bb9 94 */
mluis 0:91d1a7783bb9 95 static MulticastParams_t *MulticastChannels = NULL;
mluis 0:91d1a7783bb9 96
mluis 0:91d1a7783bb9 97 /*!
mluis 0:91d1a7783bb9 98 * Actual device class
mluis 0:91d1a7783bb9 99 */
mluis 0:91d1a7783bb9 100 static DeviceClass_t LoRaMacDeviceClass;
mluis 0:91d1a7783bb9 101
mluis 0:91d1a7783bb9 102 /*!
mluis 0:91d1a7783bb9 103 * Indicates if the node is connected to a private or public network
mluis 0:91d1a7783bb9 104 */
mluis 0:91d1a7783bb9 105 static bool PublicNetwork;
mluis 0:91d1a7783bb9 106
mluis 0:91d1a7783bb9 107 /*!
mluis 0:91d1a7783bb9 108 * Indicates if the node supports repeaters
mluis 0:91d1a7783bb9 109 */
mluis 0:91d1a7783bb9 110 static bool RepeaterSupport;
mluis 0:91d1a7783bb9 111
mluis 0:91d1a7783bb9 112 /*!
mluis 0:91d1a7783bb9 113 * Buffer containing the data to be sent or received.
mluis 0:91d1a7783bb9 114 */
mluis 0:91d1a7783bb9 115 static uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD];
mluis 0:91d1a7783bb9 116
mluis 0:91d1a7783bb9 117 /*!
mluis 0:91d1a7783bb9 118 * Length of packet in LoRaMacBuffer
mluis 0:91d1a7783bb9 119 */
mluis 0:91d1a7783bb9 120 static uint16_t LoRaMacBufferPktLen = 0;
mluis 0:91d1a7783bb9 121
mluis 0:91d1a7783bb9 122 /*!
mluis 0:91d1a7783bb9 123 * Buffer containing the upper layer data.
mluis 0:91d1a7783bb9 124 */
mluis 0:91d1a7783bb9 125 static uint8_t LoRaMacPayload[LORAMAC_PHY_MAXPAYLOAD];
mluis 0:91d1a7783bb9 126 static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];
mluis 0:91d1a7783bb9 127
mluis 0:91d1a7783bb9 128 /*!
mluis 0:91d1a7783bb9 129 * LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
mluis 0:91d1a7783bb9 130 * Only the 16 LSB bits are sent
mluis 0:91d1a7783bb9 131 */
mluis 0:91d1a7783bb9 132 static uint32_t UpLinkCounter = 1;
mluis 0:91d1a7783bb9 133
mluis 0:91d1a7783bb9 134 /*!
mluis 0:91d1a7783bb9 135 * LoRaMAC frame counter. Each time a packet is received the counter is incremented.
mluis 0:91d1a7783bb9 136 * Only the 16 LSB bits are received
mluis 0:91d1a7783bb9 137 */
mluis 0:91d1a7783bb9 138 static uint32_t DownLinkCounter = 0;
mluis 0:91d1a7783bb9 139
mluis 0:91d1a7783bb9 140 /*!
mluis 0:91d1a7783bb9 141 * IsPacketCounterFixed enables the MIC field tests by fixing the
mluis 0:91d1a7783bb9 142 * UpLinkCounter value
mluis 0:91d1a7783bb9 143 */
mluis 0:91d1a7783bb9 144 static bool IsUpLinkCounterFixed = false;
mluis 0:91d1a7783bb9 145
mluis 0:91d1a7783bb9 146 /*!
mluis 0:91d1a7783bb9 147 * Used for test purposes. Disables the opening of the reception windows.
mluis 0:91d1a7783bb9 148 */
mluis 0:91d1a7783bb9 149 static bool IsRxWindowsEnabled = true;
mluis 0:91d1a7783bb9 150
mluis 0:91d1a7783bb9 151 /*!
mluis 0:91d1a7783bb9 152 * Indicates if the MAC layer has already joined a network.
mluis 0:91d1a7783bb9 153 */
mluis 0:91d1a7783bb9 154 static bool IsLoRaMacNetworkJoined = false;
mluis 0:91d1a7783bb9 155
mluis 0:91d1a7783bb9 156 /*!
mluis 0:91d1a7783bb9 157 * LoRaMac ADR control status
mluis 0:91d1a7783bb9 158 */
mluis 0:91d1a7783bb9 159 static bool AdrCtrlOn = false;
mluis 0:91d1a7783bb9 160
mluis 0:91d1a7783bb9 161 /*!
mluis 0:91d1a7783bb9 162 * Counts the number of missed ADR acknowledgements
mluis 0:91d1a7783bb9 163 */
mluis 0:91d1a7783bb9 164 static uint32_t AdrAckCounter = 0;
mluis 0:91d1a7783bb9 165
mluis 0:91d1a7783bb9 166 /*!
mluis 0:91d1a7783bb9 167 * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
mluis 0:91d1a7783bb9 168 * if the nodes needs to manage the server acknowledgement.
mluis 0:91d1a7783bb9 169 */
mluis 0:91d1a7783bb9 170 static bool NodeAckRequested = false;
mluis 0:91d1a7783bb9 171
mluis 0:91d1a7783bb9 172 /*!
mluis 0:91d1a7783bb9 173 * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
mluis 0:91d1a7783bb9 174 * if the ACK bit must be set for the next transmission
mluis 0:91d1a7783bb9 175 */
mluis 0:91d1a7783bb9 176 static bool SrvAckRequested = false;
mluis 0:91d1a7783bb9 177
mluis 0:91d1a7783bb9 178 /*!
mluis 0:91d1a7783bb9 179 * Indicates if the MAC layer wants to send MAC commands
mluis 0:91d1a7783bb9 180 */
mluis 0:91d1a7783bb9 181 static bool MacCommandsInNextTx = false;
mluis 0:91d1a7783bb9 182
mluis 0:91d1a7783bb9 183 /*!
mluis 0:91d1a7783bb9 184 * Contains the current MacCommandsBuffer index
mluis 0:91d1a7783bb9 185 */
mluis 0:91d1a7783bb9 186 static uint8_t MacCommandsBufferIndex = 0;
mluis 0:91d1a7783bb9 187
mluis 0:91d1a7783bb9 188 /*!
mluis 7:c16969e0f70f 189 * Contains the current MacCommandsBuffer index for MAC commands to repeat
mluis 7:c16969e0f70f 190 */
mluis 7:c16969e0f70f 191 static uint8_t MacCommandsBufferToRepeatIndex = 0;
mluis 7:c16969e0f70f 192
mluis 7:c16969e0f70f 193 /*!
mluis 0:91d1a7783bb9 194 * Buffer containing the MAC layer commands
mluis 0:91d1a7783bb9 195 */
mluis 1:91e4e6c60d1e 196 static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
mluis 0:91d1a7783bb9 197
mluis 7:c16969e0f70f 198 /*!
mluis 7:c16969e0f70f 199 * Buffer containing the MAC layer commands which must be repeated
mluis 7:c16969e0f70f 200 */
mluis 7:c16969e0f70f 201 static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
mluis 7:c16969e0f70f 202
mluis 0:91d1a7783bb9 203 #if defined( USE_BAND_433 )
mluis 0:91d1a7783bb9 204 /*!
mluis 0:91d1a7783bb9 205 * Data rates table definition
mluis 0:91d1a7783bb9 206 */
mluis 0:91d1a7783bb9 207 const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
mluis 0:91d1a7783bb9 208
mluis 0:91d1a7783bb9 209 /*!
mluis 0:91d1a7783bb9 210 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
mluis 0:91d1a7783bb9 211 */
mluis 0:91d1a7783bb9 212 const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
mluis 0:91d1a7783bb9 213
mluis 0:91d1a7783bb9 214 /*!
mluis 0:91d1a7783bb9 215 * Maximum payload with respect to the datarate index. Can operate with repeater.
mluis 0:91d1a7783bb9 216 */
mluis 0:91d1a7783bb9 217 const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
mluis 0:91d1a7783bb9 218
mluis 0:91d1a7783bb9 219 /*!
mluis 0:91d1a7783bb9 220 * Tx output powers table definition
mluis 0:91d1a7783bb9 221 */
mluis 0:91d1a7783bb9 222 const int8_t TxPowers[] = { 20, 14, 11, 8, 5, 2 };
mluis 0:91d1a7783bb9 223
mluis 0:91d1a7783bb9 224 /*!
mluis 0:91d1a7783bb9 225 * LoRaMac bands
mluis 0:91d1a7783bb9 226 */
mluis 0:91d1a7783bb9 227 static Band_t Bands[LORA_MAX_NB_BANDS] =
mluis 0:91d1a7783bb9 228 {
mluis 0:91d1a7783bb9 229 BAND0,
mluis 0:91d1a7783bb9 230 };
mluis 0:91d1a7783bb9 231
mluis 0:91d1a7783bb9 232 /*!
mluis 0:91d1a7783bb9 233 * LoRaMAC channels
mluis 0:91d1a7783bb9 234 */
mluis 0:91d1a7783bb9 235 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
mluis 0:91d1a7783bb9 236 {
mluis 0:91d1a7783bb9 237 LC1,
mluis 0:91d1a7783bb9 238 LC2,
mluis 0:91d1a7783bb9 239 LC3,
mluis 0:91d1a7783bb9 240 };
mluis 0:91d1a7783bb9 241 #elif defined( USE_BAND_780 )
mluis 0:91d1a7783bb9 242 /*!
mluis 0:91d1a7783bb9 243 * Data rates table definition
mluis 0:91d1a7783bb9 244 */
mluis 0:91d1a7783bb9 245 const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
mluis 0:91d1a7783bb9 246
mluis 0:91d1a7783bb9 247 /*!
mluis 0:91d1a7783bb9 248 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
mluis 0:91d1a7783bb9 249 */
mluis 0:91d1a7783bb9 250 const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
mluis 0:91d1a7783bb9 251
mluis 0:91d1a7783bb9 252 /*!
mluis 0:91d1a7783bb9 253 * Maximum payload with respect to the datarate index. Can operate with repeater.
mluis 0:91d1a7783bb9 254 */
mluis 0:91d1a7783bb9 255 const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
mluis 0:91d1a7783bb9 256
mluis 0:91d1a7783bb9 257 /*!
mluis 0:91d1a7783bb9 258 * Tx output powers table definition
mluis 0:91d1a7783bb9 259 */
mluis 0:91d1a7783bb9 260 const int8_t TxPowers[] = { 20, 14, 11, 8, 5, 2 };
mluis 0:91d1a7783bb9 261
mluis 0:91d1a7783bb9 262 /*!
mluis 0:91d1a7783bb9 263 * LoRaMac bands
mluis 0:91d1a7783bb9 264 */
mluis 0:91d1a7783bb9 265 static Band_t Bands[LORA_MAX_NB_BANDS] =
mluis 0:91d1a7783bb9 266 {
mluis 0:91d1a7783bb9 267 BAND0,
mluis 0:91d1a7783bb9 268 };
mluis 0:91d1a7783bb9 269
mluis 0:91d1a7783bb9 270 /*!
mluis 0:91d1a7783bb9 271 * LoRaMAC channels
mluis 0:91d1a7783bb9 272 */
mluis 0:91d1a7783bb9 273 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
mluis 0:91d1a7783bb9 274 {
mluis 0:91d1a7783bb9 275 LC1,
mluis 0:91d1a7783bb9 276 LC2,
mluis 0:91d1a7783bb9 277 LC3,
mluis 0:91d1a7783bb9 278 };
mluis 0:91d1a7783bb9 279 #elif defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 280 /*!
mluis 0:91d1a7783bb9 281 * Data rates table definition
mluis 0:91d1a7783bb9 282 */
mluis 0:91d1a7783bb9 283 const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
mluis 0:91d1a7783bb9 284
mluis 0:91d1a7783bb9 285 /*!
mluis 0:91d1a7783bb9 286 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
mluis 0:91d1a7783bb9 287 */
mluis 0:91d1a7783bb9 288 const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
mluis 0:91d1a7783bb9 289
mluis 0:91d1a7783bb9 290 /*!
mluis 0:91d1a7783bb9 291 * Maximum payload with respect to the datarate index. Can operate with repeater.
mluis 0:91d1a7783bb9 292 */
mluis 0:91d1a7783bb9 293 const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
mluis 0:91d1a7783bb9 294
mluis 0:91d1a7783bb9 295 /*!
mluis 0:91d1a7783bb9 296 * Tx output powers table definition
mluis 0:91d1a7783bb9 297 */
mluis 0:91d1a7783bb9 298 const int8_t TxPowers[] = { 20, 14, 11, 8, 5, 2 };
mluis 0:91d1a7783bb9 299
mluis 0:91d1a7783bb9 300 /*!
mluis 0:91d1a7783bb9 301 * LoRaMac bands
mluis 0:91d1a7783bb9 302 */
mluis 0:91d1a7783bb9 303 static Band_t Bands[LORA_MAX_NB_BANDS] =
mluis 0:91d1a7783bb9 304 {
mluis 0:91d1a7783bb9 305 BAND0,
mluis 0:91d1a7783bb9 306 BAND1,
mluis 0:91d1a7783bb9 307 BAND2,
mluis 0:91d1a7783bb9 308 BAND3,
mluis 0:91d1a7783bb9 309 BAND4,
mluis 0:91d1a7783bb9 310 };
mluis 0:91d1a7783bb9 311
mluis 0:91d1a7783bb9 312 /*!
mluis 0:91d1a7783bb9 313 * LoRaMAC channels
mluis 0:91d1a7783bb9 314 */
mluis 0:91d1a7783bb9 315 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
mluis 0:91d1a7783bb9 316 {
mluis 0:91d1a7783bb9 317 LC1,
mluis 0:91d1a7783bb9 318 LC2,
mluis 0:91d1a7783bb9 319 LC3,
mluis 0:91d1a7783bb9 320 };
mluis 0:91d1a7783bb9 321 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 322 /*!
mluis 0:91d1a7783bb9 323 * Data rates table definition
mluis 0:91d1a7783bb9 324 */
mluis 0:91d1a7783bb9 325 const uint8_t Datarates[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
mluis 0:91d1a7783bb9 326
mluis 0:91d1a7783bb9 327 /*!
mluis 0:91d1a7783bb9 328 * Up/Down link data rates offset definition
mluis 0:91d1a7783bb9 329 */
mluis 2:14a5d6ad92d5 330 const int8_t datarateOffsets[16][4] =
mluis 0:91d1a7783bb9 331 {
mluis 0:91d1a7783bb9 332 { DR_10, DR_9 , DR_8 , DR_8 }, // DR_0
mluis 0:91d1a7783bb9 333 { DR_11, DR_10, DR_9 , DR_8 }, // DR_1
mluis 0:91d1a7783bb9 334 { DR_12, DR_11, DR_10, DR_9 }, // DR_2
mluis 0:91d1a7783bb9 335 { DR_13, DR_12, DR_11, DR_10 }, // DR_3
mluis 0:91d1a7783bb9 336 { DR_13, DR_13, DR_12, DR_11 }, // DR_4
mluis 0:91d1a7783bb9 337 };
mluis 0:91d1a7783bb9 338
mluis 0:91d1a7783bb9 339 /*!
mluis 0:91d1a7783bb9 340 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
mluis 0:91d1a7783bb9 341 */
mluis 7:c16969e0f70f 342 const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
mluis 0:91d1a7783bb9 343
mluis 0:91d1a7783bb9 344 /*!
mluis 0:91d1a7783bb9 345 * Maximum payload with respect to the datarate index. Can operate with repeater.
mluis 0:91d1a7783bb9 346 */
mluis 7:c16969e0f70f 347 const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
mluis 0:91d1a7783bb9 348
mluis 0:91d1a7783bb9 349 /*!
mluis 0:91d1a7783bb9 350 * Tx output powers table definition
mluis 0:91d1a7783bb9 351 */
mluis 0:91d1a7783bb9 352 const int8_t TxPowers[] = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 };
mluis 0:91d1a7783bb9 353
mluis 0:91d1a7783bb9 354 /*!
mluis 0:91d1a7783bb9 355 * LoRaMac bands
mluis 0:91d1a7783bb9 356 */
mluis 0:91d1a7783bb9 357 static Band_t Bands[LORA_MAX_NB_BANDS] =
mluis 0:91d1a7783bb9 358 {
mluis 0:91d1a7783bb9 359 BAND0,
mluis 0:91d1a7783bb9 360 };
mluis 0:91d1a7783bb9 361
mluis 0:91d1a7783bb9 362 /*!
mluis 0:91d1a7783bb9 363 * LoRaMAC channels
mluis 0:91d1a7783bb9 364 */
mluis 0:91d1a7783bb9 365 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS];
mluis 0:91d1a7783bb9 366
mluis 2:14a5d6ad92d5 367 /*!
mluis 2:14a5d6ad92d5 368 * Contains the channels which remain to be applied.
mluis 2:14a5d6ad92d5 369 */
mluis 2:14a5d6ad92d5 370 static uint16_t ChannelsMaskRemaining[6];
mluis 7:c16969e0f70f 371
mluis 7:c16969e0f70f 372 /*!
mluis 7:c16969e0f70f 373 * Defines the first channel for RX window 2 for US band
mluis 7:c16969e0f70f 374 */
mluis 7:c16969e0f70f 375 #define LORAMAC_FIRST_RX2_CHANNEL ( (uint32_t) 923.3e6 )
mluis 7:c16969e0f70f 376
mluis 7:c16969e0f70f 377 /*!
mluis 7:c16969e0f70f 378 * Defines the last channel for RX window 2 for US band
mluis 7:c16969e0f70f 379 */
mluis 7:c16969e0f70f 380 #define LORAMAC_LAST_RX2_CHANNEL ( (uint32_t) 927.5e6 )
mluis 7:c16969e0f70f 381
mluis 7:c16969e0f70f 382 /*!
mluis 7:c16969e0f70f 383 * Defines the step width of the channels for RX window 2
mluis 7:c16969e0f70f 384 */
mluis 7:c16969e0f70f 385 #define LORAMAC_STEPWIDTH_RX2_CHANNEL ( (uint32_t) 600e3 )
mluis 7:c16969e0f70f 386
mluis 0:91d1a7783bb9 387 #else
mluis 0:91d1a7783bb9 388 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 389 #endif
mluis 0:91d1a7783bb9 390
mluis 0:91d1a7783bb9 391 /*!
mluis 7:c16969e0f70f 392 * LoRaMac parameters
mluis 0:91d1a7783bb9 393 */
mluis 7:c16969e0f70f 394 LoRaMacParams_t LoRaMacParams;
mluis 0:91d1a7783bb9 395
mluis 0:91d1a7783bb9 396 /*!
mluis 7:c16969e0f70f 397 * LoRaMac default parameters
mluis 0:91d1a7783bb9 398 */
mluis 7:c16969e0f70f 399 LoRaMacParams_t LoRaMacParamsDefaults;
mluis 0:91d1a7783bb9 400
mluis 0:91d1a7783bb9 401 /*!
mluis 0:91d1a7783bb9 402 * Uplink messages repetitions counter
mluis 0:91d1a7783bb9 403 */
mluis 0:91d1a7783bb9 404 static uint8_t ChannelsNbRepCounter = 0;
mluis 0:91d1a7783bb9 405
mluis 0:91d1a7783bb9 406 /*!
mluis 0:91d1a7783bb9 407 * Maximum duty cycle
mluis 0:91d1a7783bb9 408 * \remark Possibility to shutdown the device.
mluis 0:91d1a7783bb9 409 */
mluis 0:91d1a7783bb9 410 static uint8_t MaxDCycle = 0;
mluis 0:91d1a7783bb9 411
mluis 0:91d1a7783bb9 412 /*!
mluis 2:14a5d6ad92d5 413 * Aggregated duty cycle management
mluis 0:91d1a7783bb9 414 */
mluis 0:91d1a7783bb9 415 static uint16_t AggregatedDCycle;
mluis 0:91d1a7783bb9 416 static TimerTime_t AggregatedLastTxDoneTime;
mluis 0:91d1a7783bb9 417 static TimerTime_t AggregatedTimeOff;
mluis 0:91d1a7783bb9 418
mluis 0:91d1a7783bb9 419 /*!
mluis 0:91d1a7783bb9 420 * Enables/Disables duty cycle management (Test only)
mluis 0:91d1a7783bb9 421 */
mluis 0:91d1a7783bb9 422 static bool DutyCycleOn;
mluis 0:91d1a7783bb9 423
mluis 0:91d1a7783bb9 424 /*!
mluis 0:91d1a7783bb9 425 * Current channel index
mluis 0:91d1a7783bb9 426 */
mluis 0:91d1a7783bb9 427 static uint8_t Channel;
mluis 0:91d1a7783bb9 428
mluis 7:c16969e0f70f 429 /*!
mluis 7:c16969e0f70f 430 * Channel index of the last transmission
mluis 7:c16969e0f70f 431 */
mluis 4:37c12dbc8dc7 432 static uint8_t LastTxChannel;
mluis 4:37c12dbc8dc7 433
mluis 0:91d1a7783bb9 434 /*!
mluis 0:91d1a7783bb9 435 * LoRaMac internal states
mluis 0:91d1a7783bb9 436 */
mluis 2:14a5d6ad92d5 437 enum eLoRaMacState
mluis 0:91d1a7783bb9 438 {
mluis 0:91d1a7783bb9 439 MAC_IDLE = 0x00000000,
mluis 0:91d1a7783bb9 440 MAC_TX_RUNNING = 0x00000001,
mluis 0:91d1a7783bb9 441 MAC_RX = 0x00000002,
mluis 0:91d1a7783bb9 442 MAC_ACK_REQ = 0x00000004,
mluis 0:91d1a7783bb9 443 MAC_ACK_RETRY = 0x00000008,
mluis 2:14a5d6ad92d5 444 MAC_TX_DELAYED = 0x00000010,
mluis 3:b9d87593a8ae 445 MAC_TX_CONFIG = 0x00000020,
mluis 4:37c12dbc8dc7 446 MAC_RX_ABORT = 0x00000040,
mluis 0:91d1a7783bb9 447 };
mluis 0:91d1a7783bb9 448
mluis 0:91d1a7783bb9 449 /*!
mluis 0:91d1a7783bb9 450 * LoRaMac internal state
mluis 0:91d1a7783bb9 451 */
mluis 0:91d1a7783bb9 452 uint32_t LoRaMacState = MAC_IDLE;
mluis 0:91d1a7783bb9 453
mluis 0:91d1a7783bb9 454 /*!
mluis 0:91d1a7783bb9 455 * LoRaMac timer used to check the LoRaMacState (runs every second)
mluis 0:91d1a7783bb9 456 */
mluis 0:91d1a7783bb9 457 static TimerEvent_t MacStateCheckTimer;
mluis 0:91d1a7783bb9 458
mluis 0:91d1a7783bb9 459 /*!
mluis 0:91d1a7783bb9 460 * LoRaMac upper layer event functions
mluis 0:91d1a7783bb9 461 */
mluis 2:14a5d6ad92d5 462 static LoRaMacPrimitives_t *LoRaMacPrimitives;
mluis 0:91d1a7783bb9 463
mluis 0:91d1a7783bb9 464 /*!
mluis 2:14a5d6ad92d5 465 * LoRaMac upper layer callback functions
mluis 0:91d1a7783bb9 466 */
mluis 2:14a5d6ad92d5 467 static LoRaMacCallback_t *LoRaMacCallbacks;
mluis 0:91d1a7783bb9 468
mluis 0:91d1a7783bb9 469 /*!
mluis 2:14a5d6ad92d5 470 * Radio events function pointer
mluis 0:91d1a7783bb9 471 */
mluis 2:14a5d6ad92d5 472 static RadioEvents_t RadioEvents;
mluis 0:91d1a7783bb9 473
mluis 0:91d1a7783bb9 474 /*!
mluis 0:91d1a7783bb9 475 * LoRaMac duty cycle delayed Tx timer
mluis 0:91d1a7783bb9 476 */
mluis 0:91d1a7783bb9 477 static TimerEvent_t TxDelayedTimer;
mluis 0:91d1a7783bb9 478
mluis 0:91d1a7783bb9 479 /*!
mluis 0:91d1a7783bb9 480 * LoRaMac reception windows timers
mluis 0:91d1a7783bb9 481 */
mluis 0:91d1a7783bb9 482 static TimerEvent_t RxWindowTimer1;
mluis 0:91d1a7783bb9 483 static TimerEvent_t RxWindowTimer2;
mluis 0:91d1a7783bb9 484
mluis 0:91d1a7783bb9 485 /*!
mluis 0:91d1a7783bb9 486 * LoRaMac reception windows delay
mluis 0:91d1a7783bb9 487 * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
mluis 0:91d1a7783bb9 488 * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
mluis 0:91d1a7783bb9 489 */
mluis 0:91d1a7783bb9 490 static uint32_t RxWindow1Delay;
mluis 0:91d1a7783bb9 491 static uint32_t RxWindow2Delay;
mluis 0:91d1a7783bb9 492
mluis 0:91d1a7783bb9 493 /*!
mluis 0:91d1a7783bb9 494 * Acknowledge timeout timer. Used for packet retransmissions.
mluis 0:91d1a7783bb9 495 */
mluis 0:91d1a7783bb9 496 static TimerEvent_t AckTimeoutTimer;
mluis 0:91d1a7783bb9 497
mluis 0:91d1a7783bb9 498 /*!
mluis 0:91d1a7783bb9 499 * Number of trials to get a frame acknowledged
mluis 0:91d1a7783bb9 500 */
mluis 0:91d1a7783bb9 501 static uint8_t AckTimeoutRetries = 1;
mluis 0:91d1a7783bb9 502
mluis 0:91d1a7783bb9 503 /*!
mluis 0:91d1a7783bb9 504 * Number of trials to get a frame acknowledged
mluis 0:91d1a7783bb9 505 */
mluis 0:91d1a7783bb9 506 static uint8_t AckTimeoutRetriesCounter = 1;
mluis 0:91d1a7783bb9 507
mluis 0:91d1a7783bb9 508 /*!
mluis 0:91d1a7783bb9 509 * Indicates if the AckTimeout timer has expired or not
mluis 0:91d1a7783bb9 510 */
mluis 0:91d1a7783bb9 511 static bool AckTimeoutRetry = false;
mluis 0:91d1a7783bb9 512
mluis 0:91d1a7783bb9 513 /*!
mluis 0:91d1a7783bb9 514 * Last transmission time on air
mluis 0:91d1a7783bb9 515 */
mluis 0:91d1a7783bb9 516 TimerTime_t TxTimeOnAir = 0;
mluis 0:91d1a7783bb9 517
mluis 0:91d1a7783bb9 518 /*!
mluis 7:c16969e0f70f 519 * Number of trials for the Join Request
mluis 7:c16969e0f70f 520 */
mluis 7:c16969e0f70f 521 static uint16_t JoinRequestTrials;
mluis 7:c16969e0f70f 522
mluis 7:c16969e0f70f 523 /*!
mluis 2:14a5d6ad92d5 524 * Structure to hold an MCPS indication data.
mluis 2:14a5d6ad92d5 525 */
mluis 2:14a5d6ad92d5 526 static McpsIndication_t McpsIndication;
mluis 2:14a5d6ad92d5 527
mluis 2:14a5d6ad92d5 528 /*!
mluis 2:14a5d6ad92d5 529 * Structure to hold MCPS confirm data.
mluis 2:14a5d6ad92d5 530 */
mluis 2:14a5d6ad92d5 531 static McpsConfirm_t McpsConfirm;
mluis 2:14a5d6ad92d5 532
mluis 2:14a5d6ad92d5 533 /*!
mluis 2:14a5d6ad92d5 534 * Structure to hold MLME confirm data.
mluis 2:14a5d6ad92d5 535 */
mluis 2:14a5d6ad92d5 536 static MlmeConfirm_t MlmeConfirm;
mluis 2:14a5d6ad92d5 537
mluis 2:14a5d6ad92d5 538 /*!
mluis 2:14a5d6ad92d5 539 * Holds the current rx window slot
mluis 2:14a5d6ad92d5 540 */
mluis 2:14a5d6ad92d5 541 static uint8_t RxSlot = 0;
mluis 2:14a5d6ad92d5 542
mluis 2:14a5d6ad92d5 543 /*!
mluis 2:14a5d6ad92d5 544 * LoRaMac tx/rx operation state
mluis 2:14a5d6ad92d5 545 */
mluis 2:14a5d6ad92d5 546 LoRaMacFlags_t LoRaMacFlags;
mluis 2:14a5d6ad92d5 547
mluis 2:14a5d6ad92d5 548 /*!
mluis 2:14a5d6ad92d5 549 * \brief Function to be executed on Radio Tx Done event
mluis 0:91d1a7783bb9 550 */
mluis 0:91d1a7783bb9 551 static void OnRadioTxDone( void );
mluis 0:91d1a7783bb9 552
mluis 0:91d1a7783bb9 553 /*!
mluis 3:b9d87593a8ae 554 * \brief This function prepares the MAC to abort the execution of function
mluis 3:b9d87593a8ae 555 * OnRadioRxDone in case of a reception error.
mluis 3:b9d87593a8ae 556 */
mluis 3:b9d87593a8ae 557 static void PrepareRxDoneAbort( void );
mluis 3:b9d87593a8ae 558
mluis 3:b9d87593a8ae 559 /*!
mluis 2:14a5d6ad92d5 560 * \brief Function to be executed on Radio Rx Done event
mluis 0:91d1a7783bb9 561 */
mluis 0:91d1a7783bb9 562 static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
mluis 0:91d1a7783bb9 563
mluis 0:91d1a7783bb9 564 /*!
mluis 2:14a5d6ad92d5 565 * \brief Function executed on Radio Tx Timeout event
mluis 0:91d1a7783bb9 566 */
mluis 0:91d1a7783bb9 567 static void OnRadioTxTimeout( void );
mluis 0:91d1a7783bb9 568
mluis 0:91d1a7783bb9 569 /*!
mluis 2:14a5d6ad92d5 570 * \brief Function executed on Radio Rx error event
mluis 0:91d1a7783bb9 571 */
mluis 0:91d1a7783bb9 572 static void OnRadioRxError( void );
mluis 0:91d1a7783bb9 573
mluis 0:91d1a7783bb9 574 /*!
mluis 2:14a5d6ad92d5 575 * \brief Function executed on Radio Rx Timeout event
mluis 0:91d1a7783bb9 576 */
mluis 0:91d1a7783bb9 577 static void OnRadioRxTimeout( void );
mluis 0:91d1a7783bb9 578
mluis 0:91d1a7783bb9 579 /*!
mluis 2:14a5d6ad92d5 580 * \brief Function executed on Resend Frame timer event.
mluis 0:91d1a7783bb9 581 */
mluis 0:91d1a7783bb9 582 static void OnMacStateCheckTimerEvent( void );
mluis 0:91d1a7783bb9 583
mluis 0:91d1a7783bb9 584 /*!
mluis 2:14a5d6ad92d5 585 * \brief Function executed on duty cycle delayed Tx timer event
mluis 0:91d1a7783bb9 586 */
mluis 0:91d1a7783bb9 587 static void OnTxDelayedTimerEvent( void );
mluis 0:91d1a7783bb9 588
mluis 0:91d1a7783bb9 589 /*!
mluis 2:14a5d6ad92d5 590 * \brief Function executed on first Rx window timer event
mluis 0:91d1a7783bb9 591 */
mluis 0:91d1a7783bb9 592 static void OnRxWindow1TimerEvent( void );
mluis 0:91d1a7783bb9 593
mluis 0:91d1a7783bb9 594 /*!
mluis 2:14a5d6ad92d5 595 * \brief Function executed on second Rx window timer event
mluis 0:91d1a7783bb9 596 */
mluis 0:91d1a7783bb9 597 static void OnRxWindow2TimerEvent( void );
mluis 0:91d1a7783bb9 598
mluis 0:91d1a7783bb9 599 /*!
mluis 2:14a5d6ad92d5 600 * \brief Function executed on AckTimeout timer event
mluis 0:91d1a7783bb9 601 */
mluis 0:91d1a7783bb9 602 static void OnAckTimeoutTimerEvent( void );
mluis 0:91d1a7783bb9 603
mluis 0:91d1a7783bb9 604 /*!
mluis 2:14a5d6ad92d5 605 * \brief Searches and set the next random available channel
mluis 2:14a5d6ad92d5 606 *
mluis 3:b9d87593a8ae 607 * \param [OUT] Time to wait for the next transmission according to the duty
mluis 3:b9d87593a8ae 608 * cycle.
mluis 3:b9d87593a8ae 609 *
mluis 3:b9d87593a8ae 610 * \retval status Function status [1: OK, 0: Unable to find a channel on the
mluis 3:b9d87593a8ae 611 * current datarate]
mluis 2:14a5d6ad92d5 612 */
mluis 3:b9d87593a8ae 613 static bool SetNextChannel( TimerTime_t* time );
mluis 2:14a5d6ad92d5 614
mluis 2:14a5d6ad92d5 615 /*!
mluis 2:14a5d6ad92d5 616 * \brief Sets the network to public or private. Updates the sync byte.
mluis 2:14a5d6ad92d5 617 *
mluis 2:14a5d6ad92d5 618 * \param [IN] enable if true, it enables a public network
mluis 2:14a5d6ad92d5 619 */
mluis 2:14a5d6ad92d5 620 static void SetPublicNetwork( bool enable );
mluis 2:14a5d6ad92d5 621
mluis 2:14a5d6ad92d5 622 /*!
mluis 2:14a5d6ad92d5 623 * \brief Initializes and opens the reception window
mluis 2:14a5d6ad92d5 624 *
mluis 2:14a5d6ad92d5 625 * \param [IN] freq window channel frequency
mluis 2:14a5d6ad92d5 626 * \param [IN] datarate window channel datarate
mluis 2:14a5d6ad92d5 627 * \param [IN] bandwidth window channel bandwidth
mluis 2:14a5d6ad92d5 628 * \param [IN] timeout window channel timeout
mluis 0:91d1a7783bb9 629 */
mluis 2:14a5d6ad92d5 630 static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
mluis 2:14a5d6ad92d5 631
mluis 2:14a5d6ad92d5 632 /*!
mluis 7:c16969e0f70f 633 * \brief Verifies if the RX window 2 frequency is in range
mluis 7:c16969e0f70f 634 *
mluis 7:c16969e0f70f 635 * \param [IN] freq window channel frequency
mluis 7:c16969e0f70f 636 *
mluis 7:c16969e0f70f 637 * \retval status Function status [1: OK, 0: Frequency not applicable]
mluis 7:c16969e0f70f 638 */
mluis 7:c16969e0f70f 639 static bool Rx2FreqInRange( uint32_t freq );
mluis 7:c16969e0f70f 640
mluis 7:c16969e0f70f 641 /*!
mluis 2:14a5d6ad92d5 642 * \brief Adds a new MAC command to be sent.
mluis 2:14a5d6ad92d5 643 *
mluis 2:14a5d6ad92d5 644 * \Remark MAC layer internal function
mluis 2:14a5d6ad92d5 645 *
mluis 2:14a5d6ad92d5 646 * \param [in] cmd MAC command to be added
mluis 2:14a5d6ad92d5 647 * [MOTE_MAC_LINK_CHECK_REQ,
mluis 2:14a5d6ad92d5 648 * MOTE_MAC_LINK_ADR_ANS,
mluis 2:14a5d6ad92d5 649 * MOTE_MAC_DUTY_CYCLE_ANS,
mluis 2:14a5d6ad92d5 650 * MOTE_MAC_RX2_PARAM_SET_ANS,
mluis 2:14a5d6ad92d5 651 * MOTE_MAC_DEV_STATUS_ANS
mluis 2:14a5d6ad92d5 652 * MOTE_MAC_NEW_CHANNEL_ANS]
mluis 2:14a5d6ad92d5 653 * \param [in] p1 1st parameter ( optional depends on the command )
mluis 2:14a5d6ad92d5 654 * \param [in] p2 2nd parameter ( optional depends on the command )
mluis 2:14a5d6ad92d5 655 *
mluis 2:14a5d6ad92d5 656 * \retval status Function status [0: OK, 1: Unknown command, 2: Buffer full]
mluis 2:14a5d6ad92d5 657 */
mluis 2:14a5d6ad92d5 658 static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 );
mluis 0:91d1a7783bb9 659
mluis 0:91d1a7783bb9 660 /*!
mluis 7:c16969e0f70f 661 * \brief Parses the MAC commands which must be repeated.
mluis 7:c16969e0f70f 662 *
mluis 7:c16969e0f70f 663 * \Remark MAC layer internal function
mluis 7:c16969e0f70f 664 *
mluis 7:c16969e0f70f 665 * \param [IN] cmdBufIn Buffer which stores the MAC commands to send
mluis 7:c16969e0f70f 666 * \param [IN] length Length of the input buffer to parse
mluis 7:c16969e0f70f 667 * \param [OUT] cmdBufOut Buffer which stores the MAC commands which must be
mluis 7:c16969e0f70f 668 * repeated.
mluis 7:c16969e0f70f 669 *
mluis 7:c16969e0f70f 670 * \retval Size of the MAC commands to repeat.
mluis 7:c16969e0f70f 671 */
mluis 7:c16969e0f70f 672 static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut );
mluis 7:c16969e0f70f 673
mluis 7:c16969e0f70f 674 /*!
mluis 0:91d1a7783bb9 675 * \brief Validates if the payload fits into the frame, taking the datarate
mluis 0:91d1a7783bb9 676 * into account.
mluis 0:91d1a7783bb9 677 *
mluis 0:91d1a7783bb9 678 * \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
mluis 0:91d1a7783bb9 679 *
mluis 0:91d1a7783bb9 680 * \param lenN Length of the application payload. The length depends on the
mluis 0:91d1a7783bb9 681 * datarate and is region specific
mluis 0:91d1a7783bb9 682 *
mluis 0:91d1a7783bb9 683 * \param datarate Current datarate
mluis 0:91d1a7783bb9 684 *
mluis 2:14a5d6ad92d5 685 * \param fOptsLen Length of the fOpts field
mluis 2:14a5d6ad92d5 686 *
mluis 0:91d1a7783bb9 687 * \retval [false: payload does not fit into the frame, true: payload fits into
mluis 0:91d1a7783bb9 688 * the frame]
mluis 0:91d1a7783bb9 689 */
mluis 2:14a5d6ad92d5 690 static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );
mluis 0:91d1a7783bb9 691
mluis 4:37c12dbc8dc7 692 /*!
mluis 4:37c12dbc8dc7 693 * \brief Counts the number of bits in a mask.
mluis 4:37c12dbc8dc7 694 *
mluis 4:37c12dbc8dc7 695 * \param [IN] mask A mask from which the function counts the active bits.
mluis 4:37c12dbc8dc7 696 * \param [IN] nbBits The number of bits to check.
mluis 4:37c12dbc8dc7 697 *
mluis 4:37c12dbc8dc7 698 * \retval Number of enabled bits in the mask.
mluis 4:37c12dbc8dc7 699 */
mluis 4:37c12dbc8dc7 700 static uint8_t CountBits( uint16_t mask, uint8_t nbBits );
mluis 4:37c12dbc8dc7 701
mluis 0:91d1a7783bb9 702 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 703 /*!
mluis 0:91d1a7783bb9 704 * \brief Counts the number of enabled 125 kHz channels in the channel mask.
mluis 0:91d1a7783bb9 705 * This function can only be applied to US915 band.
mluis 0:91d1a7783bb9 706 *
mluis 4:37c12dbc8dc7 707 * \param [IN] channelsMask Pointer to the first element of the channel mask
mluis 0:91d1a7783bb9 708 *
mluis 0:91d1a7783bb9 709 * \retval Number of enabled channels in the channel mask
mluis 0:91d1a7783bb9 710 */
mluis 0:91d1a7783bb9 711 static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask );
mluis 4:37c12dbc8dc7 712
mluis 4:37c12dbc8dc7 713 #if defined( USE_BAND_915_HYBRID )
mluis 4:37c12dbc8dc7 714 /*!
mluis 4:37c12dbc8dc7 715 * \brief Validates the correctness of the channel mask for US915, hybrid mode.
mluis 4:37c12dbc8dc7 716 *
mluis 4:37c12dbc8dc7 717 * \param [IN] mask Block definition to set.
mluis 4:37c12dbc8dc7 718 * \param [OUT] channelsMask Pointer to the first element of the channel mask
mluis 4:37c12dbc8dc7 719 */
mluis 4:37c12dbc8dc7 720 static void ReenableChannels( uint16_t mask, uint16_t* channelMask );
mluis 4:37c12dbc8dc7 721
mluis 4:37c12dbc8dc7 722 /*!
mluis 4:37c12dbc8dc7 723 * \brief Validates the correctness of the channel mask for US915, hybrid mode.
mluis 4:37c12dbc8dc7 724 *
mluis 4:37c12dbc8dc7 725 * \param [IN] channelsMask Pointer to the first element of the channel mask
mluis 4:37c12dbc8dc7 726 *
mluis 4:37c12dbc8dc7 727 * \retval [true: channel mask correct, false: channel mask not correct]
mluis 4:37c12dbc8dc7 728 */
mluis 4:37c12dbc8dc7 729 static bool ValidateChannelMask( uint16_t* channelMask );
mluis 4:37c12dbc8dc7 730 #endif
mluis 4:37c12dbc8dc7 731
mluis 0:91d1a7783bb9 732 #endif
mluis 0:91d1a7783bb9 733
mluis 0:91d1a7783bb9 734 /*!
mluis 0:91d1a7783bb9 735 * \brief Limits the Tx power according to the number of enabled channels
mluis 0:91d1a7783bb9 736 *
mluis 0:91d1a7783bb9 737 * \retval Returns the maximum valid tx power
mluis 0:91d1a7783bb9 738 */
mluis 0:91d1a7783bb9 739 static int8_t LimitTxPower( int8_t txPower );
mluis 0:91d1a7783bb9 740
mluis 0:91d1a7783bb9 741 /*!
mluis 2:14a5d6ad92d5 742 * \brief Verifies, if a value is in a given range.
mluis 2:14a5d6ad92d5 743 *
mluis 2:14a5d6ad92d5 744 * \param value Value to verify, if it is in range
mluis 2:14a5d6ad92d5 745 *
mluis 2:14a5d6ad92d5 746 * \param min Minimum possible value
mluis 2:14a5d6ad92d5 747 *
mluis 2:14a5d6ad92d5 748 * \param max Maximum possible value
mluis 2:14a5d6ad92d5 749 *
mluis 2:14a5d6ad92d5 750 * \retval Returns the maximum valid tx power
mluis 2:14a5d6ad92d5 751 */
mluis 2:14a5d6ad92d5 752 static bool ValueInRange( int8_t value, int8_t min, int8_t max );
mluis 2:14a5d6ad92d5 753
mluis 2:14a5d6ad92d5 754 /*!
mluis 2:14a5d6ad92d5 755 * \brief Calculates the next datarate to set, when ADR is on or off
mluis 2:14a5d6ad92d5 756 *
mluis 2:14a5d6ad92d5 757 * \param [IN] adrEnabled Specify whether ADR is on or off
mluis 2:14a5d6ad92d5 758 *
mluis 2:14a5d6ad92d5 759 * \param [IN] updateChannelMask Set to true, if the channel masks shall be updated
mluis 2:14a5d6ad92d5 760 *
mluis 2:14a5d6ad92d5 761 * \param [OUT] datarateOut Reports the datarate which will be used next
mluis 2:14a5d6ad92d5 762 *
mluis 2:14a5d6ad92d5 763 * \retval Returns the state of ADR ack request
mluis 2:14a5d6ad92d5 764 */
mluis 2:14a5d6ad92d5 765 static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut );
mluis 2:14a5d6ad92d5 766
mluis 2:14a5d6ad92d5 767 /*!
mluis 2:14a5d6ad92d5 768 * \brief Disables channel in a specified channel mask
mluis 2:14a5d6ad92d5 769 *
mluis 2:14a5d6ad92d5 770 * \param [IN] id - Id of the channel
mluis 2:14a5d6ad92d5 771 *
mluis 2:14a5d6ad92d5 772 * \param [IN] mask - Pointer to the channel mask to edit
mluis 0:91d1a7783bb9 773 *
mluis 2:14a5d6ad92d5 774 * \retval [true, if disable was successful, false if not]
mluis 2:14a5d6ad92d5 775 */
mluis 2:14a5d6ad92d5 776 static bool DisableChannelInMask( uint8_t id, uint16_t* mask );
mluis 2:14a5d6ad92d5 777
mluis 2:14a5d6ad92d5 778 /*!
mluis 2:14a5d6ad92d5 779 * \brief Decodes MAC commands in the fOpts field and in the payload
mluis 2:14a5d6ad92d5 780 */
mluis 2:14a5d6ad92d5 781 static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr );
mluis 2:14a5d6ad92d5 782
mluis 2:14a5d6ad92d5 783 /*!
mluis 2:14a5d6ad92d5 784 * \brief LoRaMAC layer generic send frame
mluis 2:14a5d6ad92d5 785 *
mluis 2:14a5d6ad92d5 786 * \param [IN] macHdr MAC header field
mluis 2:14a5d6ad92d5 787 * \param [IN] fPort MAC payload port
mluis 2:14a5d6ad92d5 788 * \param [IN] fBuffer MAC data buffer to be sent
mluis 2:14a5d6ad92d5 789 * \param [IN] fBufferSize MAC data buffer size
mluis 2:14a5d6ad92d5 790 * \retval status Status of the operation.
mluis 2:14a5d6ad92d5 791 */
mluis 2:14a5d6ad92d5 792 LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
mluis 2:14a5d6ad92d5 793
mluis 2:14a5d6ad92d5 794 /*!
mluis 2:14a5d6ad92d5 795 * \brief LoRaMAC layer frame buffer initialization
mluis 2:14a5d6ad92d5 796 *
mluis 2:14a5d6ad92d5 797 * \param [IN] macHdr MAC header field
mluis 2:14a5d6ad92d5 798 * \param [IN] fCtrl MAC frame control field
mluis 2:14a5d6ad92d5 799 * \param [IN] fOpts MAC commands buffer
mluis 2:14a5d6ad92d5 800 * \param [IN] fPort MAC payload port
mluis 2:14a5d6ad92d5 801 * \param [IN] fBuffer MAC data buffer to be sent
mluis 2:14a5d6ad92d5 802 * \param [IN] fBufferSize MAC data buffer size
mluis 2:14a5d6ad92d5 803 * \retval status Status of the operation.
mluis 2:14a5d6ad92d5 804 */
mluis 2:14a5d6ad92d5 805 LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
mluis 2:14a5d6ad92d5 806
mluis 2:14a5d6ad92d5 807 /*
mluis 2:14a5d6ad92d5 808 * \brief Schedules the frame according to the duty cycle
mluis 2:14a5d6ad92d5 809 *
mluis 2:14a5d6ad92d5 810 * \retval Status of the operation
mluis 2:14a5d6ad92d5 811 */
mluis 2:14a5d6ad92d5 812 static LoRaMacStatus_t ScheduleTx( void );
mluis 2:14a5d6ad92d5 813
mluis 4:37c12dbc8dc7 814 /*
mluis 7:c16969e0f70f 815 * \brief Sets the duty cycle for retransmissions
mluis 7:c16969e0f70f 816 *
mluis 7:c16969e0f70f 817 * \retval Duty cycle
mluis 7:c16969e0f70f 818 */
mluis 7:c16969e0f70f 819 static uint16_t RetransmissionDutyCylce( void );
mluis 7:c16969e0f70f 820
mluis 7:c16969e0f70f 821 /*
mluis 4:37c12dbc8dc7 822 * \brief Calculates the back-off time for the band of a channel.
mluis 4:37c12dbc8dc7 823 *
mluis 4:37c12dbc8dc7 824 * \param [IN] channel The last Tx channel index
mluis 4:37c12dbc8dc7 825 */
mluis 4:37c12dbc8dc7 826 static void CalculateBackOff( uint8_t channel );
mluis 4:37c12dbc8dc7 827
mluis 7:c16969e0f70f 828 /*
mluis 7:c16969e0f70f 829 * \brief Alternates the datarate of the channel for the join request.
mluis 7:c16969e0f70f 830 *
mluis 7:c16969e0f70f 831 * \param [IN] nbTrials Number of performed join requests.
mluis 7:c16969e0f70f 832 * \retval Datarate to apply
mluis 7:c16969e0f70f 833 */
mluis 7:c16969e0f70f 834 static int8_t AlternateDatarate( uint16_t nbTrials );
mluis 7:c16969e0f70f 835
mluis 2:14a5d6ad92d5 836 /*!
mluis 2:14a5d6ad92d5 837 * \brief LoRaMAC layer prepared frame buffer transmission with channel specification
mluis 2:14a5d6ad92d5 838 *
mluis 2:14a5d6ad92d5 839 * \remark PrepareFrame must be called at least once before calling this
mluis 2:14a5d6ad92d5 840 * function.
mluis 2:14a5d6ad92d5 841 *
mluis 2:14a5d6ad92d5 842 * \param [IN] channel Channel parameters
mluis 2:14a5d6ad92d5 843 * \retval status Status of the operation.
mluis 0:91d1a7783bb9 844 */
mluis 2:14a5d6ad92d5 845 LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel );
mluis 2:14a5d6ad92d5 846
mluis 7:c16969e0f70f 847 /*!
mluis 7:c16969e0f70f 848 * \brief Resets MAC specific parameters to default
mluis 7:c16969e0f70f 849 */
mluis 7:c16969e0f70f 850 static void ResetMacParameters( void );
mluis 2:14a5d6ad92d5 851
mluis 2:14a5d6ad92d5 852 static void OnRadioTxDone( void )
mluis 2:14a5d6ad92d5 853 {
mluis 2:14a5d6ad92d5 854 TimerTime_t curTime = TimerGetCurrentTime( );
mluis 2:14a5d6ad92d5 855 if( LoRaMacDeviceClass != CLASS_C )
mluis 2:14a5d6ad92d5 856 {
mluis 2:14a5d6ad92d5 857 Radio.Sleep( );
mluis 2:14a5d6ad92d5 858 }
mluis 2:14a5d6ad92d5 859 else
mluis 2:14a5d6ad92d5 860 {
mluis 2:14a5d6ad92d5 861 OnRxWindow2TimerEvent( );
mluis 2:14a5d6ad92d5 862 }
mluis 2:14a5d6ad92d5 863
mluis 4:37c12dbc8dc7 864 // Store last Tx channel
mluis 4:37c12dbc8dc7 865 LastTxChannel = Channel;
mluis 4:37c12dbc8dc7 866 // Update last tx done time for the current channel
mluis 4:37c12dbc8dc7 867 Bands[Channels[LastTxChannel].Band].LastTxDoneTime = curTime;
mluis 4:37c12dbc8dc7 868 // Update Aggregated last tx done time
mluis 2:14a5d6ad92d5 869 AggregatedLastTxDoneTime = curTime;
mluis 2:14a5d6ad92d5 870
mluis 2:14a5d6ad92d5 871 if( IsRxWindowsEnabled == true )
mluis 2:14a5d6ad92d5 872 {
mluis 2:14a5d6ad92d5 873 TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
mluis 2:14a5d6ad92d5 874 TimerStart( &RxWindowTimer1 );
mluis 2:14a5d6ad92d5 875 if( LoRaMacDeviceClass != CLASS_C )
mluis 2:14a5d6ad92d5 876 {
mluis 2:14a5d6ad92d5 877 TimerSetValue( &RxWindowTimer2, RxWindow2Delay );
mluis 2:14a5d6ad92d5 878 TimerStart( &RxWindowTimer2 );
mluis 2:14a5d6ad92d5 879 }
mluis 2:14a5d6ad92d5 880 if( ( LoRaMacDeviceClass == CLASS_C ) || ( NodeAckRequested == true ) )
mluis 2:14a5d6ad92d5 881 {
mluis 2:14a5d6ad92d5 882 TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + ACK_TIMEOUT +
mluis 2:14a5d6ad92d5 883 randr( -ACK_TIMEOUT_RND, ACK_TIMEOUT_RND ) );
mluis 2:14a5d6ad92d5 884 TimerStart( &AckTimeoutTimer );
mluis 2:14a5d6ad92d5 885 }
mluis 2:14a5d6ad92d5 886 }
mluis 2:14a5d6ad92d5 887 else
mluis 2:14a5d6ad92d5 888 {
mluis 2:14a5d6ad92d5 889 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 2:14a5d6ad92d5 890 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
mluis 2:14a5d6ad92d5 891
mluis 2:14a5d6ad92d5 892 if( LoRaMacFlags.Value == 0 )
mluis 2:14a5d6ad92d5 893 {
mluis 2:14a5d6ad92d5 894 LoRaMacFlags.Bits.McpsReq = 1;
mluis 2:14a5d6ad92d5 895 }
mluis 2:14a5d6ad92d5 896 LoRaMacFlags.Bits.MacDone = 1;
mluis 2:14a5d6ad92d5 897 }
mluis 2:14a5d6ad92d5 898
mluis 2:14a5d6ad92d5 899 if( NodeAckRequested == false )
mluis 2:14a5d6ad92d5 900 {
mluis 2:14a5d6ad92d5 901 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 2:14a5d6ad92d5 902 ChannelsNbRepCounter++;
mluis 2:14a5d6ad92d5 903 }
mluis 2:14a5d6ad92d5 904 }
mluis 2:14a5d6ad92d5 905
mluis 3:b9d87593a8ae 906 static void PrepareRxDoneAbort( void )
mluis 3:b9d87593a8ae 907 {
mluis 4:37c12dbc8dc7 908 LoRaMacState |= MAC_RX_ABORT;
mluis 3:b9d87593a8ae 909
mluis 3:b9d87593a8ae 910 if( NodeAckRequested )
mluis 3:b9d87593a8ae 911 {
mluis 3:b9d87593a8ae 912 OnAckTimeoutTimerEvent( );
mluis 3:b9d87593a8ae 913 }
mluis 3:b9d87593a8ae 914
mluis 3:b9d87593a8ae 915 if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
mluis 3:b9d87593a8ae 916 {
mluis 3:b9d87593a8ae 917 OnRxWindow2TimerEvent( );
mluis 3:b9d87593a8ae 918 }
mluis 3:b9d87593a8ae 919
mluis 3:b9d87593a8ae 920 LoRaMacFlags.Bits.McpsInd = 1;
mluis 3:b9d87593a8ae 921 LoRaMacFlags.Bits.MacDone = 1;
mluis 3:b9d87593a8ae 922
mluis 3:b9d87593a8ae 923 // Trig OnMacCheckTimerEvent call as soon as possible
mluis 3:b9d87593a8ae 924 TimerSetValue( &MacStateCheckTimer, 1000 );
mluis 3:b9d87593a8ae 925 TimerStart( &MacStateCheckTimer );
mluis 3:b9d87593a8ae 926 }
mluis 3:b9d87593a8ae 927
mluis 2:14a5d6ad92d5 928 static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
mluis 0:91d1a7783bb9 929 {
mluis 2:14a5d6ad92d5 930 LoRaMacHeader_t macHdr;
mluis 2:14a5d6ad92d5 931 LoRaMacFrameCtrl_t fCtrl;
mluis 4:37c12dbc8dc7 932 bool skipIndication = false;
mluis 2:14a5d6ad92d5 933
mluis 2:14a5d6ad92d5 934 uint8_t pktHeaderLen = 0;
mluis 2:14a5d6ad92d5 935 uint32_t address = 0;
mluis 2:14a5d6ad92d5 936 uint8_t appPayloadStartIndex = 0;
mluis 2:14a5d6ad92d5 937 uint8_t port = 0xFF;
mluis 2:14a5d6ad92d5 938 uint8_t frameLen = 0;
mluis 2:14a5d6ad92d5 939 uint32_t mic = 0;
mluis 2:14a5d6ad92d5 940 uint32_t micRx = 0;
mluis 2:14a5d6ad92d5 941
mluis 2:14a5d6ad92d5 942 uint16_t sequenceCounter = 0;
mluis 2:14a5d6ad92d5 943 uint16_t sequenceCounterPrev = 0;
mluis 2:14a5d6ad92d5 944 uint16_t sequenceCounterDiff = 0;
mluis 2:14a5d6ad92d5 945 uint32_t downLinkCounter = 0;
mluis 2:14a5d6ad92d5 946
mluis 2:14a5d6ad92d5 947 MulticastParams_t *curMulticastParams = NULL;
mluis 2:14a5d6ad92d5 948 uint8_t *nwkSKey = LoRaMacNwkSKey;
mluis 2:14a5d6ad92d5 949 uint8_t *appSKey = LoRaMacAppSKey;
mluis 2:14a5d6ad92d5 950
mluis 2:14a5d6ad92d5 951 uint8_t multicast = 0;
mluis 2:14a5d6ad92d5 952
mluis 2:14a5d6ad92d5 953 bool isMicOk = false;
mluis 2:14a5d6ad92d5 954
mluis 2:14a5d6ad92d5 955 McpsConfirm.AckReceived = false;
mluis 2:14a5d6ad92d5 956 McpsIndication.Rssi = rssi;
mluis 2:14a5d6ad92d5 957 McpsIndication.Snr = snr;
mluis 2:14a5d6ad92d5 958 McpsIndication.RxSlot = RxSlot;
mluis 2:14a5d6ad92d5 959 McpsIndication.Port = 0;
mluis 2:14a5d6ad92d5 960 McpsIndication.Multicast = 0;
mluis 2:14a5d6ad92d5 961 McpsIndication.FramePending = 0;
mluis 2:14a5d6ad92d5 962 McpsIndication.Buffer = NULL;
mluis 2:14a5d6ad92d5 963 McpsIndication.BufferSize = 0;
mluis 2:14a5d6ad92d5 964 McpsIndication.RxData = false;
mluis 2:14a5d6ad92d5 965 McpsIndication.AckReceived = false;
mluis 2:14a5d6ad92d5 966 McpsIndication.DownLinkCounter = 0;
mluis 2:14a5d6ad92d5 967 McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
mluis 2:14a5d6ad92d5 968
mluis 2:14a5d6ad92d5 969 if( LoRaMacDeviceClass != CLASS_C )
mluis 2:14a5d6ad92d5 970 {
mluis 2:14a5d6ad92d5 971 Radio.Sleep( );
mluis 2:14a5d6ad92d5 972 }
mluis 2:14a5d6ad92d5 973 TimerStop( &RxWindowTimer2 );
mluis 2:14a5d6ad92d5 974
mluis 2:14a5d6ad92d5 975 macHdr.Value = payload[pktHeaderLen++];
mluis 2:14a5d6ad92d5 976
mluis 2:14a5d6ad92d5 977 switch( macHdr.Bits.MType )
mluis 2:14a5d6ad92d5 978 {
mluis 2:14a5d6ad92d5 979 case FRAME_TYPE_JOIN_ACCEPT:
mluis 2:14a5d6ad92d5 980 if( IsLoRaMacNetworkJoined == true )
mluis 2:14a5d6ad92d5 981 {
mluis 2:14a5d6ad92d5 982 break;
mluis 2:14a5d6ad92d5 983 }
mluis 2:14a5d6ad92d5 984 LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
mluis 2:14a5d6ad92d5 985
mluis 2:14a5d6ad92d5 986 LoRaMacRxPayload[0] = macHdr.Value;
mluis 2:14a5d6ad92d5 987
mluis 2:14a5d6ad92d5 988 LoRaMacJoinComputeMic( LoRaMacRxPayload, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic );
mluis 2:14a5d6ad92d5 989
mluis 2:14a5d6ad92d5 990 micRx |= ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN];
mluis 2:14a5d6ad92d5 991 micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 1] << 8 );
mluis 2:14a5d6ad92d5 992 micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16 );
mluis 2:14a5d6ad92d5 993 micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24 );
mluis 2:14a5d6ad92d5 994
mluis 2:14a5d6ad92d5 995 if( micRx == mic )
mluis 2:14a5d6ad92d5 996 {
mluis 2:14a5d6ad92d5 997 LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
mluis 2:14a5d6ad92d5 998
mluis 2:14a5d6ad92d5 999 LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
mluis 2:14a5d6ad92d5 1000 LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
mluis 2:14a5d6ad92d5 1001 LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );
mluis 2:14a5d6ad92d5 1002
mluis 2:14a5d6ad92d5 1003 LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
mluis 2:14a5d6ad92d5 1004 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
mluis 2:14a5d6ad92d5 1005 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
mluis 2:14a5d6ad92d5 1006 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
mluis 2:14a5d6ad92d5 1007
mluis 2:14a5d6ad92d5 1008 // DLSettings
mluis 7:c16969e0f70f 1009 LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
mluis 7:c16969e0f70f 1010 LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
mluis 2:14a5d6ad92d5 1011 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 1012 /*
mluis 2:14a5d6ad92d5 1013 * WARNING: To be removed once Semtech server implementation
mluis 2:14a5d6ad92d5 1014 * is corrected.
mluis 2:14a5d6ad92d5 1015 */
mluis 7:c16969e0f70f 1016 if( LoRaMacParams.Rx2Channel.Datarate == DR_3 )
mluis 2:14a5d6ad92d5 1017 {
mluis 7:c16969e0f70f 1018 LoRaMacParams.Rx2Channel.Datarate = DR_8;
mluis 2:14a5d6ad92d5 1019 }
mluis 2:14a5d6ad92d5 1020 #endif
mluis 2:14a5d6ad92d5 1021 // RxDelay
mluis 7:c16969e0f70f 1022 LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
mluis 7:c16969e0f70f 1023 if( LoRaMacParams.ReceiveDelay1 == 0 )
mluis 2:14a5d6ad92d5 1024 {
mluis 7:c16969e0f70f 1025 LoRaMacParams.ReceiveDelay1 = 1;
mluis 2:14a5d6ad92d5 1026 }
mluis 7:c16969e0f70f 1027 LoRaMacParams.ReceiveDelay1 *= 1e6;
mluis 7:c16969e0f70f 1028 LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6;
mluis 2:14a5d6ad92d5 1029
mluis 2:14a5d6ad92d5 1030 #if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 2:14a5d6ad92d5 1031 //CFList
mluis 2:14a5d6ad92d5 1032 if( ( size - 1 ) > 16 )
mluis 2:14a5d6ad92d5 1033 {
mluis 2:14a5d6ad92d5 1034 ChannelParams_t param;
mluis 2:14a5d6ad92d5 1035 param.DrRange.Value = ( DR_5 << 4 ) | DR_0;
mluis 2:14a5d6ad92d5 1036
mluis 3:b9d87593a8ae 1037 LoRaMacState |= MAC_TX_CONFIG;
mluis 2:14a5d6ad92d5 1038 for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 )
mluis 2:14a5d6ad92d5 1039 {
mluis 2:14a5d6ad92d5 1040 param.Frequency = ( ( uint32_t )LoRaMacRxPayload[13 + j] | ( ( uint32_t )LoRaMacRxPayload[14 + j] << 8 ) | ( ( uint32_t )LoRaMacRxPayload[15 + j] << 16 ) ) * 100;
mluis 2:14a5d6ad92d5 1041 LoRaMacChannelAdd( i, param );
mluis 2:14a5d6ad92d5 1042 }
mluis 3:b9d87593a8ae 1043 LoRaMacState &= ~MAC_TX_CONFIG;
mluis 2:14a5d6ad92d5 1044 }
mluis 2:14a5d6ad92d5 1045 #endif
mluis 2:14a5d6ad92d5 1046 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 2:14a5d6ad92d5 1047 IsLoRaMacNetworkJoined = true;
mluis 7:c16969e0f70f 1048 LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
mluis 2:14a5d6ad92d5 1049 }
mluis 2:14a5d6ad92d5 1050 else
mluis 2:14a5d6ad92d5 1051 {
mluis 2:14a5d6ad92d5 1052 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
mluis 2:14a5d6ad92d5 1053 }
mluis 2:14a5d6ad92d5 1054 break;
mluis 2:14a5d6ad92d5 1055 case FRAME_TYPE_DATA_CONFIRMED_DOWN:
mluis 2:14a5d6ad92d5 1056 case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
mluis 2:14a5d6ad92d5 1057 {
mluis 2:14a5d6ad92d5 1058 address = payload[pktHeaderLen++];
mluis 2:14a5d6ad92d5 1059 address |= ( (uint32_t)payload[pktHeaderLen++] << 8 );
mluis 2:14a5d6ad92d5 1060 address |= ( (uint32_t)payload[pktHeaderLen++] << 16 );
mluis 2:14a5d6ad92d5 1061 address |= ( (uint32_t)payload[pktHeaderLen++] << 24 );
mluis 2:14a5d6ad92d5 1062
mluis 2:14a5d6ad92d5 1063 if( address != LoRaMacDevAddr )
mluis 2:14a5d6ad92d5 1064 {
mluis 2:14a5d6ad92d5 1065 curMulticastParams = MulticastChannels;
mluis 2:14a5d6ad92d5 1066 while( curMulticastParams != NULL )
mluis 2:14a5d6ad92d5 1067 {
mluis 2:14a5d6ad92d5 1068 if( address == curMulticastParams->Address )
mluis 2:14a5d6ad92d5 1069 {
mluis 2:14a5d6ad92d5 1070 multicast = 1;
mluis 2:14a5d6ad92d5 1071 nwkSKey = curMulticastParams->NwkSKey;
mluis 2:14a5d6ad92d5 1072 appSKey = curMulticastParams->AppSKey;
mluis 2:14a5d6ad92d5 1073 downLinkCounter = curMulticastParams->DownLinkCounter;
mluis 2:14a5d6ad92d5 1074 break;
mluis 2:14a5d6ad92d5 1075 }
mluis 2:14a5d6ad92d5 1076 curMulticastParams = curMulticastParams->Next;
mluis 2:14a5d6ad92d5 1077 }
mluis 2:14a5d6ad92d5 1078 if( multicast == 0 )
mluis 2:14a5d6ad92d5 1079 {
mluis 2:14a5d6ad92d5 1080 // We are not the destination of this frame.
mluis 2:14a5d6ad92d5 1081 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
mluis 3:b9d87593a8ae 1082 PrepareRxDoneAbort( );
mluis 2:14a5d6ad92d5 1083 return;
mluis 2:14a5d6ad92d5 1084 }
mluis 2:14a5d6ad92d5 1085 }
mluis 2:14a5d6ad92d5 1086 else
mluis 2:14a5d6ad92d5 1087 {
mluis 2:14a5d6ad92d5 1088 multicast = 0;
mluis 2:14a5d6ad92d5 1089 nwkSKey = LoRaMacNwkSKey;
mluis 2:14a5d6ad92d5 1090 appSKey = LoRaMacAppSKey;
mluis 2:14a5d6ad92d5 1091 downLinkCounter = DownLinkCounter;
mluis 2:14a5d6ad92d5 1092 }
mluis 2:14a5d6ad92d5 1093
mluis 2:14a5d6ad92d5 1094 fCtrl.Value = payload[pktHeaderLen++];
mluis 2:14a5d6ad92d5 1095
mluis 2:14a5d6ad92d5 1096 sequenceCounter = ( uint16_t )payload[pktHeaderLen++];
mluis 2:14a5d6ad92d5 1097 sequenceCounter |= ( uint16_t )payload[pktHeaderLen++] << 8;
mluis 2:14a5d6ad92d5 1098
mluis 2:14a5d6ad92d5 1099 appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen;
mluis 2:14a5d6ad92d5 1100
mluis 2:14a5d6ad92d5 1101 micRx |= ( uint32_t )payload[size - LORAMAC_MFR_LEN];
mluis 2:14a5d6ad92d5 1102 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 1] << 8 );
mluis 2:14a5d6ad92d5 1103 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 2] << 16 );
mluis 2:14a5d6ad92d5 1104 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 3] << 24 );
mluis 2:14a5d6ad92d5 1105
mluis 2:14a5d6ad92d5 1106 sequenceCounterPrev = ( uint16_t )downLinkCounter;
mluis 2:14a5d6ad92d5 1107 sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev );
mluis 2:14a5d6ad92d5 1108
mluis 2:14a5d6ad92d5 1109 if( sequenceCounterDiff < ( 1 << 15 ) )
mluis 2:14a5d6ad92d5 1110 {
mluis 2:14a5d6ad92d5 1111 downLinkCounter += sequenceCounterDiff;
mluis 2:14a5d6ad92d5 1112 LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
mluis 2:14a5d6ad92d5 1113 if( micRx == mic )
mluis 2:14a5d6ad92d5 1114 {
mluis 2:14a5d6ad92d5 1115 isMicOk = true;
mluis 2:14a5d6ad92d5 1116 }
mluis 2:14a5d6ad92d5 1117 }
mluis 2:14a5d6ad92d5 1118 else
mluis 2:14a5d6ad92d5 1119 {
mluis 2:14a5d6ad92d5 1120 // check for sequence roll-over
mluis 2:14a5d6ad92d5 1121 uint32_t downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff;
mluis 2:14a5d6ad92d5 1122 LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic );
mluis 2:14a5d6ad92d5 1123 if( micRx == mic )
mluis 2:14a5d6ad92d5 1124 {
mluis 2:14a5d6ad92d5 1125 isMicOk = true;
mluis 2:14a5d6ad92d5 1126 downLinkCounter = downLinkCounterTmp;
mluis 2:14a5d6ad92d5 1127 }
mluis 2:14a5d6ad92d5 1128 }
mluis 2:14a5d6ad92d5 1129
mluis 4:37c12dbc8dc7 1130 // Check for a the maximum allowed counter difference
mluis 4:37c12dbc8dc7 1131 if( sequenceCounterDiff >= MAX_FCNT_GAP )
mluis 4:37c12dbc8dc7 1132 {
mluis 4:37c12dbc8dc7 1133 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
mluis 4:37c12dbc8dc7 1134 McpsIndication.DownLinkCounter = downLinkCounter;
mluis 4:37c12dbc8dc7 1135 PrepareRxDoneAbort( );
mluis 4:37c12dbc8dc7 1136 return;
mluis 4:37c12dbc8dc7 1137 }
mluis 4:37c12dbc8dc7 1138
mluis 2:14a5d6ad92d5 1139 if( isMicOk == true )
mluis 2:14a5d6ad92d5 1140 {
mluis 2:14a5d6ad92d5 1141 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 2:14a5d6ad92d5 1142 McpsIndication.Multicast = multicast;
mluis 2:14a5d6ad92d5 1143 McpsIndication.FramePending = fCtrl.Bits.FPending;
mluis 2:14a5d6ad92d5 1144 McpsIndication.Buffer = NULL;
mluis 2:14a5d6ad92d5 1145 McpsIndication.BufferSize = 0;
mluis 2:14a5d6ad92d5 1146 McpsIndication.DownLinkCounter = downLinkCounter;
mluis 2:14a5d6ad92d5 1147
mluis 2:14a5d6ad92d5 1148 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 2:14a5d6ad92d5 1149
mluis 2:14a5d6ad92d5 1150 AdrAckCounter = 0;
mluis 7:c16969e0f70f 1151 MacCommandsBufferToRepeatIndex = 0;
mluis 2:14a5d6ad92d5 1152
mluis 2:14a5d6ad92d5 1153 // Update 32 bits downlink counter
mluis 2:14a5d6ad92d5 1154 if( multicast == 1 )
mluis 2:14a5d6ad92d5 1155 {
mluis 2:14a5d6ad92d5 1156 McpsIndication.McpsIndication = MCPS_MULTICAST;
mluis 2:14a5d6ad92d5 1157
mluis 2:14a5d6ad92d5 1158 if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) &&
mluis 2:14a5d6ad92d5 1159 ( curMulticastParams->DownLinkCounter != 0 ) )
mluis 2:14a5d6ad92d5 1160 {
mluis 2:14a5d6ad92d5 1161 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
mluis 2:14a5d6ad92d5 1162 McpsIndication.DownLinkCounter = downLinkCounter;
mluis 3:b9d87593a8ae 1163 PrepareRxDoneAbort( );
mluis 2:14a5d6ad92d5 1164 return;
mluis 2:14a5d6ad92d5 1165 }
mluis 2:14a5d6ad92d5 1166 curMulticastParams->DownLinkCounter = downLinkCounter;
mluis 2:14a5d6ad92d5 1167 }
mluis 2:14a5d6ad92d5 1168 else
mluis 2:14a5d6ad92d5 1169 {
mluis 2:14a5d6ad92d5 1170 if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN )
mluis 2:14a5d6ad92d5 1171 {
mluis 3:b9d87593a8ae 1172 SrvAckRequested = true;
mluis 2:14a5d6ad92d5 1173 McpsIndication.McpsIndication = MCPS_CONFIRMED;
mluis 4:37c12dbc8dc7 1174
mluis 4:37c12dbc8dc7 1175 if( ( DownLinkCounter == downLinkCounter ) &&
mluis 4:37c12dbc8dc7 1176 ( DownLinkCounter != 0 ) )
mluis 4:37c12dbc8dc7 1177 {
mluis 4:37c12dbc8dc7 1178 // Duplicated confirmed downlink. Skip indication.
mluis 4:37c12dbc8dc7 1179 skipIndication = true;
mluis 4:37c12dbc8dc7 1180 }
mluis 2:14a5d6ad92d5 1181 }
mluis 2:14a5d6ad92d5 1182 else
mluis 2:14a5d6ad92d5 1183 {
mluis 3:b9d87593a8ae 1184 SrvAckRequested = false;
mluis 2:14a5d6ad92d5 1185 McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
mluis 4:37c12dbc8dc7 1186
mluis 4:37c12dbc8dc7 1187 if( ( DownLinkCounter == downLinkCounter ) &&
mluis 4:37c12dbc8dc7 1188 ( DownLinkCounter != 0 ) )
mluis 4:37c12dbc8dc7 1189 {
mluis 4:37c12dbc8dc7 1190 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
mluis 4:37c12dbc8dc7 1191 McpsIndication.DownLinkCounter = downLinkCounter;
mluis 4:37c12dbc8dc7 1192 PrepareRxDoneAbort( );
mluis 4:37c12dbc8dc7 1193 return;
mluis 4:37c12dbc8dc7 1194 }
mluis 2:14a5d6ad92d5 1195 }
mluis 2:14a5d6ad92d5 1196 DownLinkCounter = downLinkCounter;
mluis 2:14a5d6ad92d5 1197 }
mluis 2:14a5d6ad92d5 1198
mluis 2:14a5d6ad92d5 1199 // Check if the frame is an acknowledgement
mluis 2:14a5d6ad92d5 1200 if( fCtrl.Bits.Ack == 1 )
mluis 2:14a5d6ad92d5 1201 {
mluis 2:14a5d6ad92d5 1202 McpsConfirm.AckReceived = true;
mluis 2:14a5d6ad92d5 1203 McpsIndication.AckReceived = true;
mluis 2:14a5d6ad92d5 1204
mluis 2:14a5d6ad92d5 1205 // Stop the AckTimeout timer as no more retransmissions
mluis 2:14a5d6ad92d5 1206 // are needed.
mluis 2:14a5d6ad92d5 1207 TimerStop( &AckTimeoutTimer );
mluis 2:14a5d6ad92d5 1208 }
mluis 2:14a5d6ad92d5 1209 else
mluis 2:14a5d6ad92d5 1210 {
mluis 2:14a5d6ad92d5 1211 McpsConfirm.AckReceived = false;
mluis 2:14a5d6ad92d5 1212
mluis 2:14a5d6ad92d5 1213 if( AckTimeoutRetriesCounter > AckTimeoutRetries )
mluis 2:14a5d6ad92d5 1214 {
mluis 2:14a5d6ad92d5 1215 // Stop the AckTimeout timer as no more retransmissions
mluis 2:14a5d6ad92d5 1216 // are needed.
mluis 2:14a5d6ad92d5 1217 TimerStop( &AckTimeoutTimer );
mluis 2:14a5d6ad92d5 1218 }
mluis 2:14a5d6ad92d5 1219 }
mluis 2:14a5d6ad92d5 1220
mluis 2:14a5d6ad92d5 1221 if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
mluis 2:14a5d6ad92d5 1222 {
mluis 2:14a5d6ad92d5 1223 port = payload[appPayloadStartIndex++];
mluis 2:14a5d6ad92d5 1224 frameLen = ( size - 4 ) - appPayloadStartIndex;
mluis 2:14a5d6ad92d5 1225
mluis 2:14a5d6ad92d5 1226 McpsIndication.Port = port;
mluis 2:14a5d6ad92d5 1227
mluis 2:14a5d6ad92d5 1228 if( port == 0 )
mluis 2:14a5d6ad92d5 1229 {
mluis 7:c16969e0f70f 1230 if( fCtrl.Bits.FOptsLen == 0 )
mluis 7:c16969e0f70f 1231 {
mluis 7:c16969e0f70f 1232 LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
mluis 7:c16969e0f70f 1233 frameLen,
mluis 7:c16969e0f70f 1234 nwkSKey,
mluis 7:c16969e0f70f 1235 address,
mluis 7:c16969e0f70f 1236 DOWN_LINK,
mluis 7:c16969e0f70f 1237 downLinkCounter,
mluis 7:c16969e0f70f 1238 LoRaMacRxPayload );
mluis 7:c16969e0f70f 1239
mluis 7:c16969e0f70f 1240 // Decode frame payload MAC commands
mluis 7:c16969e0f70f 1241 ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
mluis 7:c16969e0f70f 1242 }
mluis 7:c16969e0f70f 1243 else
mluis 7:c16969e0f70f 1244 {
mluis 7:c16969e0f70f 1245 skipIndication = true;
mluis 7:c16969e0f70f 1246 }
mluis 2:14a5d6ad92d5 1247 }
mluis 2:14a5d6ad92d5 1248 else
mluis 2:14a5d6ad92d5 1249 {
mluis 7:c16969e0f70f 1250 if( fCtrl.Bits.FOptsLen > 0 )
mluis 7:c16969e0f70f 1251 {
mluis 7:c16969e0f70f 1252 // Decode Options field MAC commands. Omit the fPort.
mluis 7:c16969e0f70f 1253 ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr );
mluis 7:c16969e0f70f 1254 }
mluis 7:c16969e0f70f 1255
mluis 2:14a5d6ad92d5 1256 LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
mluis 2:14a5d6ad92d5 1257 frameLen,
mluis 2:14a5d6ad92d5 1258 appSKey,
mluis 2:14a5d6ad92d5 1259 address,
mluis 2:14a5d6ad92d5 1260 DOWN_LINK,
mluis 2:14a5d6ad92d5 1261 downLinkCounter,
mluis 2:14a5d6ad92d5 1262 LoRaMacRxPayload );
mluis 2:14a5d6ad92d5 1263
mluis 4:37c12dbc8dc7 1264 if( skipIndication == false )
mluis 4:37c12dbc8dc7 1265 {
mluis 4:37c12dbc8dc7 1266 McpsIndication.Buffer = LoRaMacRxPayload;
mluis 4:37c12dbc8dc7 1267 McpsIndication.BufferSize = frameLen;
mluis 4:37c12dbc8dc7 1268 McpsIndication.RxData = true;
mluis 4:37c12dbc8dc7 1269 }
mluis 2:14a5d6ad92d5 1270 }
mluis 2:14a5d6ad92d5 1271 }
mluis 7:c16969e0f70f 1272 else
mluis 7:c16969e0f70f 1273 {
mluis 7:c16969e0f70f 1274 if( fCtrl.Bits.FOptsLen > 0 )
mluis 7:c16969e0f70f 1275 {
mluis 7:c16969e0f70f 1276 // Decode Options field MAC commands
mluis 7:c16969e0f70f 1277 ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
mluis 7:c16969e0f70f 1278 }
mluis 7:c16969e0f70f 1279 }
mluis 7:c16969e0f70f 1280
mluis 4:37c12dbc8dc7 1281 if( skipIndication == false )
mluis 4:37c12dbc8dc7 1282 {
mluis 4:37c12dbc8dc7 1283 LoRaMacFlags.Bits.McpsInd = 1;
mluis 4:37c12dbc8dc7 1284 }
mluis 2:14a5d6ad92d5 1285 }
mluis 2:14a5d6ad92d5 1286 else
mluis 2:14a5d6ad92d5 1287 {
mluis 2:14a5d6ad92d5 1288 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
mluis 3:b9d87593a8ae 1289
mluis 3:b9d87593a8ae 1290 PrepareRxDoneAbort( );
mluis 3:b9d87593a8ae 1291 return;
mluis 2:14a5d6ad92d5 1292 }
mluis 2:14a5d6ad92d5 1293 }
mluis 2:14a5d6ad92d5 1294 break;
mluis 2:14a5d6ad92d5 1295 case FRAME_TYPE_PROPRIETARY:
mluis 2:14a5d6ad92d5 1296 {
mluis 2:14a5d6ad92d5 1297 memcpy1( LoRaMacRxPayload, &payload[pktHeaderLen], size );
mluis 2:14a5d6ad92d5 1298
mluis 2:14a5d6ad92d5 1299 McpsIndication.McpsIndication = MCPS_PROPRIETARY;
mluis 2:14a5d6ad92d5 1300 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 2:14a5d6ad92d5 1301 McpsIndication.Buffer = LoRaMacRxPayload;
mluis 2:14a5d6ad92d5 1302 McpsIndication.BufferSize = size - pktHeaderLen;
mluis 3:b9d87593a8ae 1303
mluis 3:b9d87593a8ae 1304 LoRaMacFlags.Bits.McpsInd = 1;
mluis 2:14a5d6ad92d5 1305 break;
mluis 2:14a5d6ad92d5 1306 }
mluis 2:14a5d6ad92d5 1307 default:
mluis 2:14a5d6ad92d5 1308 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 3:b9d87593a8ae 1309 PrepareRxDoneAbort( );
mluis 2:14a5d6ad92d5 1310 break;
mluis 2:14a5d6ad92d5 1311 }
mluis 2:14a5d6ad92d5 1312
mluis 2:14a5d6ad92d5 1313 if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
mluis 2:14a5d6ad92d5 1314 {
mluis 2:14a5d6ad92d5 1315 OnRxWindow2TimerEvent( );
mluis 2:14a5d6ad92d5 1316 }
mluis 2:14a5d6ad92d5 1317 LoRaMacFlags.Bits.MacDone = 1;
mluis 3:b9d87593a8ae 1318
mluis 3:b9d87593a8ae 1319 // Trig OnMacCheckTimerEvent call as soon as possible
mluis 3:b9d87593a8ae 1320 TimerSetValue( &MacStateCheckTimer, 1000 );
mluis 3:b9d87593a8ae 1321 TimerStart( &MacStateCheckTimer );
mluis 2:14a5d6ad92d5 1322 }
mluis 2:14a5d6ad92d5 1323
mluis 2:14a5d6ad92d5 1324 static void OnRadioTxTimeout( void )
mluis 2:14a5d6ad92d5 1325 {
mluis 2:14a5d6ad92d5 1326 if( LoRaMacDeviceClass != CLASS_C )
mluis 2:14a5d6ad92d5 1327 {
mluis 2:14a5d6ad92d5 1328 Radio.Sleep( );
mluis 2:14a5d6ad92d5 1329 }
mluis 2:14a5d6ad92d5 1330 else
mluis 2:14a5d6ad92d5 1331 {
mluis 2:14a5d6ad92d5 1332 OnRxWindow2TimerEvent( );
mluis 2:14a5d6ad92d5 1333 }
mluis 2:14a5d6ad92d5 1334
mluis 2:14a5d6ad92d5 1335 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
mluis 2:14a5d6ad92d5 1336 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
mluis 2:14a5d6ad92d5 1337 LoRaMacFlags.Bits.MacDone = 1;
mluis 2:14a5d6ad92d5 1338 }
mluis 2:14a5d6ad92d5 1339
mluis 2:14a5d6ad92d5 1340 static void OnRadioRxError( void )
mluis 2:14a5d6ad92d5 1341 {
mluis 2:14a5d6ad92d5 1342 if( LoRaMacDeviceClass != CLASS_C )
mluis 2:14a5d6ad92d5 1343 {
mluis 2:14a5d6ad92d5 1344 Radio.Sleep( );
mluis 2:14a5d6ad92d5 1345 }
mluis 2:14a5d6ad92d5 1346 else
mluis 2:14a5d6ad92d5 1347 {
mluis 2:14a5d6ad92d5 1348 OnRxWindow2TimerEvent( );
mluis 2:14a5d6ad92d5 1349 }
mluis 2:14a5d6ad92d5 1350
mluis 2:14a5d6ad92d5 1351 if( RxSlot == 1 )
mluis 2:14a5d6ad92d5 1352 {
mluis 2:14a5d6ad92d5 1353 if( NodeAckRequested == true )
mluis 2:14a5d6ad92d5 1354 {
mluis 2:14a5d6ad92d5 1355 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
mluis 2:14a5d6ad92d5 1356 }
mluis 2:14a5d6ad92d5 1357 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
mluis 2:14a5d6ad92d5 1358 LoRaMacFlags.Bits.MacDone = 1;
mluis 2:14a5d6ad92d5 1359 }
mluis 2:14a5d6ad92d5 1360 }
mluis 2:14a5d6ad92d5 1361
mluis 2:14a5d6ad92d5 1362 static void OnRadioRxTimeout( void )
mluis 2:14a5d6ad92d5 1363 {
mluis 2:14a5d6ad92d5 1364 if( LoRaMacDeviceClass != CLASS_C )
mluis 2:14a5d6ad92d5 1365 {
mluis 2:14a5d6ad92d5 1366 Radio.Sleep( );
mluis 2:14a5d6ad92d5 1367 }
mluis 2:14a5d6ad92d5 1368 else
mluis 2:14a5d6ad92d5 1369 {
mluis 2:14a5d6ad92d5 1370 OnRxWindow2TimerEvent( );
mluis 2:14a5d6ad92d5 1371 }
mluis 2:14a5d6ad92d5 1372
mluis 2:14a5d6ad92d5 1373 if( RxSlot == 1 )
mluis 2:14a5d6ad92d5 1374 {
mluis 2:14a5d6ad92d5 1375 if( NodeAckRequested == true )
mluis 2:14a5d6ad92d5 1376 {
mluis 2:14a5d6ad92d5 1377 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
mluis 2:14a5d6ad92d5 1378 }
mluis 2:14a5d6ad92d5 1379 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
mluis 2:14a5d6ad92d5 1380 LoRaMacFlags.Bits.MacDone = 1;
mluis 2:14a5d6ad92d5 1381 }
mluis 2:14a5d6ad92d5 1382 }
mluis 2:14a5d6ad92d5 1383
mluis 2:14a5d6ad92d5 1384 static void OnMacStateCheckTimerEvent( void )
mluis 2:14a5d6ad92d5 1385 {
mluis 2:14a5d6ad92d5 1386 TimerStop( &MacStateCheckTimer );
mluis 2:14a5d6ad92d5 1387 bool txTimeout = false;
mluis 2:14a5d6ad92d5 1388
mluis 2:14a5d6ad92d5 1389 if( LoRaMacFlags.Bits.MacDone == 1 )
mluis 2:14a5d6ad92d5 1390 {
mluis 4:37c12dbc8dc7 1391 if( ( LoRaMacState & MAC_RX_ABORT ) == MAC_RX_ABORT )
mluis 4:37c12dbc8dc7 1392 {
mluis 4:37c12dbc8dc7 1393 LoRaMacState &= ~MAC_RX_ABORT;
mluis 4:37c12dbc8dc7 1394 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 4:37c12dbc8dc7 1395 }
mluis 4:37c12dbc8dc7 1396
mluis 2:14a5d6ad92d5 1397 if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
mluis 2:14a5d6ad92d5 1398 {
mluis 2:14a5d6ad92d5 1399 if( ( McpsConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) ||
mluis 2:14a5d6ad92d5 1400 ( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) )
mluis 2:14a5d6ad92d5 1401 {
mluis 2:14a5d6ad92d5 1402 // Stop transmit cycle due to tx timeout.
mluis 2:14a5d6ad92d5 1403 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 2:14a5d6ad92d5 1404 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
mluis 2:14a5d6ad92d5 1405 McpsConfirm.AckReceived = false;
mluis 2:14a5d6ad92d5 1406 McpsConfirm.TxTimeOnAir = 0;
mluis 2:14a5d6ad92d5 1407 txTimeout = true;
mluis 2:14a5d6ad92d5 1408 }
mluis 2:14a5d6ad92d5 1409 }
mluis 2:14a5d6ad92d5 1410
mluis 2:14a5d6ad92d5 1411 if( ( NodeAckRequested == false ) && ( txTimeout == false ) )
mluis 2:14a5d6ad92d5 1412 {
mluis 2:14a5d6ad92d5 1413 if( LoRaMacFlags.Bits.MlmeReq == 1 )
mluis 2:14a5d6ad92d5 1414 {
mluis 2:14a5d6ad92d5 1415 if( MlmeConfirm.MlmeRequest == MLME_JOIN )
mluis 2:14a5d6ad92d5 1416 {
mluis 7:c16969e0f70f 1417 // Retransmit only if the answer is not OK
mluis 7:c16969e0f70f 1418 ChannelsNbRepCounter = 0;
mluis 7:c16969e0f70f 1419
mluis 2:14a5d6ad92d5 1420 if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
mluis 2:14a5d6ad92d5 1421 {
mluis 7:c16969e0f70f 1422 // Stop retransmission
mluis 7:c16969e0f70f 1423 ChannelsNbRepCounter = LoRaMacParams.ChannelsNbRep;
mluis 2:14a5d6ad92d5 1424 UpLinkCounter = 0;
mluis 2:14a5d6ad92d5 1425 }
mluis 2:14a5d6ad92d5 1426 }
mluis 2:14a5d6ad92d5 1427 }
mluis 2:14a5d6ad92d5 1428 if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
mluis 2:14a5d6ad92d5 1429 {
mluis 7:c16969e0f70f 1430 if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
mluis 2:14a5d6ad92d5 1431 {
mluis 2:14a5d6ad92d5 1432 ChannelsNbRepCounter = 0;
mluis 2:14a5d6ad92d5 1433
mluis 2:14a5d6ad92d5 1434 AdrAckCounter++;
mluis 2:14a5d6ad92d5 1435 if( IsUpLinkCounterFixed == false )
mluis 2:14a5d6ad92d5 1436 {
mluis 2:14a5d6ad92d5 1437 UpLinkCounter++;
mluis 2:14a5d6ad92d5 1438 }
mluis 2:14a5d6ad92d5 1439
mluis 2:14a5d6ad92d5 1440 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 2:14a5d6ad92d5 1441 }
mluis 2:14a5d6ad92d5 1442 else
mluis 2:14a5d6ad92d5 1443 {
mluis 2:14a5d6ad92d5 1444 LoRaMacFlags.Bits.MacDone = 0;
mluis 2:14a5d6ad92d5 1445 // Sends the same frame again
mluis 2:14a5d6ad92d5 1446 ScheduleTx( );
mluis 2:14a5d6ad92d5 1447 }
mluis 2:14a5d6ad92d5 1448 }
mluis 2:14a5d6ad92d5 1449 }
mluis 2:14a5d6ad92d5 1450
mluis 2:14a5d6ad92d5 1451 if( LoRaMacFlags.Bits.McpsInd == 1 )
mluis 2:14a5d6ad92d5 1452 {
mluis 2:14a5d6ad92d5 1453 if( ( McpsConfirm.AckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) )
mluis 2:14a5d6ad92d5 1454 {
mluis 2:14a5d6ad92d5 1455 AckTimeoutRetry = false;
mluis 3:b9d87593a8ae 1456 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 1457 if( IsUpLinkCounterFixed == false )
mluis 2:14a5d6ad92d5 1458 {
mluis 2:14a5d6ad92d5 1459 UpLinkCounter++;
mluis 2:14a5d6ad92d5 1460 }
mluis 2:14a5d6ad92d5 1461 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
mluis 2:14a5d6ad92d5 1462
mluis 2:14a5d6ad92d5 1463 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 2:14a5d6ad92d5 1464 }
mluis 2:14a5d6ad92d5 1465 }
mluis 2:14a5d6ad92d5 1466
mluis 2:14a5d6ad92d5 1467 if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & MAC_TX_DELAYED ) == 0 ) )
mluis 2:14a5d6ad92d5 1468 {
mluis 2:14a5d6ad92d5 1469 AckTimeoutRetry = false;
mluis 2:14a5d6ad92d5 1470 if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) )
mluis 2:14a5d6ad92d5 1471 {
mluis 2:14a5d6ad92d5 1472 AckTimeoutRetriesCounter++;
mluis 2:14a5d6ad92d5 1473
mluis 2:14a5d6ad92d5 1474 if( ( AckTimeoutRetriesCounter % 2 ) == 1 )
mluis 2:14a5d6ad92d5 1475 {
mluis 7:c16969e0f70f 1476 LoRaMacParams.ChannelsDatarate = MAX( LoRaMacParams.ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
mluis 2:14a5d6ad92d5 1477 }
mluis 2:14a5d6ad92d5 1478 LoRaMacFlags.Bits.MacDone = 0;
mluis 2:14a5d6ad92d5 1479 // Sends the same frame again
mluis 2:14a5d6ad92d5 1480 ScheduleTx( );
mluis 2:14a5d6ad92d5 1481 }
mluis 2:14a5d6ad92d5 1482 else
mluis 2:14a5d6ad92d5 1483 {
mluis 2:14a5d6ad92d5 1484 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 2:14a5d6ad92d5 1485 // Re-enable default channels LC1, LC2, LC3
mluis 7:c16969e0f70f 1486 LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
mluis 2:14a5d6ad92d5 1487 #elif defined( USE_BAND_915 )
mluis 2:14a5d6ad92d5 1488 // Re-enable default channels
mluis 7:c16969e0f70f 1489 LoRaMacParams.ChannelsMask[0] = 0xFFFF;
mluis 7:c16969e0f70f 1490 LoRaMacParams.ChannelsMask[1] = 0xFFFF;
mluis 7:c16969e0f70f 1491 LoRaMacParams.ChannelsMask[2] = 0xFFFF;
mluis 7:c16969e0f70f 1492 LoRaMacParams.ChannelsMask[3] = 0xFFFF;
mluis 7:c16969e0f70f 1493 LoRaMacParams.ChannelsMask[4] = 0x00FF;
mluis 7:c16969e0f70f 1494 LoRaMacParams.ChannelsMask[5] = 0x0000;
mluis 2:14a5d6ad92d5 1495 #elif defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 1496 // Re-enable default channels
mluis 7:c16969e0f70f 1497 ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
mluis 2:14a5d6ad92d5 1498 #else
mluis 2:14a5d6ad92d5 1499 #error "Please define a frequency band in the compiler options."
mluis 2:14a5d6ad92d5 1500 #endif
mluis 2:14a5d6ad92d5 1501 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 2:14a5d6ad92d5 1502
mluis 3:b9d87593a8ae 1503 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 1504 McpsConfirm.AckReceived = false;
mluis 2:14a5d6ad92d5 1505 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
mluis 2:14a5d6ad92d5 1506 if( IsUpLinkCounterFixed == false )
mluis 2:14a5d6ad92d5 1507 {
mluis 2:14a5d6ad92d5 1508 UpLinkCounter++;
mluis 2:14a5d6ad92d5 1509 }
mluis 2:14a5d6ad92d5 1510 }
mluis 2:14a5d6ad92d5 1511 }
mluis 2:14a5d6ad92d5 1512 }
mluis 2:14a5d6ad92d5 1513 // Handle reception for Class B and Class C
mluis 2:14a5d6ad92d5 1514 if( ( LoRaMacState & MAC_RX ) == MAC_RX )
mluis 2:14a5d6ad92d5 1515 {
mluis 2:14a5d6ad92d5 1516 LoRaMacState &= ~MAC_RX;
mluis 2:14a5d6ad92d5 1517 }
mluis 2:14a5d6ad92d5 1518 if( LoRaMacState == MAC_IDLE )
mluis 2:14a5d6ad92d5 1519 {
mluis 2:14a5d6ad92d5 1520 if( LoRaMacFlags.Bits.McpsReq == 1 )
mluis 2:14a5d6ad92d5 1521 {
mluis 2:14a5d6ad92d5 1522 LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm );
mluis 2:14a5d6ad92d5 1523 LoRaMacFlags.Bits.McpsReq = 0;
mluis 2:14a5d6ad92d5 1524 }
mluis 2:14a5d6ad92d5 1525
mluis 2:14a5d6ad92d5 1526 if( LoRaMacFlags.Bits.MlmeReq == 1 )
mluis 2:14a5d6ad92d5 1527 {
mluis 2:14a5d6ad92d5 1528 LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm );
mluis 2:14a5d6ad92d5 1529 LoRaMacFlags.Bits.MlmeReq = 0;
mluis 2:14a5d6ad92d5 1530 }
mluis 2:14a5d6ad92d5 1531
mluis 2:14a5d6ad92d5 1532 LoRaMacFlags.Bits.MacDone = 0;
mluis 2:14a5d6ad92d5 1533 }
mluis 2:14a5d6ad92d5 1534 else
mluis 2:14a5d6ad92d5 1535 {
mluis 2:14a5d6ad92d5 1536 // Operation not finished restart timer
mluis 3:b9d87593a8ae 1537 TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
mluis 2:14a5d6ad92d5 1538 TimerStart( &MacStateCheckTimer );
mluis 2:14a5d6ad92d5 1539 }
mluis 2:14a5d6ad92d5 1540
mluis 2:14a5d6ad92d5 1541 if( LoRaMacFlags.Bits.McpsInd == 1 )
mluis 2:14a5d6ad92d5 1542 {
mluis 2:14a5d6ad92d5 1543 LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
mluis 2:14a5d6ad92d5 1544 LoRaMacFlags.Bits.McpsInd = 0;
mluis 2:14a5d6ad92d5 1545 }
mluis 2:14a5d6ad92d5 1546 }
mluis 2:14a5d6ad92d5 1547
mluis 2:14a5d6ad92d5 1548 static void OnTxDelayedTimerEvent( void )
mluis 2:14a5d6ad92d5 1549 {
mluis 7:c16969e0f70f 1550 LoRaMacHeader_t macHdr;
mluis 7:c16969e0f70f 1551 LoRaMacFrameCtrl_t fCtrl;
mluis 7:c16969e0f70f 1552
mluis 2:14a5d6ad92d5 1553 TimerStop( &TxDelayedTimer );
mluis 2:14a5d6ad92d5 1554 LoRaMacState &= ~MAC_TX_DELAYED;
mluis 2:14a5d6ad92d5 1555
mluis 7:c16969e0f70f 1556 if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
mluis 7:c16969e0f70f 1557 {
mluis 7:c16969e0f70f 1558 macHdr.Value = 0;
mluis 7:c16969e0f70f 1559 macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
mluis 7:c16969e0f70f 1560
mluis 7:c16969e0f70f 1561 fCtrl.Value = 0;
mluis 7:c16969e0f70f 1562 fCtrl.Bits.Adr = AdrCtrlOn;
mluis 7:c16969e0f70f 1563
mluis 7:c16969e0f70f 1564 /* In case of a join request retransmission, the stack must prepare
mluis 7:c16969e0f70f 1565 * the frame again, because the network server keeps track of the random
mluis 7:c16969e0f70f 1566 * LoRaMacDevNonce values to prevent reply attacks. */
mluis 7:c16969e0f70f 1567 PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 );
mluis 7:c16969e0f70f 1568 }
mluis 7:c16969e0f70f 1569
mluis 2:14a5d6ad92d5 1570 ScheduleTx( );
mluis 2:14a5d6ad92d5 1571 }
mluis 2:14a5d6ad92d5 1572
mluis 2:14a5d6ad92d5 1573 static void OnRxWindow1TimerEvent( void )
mluis 2:14a5d6ad92d5 1574 {
mluis 2:14a5d6ad92d5 1575 uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
mluis 2:14a5d6ad92d5 1576 int8_t datarate = 0;
mluis 2:14a5d6ad92d5 1577 uint32_t bandwidth = 0; // LoRa 125 kHz
mluis 2:14a5d6ad92d5 1578
mluis 2:14a5d6ad92d5 1579 TimerStop( &RxWindowTimer1 );
mluis 2:14a5d6ad92d5 1580 RxSlot = 0;
mluis 2:14a5d6ad92d5 1581
mluis 2:14a5d6ad92d5 1582 if( LoRaMacDeviceClass == CLASS_C )
mluis 2:14a5d6ad92d5 1583 {
mluis 2:14a5d6ad92d5 1584 Radio.Standby( );
mluis 2:14a5d6ad92d5 1585 }
mluis 2:14a5d6ad92d5 1586
mluis 2:14a5d6ad92d5 1587 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 7:c16969e0f70f 1588 datarate = LoRaMacParams.ChannelsDatarate - LoRaMacParams.Rx1DrOffset;
mluis 2:14a5d6ad92d5 1589 if( datarate < 0 )
mluis 2:14a5d6ad92d5 1590 {
mluis 2:14a5d6ad92d5 1591 datarate = DR_0;
mluis 2:14a5d6ad92d5 1592 }
mluis 2:14a5d6ad92d5 1593
mluis 2:14a5d6ad92d5 1594 // For higher datarates, we increase the number of symbols generating a Rx Timeout
mluis 4:37c12dbc8dc7 1595 if( ( datarate == DR_3 ) || ( datarate == DR_4 ) )
mluis 4:37c12dbc8dc7 1596 { // DR_4, DR_3
mluis 2:14a5d6ad92d5 1597 symbTimeout = 8;
mluis 2:14a5d6ad92d5 1598 }
mluis 4:37c12dbc8dc7 1599 else if( datarate == DR_5 )
mluis 4:37c12dbc8dc7 1600 {
mluis 4:37c12dbc8dc7 1601 symbTimeout = 10;
mluis 4:37c12dbc8dc7 1602 }
mluis 4:37c12dbc8dc7 1603 else if( datarate == DR_6 )
mluis 2:14a5d6ad92d5 1604 {// LoRa 250 kHz
mluis 2:14a5d6ad92d5 1605 bandwidth = 1;
mluis 4:37c12dbc8dc7 1606 symbTimeout = 14;
mluis 2:14a5d6ad92d5 1607 }
mluis 2:14a5d6ad92d5 1608 RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
mluis 2:14a5d6ad92d5 1609 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 7:c16969e0f70f 1610 datarate = datarateOffsets[LoRaMacParams.ChannelsDatarate][LoRaMacParams.Rx1DrOffset];
mluis 2:14a5d6ad92d5 1611 if( datarate < 0 )
mluis 2:14a5d6ad92d5 1612 {
mluis 2:14a5d6ad92d5 1613 datarate = DR_0;
mluis 2:14a5d6ad92d5 1614 }
mluis 2:14a5d6ad92d5 1615 // For higher datarates, we increase the number of symbols generating a Rx Timeout
mluis 4:37c12dbc8dc7 1616 switch( datarate )
mluis 4:37c12dbc8dc7 1617 {
mluis 4:37c12dbc8dc7 1618 case DR_0: // SF10 - BW125
mluis 4:37c12dbc8dc7 1619 symbTimeout = 5;
mluis 4:37c12dbc8dc7 1620 break;
mluis 4:37c12dbc8dc7 1621
mluis 4:37c12dbc8dc7 1622 case DR_1: // SF9 - BW125
mluis 4:37c12dbc8dc7 1623 case DR_2: // SF8 - BW125
mluis 4:37c12dbc8dc7 1624 case DR_8: // SF12 - BW500
mluis 4:37c12dbc8dc7 1625 case DR_9: // SF11 - BW500
mluis 4:37c12dbc8dc7 1626 case DR_10: // SF10 - BW500
mluis 4:37c12dbc8dc7 1627 symbTimeout = 8;
mluis 4:37c12dbc8dc7 1628 break;
mluis 4:37c12dbc8dc7 1629
mluis 4:37c12dbc8dc7 1630 case DR_3: // SF7 - BW125
mluis 4:37c12dbc8dc7 1631 case DR_11: // SF9 - BW500
mluis 4:37c12dbc8dc7 1632 symbTimeout = 10;
mluis 4:37c12dbc8dc7 1633 break;
mluis 4:37c12dbc8dc7 1634
mluis 4:37c12dbc8dc7 1635 case DR_4: // SF8 - BW500
mluis 4:37c12dbc8dc7 1636 case DR_12: // SF8 - BW500
mluis 4:37c12dbc8dc7 1637 symbTimeout = 14;
mluis 4:37c12dbc8dc7 1638 break;
mluis 4:37c12dbc8dc7 1639
mluis 4:37c12dbc8dc7 1640 case DR_13: // SF7 - BW500
mluis 4:37c12dbc8dc7 1641 symbTimeout = 16;
mluis 4:37c12dbc8dc7 1642 break;
mluis 4:37c12dbc8dc7 1643 default:
mluis 4:37c12dbc8dc7 1644 break;
mluis 2:14a5d6ad92d5 1645 }
mluis 2:14a5d6ad92d5 1646 if( datarate >= DR_4 )
mluis 2:14a5d6ad92d5 1647 {// LoRa 500 kHz
mluis 2:14a5d6ad92d5 1648 bandwidth = 2;
mluis 2:14a5d6ad92d5 1649 }
mluis 7:c16969e0f70f 1650 RxWindowSetup( LORAMAC_FIRST_RX2_CHANNEL + ( Channel % 8 ) * LORAMAC_STEPWIDTH_RX2_CHANNEL, datarate, bandwidth, symbTimeout, false );
mluis 2:14a5d6ad92d5 1651 #else
mluis 2:14a5d6ad92d5 1652 #error "Please define a frequency band in the compiler options."
mluis 2:14a5d6ad92d5 1653 #endif
mluis 2:14a5d6ad92d5 1654 }
mluis 2:14a5d6ad92d5 1655
mluis 2:14a5d6ad92d5 1656 static void OnRxWindow2TimerEvent( void )
mluis 2:14a5d6ad92d5 1657 {
mluis 2:14a5d6ad92d5 1658 uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
mluis 2:14a5d6ad92d5 1659 uint32_t bandwidth = 0; // LoRa 125 kHz
mluis 2:14a5d6ad92d5 1660
mluis 2:14a5d6ad92d5 1661 TimerStop( &RxWindowTimer2 );
mluis 2:14a5d6ad92d5 1662 RxSlot = 1;
mluis 2:14a5d6ad92d5 1663
mluis 2:14a5d6ad92d5 1664 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 2:14a5d6ad92d5 1665 // For higher datarates, we increase the number of symbols generating a Rx Timeout
mluis 7:c16969e0f70f 1666 if( ( LoRaMacParams.Rx2Channel.Datarate == DR_3 ) || ( LoRaMacParams.Rx2Channel.Datarate == DR_4 ) )
mluis 4:37c12dbc8dc7 1667 { // DR_4, DR_3
mluis 2:14a5d6ad92d5 1668 symbTimeout = 8;
mluis 2:14a5d6ad92d5 1669 }
mluis 7:c16969e0f70f 1670 else if( LoRaMacParams.Rx2Channel.Datarate == DR_5 )
mluis 4:37c12dbc8dc7 1671 {
mluis 4:37c12dbc8dc7 1672 symbTimeout = 10;
mluis 4:37c12dbc8dc7 1673 }
mluis 7:c16969e0f70f 1674 else if( LoRaMacParams.Rx2Channel.Datarate == DR_6 )
mluis 2:14a5d6ad92d5 1675 {// LoRa 250 kHz
mluis 2:14a5d6ad92d5 1676 bandwidth = 1;
mluis 4:37c12dbc8dc7 1677 symbTimeout = 14;
mluis 2:14a5d6ad92d5 1678 }
mluis 2:14a5d6ad92d5 1679 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 2:14a5d6ad92d5 1680 // For higher datarates, we increase the number of symbols generating a Rx Timeout
mluis 7:c16969e0f70f 1681 switch( LoRaMacParams.Rx2Channel.Datarate )
mluis 4:37c12dbc8dc7 1682 {
mluis 4:37c12dbc8dc7 1683 case DR_0: // SF10 - BW125
mluis 4:37c12dbc8dc7 1684 symbTimeout = 5;
mluis 4:37c12dbc8dc7 1685 break;
mluis 4:37c12dbc8dc7 1686
mluis 4:37c12dbc8dc7 1687 case DR_1: // SF9 - BW125
mluis 4:37c12dbc8dc7 1688 case DR_2: // SF8 - BW125
mluis 4:37c12dbc8dc7 1689 case DR_8: // SF12 - BW500
mluis 4:37c12dbc8dc7 1690 case DR_9: // SF11 - BW500
mluis 4:37c12dbc8dc7 1691 case DR_10: // SF10 - BW500
mluis 4:37c12dbc8dc7 1692 symbTimeout = 8;
mluis 4:37c12dbc8dc7 1693 break;
mluis 4:37c12dbc8dc7 1694
mluis 4:37c12dbc8dc7 1695 case DR_3: // SF7 - BW125
mluis 4:37c12dbc8dc7 1696 case DR_11: // SF9 - BW500
mluis 4:37c12dbc8dc7 1697 symbTimeout = 10;
mluis 4:37c12dbc8dc7 1698 break;
mluis 4:37c12dbc8dc7 1699
mluis 4:37c12dbc8dc7 1700 case DR_4: // SF8 - BW500
mluis 4:37c12dbc8dc7 1701 case DR_12: // SF8 - BW500
mluis 4:37c12dbc8dc7 1702 symbTimeout = 14;
mluis 4:37c12dbc8dc7 1703 break;
mluis 4:37c12dbc8dc7 1704
mluis 4:37c12dbc8dc7 1705 case DR_13: // SF7 - BW500
mluis 4:37c12dbc8dc7 1706 symbTimeout = 16;
mluis 4:37c12dbc8dc7 1707 break;
mluis 4:37c12dbc8dc7 1708 default:
mluis 4:37c12dbc8dc7 1709 break;
mluis 2:14a5d6ad92d5 1710 }
mluis 7:c16969e0f70f 1711 if( LoRaMacParams.Rx2Channel.Datarate >= DR_4 )
mluis 2:14a5d6ad92d5 1712 {// LoRa 500 kHz
mluis 2:14a5d6ad92d5 1713 bandwidth = 2;
mluis 2:14a5d6ad92d5 1714 }
mluis 2:14a5d6ad92d5 1715 #else
mluis 2:14a5d6ad92d5 1716 #error "Please define a frequency band in the compiler options."
mluis 2:14a5d6ad92d5 1717 #endif
mluis 2:14a5d6ad92d5 1718 if( LoRaMacDeviceClass != CLASS_C )
mluis 2:14a5d6ad92d5 1719 {
mluis 7:c16969e0f70f 1720 RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, false );
mluis 2:14a5d6ad92d5 1721 }
mluis 2:14a5d6ad92d5 1722 else
mluis 2:14a5d6ad92d5 1723 {
mluis 7:c16969e0f70f 1724 RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, true );
mluis 2:14a5d6ad92d5 1725 }
mluis 2:14a5d6ad92d5 1726 }
mluis 2:14a5d6ad92d5 1727
mluis 2:14a5d6ad92d5 1728 static void OnAckTimeoutTimerEvent( void )
mluis 2:14a5d6ad92d5 1729 {
mluis 2:14a5d6ad92d5 1730 TimerStop( &AckTimeoutTimer );
mluis 2:14a5d6ad92d5 1731
mluis 2:14a5d6ad92d5 1732 if( NodeAckRequested == true )
mluis 2:14a5d6ad92d5 1733 {
mluis 2:14a5d6ad92d5 1734 AckTimeoutRetry = true;
mluis 2:14a5d6ad92d5 1735 LoRaMacState &= ~MAC_ACK_REQ;
mluis 2:14a5d6ad92d5 1736 }
mluis 2:14a5d6ad92d5 1737 if( LoRaMacDeviceClass == CLASS_C )
mluis 2:14a5d6ad92d5 1738 {
mluis 2:14a5d6ad92d5 1739 LoRaMacFlags.Bits.MacDone = 1;
mluis 2:14a5d6ad92d5 1740 }
mluis 2:14a5d6ad92d5 1741 }
mluis 2:14a5d6ad92d5 1742
mluis 3:b9d87593a8ae 1743 static bool SetNextChannel( TimerTime_t* time )
mluis 2:14a5d6ad92d5 1744 {
mluis 0:91d1a7783bb9 1745 uint8_t nbEnabledChannels = 0;
mluis 3:b9d87593a8ae 1746 uint8_t delayTx = 0;
mluis 0:91d1a7783bb9 1747 uint8_t enabledChannels[LORA_MAX_NB_CHANNELS];
mluis 2:14a5d6ad92d5 1748 TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
mluis 0:91d1a7783bb9 1749
mluis 1:91e4e6c60d1e 1750 memset1( enabledChannels, 0, LORA_MAX_NB_CHANNELS );
mluis 0:91d1a7783bb9 1751
mluis 2:14a5d6ad92d5 1752 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 3:b9d87593a8ae 1753 if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 )
mluis 3:b9d87593a8ae 1754 { // Restore default channels
mluis 7:c16969e0f70f 1755 memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParams.ChannelsMask, 8 );
mluis 3:b9d87593a8ae 1756 }
mluis 7:c16969e0f70f 1757 if( ( LoRaMacParams.ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) )
mluis 3:b9d87593a8ae 1758 { // Make sure, that the channels are activated
mluis 7:c16969e0f70f 1759 ChannelsMaskRemaining[4] = LoRaMacParams.ChannelsMask[4];
mluis 3:b9d87593a8ae 1760 }
mluis 3:b9d87593a8ae 1761 #else
mluis 7:c16969e0f70f 1762 if( CountBits( LoRaMacParams.ChannelsMask[0], 16 ) == 0 )
mluis 3:b9d87593a8ae 1763 {
mluis 3:b9d87593a8ae 1764 // Re-enable default channels, if no channel is enabled
mluis 7:c16969e0f70f 1765 LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
mluis 2:14a5d6ad92d5 1766 }
mluis 2:14a5d6ad92d5 1767 #endif
mluis 2:14a5d6ad92d5 1768
mluis 0:91d1a7783bb9 1769 // Update Aggregated duty cycle
mluis 4:37c12dbc8dc7 1770 if( AggregatedTimeOff <= TimerGetElapsedTime( AggregatedLastTxDoneTime ) )
mluis 0:91d1a7783bb9 1771 {
mluis 0:91d1a7783bb9 1772 AggregatedTimeOff = 0;
mluis 2:14a5d6ad92d5 1773
mluis 2:14a5d6ad92d5 1774 // Update bands Time OFF
mluis 2:14a5d6ad92d5 1775 for( uint8_t i = 0; i < LORA_MAX_NB_BANDS; i++ )
mluis 0:91d1a7783bb9 1776 {
mluis 2:14a5d6ad92d5 1777 if( DutyCycleOn == true )
mluis 0:91d1a7783bb9 1778 {
mluis 4:37c12dbc8dc7 1779 if( Bands[i].TimeOff <= TimerGetElapsedTime( Bands[i].LastTxDoneTime ) )
mluis 2:14a5d6ad92d5 1780 {
mluis 2:14a5d6ad92d5 1781 Bands[i].TimeOff = 0;
mluis 2:14a5d6ad92d5 1782 }
mluis 2:14a5d6ad92d5 1783 if( Bands[i].TimeOff != 0 )
mluis 2:14a5d6ad92d5 1784 {
mluis 2:14a5d6ad92d5 1785 nextTxDelay = MIN( Bands[i].TimeOff -
mluis 4:37c12dbc8dc7 1786 TimerGetElapsedTime( Bands[i].LastTxDoneTime ),
mluis 2:14a5d6ad92d5 1787 nextTxDelay );
mluis 2:14a5d6ad92d5 1788 }
mluis 2:14a5d6ad92d5 1789 }
mluis 2:14a5d6ad92d5 1790 else
mluis 2:14a5d6ad92d5 1791 {
mluis 2:14a5d6ad92d5 1792 nextTxDelay = 0;
mluis 0:91d1a7783bb9 1793 Bands[i].TimeOff = 0;
mluis 0:91d1a7783bb9 1794 }
mluis 2:14a5d6ad92d5 1795 }
mluis 2:14a5d6ad92d5 1796
mluis 2:14a5d6ad92d5 1797 // Search how many channels are enabled
mluis 2:14a5d6ad92d5 1798 for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
mluis 2:14a5d6ad92d5 1799 {
mluis 2:14a5d6ad92d5 1800 for( uint8_t j = 0; j < 16; j++ )
mluis 0:91d1a7783bb9 1801 {
mluis 2:14a5d6ad92d5 1802 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 1803 if( ( ChannelsMaskRemaining[k] & ( 1 << j ) ) != 0 )
mluis 2:14a5d6ad92d5 1804 #else
mluis 7:c16969e0f70f 1805 if( ( LoRaMacParams.ChannelsMask[k] & ( 1 << j ) ) != 0 )
mluis 2:14a5d6ad92d5 1806 #endif
mluis 2:14a5d6ad92d5 1807 {
mluis 2:14a5d6ad92d5 1808 if( Channels[i + j].Frequency == 0 )
mluis 2:14a5d6ad92d5 1809 { // Check if the channel is enabled
mluis 2:14a5d6ad92d5 1810 continue;
mluis 2:14a5d6ad92d5 1811 }
mluis 4:37c12dbc8dc7 1812 #if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
mluis 4:37c12dbc8dc7 1813 if( IsLoRaMacNetworkJoined == false )
mluis 4:37c12dbc8dc7 1814 {
mluis 4:37c12dbc8dc7 1815 if( ( JOIN_CHANNELS & ( 1 << j ) ) == 0 )
mluis 4:37c12dbc8dc7 1816 {
mluis 4:37c12dbc8dc7 1817 continue;
mluis 4:37c12dbc8dc7 1818 }
mluis 4:37c12dbc8dc7 1819 }
mluis 4:37c12dbc8dc7 1820 #endif
mluis 7:c16969e0f70f 1821 if( ( ( Channels[i + j].DrRange.Fields.Min <= LoRaMacParams.ChannelsDatarate ) &&
mluis 7:c16969e0f70f 1822 ( LoRaMacParams.ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false )
mluis 2:14a5d6ad92d5 1823 { // Check if the current channel selection supports the given datarate
mluis 2:14a5d6ad92d5 1824 continue;
mluis 2:14a5d6ad92d5 1825 }
mluis 2:14a5d6ad92d5 1826 if( Bands[Channels[i + j].Band].TimeOff > 0 )
mluis 2:14a5d6ad92d5 1827 { // Check if the band is available for transmission
mluis 3:b9d87593a8ae 1828 delayTx++;
mluis 2:14a5d6ad92d5 1829 continue;
mluis 2:14a5d6ad92d5 1830 }
mluis 2:14a5d6ad92d5 1831 enabledChannels[nbEnabledChannels++] = i + j;
mluis 2:14a5d6ad92d5 1832 }
mluis 2:14a5d6ad92d5 1833 }
mluis 2:14a5d6ad92d5 1834 }
mluis 2:14a5d6ad92d5 1835 }
mluis 2:14a5d6ad92d5 1836 else
mluis 2:14a5d6ad92d5 1837 {
mluis 3:b9d87593a8ae 1838 delayTx++;
mluis 4:37c12dbc8dc7 1839 nextTxDelay = AggregatedTimeOff - TimerGetElapsedTime( AggregatedLastTxDoneTime );
mluis 2:14a5d6ad92d5 1840 }
mluis 2:14a5d6ad92d5 1841
mluis 2:14a5d6ad92d5 1842 if( nbEnabledChannels > 0 )
mluis 2:14a5d6ad92d5 1843 {
mluis 2:14a5d6ad92d5 1844 Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
mluis 2:14a5d6ad92d5 1845 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 3:b9d87593a8ae 1846 if( Channel < ( LORA_MAX_NB_CHANNELS - 8 ) )
mluis 3:b9d87593a8ae 1847 {
mluis 3:b9d87593a8ae 1848 DisableChannelInMask( Channel, ChannelsMaskRemaining );
mluis 3:b9d87593a8ae 1849 }
mluis 2:14a5d6ad92d5 1850 #endif
mluis 3:b9d87593a8ae 1851 *time = 0;
mluis 3:b9d87593a8ae 1852 return true;
mluis 2:14a5d6ad92d5 1853 }
mluis 2:14a5d6ad92d5 1854 else
mluis 2:14a5d6ad92d5 1855 {
mluis 3:b9d87593a8ae 1856 if( delayTx > 0 )
mluis 3:b9d87593a8ae 1857 {
mluis 3:b9d87593a8ae 1858 // Delay transmission due to AggregatedTimeOff or to a band time off
mluis 3:b9d87593a8ae 1859 *time = nextTxDelay;
mluis 3:b9d87593a8ae 1860 return true;
mluis 3:b9d87593a8ae 1861 }
mluis 3:b9d87593a8ae 1862 // Datarate not supported by any channel
mluis 3:b9d87593a8ae 1863 *time = 0;
mluis 3:b9d87593a8ae 1864 return false;
mluis 2:14a5d6ad92d5 1865 }
mluis 2:14a5d6ad92d5 1866 }
mluis 2:14a5d6ad92d5 1867
mluis 2:14a5d6ad92d5 1868 static void SetPublicNetwork( bool enable )
mluis 2:14a5d6ad92d5 1869 {
mluis 2:14a5d6ad92d5 1870 PublicNetwork = enable;
mluis 2:14a5d6ad92d5 1871 Radio.SetModem( MODEM_LORA );
mluis 2:14a5d6ad92d5 1872 if( PublicNetwork == true )
mluis 2:14a5d6ad92d5 1873 {
mluis 2:14a5d6ad92d5 1874 // Change LoRa modem SyncWord
mluis 2:14a5d6ad92d5 1875 Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD );
mluis 2:14a5d6ad92d5 1876 }
mluis 2:14a5d6ad92d5 1877 else
mluis 2:14a5d6ad92d5 1878 {
mluis 2:14a5d6ad92d5 1879 // Change LoRa modem SyncWord
mluis 2:14a5d6ad92d5 1880 Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD );
mluis 2:14a5d6ad92d5 1881 }
mluis 2:14a5d6ad92d5 1882 }
mluis 2:14a5d6ad92d5 1883
mluis 2:14a5d6ad92d5 1884 static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
mluis 2:14a5d6ad92d5 1885 {
mluis 2:14a5d6ad92d5 1886 uint8_t downlinkDatarate = Datarates[datarate];
mluis 2:14a5d6ad92d5 1887 RadioModems_t modem;
mluis 2:14a5d6ad92d5 1888
mluis 2:14a5d6ad92d5 1889 if( Radio.GetStatus( ) == RF_IDLE )
mluis 2:14a5d6ad92d5 1890 {
mluis 2:14a5d6ad92d5 1891 Radio.SetChannel( freq );
mluis 2:14a5d6ad92d5 1892
mluis 2:14a5d6ad92d5 1893 // Store downlink datarate
mluis 2:14a5d6ad92d5 1894 McpsIndication.RxDatarate = ( uint8_t ) datarate;
mluis 2:14a5d6ad92d5 1895
mluis 2:14a5d6ad92d5 1896 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 2:14a5d6ad92d5 1897 if( datarate == DR_7 )
mluis 2:14a5d6ad92d5 1898 {
mluis 2:14a5d6ad92d5 1899 modem = MODEM_FSK;
mluis 2:14a5d6ad92d5 1900 Radio.SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, rxContinuous );
mluis 2:14a5d6ad92d5 1901 }
mluis 2:14a5d6ad92d5 1902 else
mluis 2:14a5d6ad92d5 1903 {
mluis 2:14a5d6ad92d5 1904 modem = MODEM_LORA;
mluis 2:14a5d6ad92d5 1905 Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
mluis 2:14a5d6ad92d5 1906 }
mluis 2:14a5d6ad92d5 1907 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 1908 modem = MODEM_LORA;
mluis 2:14a5d6ad92d5 1909 Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
mluis 2:14a5d6ad92d5 1910 #endif
mluis 2:14a5d6ad92d5 1911
mluis 2:14a5d6ad92d5 1912 if( RepeaterSupport == true )
mluis 2:14a5d6ad92d5 1913 {
mluis 4:37c12dbc8dc7 1914 Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRepeater[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
mluis 2:14a5d6ad92d5 1915 }
mluis 2:14a5d6ad92d5 1916 else
mluis 2:14a5d6ad92d5 1917 {
mluis 4:37c12dbc8dc7 1918 Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
mluis 2:14a5d6ad92d5 1919 }
mluis 2:14a5d6ad92d5 1920
mluis 2:14a5d6ad92d5 1921 if( rxContinuous == false )
mluis 2:14a5d6ad92d5 1922 {
mluis 7:c16969e0f70f 1923 Radio.Rx( LoRaMacParams.MaxRxWindow );
mluis 2:14a5d6ad92d5 1924 }
mluis 2:14a5d6ad92d5 1925 else
mluis 2:14a5d6ad92d5 1926 {
mluis 2:14a5d6ad92d5 1927 Radio.Rx( 0 ); // Continuous mode
mluis 2:14a5d6ad92d5 1928 }
mluis 2:14a5d6ad92d5 1929 }
mluis 2:14a5d6ad92d5 1930 }
mluis 2:14a5d6ad92d5 1931
mluis 7:c16969e0f70f 1932 static bool Rx2FreqInRange( uint32_t freq )
mluis 7:c16969e0f70f 1933 {
mluis 7:c16969e0f70f 1934 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 7:c16969e0f70f 1935 if( Radio.CheckRfFrequency( freq ) == true )
mluis 7:c16969e0f70f 1936 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 7:c16969e0f70f 1937 if( ( Radio.CheckRfFrequency( freq ) == true ) &&
mluis 7:c16969e0f70f 1938 ( freq >= LORAMAC_FIRST_RX2_CHANNEL ) &&
mluis 7:c16969e0f70f 1939 ( freq <= LORAMAC_LAST_RX2_CHANNEL ) &&
mluis 7:c16969e0f70f 1940 ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX2_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX2_CHANNEL ) == 0 ) )
mluis 7:c16969e0f70f 1941 #endif
mluis 7:c16969e0f70f 1942 {
mluis 7:c16969e0f70f 1943 return true;
mluis 7:c16969e0f70f 1944 }
mluis 7:c16969e0f70f 1945 return false;
mluis 7:c16969e0f70f 1946 }
mluis 7:c16969e0f70f 1947
mluis 2:14a5d6ad92d5 1948 static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
mluis 2:14a5d6ad92d5 1949 {
mluis 2:14a5d6ad92d5 1950 uint16_t maxN = 0;
mluis 2:14a5d6ad92d5 1951 uint16_t payloadSize = 0;
mluis 2:14a5d6ad92d5 1952
mluis 2:14a5d6ad92d5 1953 // Get the maximum payload length
mluis 2:14a5d6ad92d5 1954 if( RepeaterSupport == true )
mluis 2:14a5d6ad92d5 1955 {
mluis 2:14a5d6ad92d5 1956 maxN = MaxPayloadOfDatarateRepeater[datarate];
mluis 2:14a5d6ad92d5 1957 }
mluis 2:14a5d6ad92d5 1958 else
mluis 2:14a5d6ad92d5 1959 {
mluis 2:14a5d6ad92d5 1960 maxN = MaxPayloadOfDatarate[datarate];
mluis 2:14a5d6ad92d5 1961 }
mluis 2:14a5d6ad92d5 1962
mluis 2:14a5d6ad92d5 1963 // Calculate the resulting payload size
mluis 2:14a5d6ad92d5 1964 payloadSize = ( lenN + fOptsLen );
mluis 2:14a5d6ad92d5 1965
mluis 2:14a5d6ad92d5 1966 // Validation of the application payload size
mluis 2:14a5d6ad92d5 1967 if( ( payloadSize <= maxN ) && ( payloadSize <= LORAMAC_PHY_MAXPAYLOAD ) )
mluis 2:14a5d6ad92d5 1968 {
mluis 2:14a5d6ad92d5 1969 return true;
mluis 2:14a5d6ad92d5 1970 }
mluis 2:14a5d6ad92d5 1971 return false;
mluis 2:14a5d6ad92d5 1972 }
mluis 2:14a5d6ad92d5 1973
mluis 4:37c12dbc8dc7 1974 static uint8_t CountBits( uint16_t mask, uint8_t nbBits )
mluis 4:37c12dbc8dc7 1975 {
mluis 4:37c12dbc8dc7 1976 uint8_t nbActiveBits = 0;
mluis 4:37c12dbc8dc7 1977
mluis 4:37c12dbc8dc7 1978 for( uint8_t j = 0; j < nbBits; j++ )
mluis 4:37c12dbc8dc7 1979 {
mluis 4:37c12dbc8dc7 1980 if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
mluis 4:37c12dbc8dc7 1981 {
mluis 4:37c12dbc8dc7 1982 nbActiveBits++;
mluis 4:37c12dbc8dc7 1983 }
mluis 4:37c12dbc8dc7 1984 }
mluis 4:37c12dbc8dc7 1985 return nbActiveBits;
mluis 4:37c12dbc8dc7 1986 }
mluis 4:37c12dbc8dc7 1987
mluis 2:14a5d6ad92d5 1988 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 1989 static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask )
mluis 2:14a5d6ad92d5 1990 {
mluis 2:14a5d6ad92d5 1991 uint8_t nb125kHzChannels = 0;
mluis 2:14a5d6ad92d5 1992
mluis 2:14a5d6ad92d5 1993 for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
mluis 2:14a5d6ad92d5 1994 {
mluis 4:37c12dbc8dc7 1995 nb125kHzChannels += CountBits( channelsMask[k], 16 );
mluis 2:14a5d6ad92d5 1996 }
mluis 2:14a5d6ad92d5 1997
mluis 2:14a5d6ad92d5 1998 return nb125kHzChannels;
mluis 2:14a5d6ad92d5 1999 }
mluis 4:37c12dbc8dc7 2000
mluis 4:37c12dbc8dc7 2001 #if defined( USE_BAND_915_HYBRID )
mluis 4:37c12dbc8dc7 2002 static void ReenableChannels( uint16_t mask, uint16_t* channelMask )
mluis 4:37c12dbc8dc7 2003 {
mluis 4:37c12dbc8dc7 2004 uint16_t blockMask = mask;
mluis 4:37c12dbc8dc7 2005
mluis 4:37c12dbc8dc7 2006 for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
mluis 4:37c12dbc8dc7 2007 {
mluis 4:37c12dbc8dc7 2008 channelMask[i] = 0;
mluis 4:37c12dbc8dc7 2009 if( ( blockMask & ( 1 << j ) ) != 0 )
mluis 4:37c12dbc8dc7 2010 {
mluis 4:37c12dbc8dc7 2011 channelMask[i] |= 0x00FF;
mluis 4:37c12dbc8dc7 2012 }
mluis 4:37c12dbc8dc7 2013 if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
mluis 4:37c12dbc8dc7 2014 {
mluis 4:37c12dbc8dc7 2015 channelMask[i] |= 0xFF00;
mluis 4:37c12dbc8dc7 2016 }
mluis 4:37c12dbc8dc7 2017 }
mluis 4:37c12dbc8dc7 2018 channelMask[4] = blockMask;
mluis 4:37c12dbc8dc7 2019 channelMask[5] = 0x0000;
mluis 4:37c12dbc8dc7 2020 }
mluis 4:37c12dbc8dc7 2021
mluis 4:37c12dbc8dc7 2022 static bool ValidateChannelMask( uint16_t* channelMask )
mluis 4:37c12dbc8dc7 2023 {
mluis 4:37c12dbc8dc7 2024 bool chanMaskState = false;
mluis 4:37c12dbc8dc7 2025 uint16_t block1 = 0;
mluis 4:37c12dbc8dc7 2026 uint16_t block2 = 0;
mluis 4:37c12dbc8dc7 2027 uint8_t index = 0;
mluis 4:37c12dbc8dc7 2028
mluis 4:37c12dbc8dc7 2029 for( uint8_t i = 0; i < 4; i++ )
mluis 4:37c12dbc8dc7 2030 {
mluis 4:37c12dbc8dc7 2031 block1 = channelMask[i] & 0x00FF;
mluis 4:37c12dbc8dc7 2032 block2 = channelMask[i] & 0xFF00;
mluis 4:37c12dbc8dc7 2033
mluis 4:37c12dbc8dc7 2034 if( ( CountBits( block1, 16 ) > 5 ) && ( chanMaskState == false ) )
mluis 4:37c12dbc8dc7 2035 {
mluis 4:37c12dbc8dc7 2036 channelMask[i] &= block1;
mluis 4:37c12dbc8dc7 2037 channelMask[4] = 1 << ( i * 2 );
mluis 4:37c12dbc8dc7 2038 chanMaskState = true;
mluis 4:37c12dbc8dc7 2039 index = i;
mluis 4:37c12dbc8dc7 2040 }
mluis 4:37c12dbc8dc7 2041 else if( ( CountBits( block2, 16 ) > 5 ) && ( chanMaskState == false ) )
mluis 4:37c12dbc8dc7 2042 {
mluis 4:37c12dbc8dc7 2043 channelMask[i] &= block2;
mluis 4:37c12dbc8dc7 2044 channelMask[4] = 1 << ( i * 2 + 1 );
mluis 4:37c12dbc8dc7 2045 chanMaskState = true;
mluis 4:37c12dbc8dc7 2046 index = i;
mluis 4:37c12dbc8dc7 2047 }
mluis 4:37c12dbc8dc7 2048 }
mluis 4:37c12dbc8dc7 2049
mluis 4:37c12dbc8dc7 2050 // Do only change the channel mask, if we have found a valid block.
mluis 4:37c12dbc8dc7 2051 if( chanMaskState == true )
mluis 4:37c12dbc8dc7 2052 {
mluis 4:37c12dbc8dc7 2053 for( uint8_t i = 0; i < 4; i++ )
mluis 4:37c12dbc8dc7 2054 {
mluis 4:37c12dbc8dc7 2055 if( i != index )
mluis 4:37c12dbc8dc7 2056 {
mluis 4:37c12dbc8dc7 2057 channelMask[i] = 0;
mluis 4:37c12dbc8dc7 2058 }
mluis 4:37c12dbc8dc7 2059 }
mluis 4:37c12dbc8dc7 2060 }
mluis 4:37c12dbc8dc7 2061 return chanMaskState;
mluis 4:37c12dbc8dc7 2062 }
mluis 4:37c12dbc8dc7 2063 #endif
mluis 2:14a5d6ad92d5 2064 #endif
mluis 2:14a5d6ad92d5 2065
mluis 2:14a5d6ad92d5 2066 static int8_t LimitTxPower( int8_t txPower )
mluis 2:14a5d6ad92d5 2067 {
mluis 2:14a5d6ad92d5 2068 int8_t resultTxPower = txPower;
mluis 2:14a5d6ad92d5 2069 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 2070 if( ( LoRaMacParams.ChannelsDatarate == DR_4 ) ||
mluis 7:c16969e0f70f 2071 ( ( LoRaMacParams.ChannelsDatarate >= DR_8 ) && ( LoRaMacParams.ChannelsDatarate <= DR_13 ) ) )
mluis 2:14a5d6ad92d5 2072 {// Limit tx power to max 26dBm
mluis 2:14a5d6ad92d5 2073 resultTxPower = MAX( txPower, TX_POWER_26_DBM );
mluis 2:14a5d6ad92d5 2074 }
mluis 2:14a5d6ad92d5 2075 else
mluis 2:14a5d6ad92d5 2076 {
mluis 7:c16969e0f70f 2077 if( CountNbEnabled125kHzChannels( LoRaMacParams.ChannelsMask ) < 50 )
mluis 2:14a5d6ad92d5 2078 {// Limit tx power to max 21dBm
mluis 2:14a5d6ad92d5 2079 resultTxPower = MAX( txPower, TX_POWER_20_DBM );
mluis 2:14a5d6ad92d5 2080 }
mluis 2:14a5d6ad92d5 2081 }
mluis 2:14a5d6ad92d5 2082 #endif
mluis 2:14a5d6ad92d5 2083 return resultTxPower;
mluis 2:14a5d6ad92d5 2084 }
mluis 2:14a5d6ad92d5 2085
mluis 2:14a5d6ad92d5 2086 static bool ValueInRange( int8_t value, int8_t min, int8_t max )
mluis 2:14a5d6ad92d5 2087 {
mluis 2:14a5d6ad92d5 2088 if( ( value >= min ) && ( value <= max ) )
mluis 2:14a5d6ad92d5 2089 {
mluis 2:14a5d6ad92d5 2090 return true;
mluis 2:14a5d6ad92d5 2091 }
mluis 2:14a5d6ad92d5 2092 return false;
mluis 2:14a5d6ad92d5 2093 }
mluis 2:14a5d6ad92d5 2094
mluis 2:14a5d6ad92d5 2095 static bool DisableChannelInMask( uint8_t id, uint16_t* mask )
mluis 2:14a5d6ad92d5 2096 {
mluis 2:14a5d6ad92d5 2097 uint8_t index = 0;
mluis 2:14a5d6ad92d5 2098 index = id / 16;
mluis 2:14a5d6ad92d5 2099
mluis 2:14a5d6ad92d5 2100 if( ( index > 4 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
mluis 2:14a5d6ad92d5 2101 {
mluis 2:14a5d6ad92d5 2102 return false;
mluis 2:14a5d6ad92d5 2103 }
mluis 2:14a5d6ad92d5 2104
mluis 2:14a5d6ad92d5 2105 // Deactivate channel
mluis 2:14a5d6ad92d5 2106 mask[index] &= ~( 1 << ( id % 16 ) );
mluis 2:14a5d6ad92d5 2107
mluis 2:14a5d6ad92d5 2108 return true;
mluis 2:14a5d6ad92d5 2109 }
mluis 2:14a5d6ad92d5 2110
mluis 2:14a5d6ad92d5 2111 static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut )
mluis 2:14a5d6ad92d5 2112 {
mluis 2:14a5d6ad92d5 2113 bool adrAckReq = false;
mluis 7:c16969e0f70f 2114 int8_t datarate = LoRaMacParams.ChannelsDatarate;
mluis 2:14a5d6ad92d5 2115
mluis 2:14a5d6ad92d5 2116 if( adrEnabled == true )
mluis 2:14a5d6ad92d5 2117 {
mluis 4:37c12dbc8dc7 2118 if( datarate == LORAMAC_TX_MIN_DATARATE )
mluis 2:14a5d6ad92d5 2119 {
mluis 2:14a5d6ad92d5 2120 AdrAckCounter = 0;
mluis 2:14a5d6ad92d5 2121 adrAckReq = false;
mluis 0:91d1a7783bb9 2122 }
mluis 0:91d1a7783bb9 2123 else
mluis 0:91d1a7783bb9 2124 {
mluis 3:b9d87593a8ae 2125 if( AdrAckCounter >= ADR_ACK_LIMIT )
mluis 2:14a5d6ad92d5 2126 {
mluis 2:14a5d6ad92d5 2127 adrAckReq = true;
mluis 2:14a5d6ad92d5 2128 }
mluis 2:14a5d6ad92d5 2129 else
mluis 2:14a5d6ad92d5 2130 {
mluis 2:14a5d6ad92d5 2131 adrAckReq = false;
mluis 2:14a5d6ad92d5 2132 }
mluis 3:b9d87593a8ae 2133 if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) )
mluis 0:91d1a7783bb9 2134 {
mluis 7:c16969e0f70f 2135 if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 )
mluis 3:b9d87593a8ae 2136 {
mluis 2:14a5d6ad92d5 2137 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 4:37c12dbc8dc7 2138 if( datarate > LORAMAC_TX_MIN_DATARATE )
mluis 3:b9d87593a8ae 2139 {
mluis 3:b9d87593a8ae 2140 datarate--;
mluis 3:b9d87593a8ae 2141 }
mluis 4:37c12dbc8dc7 2142 if( datarate == LORAMAC_TX_MIN_DATARATE )
mluis 3:b9d87593a8ae 2143 {
mluis 3:b9d87593a8ae 2144 if( updateChannelMask == true )
mluis 3:b9d87593a8ae 2145 {
mluis 3:b9d87593a8ae 2146 // Re-enable default channels LC1, LC2, LC3
mluis 7:c16969e0f70f 2147 LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
mluis 3:b9d87593a8ae 2148 }
mluis 3:b9d87593a8ae 2149 }
mluis 2:14a5d6ad92d5 2150 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 4:37c12dbc8dc7 2151 if( ( datarate > LORAMAC_TX_MIN_DATARATE ) && ( datarate == DR_8 ) )
mluis 3:b9d87593a8ae 2152 {
mluis 3:b9d87593a8ae 2153 datarate = DR_4;
mluis 3:b9d87593a8ae 2154 }
mluis 4:37c12dbc8dc7 2155 else if( datarate > LORAMAC_TX_MIN_DATARATE )
mluis 3:b9d87593a8ae 2156 {
mluis 3:b9d87593a8ae 2157 datarate--;
mluis 3:b9d87593a8ae 2158 }
mluis 4:37c12dbc8dc7 2159 if( datarate == LORAMAC_TX_MIN_DATARATE )
mluis 3:b9d87593a8ae 2160 {
mluis 3:b9d87593a8ae 2161 if( updateChannelMask == true )
mluis 3:b9d87593a8ae 2162 {
mluis 3:b9d87593a8ae 2163 #if defined( USE_BAND_915 )
mluis 3:b9d87593a8ae 2164 // Re-enable default channels
mluis 7:c16969e0f70f 2165 LoRaMacParams.ChannelsMask[0] = 0xFFFF;
mluis 7:c16969e0f70f 2166 LoRaMacParams.ChannelsMask[1] = 0xFFFF;
mluis 7:c16969e0f70f 2167 LoRaMacParams.ChannelsMask[2] = 0xFFFF;
mluis 7:c16969e0f70f 2168 LoRaMacParams.ChannelsMask[3] = 0xFFFF;
mluis 7:c16969e0f70f 2169 LoRaMacParams.ChannelsMask[4] = 0x00FF;
mluis 7:c16969e0f70f 2170 LoRaMacParams.ChannelsMask[5] = 0x0000;
mluis 3:b9d87593a8ae 2171 #else // defined( USE_BAND_915_HYBRID )
mluis 3:b9d87593a8ae 2172 // Re-enable default channels
mluis 7:c16969e0f70f 2173 ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
mluis 3:b9d87593a8ae 2174 #endif
mluis 3:b9d87593a8ae 2175 }
mluis 3:b9d87593a8ae 2176 }
mluis 2:14a5d6ad92d5 2177 #else
mluis 2:14a5d6ad92d5 2178 #error "Please define a frequency band in the compiler options."
mluis 2:14a5d6ad92d5 2179 #endif
mluis 3:b9d87593a8ae 2180 }
mluis 0:91d1a7783bb9 2181 }
mluis 0:91d1a7783bb9 2182 }
mluis 0:91d1a7783bb9 2183 }
mluis 2:14a5d6ad92d5 2184
mluis 2:14a5d6ad92d5 2185 *datarateOut = datarate;
mluis 2:14a5d6ad92d5 2186
mluis 2:14a5d6ad92d5 2187 return adrAckReq;
mluis 0:91d1a7783bb9 2188 }
mluis 0:91d1a7783bb9 2189
mluis 2:14a5d6ad92d5 2190 static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
mluis 0:91d1a7783bb9 2191 {
mluis 2:14a5d6ad92d5 2192 LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
mluis 7:c16969e0f70f 2193 // The maximum buffer length must take MAC commands to re-send into account.
mluis 7:c16969e0f70f 2194 uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex;
mluis 1:91e4e6c60d1e 2195
mluis 0:91d1a7783bb9 2196 switch( cmd )
mluis 0:91d1a7783bb9 2197 {
mluis 0:91d1a7783bb9 2198 case MOTE_MAC_LINK_CHECK_REQ:
mluis 7:c16969e0f70f 2199 if( MacCommandsBufferIndex < bufLen )
mluis 1:91e4e6c60d1e 2200 {
mluis 1:91e4e6c60d1e 2201 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
mluis 1:91e4e6c60d1e 2202 // No payload for this command
mluis 2:14a5d6ad92d5 2203 status = LORAMAC_STATUS_OK;
mluis 1:91e4e6c60d1e 2204 }
mluis 0:91d1a7783bb9 2205 break;
mluis 0:91d1a7783bb9 2206 case MOTE_MAC_LINK_ADR_ANS:
mluis 7:c16969e0f70f 2207 if( MacCommandsBufferIndex < ( bufLen - 1 ) )
mluis 1:91e4e6c60d1e 2208 {
mluis 1:91e4e6c60d1e 2209 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
mluis 1:91e4e6c60d1e 2210 // Margin
mluis 1:91e4e6c60d1e 2211 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
mluis 2:14a5d6ad92d5 2212 status = LORAMAC_STATUS_OK;
mluis 1:91e4e6c60d1e 2213 }
mluis 0:91d1a7783bb9 2214 break;
mluis 0:91d1a7783bb9 2215 case MOTE_MAC_DUTY_CYCLE_ANS:
mluis 7:c16969e0f70f 2216 if( MacCommandsBufferIndex < bufLen )
mluis 1:91e4e6c60d1e 2217 {
mluis 1:91e4e6c60d1e 2218 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
mluis 1:91e4e6c60d1e 2219 // No payload for this answer
mluis 2:14a5d6ad92d5 2220 status = LORAMAC_STATUS_OK;
mluis 1:91e4e6c60d1e 2221 }
mluis 0:91d1a7783bb9 2222 break;
mluis 0:91d1a7783bb9 2223 case MOTE_MAC_RX_PARAM_SETUP_ANS:
mluis 7:c16969e0f70f 2224 if( MacCommandsBufferIndex < ( bufLen - 1 ) )
mluis 1:91e4e6c60d1e 2225 {
mluis 1:91e4e6c60d1e 2226 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
mluis 1:91e4e6c60d1e 2227 // Status: Datarate ACK, Channel ACK
mluis 1:91e4e6c60d1e 2228 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
mluis 2:14a5d6ad92d5 2229 status = LORAMAC_STATUS_OK;
mluis 1:91e4e6c60d1e 2230 }
mluis 0:91d1a7783bb9 2231 break;
mluis 0:91d1a7783bb9 2232 case MOTE_MAC_DEV_STATUS_ANS:
mluis 7:c16969e0f70f 2233 if( MacCommandsBufferIndex < ( bufLen - 2 ) )
mluis 1:91e4e6c60d1e 2234 {
mluis 1:91e4e6c60d1e 2235 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
mluis 1:91e4e6c60d1e 2236 // 1st byte Battery
mluis 1:91e4e6c60d1e 2237 // 2nd byte Margin
mluis 1:91e4e6c60d1e 2238 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
mluis 1:91e4e6c60d1e 2239 MacCommandsBuffer[MacCommandsBufferIndex++] = p2;
mluis 2:14a5d6ad92d5 2240 status = LORAMAC_STATUS_OK;
mluis 1:91e4e6c60d1e 2241 }
mluis 0:91d1a7783bb9 2242 break;
mluis 0:91d1a7783bb9 2243 case MOTE_MAC_NEW_CHANNEL_ANS:
mluis 7:c16969e0f70f 2244 if( MacCommandsBufferIndex < ( bufLen - 1 ) )
mluis 1:91e4e6c60d1e 2245 {
mluis 1:91e4e6c60d1e 2246 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
mluis 1:91e4e6c60d1e 2247 // Status: Datarate range OK, Channel frequency OK
mluis 1:91e4e6c60d1e 2248 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
mluis 2:14a5d6ad92d5 2249 status = LORAMAC_STATUS_OK;
mluis 1:91e4e6c60d1e 2250 }
mluis 0:91d1a7783bb9 2251 break;
mluis 0:91d1a7783bb9 2252 case MOTE_MAC_RX_TIMING_SETUP_ANS:
mluis 7:c16969e0f70f 2253 if( MacCommandsBufferIndex < bufLen )
mluis 1:91e4e6c60d1e 2254 {
mluis 1:91e4e6c60d1e 2255 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
mluis 1:91e4e6c60d1e 2256 // No payload for this answer
mluis 2:14a5d6ad92d5 2257 status = LORAMAC_STATUS_OK;
mluis 1:91e4e6c60d1e 2258 }
mluis 0:91d1a7783bb9 2259 break;
mluis 0:91d1a7783bb9 2260 default:
mluis 2:14a5d6ad92d5 2261 return LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 0:91d1a7783bb9 2262 }
mluis 2:14a5d6ad92d5 2263 if( status == LORAMAC_STATUS_OK )
mluis 0:91d1a7783bb9 2264 {
mluis 0:91d1a7783bb9 2265 MacCommandsInNextTx = true;
mluis 0:91d1a7783bb9 2266 }
mluis 1:91e4e6c60d1e 2267 return status;
mluis 0:91d1a7783bb9 2268 }
mluis 0:91d1a7783bb9 2269
mluis 7:c16969e0f70f 2270 static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut )
mluis 7:c16969e0f70f 2271 {
mluis 7:c16969e0f70f 2272 uint8_t i = 0;
mluis 7:c16969e0f70f 2273 uint8_t cmdCount = 0;
mluis 7:c16969e0f70f 2274
mluis 7:c16969e0f70f 2275 if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) )
mluis 7:c16969e0f70f 2276 {
mluis 7:c16969e0f70f 2277 return 0;
mluis 7:c16969e0f70f 2278 }
mluis 7:c16969e0f70f 2279
mluis 7:c16969e0f70f 2280 for( i = 0; i < length; i++ )
mluis 7:c16969e0f70f 2281 {
mluis 7:c16969e0f70f 2282 switch( cmdBufIn[i] )
mluis 7:c16969e0f70f 2283 {
mluis 7:c16969e0f70f 2284 case MOTE_MAC_RX_PARAM_SETUP_ANS:
mluis 7:c16969e0f70f 2285 {
mluis 7:c16969e0f70f 2286 cmdBufOut[cmdCount++] = cmdBufIn[i++];
mluis 7:c16969e0f70f 2287 cmdBufOut[cmdCount++] = cmdBufIn[i++];
mluis 7:c16969e0f70f 2288 cmdBufOut[cmdCount++] = cmdBufIn[i];
mluis 7:c16969e0f70f 2289 break;
mluis 7:c16969e0f70f 2290 }
mluis 7:c16969e0f70f 2291 case MOTE_MAC_RX_TIMING_SETUP_ANS:
mluis 7:c16969e0f70f 2292 {
mluis 7:c16969e0f70f 2293 cmdBufOut[cmdCount++] = cmdBufIn[i];
mluis 7:c16969e0f70f 2294 break;
mluis 7:c16969e0f70f 2295 }
mluis 7:c16969e0f70f 2296 default:
mluis 7:c16969e0f70f 2297 break;
mluis 7:c16969e0f70f 2298 }
mluis 7:c16969e0f70f 2299 }
mluis 7:c16969e0f70f 2300
mluis 7:c16969e0f70f 2301 return cmdCount;
mluis 7:c16969e0f70f 2302 }
mluis 7:c16969e0f70f 2303
mluis 2:14a5d6ad92d5 2304 static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr )
mluis 0:91d1a7783bb9 2305 {
mluis 0:91d1a7783bb9 2306 while( macIndex < commandsSize )
mluis 0:91d1a7783bb9 2307 {
mluis 0:91d1a7783bb9 2308 // Decode Frame MAC commands
mluis 0:91d1a7783bb9 2309 switch( payload[macIndex++] )
mluis 0:91d1a7783bb9 2310 {
mluis 0:91d1a7783bb9 2311 case SRV_MAC_LINK_CHECK_ANS:
mluis 2:14a5d6ad92d5 2312 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 2:14a5d6ad92d5 2313 MlmeConfirm.DemodMargin = payload[macIndex++];
mluis 2:14a5d6ad92d5 2314 MlmeConfirm.NbGateways = payload[macIndex++];
mluis 0:91d1a7783bb9 2315 break;
mluis 0:91d1a7783bb9 2316 case SRV_MAC_LINK_ADR_REQ:
mluis 0:91d1a7783bb9 2317 {
mluis 2:14a5d6ad92d5 2318 uint8_t i;
mluis 0:91d1a7783bb9 2319 uint8_t status = 0x07;
mluis 0:91d1a7783bb9 2320 uint16_t chMask;
mluis 0:91d1a7783bb9 2321 int8_t txPower = 0;
mluis 0:91d1a7783bb9 2322 int8_t datarate = 0;
mluis 0:91d1a7783bb9 2323 uint8_t nbRep = 0;
mluis 0:91d1a7783bb9 2324 uint8_t chMaskCntl = 0;
mluis 0:91d1a7783bb9 2325 uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
mluis 2:14a5d6ad92d5 2326
mluis 0:91d1a7783bb9 2327 // Initialize local copy of the channels mask array
mluis 2:14a5d6ad92d5 2328 for( i = 0; i < 6; i++ )
mluis 0:91d1a7783bb9 2329 {
mluis 7:c16969e0f70f 2330 channelsMask[i] = LoRaMacParams.ChannelsMask[i];
mluis 0:91d1a7783bb9 2331 }
mluis 0:91d1a7783bb9 2332 datarate = payload[macIndex++];
mluis 0:91d1a7783bb9 2333 txPower = datarate & 0x0F;
mluis 0:91d1a7783bb9 2334 datarate = ( datarate >> 4 ) & 0x0F;
mluis 0:91d1a7783bb9 2335
mluis 2:14a5d6ad92d5 2336 if( ( AdrCtrlOn == false ) &&
mluis 7:c16969e0f70f 2337 ( ( LoRaMacParams.ChannelsDatarate != datarate ) || ( LoRaMacParams.ChannelsTxPower != txPower ) ) )
mluis 0:91d1a7783bb9 2338 { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower
mluis 0:91d1a7783bb9 2339 // Answer the server with fail status
mluis 0:91d1a7783bb9 2340 // Power ACK = 0
mluis 0:91d1a7783bb9 2341 // Data rate ACK = 0
mluis 0:91d1a7783bb9 2342 // Channel mask = 0
mluis 0:91d1a7783bb9 2343 AddMacCommand( MOTE_MAC_LINK_ADR_ANS, 0, 0 );
mluis 1:91e4e6c60d1e 2344 macIndex += 3; // Skip over the remaining bytes of the request
mluis 0:91d1a7783bb9 2345 break;
mluis 0:91d1a7783bb9 2346 }
mluis 1:91e4e6c60d1e 2347 chMask = ( uint16_t )payload[macIndex++];
mluis 1:91e4e6c60d1e 2348 chMask |= ( uint16_t )payload[macIndex++] << 8;
mluis 0:91d1a7783bb9 2349
mluis 0:91d1a7783bb9 2350 nbRep = payload[macIndex++];
mluis 0:91d1a7783bb9 2351 chMaskCntl = ( nbRep >> 4 ) & 0x07;
mluis 0:91d1a7783bb9 2352 nbRep &= 0x0F;
mluis 0:91d1a7783bb9 2353 if( nbRep == 0 )
mluis 0:91d1a7783bb9 2354 {
mluis 0:91d1a7783bb9 2355 nbRep = 1;
mluis 0:91d1a7783bb9 2356 }
mluis 0:91d1a7783bb9 2357 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 2358 if( ( chMaskCntl == 0 ) && ( chMask == 0 ) )
mluis 0:91d1a7783bb9 2359 {
mluis 0:91d1a7783bb9 2360 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 2361 }
mluis 2:14a5d6ad92d5 2362 else if( ( ( chMaskCntl >= 1 ) && ( chMaskCntl <= 5 )) ||
mluis 2:14a5d6ad92d5 2363 ( chMaskCntl >= 7 ) )
mluis 0:91d1a7783bb9 2364 {
mluis 0:91d1a7783bb9 2365 // RFU
mluis 0:91d1a7783bb9 2366 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 2367 }
mluis 0:91d1a7783bb9 2368 else
mluis 0:91d1a7783bb9 2369 {
mluis 2:14a5d6ad92d5 2370 for( i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
mluis 0:91d1a7783bb9 2371 {
mluis 0:91d1a7783bb9 2372 if( chMaskCntl == 6 )
mluis 0:91d1a7783bb9 2373 {
mluis 0:91d1a7783bb9 2374 if( Channels[i].Frequency != 0 )
mluis 0:91d1a7783bb9 2375 {
mluis 0:91d1a7783bb9 2376 chMask |= 1 << i;
mluis 0:91d1a7783bb9 2377 }
mluis 0:91d1a7783bb9 2378 }
mluis 0:91d1a7783bb9 2379 else
mluis 0:91d1a7783bb9 2380 {
mluis 0:91d1a7783bb9 2381 if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
mluis 0:91d1a7783bb9 2382 ( Channels[i].Frequency == 0 ) )
mluis 0:91d1a7783bb9 2383 {// Trying to enable an undefined channel
mluis 0:91d1a7783bb9 2384 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 2385 }
mluis 0:91d1a7783bb9 2386 }
mluis 0:91d1a7783bb9 2387 }
mluis 0:91d1a7783bb9 2388 channelsMask[0] = chMask;
mluis 0:91d1a7783bb9 2389 }
mluis 0:91d1a7783bb9 2390 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 2391 if( chMaskCntl == 6 )
mluis 0:91d1a7783bb9 2392 {
mluis 0:91d1a7783bb9 2393 // Enable all 125 kHz channels
mluis 0:91d1a7783bb9 2394 for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
mluis 0:91d1a7783bb9 2395 {
mluis 0:91d1a7783bb9 2396 for( uint8_t j = 0; j < 16; j++ )
mluis 0:91d1a7783bb9 2397 {
mluis 0:91d1a7783bb9 2398 if( Channels[i + j].Frequency != 0 )
mluis 0:91d1a7783bb9 2399 {
mluis 0:91d1a7783bb9 2400 channelsMask[k] |= 1 << j;
mluis 0:91d1a7783bb9 2401 }
mluis 0:91d1a7783bb9 2402 }
mluis 0:91d1a7783bb9 2403 }
mluis 0:91d1a7783bb9 2404 }
mluis 0:91d1a7783bb9 2405 else if( chMaskCntl == 7 )
mluis 0:91d1a7783bb9 2406 {
mluis 0:91d1a7783bb9 2407 // Disable all 125 kHz channels
mluis 0:91d1a7783bb9 2408 channelsMask[0] = 0x0000;
mluis 0:91d1a7783bb9 2409 channelsMask[1] = 0x0000;
mluis 0:91d1a7783bb9 2410 channelsMask[2] = 0x0000;
mluis 0:91d1a7783bb9 2411 channelsMask[3] = 0x0000;
mluis 0:91d1a7783bb9 2412 }
mluis 0:91d1a7783bb9 2413 else if( chMaskCntl == 5 )
mluis 0:91d1a7783bb9 2414 {
mluis 0:91d1a7783bb9 2415 // RFU
mluis 0:91d1a7783bb9 2416 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 2417 }
mluis 0:91d1a7783bb9 2418 else
mluis 0:91d1a7783bb9 2419 {
mluis 0:91d1a7783bb9 2420 for( uint8_t i = 0; i < 16; i++ )
mluis 0:91d1a7783bb9 2421 {
mluis 0:91d1a7783bb9 2422 if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
mluis 0:91d1a7783bb9 2423 ( Channels[chMaskCntl * 16 + i].Frequency == 0 ) )
mluis 0:91d1a7783bb9 2424 {// Trying to enable an undefined channel
mluis 0:91d1a7783bb9 2425 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 2426 }
mluis 0:91d1a7783bb9 2427 }
mluis 0:91d1a7783bb9 2428 channelsMask[chMaskCntl] = chMask;
mluis 2:14a5d6ad92d5 2429
mluis 0:91d1a7783bb9 2430 if( CountNbEnabled125kHzChannels( channelsMask ) < 6 )
mluis 0:91d1a7783bb9 2431 {
mluis 0:91d1a7783bb9 2432 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 2433 }
mluis 4:37c12dbc8dc7 2434
mluis 4:37c12dbc8dc7 2435 #if defined( USE_BAND_915_HYBRID )
mluis 4:37c12dbc8dc7 2436 if( ValidateChannelMask( channelsMask ) == false )
mluis 4:37c12dbc8dc7 2437 {
mluis 4:37c12dbc8dc7 2438 status &= 0xFE; // Channel mask KO
mluis 4:37c12dbc8dc7 2439 }
mluis 4:37c12dbc8dc7 2440 #endif
mluis 0:91d1a7783bb9 2441 }
mluis 0:91d1a7783bb9 2442 #else
mluis 0:91d1a7783bb9 2443 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 2444 #endif
mluis 4:37c12dbc8dc7 2445 if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false )
mluis 0:91d1a7783bb9 2446 {
mluis 0:91d1a7783bb9 2447 status &= 0xFD; // Datarate KO
mluis 0:91d1a7783bb9 2448 }
mluis 0:91d1a7783bb9 2449
mluis 0:91d1a7783bb9 2450 //
mluis 0:91d1a7783bb9 2451 // Remark MaxTxPower = 0 and MinTxPower = 5
mluis 0:91d1a7783bb9 2452 //
mluis 2:14a5d6ad92d5 2453 if( ValueInRange( txPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) == false )
mluis 0:91d1a7783bb9 2454 {
mluis 0:91d1a7783bb9 2455 status &= 0xFB; // TxPower KO
mluis 0:91d1a7783bb9 2456 }
mluis 0:91d1a7783bb9 2457 if( ( status & 0x07 ) == 0x07 )
mluis 0:91d1a7783bb9 2458 {
mluis 7:c16969e0f70f 2459 LoRaMacParams.ChannelsDatarate = datarate;
mluis 7:c16969e0f70f 2460 LoRaMacParams.ChannelsTxPower = txPower;
mluis 7:c16969e0f70f 2461
mluis 7:c16969e0f70f 2462 LoRaMacParams.ChannelsMask[0] = channelsMask[0];
mluis 7:c16969e0f70f 2463 LoRaMacParams.ChannelsMask[1] = channelsMask[1];
mluis 7:c16969e0f70f 2464 LoRaMacParams.ChannelsMask[2] = channelsMask[2];
mluis 7:c16969e0f70f 2465 LoRaMacParams.ChannelsMask[3] = channelsMask[3];
mluis 7:c16969e0f70f 2466 LoRaMacParams.ChannelsMask[4] = channelsMask[4];
mluis 7:c16969e0f70f 2467 LoRaMacParams.ChannelsMask[5] = channelsMask[5];
mluis 7:c16969e0f70f 2468
mluis 7:c16969e0f70f 2469 LoRaMacParams.ChannelsNbRep = nbRep;
mluis 0:91d1a7783bb9 2470 }
mluis 0:91d1a7783bb9 2471 AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
mluis 0:91d1a7783bb9 2472 }
mluis 0:91d1a7783bb9 2473 break;
mluis 0:91d1a7783bb9 2474 case SRV_MAC_DUTY_CYCLE_REQ:
mluis 0:91d1a7783bb9 2475 MaxDCycle = payload[macIndex++];
mluis 0:91d1a7783bb9 2476 AggregatedDCycle = 1 << MaxDCycle;
mluis 0:91d1a7783bb9 2477 AddMacCommand( MOTE_MAC_DUTY_CYCLE_ANS, 0, 0 );
mluis 0:91d1a7783bb9 2478 break;
mluis 0:91d1a7783bb9 2479 case SRV_MAC_RX_PARAM_SETUP_REQ:
mluis 0:91d1a7783bb9 2480 {
mluis 0:91d1a7783bb9 2481 uint8_t status = 0x07;
mluis 0:91d1a7783bb9 2482 int8_t datarate = 0;
mluis 0:91d1a7783bb9 2483 int8_t drOffset = 0;
mluis 0:91d1a7783bb9 2484 uint32_t freq = 0;
mluis 2:14a5d6ad92d5 2485
mluis 1:91e4e6c60d1e 2486 drOffset = ( payload[macIndex] >> 4 ) & 0x07;
mluis 1:91e4e6c60d1e 2487 datarate = payload[macIndex] & 0x0F;
mluis 1:91e4e6c60d1e 2488 macIndex++;
mluis 2:14a5d6ad92d5 2489
mluis 2:14a5d6ad92d5 2490 freq = ( uint32_t )payload[macIndex++];
mluis 0:91d1a7783bb9 2491 freq |= ( uint32_t )payload[macIndex++] << 8;
mluis 0:91d1a7783bb9 2492 freq |= ( uint32_t )payload[macIndex++] << 16;
mluis 0:91d1a7783bb9 2493 freq *= 100;
mluis 2:14a5d6ad92d5 2494
mluis 7:c16969e0f70f 2495 if( Rx2FreqInRange( freq ) == false )
mluis 0:91d1a7783bb9 2496 {
mluis 0:91d1a7783bb9 2497 status &= 0xFE; // Channel frequency KO
mluis 0:91d1a7783bb9 2498 }
mluis 2:14a5d6ad92d5 2499
mluis 4:37c12dbc8dc7 2500 if( ValueInRange( datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE ) == false )
mluis 0:91d1a7783bb9 2501 {
mluis 0:91d1a7783bb9 2502 status &= 0xFD; // Datarate KO
mluis 0:91d1a7783bb9 2503 }
mluis 2:14a5d6ad92d5 2504 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 2:14a5d6ad92d5 2505 if( ( ValueInRange( datarate, DR_5, DR_7 ) == true ) ||
mluis 2:14a5d6ad92d5 2506 ( datarate > DR_13 ) )
mluis 2:14a5d6ad92d5 2507 {
mluis 2:14a5d6ad92d5 2508 status &= 0xFD; // Datarate KO
mluis 2:14a5d6ad92d5 2509 }
mluis 2:14a5d6ad92d5 2510 #endif
mluis 2:14a5d6ad92d5 2511 if( ValueInRange( drOffset, LORAMAC_MIN_RX1_DR_OFFSET, LORAMAC_MAX_RX1_DR_OFFSET ) == false )
mluis 0:91d1a7783bb9 2512 {
mluis 0:91d1a7783bb9 2513 status &= 0xFB; // Rx1DrOffset range KO
mluis 0:91d1a7783bb9 2514 }
mluis 2:14a5d6ad92d5 2515
mluis 0:91d1a7783bb9 2516 if( ( status & 0x07 ) == 0x07 )
mluis 0:91d1a7783bb9 2517 {
mluis 7:c16969e0f70f 2518 LoRaMacParams.Rx2Channel.Datarate = datarate;
mluis 7:c16969e0f70f 2519 LoRaMacParams.Rx2Channel.Frequency = freq;
mluis 7:c16969e0f70f 2520 LoRaMacParams.Rx1DrOffset = drOffset;
mluis 0:91d1a7783bb9 2521 }
mluis 0:91d1a7783bb9 2522 AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
mluis 0:91d1a7783bb9 2523 }
mluis 0:91d1a7783bb9 2524 break;
mluis 0:91d1a7783bb9 2525 case SRV_MAC_DEV_STATUS_REQ:
mluis 1:91e4e6c60d1e 2526 {
mluis 1:91e4e6c60d1e 2527 uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
mluis 1:91e4e6c60d1e 2528 if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) )
mluis 1:91e4e6c60d1e 2529 {
mluis 1:91e4e6c60d1e 2530 batteryLevel = LoRaMacCallbacks->GetBatteryLevel( );
mluis 1:91e4e6c60d1e 2531 }
mluis 2:14a5d6ad92d5 2532 AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr );
mluis 2:14a5d6ad92d5 2533 break;
mluis 1:91e4e6c60d1e 2534 }
mluis 0:91d1a7783bb9 2535 case SRV_MAC_NEW_CHANNEL_REQ:
mluis 0:91d1a7783bb9 2536 {
mluis 0:91d1a7783bb9 2537 uint8_t status = 0x03;
mluis 3:b9d87593a8ae 2538
mluis 2:14a5d6ad92d5 2539 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 3:b9d87593a8ae 2540 status &= 0xFC; // Channel frequency and datarate KO
mluis 3:b9d87593a8ae 2541 macIndex += 5;
mluis 2:14a5d6ad92d5 2542 #else
mluis 0:91d1a7783bb9 2543 int8_t channelIndex = 0;
mluis 0:91d1a7783bb9 2544 ChannelParams_t chParam;
mluis 2:14a5d6ad92d5 2545
mluis 0:91d1a7783bb9 2546 channelIndex = payload[macIndex++];
mluis 0:91d1a7783bb9 2547 chParam.Frequency = ( uint32_t )payload[macIndex++];
mluis 0:91d1a7783bb9 2548 chParam.Frequency |= ( uint32_t )payload[macIndex++] << 8;
mluis 0:91d1a7783bb9 2549 chParam.Frequency |= ( uint32_t )payload[macIndex++] << 16;
mluis 0:91d1a7783bb9 2550 chParam.Frequency *= 100;
mluis 0:91d1a7783bb9 2551 chParam.DrRange.Value = payload[macIndex++];
mluis 2:14a5d6ad92d5 2552
mluis 3:b9d87593a8ae 2553 LoRaMacState |= MAC_TX_CONFIG;
mluis 3:b9d87593a8ae 2554 if( chParam.Frequency == 0 )
mluis 0:91d1a7783bb9 2555 {
mluis 3:b9d87593a8ae 2556 if( channelIndex < 3 )
mluis 3:b9d87593a8ae 2557 {
mluis 3:b9d87593a8ae 2558 status &= 0xFC;
mluis 3:b9d87593a8ae 2559 }
mluis 3:b9d87593a8ae 2560 else
mluis 3:b9d87593a8ae 2561 {
mluis 3:b9d87593a8ae 2562 if( LoRaMacChannelRemove( channelIndex ) != LORAMAC_STATUS_OK )
mluis 3:b9d87593a8ae 2563 {
mluis 3:b9d87593a8ae 2564 status &= 0xFC;
mluis 3:b9d87593a8ae 2565 }
mluis 3:b9d87593a8ae 2566 }
mluis 0:91d1a7783bb9 2567 }
mluis 3:b9d87593a8ae 2568 else
mluis 0:91d1a7783bb9 2569 {
mluis 3:b9d87593a8ae 2570 switch( LoRaMacChannelAdd( channelIndex, chParam ) )
mluis 3:b9d87593a8ae 2571 {
mluis 3:b9d87593a8ae 2572 case LORAMAC_STATUS_OK:
mluis 3:b9d87593a8ae 2573 {
mluis 3:b9d87593a8ae 2574 break;
mluis 3:b9d87593a8ae 2575 }
mluis 3:b9d87593a8ae 2576 case LORAMAC_STATUS_FREQUENCY_INVALID:
mluis 3:b9d87593a8ae 2577 {
mluis 3:b9d87593a8ae 2578 status &= 0xFE;
mluis 3:b9d87593a8ae 2579 break;
mluis 3:b9d87593a8ae 2580 }
mluis 3:b9d87593a8ae 2581 case LORAMAC_STATUS_DATARATE_INVALID:
mluis 3:b9d87593a8ae 2582 {
mluis 3:b9d87593a8ae 2583 status &= 0xFD;
mluis 3:b9d87593a8ae 2584 break;
mluis 3:b9d87593a8ae 2585 }
mluis 3:b9d87593a8ae 2586 case LORAMAC_STATUS_FREQ_AND_DR_INVALID:
mluis 3:b9d87593a8ae 2587 {
mluis 3:b9d87593a8ae 2588 status &= 0xFC;
mluis 3:b9d87593a8ae 2589 break;
mluis 3:b9d87593a8ae 2590 }
mluis 3:b9d87593a8ae 2591 default:
mluis 3:b9d87593a8ae 2592 {
mluis 3:b9d87593a8ae 2593 status &= 0xFC;
mluis 3:b9d87593a8ae 2594 break;
mluis 3:b9d87593a8ae 2595 }
mluis 3:b9d87593a8ae 2596 }
mluis 0:91d1a7783bb9 2597 }
mluis 3:b9d87593a8ae 2598 LoRaMacState &= ~MAC_TX_CONFIG;
mluis 2:14a5d6ad92d5 2599 #endif
mluis 0:91d1a7783bb9 2600 AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
mluis 0:91d1a7783bb9 2601 }
mluis 0:91d1a7783bb9 2602 break;
mluis 0:91d1a7783bb9 2603 case SRV_MAC_RX_TIMING_SETUP_REQ:
mluis 0:91d1a7783bb9 2604 {
mluis 0:91d1a7783bb9 2605 uint8_t delay = payload[macIndex++] & 0x0F;
mluis 2:14a5d6ad92d5 2606
mluis 0:91d1a7783bb9 2607 if( delay == 0 )
mluis 0:91d1a7783bb9 2608 {
mluis 0:91d1a7783bb9 2609 delay++;
mluis 0:91d1a7783bb9 2610 }
mluis 7:c16969e0f70f 2611 LoRaMacParams.ReceiveDelay1 = delay * 1e6;
mluis 7:c16969e0f70f 2612 LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6;
mluis 0:91d1a7783bb9 2613 AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
mluis 0:91d1a7783bb9 2614 }
mluis 0:91d1a7783bb9 2615 break;
mluis 0:91d1a7783bb9 2616 default:
mluis 0:91d1a7783bb9 2617 // Unknown command. ABORT MAC commands processing
mluis 0:91d1a7783bb9 2618 return;
mluis 0:91d1a7783bb9 2619 }
mluis 0:91d1a7783bb9 2620 }
mluis 0:91d1a7783bb9 2621 }
mluis 0:91d1a7783bb9 2622
mluis 2:14a5d6ad92d5 2623 LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
mluis 0:91d1a7783bb9 2624 {
mluis 2:14a5d6ad92d5 2625 LoRaMacFrameCtrl_t fCtrl;
mluis 2:14a5d6ad92d5 2626 LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 2627
mluis 2:14a5d6ad92d5 2628 fCtrl.Value = 0;
mluis 2:14a5d6ad92d5 2629 fCtrl.Bits.FOptsLen = 0;
mluis 2:14a5d6ad92d5 2630 fCtrl.Bits.FPending = 0;
mluis 2:14a5d6ad92d5 2631 fCtrl.Bits.Ack = false;
mluis 2:14a5d6ad92d5 2632 fCtrl.Bits.AdrAckReq = false;
mluis 2:14a5d6ad92d5 2633 fCtrl.Bits.Adr = AdrCtrlOn;
mluis 2:14a5d6ad92d5 2634
mluis 2:14a5d6ad92d5 2635 // Prepare the frame
mluis 2:14a5d6ad92d5 2636 status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize );
mluis 2:14a5d6ad92d5 2637
mluis 2:14a5d6ad92d5 2638 // Validate status
mluis 2:14a5d6ad92d5 2639 if( status != LORAMAC_STATUS_OK )
mluis 0:91d1a7783bb9 2640 {
mluis 2:14a5d6ad92d5 2641 return status;
mluis 0:91d1a7783bb9 2642 }
mluis 2:14a5d6ad92d5 2643
mluis 2:14a5d6ad92d5 2644 // Reset confirm parameters
mluis 2:14a5d6ad92d5 2645 McpsConfirm.NbRetries = 0;
mluis 2:14a5d6ad92d5 2646 McpsConfirm.AckReceived = false;
mluis 2:14a5d6ad92d5 2647 McpsConfirm.UpLinkCounter = UpLinkCounter;
mluis 2:14a5d6ad92d5 2648
mluis 2:14a5d6ad92d5 2649 status = ScheduleTx( );
mluis 2:14a5d6ad92d5 2650
mluis 2:14a5d6ad92d5 2651 return status;
mluis 0:91d1a7783bb9 2652 }
mluis 0:91d1a7783bb9 2653
mluis 2:14a5d6ad92d5 2654 static LoRaMacStatus_t ScheduleTx( )
mluis 0:91d1a7783bb9 2655 {
mluis 2:14a5d6ad92d5 2656 TimerTime_t dutyCycleTimeOff = 0;
mluis 2:14a5d6ad92d5 2657
mluis 2:14a5d6ad92d5 2658 // Check if the device is off
mluis 2:14a5d6ad92d5 2659 if( MaxDCycle == 255 )
mluis 2:14a5d6ad92d5 2660 {
mluis 2:14a5d6ad92d5 2661 return LORAMAC_STATUS_DEVICE_OFF;
mluis 2:14a5d6ad92d5 2662 }
mluis 2:14a5d6ad92d5 2663 if( MaxDCycle == 0 )
mluis 0:91d1a7783bb9 2664 {
mluis 2:14a5d6ad92d5 2665 AggregatedTimeOff = 0;
mluis 2:14a5d6ad92d5 2666 }
mluis 2:14a5d6ad92d5 2667
mluis 4:37c12dbc8dc7 2668 CalculateBackOff( LastTxChannel );
mluis 4:37c12dbc8dc7 2669
mluis 2:14a5d6ad92d5 2670 // Select channel
mluis 3:b9d87593a8ae 2671 while( SetNextChannel( &dutyCycleTimeOff ) == false )
mluis 3:b9d87593a8ae 2672 {
mluis 3:b9d87593a8ae 2673 // Set the default datarate
mluis 7:c16969e0f70f 2674 LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
mluis 3:b9d87593a8ae 2675
mluis 3:b9d87593a8ae 2676 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 3:b9d87593a8ae 2677 // Re-enable default channels LC1, LC2, LC3
mluis 7:c16969e0f70f 2678 LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
mluis 3:b9d87593a8ae 2679 #endif
mluis 3:b9d87593a8ae 2680 }
mluis 2:14a5d6ad92d5 2681
mluis 2:14a5d6ad92d5 2682 // Schedule transmission of frame
mluis 2:14a5d6ad92d5 2683 if( dutyCycleTimeOff == 0 )
mluis 2:14a5d6ad92d5 2684 {
mluis 2:14a5d6ad92d5 2685 // Try to send now
mluis 2:14a5d6ad92d5 2686 return SendFrameOnChannel( Channels[Channel] );
mluis 0:91d1a7783bb9 2687 }
mluis 0:91d1a7783bb9 2688 else
mluis 0:91d1a7783bb9 2689 {
mluis 2:14a5d6ad92d5 2690 // Send later - prepare timer
mluis 2:14a5d6ad92d5 2691 LoRaMacState |= MAC_TX_DELAYED;
mluis 2:14a5d6ad92d5 2692 TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
mluis 2:14a5d6ad92d5 2693 TimerStart( &TxDelayedTimer );
mluis 2:14a5d6ad92d5 2694
mluis 2:14a5d6ad92d5 2695 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 2696 }
mluis 2:14a5d6ad92d5 2697 }
mluis 2:14a5d6ad92d5 2698
mluis 7:c16969e0f70f 2699 static uint16_t RetransmissionDutyCylce( void )
mluis 7:c16969e0f70f 2700 {
mluis 7:c16969e0f70f 2701 uint16_t dutyCycle = 0;
mluis 7:c16969e0f70f 2702
mluis 7:c16969e0f70f 2703 #if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
mluis 7:c16969e0f70f 2704 TimerTime_t timeElapsed = TimerGetElapsedTime( 0 );
mluis 7:c16969e0f70f 2705
mluis 7:c16969e0f70f 2706 if( timeElapsed < 3600000000 )
mluis 7:c16969e0f70f 2707 {
mluis 7:c16969e0f70f 2708 dutyCycle = BACKOFF_DC_1_HOUR;
mluis 7:c16969e0f70f 2709 }
mluis 7:c16969e0f70f 2710 else if( timeElapsed < ( 3600000000 + 36000000000 ) )
mluis 7:c16969e0f70f 2711 {
mluis 7:c16969e0f70f 2712 dutyCycle = BACKOFF_DC_10_HOURS;
mluis 7:c16969e0f70f 2713 }
mluis 7:c16969e0f70f 2714 else
mluis 7:c16969e0f70f 2715 {
mluis 7:c16969e0f70f 2716 dutyCycle = BACKOFF_DC_24_HOURS;
mluis 7:c16969e0f70f 2717 }
mluis 7:c16969e0f70f 2718 #endif
mluis 7:c16969e0f70f 2719 return dutyCycle;
mluis 7:c16969e0f70f 2720 }
mluis 7:c16969e0f70f 2721
mluis 4:37c12dbc8dc7 2722 static void CalculateBackOff( uint8_t channel )
mluis 4:37c12dbc8dc7 2723 {
mluis 4:37c12dbc8dc7 2724 uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
mluis 7:c16969e0f70f 2725 uint16_t joinDutyCycle = 0;
mluis 7:c16969e0f70f 2726 bool rndTimeOff = false;
mluis 4:37c12dbc8dc7 2727
mluis 4:37c12dbc8dc7 2728 if( IsLoRaMacNetworkJoined == false )
mluis 4:37c12dbc8dc7 2729 {
mluis 7:c16969e0f70f 2730 joinDutyCycle = RetransmissionDutyCylce( );
mluis 7:c16969e0f70f 2731 dutyCycle = MAX( dutyCycle, joinDutyCycle );
mluis 7:c16969e0f70f 2732
mluis 7:c16969e0f70f 2733 // Make sure to not apply the random back-off to the first TX
mluis 7:c16969e0f70f 2734 if( TxTimeOnAir > 0 )
mluis 7:c16969e0f70f 2735 {
mluis 7:c16969e0f70f 2736 rndTimeOff = true;
mluis 7:c16969e0f70f 2737 }
mluis 4:37c12dbc8dc7 2738 }
mluis 4:37c12dbc8dc7 2739
mluis 4:37c12dbc8dc7 2740 // Update Band Time OFF
mluis 4:37c12dbc8dc7 2741 if( DutyCycleOn == true )
mluis 4:37c12dbc8dc7 2742 {
mluis 4:37c12dbc8dc7 2743 Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
mluis 4:37c12dbc8dc7 2744 }
mluis 4:37c12dbc8dc7 2745 else
mluis 4:37c12dbc8dc7 2746 {
mluis 4:37c12dbc8dc7 2747 Bands[Channels[channel].Band].TimeOff = 0;
mluis 4:37c12dbc8dc7 2748 }
mluis 7:c16969e0f70f 2749
mluis 7:c16969e0f70f 2750 if( rndTimeOff == true )
mluis 7:c16969e0f70f 2751 {
mluis 7:c16969e0f70f 2752 Bands[Channels[channel].Band].TimeOff = randr( Bands[Channels[channel].Band].TimeOff,
mluis 7:c16969e0f70f 2753 Bands[Channels[channel].Band].TimeOff + BACKOFF_RND_OFFSET );
mluis 7:c16969e0f70f 2754 }
mluis 7:c16969e0f70f 2755
mluis 4:37c12dbc8dc7 2756 // Update Aggregated Time OFF
mluis 4:37c12dbc8dc7 2757 AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
mluis 4:37c12dbc8dc7 2758 }
mluis 4:37c12dbc8dc7 2759
mluis 7:c16969e0f70f 2760 static int8_t AlternateDatarate( uint16_t nbTrials )
mluis 7:c16969e0f70f 2761 {
mluis 7:c16969e0f70f 2762 int8_t datarate = LORAMAC_TX_MIN_DATARATE;
mluis 7:c16969e0f70f 2763 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 2764 #if defined( USE_BAND_915 )
mluis 7:c16969e0f70f 2765 // Re-enable 500 kHz default channels
mluis 7:c16969e0f70f 2766 LoRaMacParams.ChannelsMask[4] = 0x00FF;
mluis 7:c16969e0f70f 2767 #else // defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 2768 // Re-enable 500 kHz default channels
mluis 7:c16969e0f70f 2769 ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask );
mluis 7:c16969e0f70f 2770 #endif
mluis 7:c16969e0f70f 2771
mluis 7:c16969e0f70f 2772 if( ( nbTrials & 0x01 ) == 0x01 )
mluis 7:c16969e0f70f 2773 {
mluis 7:c16969e0f70f 2774 datarate = DR_4;
mluis 7:c16969e0f70f 2775 }
mluis 7:c16969e0f70f 2776 else
mluis 7:c16969e0f70f 2777 {
mluis 7:c16969e0f70f 2778 datarate = DR_1;
mluis 7:c16969e0f70f 2779 }
mluis 7:c16969e0f70f 2780 #else
mluis 7:c16969e0f70f 2781 if( ( nbTrials % 48 ) == 0 )
mluis 7:c16969e0f70f 2782 {
mluis 7:c16969e0f70f 2783 datarate = DR_0;
mluis 7:c16969e0f70f 2784 }
mluis 7:c16969e0f70f 2785 else if( ( nbTrials % 32 ) == 0 )
mluis 7:c16969e0f70f 2786 {
mluis 7:c16969e0f70f 2787 datarate = DR_1;
mluis 7:c16969e0f70f 2788 }
mluis 7:c16969e0f70f 2789 else if( ( nbTrials % 24 ) == 0 )
mluis 7:c16969e0f70f 2790 {
mluis 7:c16969e0f70f 2791 datarate = DR_2;
mluis 7:c16969e0f70f 2792 }
mluis 7:c16969e0f70f 2793 else if( ( nbTrials % 16 ) == 0 )
mluis 7:c16969e0f70f 2794 {
mluis 7:c16969e0f70f 2795 datarate = DR_3;
mluis 7:c16969e0f70f 2796 }
mluis 7:c16969e0f70f 2797 else if( ( nbTrials % 8 ) == 0 )
mluis 7:c16969e0f70f 2798 {
mluis 7:c16969e0f70f 2799 datarate = DR_4;
mluis 7:c16969e0f70f 2800 }
mluis 7:c16969e0f70f 2801 else
mluis 7:c16969e0f70f 2802 {
mluis 7:c16969e0f70f 2803 datarate = DR_5;
mluis 7:c16969e0f70f 2804 }
mluis 7:c16969e0f70f 2805 #endif
mluis 7:c16969e0f70f 2806 return datarate;
mluis 7:c16969e0f70f 2807 }
mluis 7:c16969e0f70f 2808
mluis 7:c16969e0f70f 2809 static void ResetMacParameters( void )
mluis 7:c16969e0f70f 2810 {
mluis 7:c16969e0f70f 2811 IsLoRaMacNetworkJoined = false;
mluis 7:c16969e0f70f 2812
mluis 7:c16969e0f70f 2813 // Counters
mluis 7:c16969e0f70f 2814 UpLinkCounter = 1;
mluis 7:c16969e0f70f 2815 DownLinkCounter = 0;
mluis 7:c16969e0f70f 2816 AdrAckCounter = 0;
mluis 7:c16969e0f70f 2817
mluis 7:c16969e0f70f 2818 ChannelsNbRepCounter = 0;
mluis 7:c16969e0f70f 2819
mluis 7:c16969e0f70f 2820 AckTimeoutRetries = 1;
mluis 7:c16969e0f70f 2821 AckTimeoutRetriesCounter = 1;
mluis 7:c16969e0f70f 2822 AckTimeoutRetry = false;
mluis 7:c16969e0f70f 2823
mluis 7:c16969e0f70f 2824 MaxDCycle = 0;
mluis 7:c16969e0f70f 2825 AggregatedDCycle = 1;
mluis 7:c16969e0f70f 2826
mluis 7:c16969e0f70f 2827 MacCommandsBufferIndex = 0;
mluis 7:c16969e0f70f 2828 MacCommandsBufferToRepeatIndex = 0;
mluis 7:c16969e0f70f 2829
mluis 7:c16969e0f70f 2830 IsRxWindowsEnabled = true;
mluis 7:c16969e0f70f 2831
mluis 7:c16969e0f70f 2832 LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
mluis 7:c16969e0f70f 2833 LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
mluis 7:c16969e0f70f 2834
mluis 7:c16969e0f70f 2835 LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow;
mluis 7:c16969e0f70f 2836 LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1;
mluis 7:c16969e0f70f 2837 LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2;
mluis 7:c16969e0f70f 2838 LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1;
mluis 7:c16969e0f70f 2839 LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2;
mluis 7:c16969e0f70f 2840
mluis 7:c16969e0f70f 2841 LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset;
mluis 7:c16969e0f70f 2842 LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep;
mluis 7:c16969e0f70f 2843
mluis 7:c16969e0f70f 2844 LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
mluis 7:c16969e0f70f 2845
mluis 7:c16969e0f70f 2846 memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
mluis 7:c16969e0f70f 2847
mluis 7:c16969e0f70f 2848 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 2849 memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
mluis 7:c16969e0f70f 2850 #endif
mluis 7:c16969e0f70f 2851
mluis 7:c16969e0f70f 2852
mluis 7:c16969e0f70f 2853 NodeAckRequested = false;
mluis 7:c16969e0f70f 2854 SrvAckRequested = false;
mluis 7:c16969e0f70f 2855 MacCommandsInNextTx = false;
mluis 7:c16969e0f70f 2856
mluis 7:c16969e0f70f 2857 // Reset Multicast downlink counters
mluis 7:c16969e0f70f 2858 MulticastParams_t *cur = MulticastChannels;
mluis 7:c16969e0f70f 2859 while( cur != NULL )
mluis 7:c16969e0f70f 2860 {
mluis 7:c16969e0f70f 2861 cur->DownLinkCounter = 0;
mluis 7:c16969e0f70f 2862 cur = cur->Next;
mluis 7:c16969e0f70f 2863 }
mluis 7:c16969e0f70f 2864
mluis 7:c16969e0f70f 2865 // Initialize channel index.
mluis 7:c16969e0f70f 2866 Channel = LORA_MAX_NB_CHANNELS;
mluis 7:c16969e0f70f 2867 }
mluis 7:c16969e0f70f 2868
mluis 2:14a5d6ad92d5 2869 LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
mluis 2:14a5d6ad92d5 2870 {
mluis 2:14a5d6ad92d5 2871 uint16_t i;
mluis 2:14a5d6ad92d5 2872 uint8_t pktHeaderLen = 0;
mluis 2:14a5d6ad92d5 2873 uint32_t mic = 0;
mluis 2:14a5d6ad92d5 2874 const void* payload = fBuffer;
mluis 2:14a5d6ad92d5 2875 uint8_t payloadSize = fBufferSize;
mluis 2:14a5d6ad92d5 2876 uint8_t framePort = fPort;
mluis 2:14a5d6ad92d5 2877
mluis 2:14a5d6ad92d5 2878 LoRaMacBufferPktLen = 0;
mluis 2:14a5d6ad92d5 2879
mluis 2:14a5d6ad92d5 2880 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 2881
mluis 2:14a5d6ad92d5 2882 if( fBuffer == NULL )
mluis 0:91d1a7783bb9 2883 {
mluis 2:14a5d6ad92d5 2884 fBufferSize = 0;
mluis 2:14a5d6ad92d5 2885 }
mluis 2:14a5d6ad92d5 2886
mluis 2:14a5d6ad92d5 2887 LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
mluis 2:14a5d6ad92d5 2888
mluis 2:14a5d6ad92d5 2889 switch( macHdr->Bits.MType )
mluis 2:14a5d6ad92d5 2890 {
mluis 2:14a5d6ad92d5 2891 case FRAME_TYPE_JOIN_REQ:
mluis 7:c16969e0f70f 2892 RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
mluis 7:c16969e0f70f 2893 RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
mluis 2:14a5d6ad92d5 2894
mluis 2:14a5d6ad92d5 2895 LoRaMacBufferPktLen = pktHeaderLen;
mluis 2:14a5d6ad92d5 2896
mluis 2:14a5d6ad92d5 2897 memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
mluis 2:14a5d6ad92d5 2898 LoRaMacBufferPktLen += 8;
mluis 2:14a5d6ad92d5 2899 memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacDevEui, 8 );
mluis 2:14a5d6ad92d5 2900 LoRaMacBufferPktLen += 8;
mluis 2:14a5d6ad92d5 2901
mluis 2:14a5d6ad92d5 2902 LoRaMacDevNonce = Radio.Random( );
mluis 2:14a5d6ad92d5 2903
mluis 2:14a5d6ad92d5 2904 LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF;
mluis 2:14a5d6ad92d5 2905 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( LoRaMacDevNonce >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 2906
mluis 2:14a5d6ad92d5 2907 LoRaMacJoinComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic );
mluis 2:14a5d6ad92d5 2908
mluis 2:14a5d6ad92d5 2909 LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF;
mluis 2:14a5d6ad92d5 2910 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 2911 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF;
mluis 2:14a5d6ad92d5 2912 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF;
mluis 2:14a5d6ad92d5 2913
mluis 2:14a5d6ad92d5 2914 break;
mluis 2:14a5d6ad92d5 2915 case FRAME_TYPE_DATA_CONFIRMED_UP:
mluis 2:14a5d6ad92d5 2916 NodeAckRequested = true;
mluis 2:14a5d6ad92d5 2917 //Intentional falltrough
mluis 2:14a5d6ad92d5 2918 case FRAME_TYPE_DATA_UNCONFIRMED_UP:
mluis 2:14a5d6ad92d5 2919 if( IsLoRaMacNetworkJoined == false )
mluis 0:91d1a7783bb9 2920 {
mluis 2:14a5d6ad92d5 2921 return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet
mluis 2:14a5d6ad92d5 2922 }
mluis 2:14a5d6ad92d5 2923
mluis 7:c16969e0f70f 2924 fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate );
mluis 7:c16969e0f70f 2925
mluis 7:c16969e0f70f 2926 if( ValidatePayloadLength( fBufferSize, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false )
mluis 2:14a5d6ad92d5 2927 {
mluis 2:14a5d6ad92d5 2928 return LORAMAC_STATUS_LENGTH_ERROR;
mluis 2:14a5d6ad92d5 2929 }
mluis 2:14a5d6ad92d5 2930
mluis 7:c16969e0f70f 2931 RxWindow1Delay = LoRaMacParams.ReceiveDelay1 - RADIO_WAKEUP_TIME;
mluis 7:c16969e0f70f 2932 RxWindow2Delay = LoRaMacParams.ReceiveDelay2 - RADIO_WAKEUP_TIME;
mluis 2:14a5d6ad92d5 2933
mluis 2:14a5d6ad92d5 2934 if( SrvAckRequested == true )
mluis 2:14a5d6ad92d5 2935 {
mluis 2:14a5d6ad92d5 2936 SrvAckRequested = false;
mluis 2:14a5d6ad92d5 2937 fCtrl->Bits.Ack = 1;
mluis 2:14a5d6ad92d5 2938 }
mluis 2:14a5d6ad92d5 2939
mluis 2:14a5d6ad92d5 2940 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;
mluis 2:14a5d6ad92d5 2941 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 2942 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;
mluis 2:14a5d6ad92d5 2943 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF;
mluis 2:14a5d6ad92d5 2944
mluis 2:14a5d6ad92d5 2945 LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value;
mluis 2:14a5d6ad92d5 2946
mluis 2:14a5d6ad92d5 2947 LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
mluis 2:14a5d6ad92d5 2948 LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 2949
mluis 7:c16969e0f70f 2950 // Copy the MAC commands which must be re-send into the MAC command buffer
mluis 7:c16969e0f70f 2951 memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
mluis 7:c16969e0f70f 2952 MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
mluis 7:c16969e0f70f 2953
mluis 2:14a5d6ad92d5 2954 if( ( payload != NULL ) && ( payloadSize > 0 ) )
mluis 2:14a5d6ad92d5 2955 {
mluis 2:14a5d6ad92d5 2956 if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
mluis 1:91e4e6c60d1e 2957 {
mluis 2:14a5d6ad92d5 2958 fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
mluis 2:14a5d6ad92d5 2959
mluis 2:14a5d6ad92d5 2960 // Update FCtrl field with new value of OptionsLength
mluis 2:14a5d6ad92d5 2961 LoRaMacBuffer[0x05] = fCtrl->Value;
mluis 2:14a5d6ad92d5 2962 for( i = 0; i < MacCommandsBufferIndex; i++ )
mluis 0:91d1a7783bb9 2963 {
mluis 2:14a5d6ad92d5 2964 LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
mluis 0:91d1a7783bb9 2965 }
mluis 0:91d1a7783bb9 2966 }
mluis 0:91d1a7783bb9 2967 }
mluis 0:91d1a7783bb9 2968 else
mluis 0:91d1a7783bb9 2969 {
mluis 2:14a5d6ad92d5 2970 if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
mluis 0:91d1a7783bb9 2971 {
mluis 2:14a5d6ad92d5 2972 payloadSize = MacCommandsBufferIndex;
mluis 2:14a5d6ad92d5 2973 payload = MacCommandsBuffer;
mluis 2:14a5d6ad92d5 2974 framePort = 0;
mluis 0:91d1a7783bb9 2975 }
mluis 2:14a5d6ad92d5 2976 }
mluis 2:14a5d6ad92d5 2977 MacCommandsInNextTx = false;
mluis 7:c16969e0f70f 2978 // Store MAC commands which must be re-send in case the device does not receive a downlink anymore
mluis 7:c16969e0f70f 2979 MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat );
mluis 7:c16969e0f70f 2980 if( MacCommandsBufferToRepeatIndex > 0 )
mluis 7:c16969e0f70f 2981 {
mluis 7:c16969e0f70f 2982 MacCommandsInNextTx = true;
mluis 7:c16969e0f70f 2983 }
mluis 2:14a5d6ad92d5 2984 MacCommandsBufferIndex = 0;
mluis 2:14a5d6ad92d5 2985
mluis 2:14a5d6ad92d5 2986 if( ( payload != NULL ) && ( payloadSize > 0 ) )
mluis 2:14a5d6ad92d5 2987 {
mluis 2:14a5d6ad92d5 2988 LoRaMacBuffer[pktHeaderLen++] = framePort;
mluis 2:14a5d6ad92d5 2989
mluis 2:14a5d6ad92d5 2990 if( framePort == 0 )
mluis 0:91d1a7783bb9 2991 {
mluis 2:14a5d6ad92d5 2992 LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
mluis 0:91d1a7783bb9 2993 }
mluis 0:91d1a7783bb9 2994 else
mluis 0:91d1a7783bb9 2995 {
mluis 2:14a5d6ad92d5 2996 LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
mluis 0:91d1a7783bb9 2997 }
mluis 2:14a5d6ad92d5 2998 memcpy1( LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, payloadSize );
mluis 2:14a5d6ad92d5 2999 }
mluis 2:14a5d6ad92d5 3000 LoRaMacBufferPktLen = pktHeaderLen + payloadSize;
mluis 2:14a5d6ad92d5 3001
mluis 2:14a5d6ad92d5 3002 LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
mluis 2:14a5d6ad92d5 3003
mluis 2:14a5d6ad92d5 3004 LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;
mluis 2:14a5d6ad92d5 3005 LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 3006 LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0xFF;
mluis 2:14a5d6ad92d5 3007 LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF;
mluis 2:14a5d6ad92d5 3008
mluis 2:14a5d6ad92d5 3009 LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
mluis 2:14a5d6ad92d5 3010
mluis 2:14a5d6ad92d5 3011 break;
mluis 2:14a5d6ad92d5 3012 case FRAME_TYPE_PROPRIETARY:
mluis 2:14a5d6ad92d5 3013 if( ( fBuffer != NULL ) && ( fBufferSize > 0 ) )
mluis 2:14a5d6ad92d5 3014 {
mluis 2:14a5d6ad92d5 3015 memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, fBufferSize );
mluis 2:14a5d6ad92d5 3016 LoRaMacBufferPktLen = pktHeaderLen + fBufferSize;
mluis 0:91d1a7783bb9 3017 }
mluis 0:91d1a7783bb9 3018 break;
mluis 0:91d1a7783bb9 3019 default:
mluis 2:14a5d6ad92d5 3020 return LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 0:91d1a7783bb9 3021 }
mluis 2:14a5d6ad92d5 3022
mluis 2:14a5d6ad92d5 3023 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 3024 }
mluis 0:91d1a7783bb9 3025
mluis 2:14a5d6ad92d5 3026 LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel )
mluis 0:91d1a7783bb9 3027 {
mluis 7:c16969e0f70f 3028 int8_t datarate = Datarates[LoRaMacParams.ChannelsDatarate];
mluis 4:37c12dbc8dc7 3029 int8_t txPowerIndex = 0;
mluis 2:14a5d6ad92d5 3030 int8_t txPower = 0;
mluis 2:14a5d6ad92d5 3031
mluis 7:c16969e0f70f 3032 txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower );
mluis 4:37c12dbc8dc7 3033 txPower = TxPowers[txPowerIndex];
mluis 2:14a5d6ad92d5 3034
mluis 2:14a5d6ad92d5 3035 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 2:14a5d6ad92d5 3036 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 7:c16969e0f70f 3037 McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
mluis 4:37c12dbc8dc7 3038 McpsConfirm.TxPower = txPowerIndex;
mluis 2:14a5d6ad92d5 3039
mluis 2:14a5d6ad92d5 3040 Radio.SetChannel( channel.Frequency );
mluis 2:14a5d6ad92d5 3041
mluis 2:14a5d6ad92d5 3042 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 7:c16969e0f70f 3043 if( LoRaMacParams.ChannelsDatarate == DR_7 )
mluis 2:14a5d6ad92d5 3044 { // High Speed FSK channel
mluis 2:14a5d6ad92d5 3045 Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen );
mluis 2:14a5d6ad92d5 3046 Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 );
mluis 2:14a5d6ad92d5 3047 TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
mluis 2:14a5d6ad92d5 3048
mluis 0:91d1a7783bb9 3049 }
mluis 7:c16969e0f70f 3050 else if( LoRaMacParams.ChannelsDatarate == DR_6 )
mluis 2:14a5d6ad92d5 3051 { // High speed LoRa channel
mluis 2:14a5d6ad92d5 3052 Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
mluis 2:14a5d6ad92d5 3053 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
mluis 2:14a5d6ad92d5 3054 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3055 }
mluis 1:91e4e6c60d1e 3056 else
mluis 2:14a5d6ad92d5 3057 { // Normal LoRa channel
mluis 2:14a5d6ad92d5 3058 Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
mluis 2:14a5d6ad92d5 3059 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
mluis 2:14a5d6ad92d5 3060 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3061 }
mluis 2:14a5d6ad92d5 3062 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 3063 Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
mluis 7:c16969e0f70f 3064 if( LoRaMacParams.ChannelsDatarate >= DR_4 )
mluis 2:14a5d6ad92d5 3065 { // High speed LoRa channel BW500 kHz
mluis 2:14a5d6ad92d5 3066 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
mluis 2:14a5d6ad92d5 3067 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3068 }
mluis 1:91e4e6c60d1e 3069 else
mluis 2:14a5d6ad92d5 3070 { // Normal LoRa channel
mluis 2:14a5d6ad92d5 3071 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
mluis 2:14a5d6ad92d5 3072 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3073 }
mluis 0:91d1a7783bb9 3074 #else
mluis 0:91d1a7783bb9 3075 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 3076 #endif
mluis 2:14a5d6ad92d5 3077
mluis 2:14a5d6ad92d5 3078 // Store the time on air
mluis 2:14a5d6ad92d5 3079 McpsConfirm.TxTimeOnAir = TxTimeOnAir;
mluis 2:14a5d6ad92d5 3080 MlmeConfirm.TxTimeOnAir = TxTimeOnAir;
mluis 2:14a5d6ad92d5 3081
mluis 2:14a5d6ad92d5 3082 // Starts the MAC layer status check timer
mluis 3:b9d87593a8ae 3083 TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
mluis 2:14a5d6ad92d5 3084 TimerStart( &MacStateCheckTimer );
mluis 2:14a5d6ad92d5 3085
mluis 2:14a5d6ad92d5 3086 // Send now
mluis 2:14a5d6ad92d5 3087 Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
mluis 2:14a5d6ad92d5 3088
mluis 2:14a5d6ad92d5 3089 LoRaMacState |= MAC_TX_RUNNING;
mluis 2:14a5d6ad92d5 3090
mluis 2:14a5d6ad92d5 3091 return LORAMAC_STATUS_OK;
mluis 2:14a5d6ad92d5 3092 }
mluis 2:14a5d6ad92d5 3093
mluis 2:14a5d6ad92d5 3094 LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks )
mluis 2:14a5d6ad92d5 3095 {
mluis 2:14a5d6ad92d5 3096 if( primitives == NULL )
mluis 2:14a5d6ad92d5 3097 {
mluis 2:14a5d6ad92d5 3098 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3099 }
mluis 2:14a5d6ad92d5 3100
mluis 2:14a5d6ad92d5 3101 if( ( primitives->MacMcpsConfirm == NULL ) ||
mluis 2:14a5d6ad92d5 3102 ( primitives->MacMcpsIndication == NULL ) ||
mluis 2:14a5d6ad92d5 3103 ( primitives->MacMlmeConfirm == NULL ))
mluis 2:14a5d6ad92d5 3104 {
mluis 2:14a5d6ad92d5 3105 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3106 }
mluis 2:14a5d6ad92d5 3107
mluis 2:14a5d6ad92d5 3108 LoRaMacPrimitives = primitives;
mluis 2:14a5d6ad92d5 3109 LoRaMacCallbacks = callbacks;
mluis 2:14a5d6ad92d5 3110
mluis 2:14a5d6ad92d5 3111 LoRaMacFlags.Value = 0;
mluis 2:14a5d6ad92d5 3112
mluis 2:14a5d6ad92d5 3113 LoRaMacDeviceClass = CLASS_A;
mluis 7:c16969e0f70f 3114 LoRaMacState = MAC_IDLE;
mluis 7:c16969e0f70f 3115
mluis 7:c16969e0f70f 3116 JoinRequestTrials = 0;
mluis 2:14a5d6ad92d5 3117 RepeaterSupport = false;
mluis 7:c16969e0f70f 3118
mluis 7:c16969e0f70f 3119 // Reset duty cycle times
mluis 7:c16969e0f70f 3120 AggregatedLastTxDoneTime = 0;
mluis 7:c16969e0f70f 3121 AggregatedTimeOff = 0;
mluis 7:c16969e0f70f 3122
mluis 7:c16969e0f70f 3123 // Duty cycle
mluis 2:14a5d6ad92d5 3124 #if defined( USE_BAND_433 )
mluis 7:c16969e0f70f 3125 DutyCycleOn = false;
mluis 2:14a5d6ad92d5 3126 #elif defined( USE_BAND_780 )
mluis 7:c16969e0f70f 3127 DutyCycleOn = false;
mluis 2:14a5d6ad92d5 3128 #elif defined( USE_BAND_868 )
mluis 7:c16969e0f70f 3129 DutyCycleOn = true;
mluis 7:c16969e0f70f 3130 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 3131 DutyCycleOn = false;
mluis 7:c16969e0f70f 3132 #else
mluis 7:c16969e0f70f 3133 #error "Please define a frequency band in the compiler options."
mluis 7:c16969e0f70f 3134 #endif
mluis 7:c16969e0f70f 3135
mluis 7:c16969e0f70f 3136 // Reset to defaults
mluis 7:c16969e0f70f 3137 LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
mluis 7:c16969e0f70f 3138 LoRaMacParamsDefaults.ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
mluis 7:c16969e0f70f 3139
mluis 7:c16969e0f70f 3140 LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW;
mluis 7:c16969e0f70f 3141 LoRaMacParamsDefaults.ReceiveDelay1 = RECEIVE_DELAY1;
mluis 7:c16969e0f70f 3142 LoRaMacParamsDefaults.ReceiveDelay2 = RECEIVE_DELAY2;
mluis 7:c16969e0f70f 3143 LoRaMacParamsDefaults.JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
mluis 7:c16969e0f70f 3144 LoRaMacParamsDefaults.JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
mluis 7:c16969e0f70f 3145
mluis 7:c16969e0f70f 3146 LoRaMacParamsDefaults.ChannelsNbRep = 1;
mluis 7:c16969e0f70f 3147 LoRaMacParamsDefaults.Rx1DrOffset = 0;
mluis 7:c16969e0f70f 3148
mluis 7:c16969e0f70f 3149 LoRaMacParamsDefaults.Rx2Channel = ( Rx2ChannelParams_t )RX_WND_2_CHANNEL;
mluis 7:c16969e0f70f 3150
mluis 7:c16969e0f70f 3151 // Channel mask
mluis 7:c16969e0f70f 3152 #if defined( USE_BAND_433 )
mluis 7:c16969e0f70f 3153 LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 7:c16969e0f70f 3154 #elif defined( USE_BAND_780 )
mluis 7:c16969e0f70f 3155 LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 7:c16969e0f70f 3156 #elif defined( USE_BAND_868 )
mluis 7:c16969e0f70f 3157 LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 2:14a5d6ad92d5 3158 #elif defined( USE_BAND_915 )
mluis 7:c16969e0f70f 3159 LoRaMacParamsDefaults.ChannelsMask[0] = 0xFFFF;
mluis 7:c16969e0f70f 3160 LoRaMacParamsDefaults.ChannelsMask[1] = 0xFFFF;
mluis 7:c16969e0f70f 3161 LoRaMacParamsDefaults.ChannelsMask[2] = 0xFFFF;
mluis 7:c16969e0f70f 3162 LoRaMacParamsDefaults.ChannelsMask[3] = 0xFFFF;
mluis 7:c16969e0f70f 3163 LoRaMacParamsDefaults.ChannelsMask[4] = 0x00FF;
mluis 7:c16969e0f70f 3164 LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000;
mluis 2:14a5d6ad92d5 3165 #elif defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 3166 LoRaMacParamsDefaults.ChannelsMask[0] = 0x00FF;
mluis 7:c16969e0f70f 3167 LoRaMacParamsDefaults.ChannelsMask[1] = 0x0000;
mluis 7:c16969e0f70f 3168 LoRaMacParamsDefaults.ChannelsMask[2] = 0x0000;
mluis 7:c16969e0f70f 3169 LoRaMacParamsDefaults.ChannelsMask[3] = 0x0000;
mluis 7:c16969e0f70f 3170 LoRaMacParamsDefaults.ChannelsMask[4] = 0x0001;
mluis 7:c16969e0f70f 3171 LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000;
mluis 2:14a5d6ad92d5 3172 #else
mluis 2:14a5d6ad92d5 3173 #error "Please define a frequency band in the compiler options."
mluis 2:14a5d6ad92d5 3174 #endif
mluis 2:14a5d6ad92d5 3175
mluis 2:14a5d6ad92d5 3176 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 3177 // 125 kHz channels
mluis 2:14a5d6ad92d5 3178 for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ )
mluis 0:91d1a7783bb9 3179 {
mluis 2:14a5d6ad92d5 3180 Channels[i].Frequency = 902.3e6 + i * 200e3;
mluis 2:14a5d6ad92d5 3181 Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
mluis 2:14a5d6ad92d5 3182 Channels[i].Band = 0;
mluis 2:14a5d6ad92d5 3183 }
mluis 2:14a5d6ad92d5 3184 // 500 kHz channels
mluis 2:14a5d6ad92d5 3185 for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ )
mluis 2:14a5d6ad92d5 3186 {
mluis 2:14a5d6ad92d5 3187 Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6;
mluis 2:14a5d6ad92d5 3188 Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
mluis 2:14a5d6ad92d5 3189 Channels[i].Band = 0;
mluis 2:14a5d6ad92d5 3190 }
mluis 2:14a5d6ad92d5 3191 #endif
mluis 2:14a5d6ad92d5 3192
mluis 7:c16969e0f70f 3193 ResetMacParameters( );
mluis 7:c16969e0f70f 3194
mluis 7:c16969e0f70f 3195 // Initialize timers
mluis 2:14a5d6ad92d5 3196 TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent );
mluis 2:14a5d6ad92d5 3197 TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
mluis 2:14a5d6ad92d5 3198
mluis 2:14a5d6ad92d5 3199 TimerInit( &TxDelayedTimer, OnTxDelayedTimerEvent );
mluis 2:14a5d6ad92d5 3200 TimerInit( &RxWindowTimer1, OnRxWindow1TimerEvent );
mluis 2:14a5d6ad92d5 3201 TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
mluis 2:14a5d6ad92d5 3202 TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
mluis 2:14a5d6ad92d5 3203
mluis 2:14a5d6ad92d5 3204 // Initialize Radio driver
mluis 2:14a5d6ad92d5 3205 RadioEvents.TxDone = OnRadioTxDone;
mluis 2:14a5d6ad92d5 3206 RadioEvents.RxDone = OnRadioRxDone;
mluis 2:14a5d6ad92d5 3207 RadioEvents.RxError = OnRadioRxError;
mluis 2:14a5d6ad92d5 3208 RadioEvents.TxTimeout = OnRadioTxTimeout;
mluis 2:14a5d6ad92d5 3209 RadioEvents.RxTimeout = OnRadioRxTimeout;
mluis 2:14a5d6ad92d5 3210 Radio.Init( &RadioEvents );
mluis 2:14a5d6ad92d5 3211
mluis 2:14a5d6ad92d5 3212 // Random seed initialization
mluis 2:14a5d6ad92d5 3213 srand1( Radio.Random( ) );
mluis 2:14a5d6ad92d5 3214
mluis 2:14a5d6ad92d5 3215 PublicNetwork = true;
mluis 2:14a5d6ad92d5 3216 SetPublicNetwork( PublicNetwork );
mluis 2:14a5d6ad92d5 3217 Radio.Sleep( );
mluis 2:14a5d6ad92d5 3218
mluis 2:14a5d6ad92d5 3219 return LORAMAC_STATUS_OK;
mluis 2:14a5d6ad92d5 3220 }
mluis 2:14a5d6ad92d5 3221
mluis 2:14a5d6ad92d5 3222 LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
mluis 2:14a5d6ad92d5 3223 {
mluis 7:c16969e0f70f 3224 int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate;
mluis 7:c16969e0f70f 3225 uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
mluis 2:14a5d6ad92d5 3226
mluis 2:14a5d6ad92d5 3227 if( txInfo == NULL )
mluis 2:14a5d6ad92d5 3228 {
mluis 2:14a5d6ad92d5 3229 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3230 }
mluis 2:14a5d6ad92d5 3231
mluis 2:14a5d6ad92d5 3232 AdrNextDr( AdrCtrlOn, false, &datarate );
mluis 2:14a5d6ad92d5 3233
mluis 2:14a5d6ad92d5 3234 if( RepeaterSupport == true )
mluis 2:14a5d6ad92d5 3235 {
mluis 2:14a5d6ad92d5 3236 txInfo->CurrentPayloadSize = MaxPayloadOfDatarateRepeater[datarate];
mluis 0:91d1a7783bb9 3237 }
mluis 0:91d1a7783bb9 3238 else
mluis 0:91d1a7783bb9 3239 {
mluis 2:14a5d6ad92d5 3240 txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate];
mluis 0:91d1a7783bb9 3241 }
mluis 2:14a5d6ad92d5 3242
mluis 7:c16969e0f70f 3243 if( txInfo->CurrentPayloadSize >= fOptLen )
mluis 0:91d1a7783bb9 3244 {
mluis 7:c16969e0f70f 3245 txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
mluis 0:91d1a7783bb9 3246 }
mluis 0:91d1a7783bb9 3247 else
mluis 0:91d1a7783bb9 3248 {
mluis 2:14a5d6ad92d5 3249 return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
mluis 2:14a5d6ad92d5 3250 }
mluis 2:14a5d6ad92d5 3251
mluis 2:14a5d6ad92d5 3252 if( ValidatePayloadLength( size, datarate, 0 ) == false )
mluis 2:14a5d6ad92d5 3253 {
mluis 2:14a5d6ad92d5 3254 return LORAMAC_STATUS_LENGTH_ERROR;
mluis 0:91d1a7783bb9 3255 }
mluis 2:14a5d6ad92d5 3256
mluis 7:c16969e0f70f 3257 if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
mluis 0:91d1a7783bb9 3258 {
mluis 2:14a5d6ad92d5 3259 return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
mluis 0:91d1a7783bb9 3260 }
mluis 0:91d1a7783bb9 3261
mluis 2:14a5d6ad92d5 3262 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 3263 }
mluis 0:91d1a7783bb9 3264
mluis 2:14a5d6ad92d5 3265 LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
mluis 0:91d1a7783bb9 3266 {
mluis 2:14a5d6ad92d5 3267 LoRaMacStatus_t status = LORAMAC_STATUS_OK;
mluis 2:14a5d6ad92d5 3268
mluis 2:14a5d6ad92d5 3269 if( mibGet == NULL )
mluis 2:14a5d6ad92d5 3270 {
mluis 2:14a5d6ad92d5 3271 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3272 }
mluis 2:14a5d6ad92d5 3273
mluis 2:14a5d6ad92d5 3274 switch( mibGet->Type )
mluis 0:91d1a7783bb9 3275 {
mluis 2:14a5d6ad92d5 3276 case MIB_DEVICE_CLASS:
mluis 2:14a5d6ad92d5 3277 {
mluis 2:14a5d6ad92d5 3278 mibGet->Param.Class = LoRaMacDeviceClass;
mluis 2:14a5d6ad92d5 3279 break;
mluis 2:14a5d6ad92d5 3280 }
mluis 2:14a5d6ad92d5 3281 case MIB_NETWORK_JOINED:
mluis 2:14a5d6ad92d5 3282 {
mluis 2:14a5d6ad92d5 3283 mibGet->Param.IsNetworkJoined = IsLoRaMacNetworkJoined;
mluis 2:14a5d6ad92d5 3284 break;
mluis 2:14a5d6ad92d5 3285 }
mluis 2:14a5d6ad92d5 3286 case MIB_ADR:
mluis 2:14a5d6ad92d5 3287 {
mluis 2:14a5d6ad92d5 3288 mibGet->Param.AdrEnable = AdrCtrlOn;
mluis 2:14a5d6ad92d5 3289 break;
mluis 2:14a5d6ad92d5 3290 }
mluis 2:14a5d6ad92d5 3291 case MIB_NET_ID:
mluis 2:14a5d6ad92d5 3292 {
mluis 2:14a5d6ad92d5 3293 mibGet->Param.NetID = LoRaMacNetID;
mluis 2:14a5d6ad92d5 3294 break;
mluis 2:14a5d6ad92d5 3295 }
mluis 2:14a5d6ad92d5 3296 case MIB_DEV_ADDR:
mluis 2:14a5d6ad92d5 3297 {
mluis 2:14a5d6ad92d5 3298 mibGet->Param.DevAddr = LoRaMacDevAddr;
mluis 2:14a5d6ad92d5 3299 break;
mluis 2:14a5d6ad92d5 3300 }
mluis 2:14a5d6ad92d5 3301 case MIB_NWK_SKEY:
mluis 2:14a5d6ad92d5 3302 {
mluis 2:14a5d6ad92d5 3303 mibGet->Param.NwkSKey = LoRaMacNwkSKey;
mluis 2:14a5d6ad92d5 3304 break;
mluis 2:14a5d6ad92d5 3305 }
mluis 2:14a5d6ad92d5 3306 case MIB_APP_SKEY:
mluis 2:14a5d6ad92d5 3307 {
mluis 2:14a5d6ad92d5 3308 mibGet->Param.AppSKey = LoRaMacAppSKey;
mluis 2:14a5d6ad92d5 3309 break;
mluis 2:14a5d6ad92d5 3310 }
mluis 2:14a5d6ad92d5 3311 case MIB_PUBLIC_NETWORK:
mluis 2:14a5d6ad92d5 3312 {
mluis 2:14a5d6ad92d5 3313 mibGet->Param.EnablePublicNetwork = PublicNetwork;
mluis 2:14a5d6ad92d5 3314 break;
mluis 2:14a5d6ad92d5 3315 }
mluis 2:14a5d6ad92d5 3316 case MIB_REPEATER_SUPPORT:
mluis 2:14a5d6ad92d5 3317 {
mluis 2:14a5d6ad92d5 3318 mibGet->Param.EnableRepeaterSupport = RepeaterSupport;
mluis 2:14a5d6ad92d5 3319 break;
mluis 2:14a5d6ad92d5 3320 }
mluis 2:14a5d6ad92d5 3321 case MIB_CHANNELS:
mluis 2:14a5d6ad92d5 3322 {
mluis 2:14a5d6ad92d5 3323 mibGet->Param.ChannelList = Channels;
mluis 2:14a5d6ad92d5 3324 break;
mluis 2:14a5d6ad92d5 3325 }
mluis 2:14a5d6ad92d5 3326 case MIB_RX2_CHANNEL:
mluis 2:14a5d6ad92d5 3327 {
mluis 7:c16969e0f70f 3328 mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel;
mluis 2:14a5d6ad92d5 3329 break;
mluis 2:14a5d6ad92d5 3330 }
mluis 2:14a5d6ad92d5 3331 case MIB_CHANNELS_MASK:
mluis 2:14a5d6ad92d5 3332 {
mluis 7:c16969e0f70f 3333 mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask;
mluis 2:14a5d6ad92d5 3334 break;
mluis 0:91d1a7783bb9 3335 }
mluis 2:14a5d6ad92d5 3336 case MIB_CHANNELS_NB_REP:
mluis 2:14a5d6ad92d5 3337 {
mluis 7:c16969e0f70f 3338 mibGet->Param.ChannelNbRep = LoRaMacParams.ChannelsNbRep;
mluis 2:14a5d6ad92d5 3339 break;
mluis 2:14a5d6ad92d5 3340 }
mluis 2:14a5d6ad92d5 3341 case MIB_MAX_RX_WINDOW_DURATION:
mluis 2:14a5d6ad92d5 3342 {
mluis 7:c16969e0f70f 3343 mibGet->Param.MaxRxWindow = LoRaMacParams.MaxRxWindow;
mluis 2:14a5d6ad92d5 3344 break;
mluis 2:14a5d6ad92d5 3345 }
mluis 2:14a5d6ad92d5 3346 case MIB_RECEIVE_DELAY_1:
mluis 2:14a5d6ad92d5 3347 {
mluis 7:c16969e0f70f 3348 mibGet->Param.ReceiveDelay1 = LoRaMacParams.ReceiveDelay1;
mluis 2:14a5d6ad92d5 3349 break;
mluis 2:14a5d6ad92d5 3350 }
mluis 2:14a5d6ad92d5 3351 case MIB_RECEIVE_DELAY_2:
mluis 2:14a5d6ad92d5 3352 {
mluis 7:c16969e0f70f 3353 mibGet->Param.ReceiveDelay2 = LoRaMacParams.ReceiveDelay2;
mluis 2:14a5d6ad92d5 3354 break;
mluis 2:14a5d6ad92d5 3355 }
mluis 2:14a5d6ad92d5 3356 case MIB_JOIN_ACCEPT_DELAY_1:
mluis 2:14a5d6ad92d5 3357 {
mluis 7:c16969e0f70f 3358 mibGet->Param.JoinAcceptDelay1 = LoRaMacParams.JoinAcceptDelay1;
mluis 2:14a5d6ad92d5 3359 break;
mluis 2:14a5d6ad92d5 3360 }
mluis 2:14a5d6ad92d5 3361 case MIB_JOIN_ACCEPT_DELAY_2:
mluis 2:14a5d6ad92d5 3362 {
mluis 7:c16969e0f70f 3363 mibGet->Param.JoinAcceptDelay2 = LoRaMacParams.JoinAcceptDelay2;
mluis 2:14a5d6ad92d5 3364 break;
mluis 2:14a5d6ad92d5 3365 }
mluis 4:37c12dbc8dc7 3366 case MIB_CHANNELS_DEFAULT_DATARATE:
mluis 4:37c12dbc8dc7 3367 {
mluis 7:c16969e0f70f 3368 mibGet->Param.ChannelsDefaultDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
mluis 4:37c12dbc8dc7 3369 break;
mluis 4:37c12dbc8dc7 3370 }
mluis 2:14a5d6ad92d5 3371 case MIB_CHANNELS_DATARATE:
mluis 2:14a5d6ad92d5 3372 {
mluis 7:c16969e0f70f 3373 mibGet->Param.ChannelsDatarate = LoRaMacParams.ChannelsDatarate;
mluis 2:14a5d6ad92d5 3374 break;
mluis 2:14a5d6ad92d5 3375 }
mluis 2:14a5d6ad92d5 3376 case MIB_CHANNELS_TX_POWER:
mluis 2:14a5d6ad92d5 3377 {
mluis 7:c16969e0f70f 3378 mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower;
mluis 2:14a5d6ad92d5 3379 break;
mluis 2:14a5d6ad92d5 3380 }
mluis 2:14a5d6ad92d5 3381 case MIB_UPLINK_COUNTER:
mluis 2:14a5d6ad92d5 3382 {
mluis 2:14a5d6ad92d5 3383 mibGet->Param.UpLinkCounter = UpLinkCounter;
mluis 2:14a5d6ad92d5 3384 break;
mluis 2:14a5d6ad92d5 3385 }
mluis 2:14a5d6ad92d5 3386 case MIB_DOWNLINK_COUNTER:
mluis 2:14a5d6ad92d5 3387 {
mluis 2:14a5d6ad92d5 3388 mibGet->Param.DownLinkCounter = DownLinkCounter;
mluis 2:14a5d6ad92d5 3389 break;
mluis 2:14a5d6ad92d5 3390 }
mluis 2:14a5d6ad92d5 3391 case MIB_MULTICAST_CHANNEL:
mluis 2:14a5d6ad92d5 3392 {
mluis 2:14a5d6ad92d5 3393 mibGet->Param.MulticastList = MulticastChannels;
mluis 2:14a5d6ad92d5 3394 break;
mluis 2:14a5d6ad92d5 3395 }
mluis 2:14a5d6ad92d5 3396 default:
mluis 2:14a5d6ad92d5 3397 status = LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 2:14a5d6ad92d5 3398 break;
mluis 0:91d1a7783bb9 3399 }
mluis 0:91d1a7783bb9 3400
mluis 2:14a5d6ad92d5 3401 return status;
mluis 0:91d1a7783bb9 3402 }
mluis 2:14a5d6ad92d5 3403
mluis 2:14a5d6ad92d5 3404 LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
mluis 0:91d1a7783bb9 3405 {
mluis 2:14a5d6ad92d5 3406 LoRaMacStatus_t status = LORAMAC_STATUS_OK;
mluis 2:14a5d6ad92d5 3407
mluis 2:14a5d6ad92d5 3408 if( mibSet == NULL )
mluis 2:14a5d6ad92d5 3409 {
mluis 2:14a5d6ad92d5 3410 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 0:91d1a7783bb9 3411 }
mluis 0:91d1a7783bb9 3412 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 0:91d1a7783bb9 3413 {
mluis 2:14a5d6ad92d5 3414 return LORAMAC_STATUS_BUSY;
mluis 0:91d1a7783bb9 3415 }
mluis 2:14a5d6ad92d5 3416
mluis 2:14a5d6ad92d5 3417 switch( mibSet->Type )
mluis 0:91d1a7783bb9 3418 {
mluis 2:14a5d6ad92d5 3419 case MIB_DEVICE_CLASS:
mluis 2:14a5d6ad92d5 3420 {
mluis 2:14a5d6ad92d5 3421 LoRaMacDeviceClass = mibSet->Param.Class;
mluis 2:14a5d6ad92d5 3422 switch( LoRaMacDeviceClass )
mluis 2:14a5d6ad92d5 3423 {
mluis 2:14a5d6ad92d5 3424 case CLASS_A:
mluis 2:14a5d6ad92d5 3425 {
mluis 2:14a5d6ad92d5 3426 // Set the radio into sleep to setup a defined state
mluis 2:14a5d6ad92d5 3427 Radio.Sleep( );
mluis 2:14a5d6ad92d5 3428 break;
mluis 2:14a5d6ad92d5 3429 }
mluis 2:14a5d6ad92d5 3430 case CLASS_B:
mluis 2:14a5d6ad92d5 3431 {
mluis 2:14a5d6ad92d5 3432 break;
mluis 2:14a5d6ad92d5 3433 }
mluis 2:14a5d6ad92d5 3434 case CLASS_C:
mluis 2:14a5d6ad92d5 3435 {
mluis 2:14a5d6ad92d5 3436 // Set the NodeAckRequested indicator to default
mluis 2:14a5d6ad92d5 3437 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 3438 OnRxWindow2TimerEvent( );
mluis 2:14a5d6ad92d5 3439 break;
mluis 2:14a5d6ad92d5 3440 }
mluis 2:14a5d6ad92d5 3441 }
mluis 2:14a5d6ad92d5 3442 break;
mluis 2:14a5d6ad92d5 3443 }
mluis 2:14a5d6ad92d5 3444 case MIB_NETWORK_JOINED:
mluis 2:14a5d6ad92d5 3445 {
mluis 2:14a5d6ad92d5 3446 IsLoRaMacNetworkJoined = mibSet->Param.IsNetworkJoined;
mluis 2:14a5d6ad92d5 3447 break;
mluis 2:14a5d6ad92d5 3448 }
mluis 2:14a5d6ad92d5 3449 case MIB_ADR:
mluis 2:14a5d6ad92d5 3450 {
mluis 2:14a5d6ad92d5 3451 AdrCtrlOn = mibSet->Param.AdrEnable;
mluis 2:14a5d6ad92d5 3452 break;
mluis 2:14a5d6ad92d5 3453 }
mluis 2:14a5d6ad92d5 3454 case MIB_NET_ID:
mluis 2:14a5d6ad92d5 3455 {
mluis 2:14a5d6ad92d5 3456 LoRaMacNetID = mibSet->Param.NetID;
mluis 2:14a5d6ad92d5 3457 break;
mluis 2:14a5d6ad92d5 3458 }
mluis 2:14a5d6ad92d5 3459 case MIB_DEV_ADDR:
mluis 2:14a5d6ad92d5 3460 {
mluis 2:14a5d6ad92d5 3461 LoRaMacDevAddr = mibSet->Param.DevAddr;
mluis 2:14a5d6ad92d5 3462 break;
mluis 2:14a5d6ad92d5 3463 }
mluis 2:14a5d6ad92d5 3464 case MIB_NWK_SKEY:
mluis 0:91d1a7783bb9 3465 {
mluis 2:14a5d6ad92d5 3466 if( mibSet->Param.NwkSKey != NULL )
mluis 2:14a5d6ad92d5 3467 {
mluis 2:14a5d6ad92d5 3468 memcpy1( LoRaMacNwkSKey, mibSet->Param.NwkSKey,
mluis 2:14a5d6ad92d5 3469 sizeof( LoRaMacNwkSKey ) );
mluis 2:14a5d6ad92d5 3470 }
mluis 2:14a5d6ad92d5 3471 else
mluis 2:14a5d6ad92d5 3472 {
mluis 2:14a5d6ad92d5 3473 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3474 }
mluis 2:14a5d6ad92d5 3475 break;
mluis 2:14a5d6ad92d5 3476 }
mluis 2:14a5d6ad92d5 3477 case MIB_APP_SKEY:
mluis 2:14a5d6ad92d5 3478 {
mluis 2:14a5d6ad92d5 3479 if( mibSet->Param.AppSKey != NULL )
mluis 2:14a5d6ad92d5 3480 {
mluis 2:14a5d6ad92d5 3481 memcpy1( LoRaMacAppSKey, mibSet->Param.AppSKey,
mluis 2:14a5d6ad92d5 3482 sizeof( LoRaMacAppSKey ) );
mluis 2:14a5d6ad92d5 3483 }
mluis 2:14a5d6ad92d5 3484 else
mluis 2:14a5d6ad92d5 3485 {
mluis 2:14a5d6ad92d5 3486 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3487 }
mluis 2:14a5d6ad92d5 3488 break;
mluis 2:14a5d6ad92d5 3489 }
mluis 2:14a5d6ad92d5 3490 case MIB_PUBLIC_NETWORK:
mluis 2:14a5d6ad92d5 3491 {
mluis 2:14a5d6ad92d5 3492 SetPublicNetwork( mibSet->Param.EnablePublicNetwork );
mluis 2:14a5d6ad92d5 3493 break;
mluis 0:91d1a7783bb9 3494 }
mluis 2:14a5d6ad92d5 3495 case MIB_REPEATER_SUPPORT:
mluis 2:14a5d6ad92d5 3496 {
mluis 2:14a5d6ad92d5 3497 RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
mluis 2:14a5d6ad92d5 3498 break;
mluis 2:14a5d6ad92d5 3499 }
mluis 2:14a5d6ad92d5 3500 case MIB_RX2_CHANNEL:
mluis 2:14a5d6ad92d5 3501 {
mluis 7:c16969e0f70f 3502 LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel;
mluis 2:14a5d6ad92d5 3503 break;
mluis 2:14a5d6ad92d5 3504 }
mluis 2:14a5d6ad92d5 3505 case MIB_CHANNELS_MASK:
mluis 2:14a5d6ad92d5 3506 {
mluis 2:14a5d6ad92d5 3507 if( mibSet->Param.ChannelsMask )
mluis 2:14a5d6ad92d5 3508 {
mluis 2:14a5d6ad92d5 3509 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 4:37c12dbc8dc7 3510 bool chanMaskState = true;
mluis 4:37c12dbc8dc7 3511
mluis 4:37c12dbc8dc7 3512 #if defined( USE_BAND_915_HYBRID )
mluis 4:37c12dbc8dc7 3513 chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsMask );
mluis 4:37c12dbc8dc7 3514 #endif
mluis 4:37c12dbc8dc7 3515 if( chanMaskState == true )
mluis 2:14a5d6ad92d5 3516 {
mluis 4:37c12dbc8dc7 3517 if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 6 ) &&
mluis 4:37c12dbc8dc7 3518 ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
mluis 4:37c12dbc8dc7 3519 {
mluis 4:37c12dbc8dc7 3520 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 4:37c12dbc8dc7 3521 }
mluis 4:37c12dbc8dc7 3522 else
mluis 4:37c12dbc8dc7 3523 {
mluis 7:c16969e0f70f 3524 memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
mluis 7:c16969e0f70f 3525 ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
mluis 7:c16969e0f70f 3526 for ( uint8_t i = 0; i < sizeof( LoRaMacParams.ChannelsMask ) / 2; i++ )
mluis 4:37c12dbc8dc7 3527 {
mluis 4:37c12dbc8dc7 3528 // Disable channels which are no longer available
mluis 7:c16969e0f70f 3529 ChannelsMaskRemaining[i] &= LoRaMacParams.ChannelsMask[i];
mluis 4:37c12dbc8dc7 3530 }
mluis 4:37c12dbc8dc7 3531 }
mluis 2:14a5d6ad92d5 3532 }
mluis 2:14a5d6ad92d5 3533 else
mluis 2:14a5d6ad92d5 3534 {
mluis 4:37c12dbc8dc7 3535 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3536 }
mluis 0:91d1a7783bb9 3537 #else
mluis 7:c16969e0f70f 3538 memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
mluis 2:14a5d6ad92d5 3539 ( uint8_t* ) mibSet->Param.ChannelsMask, 2 );
mluis 0:91d1a7783bb9 3540 #endif
mluis 2:14a5d6ad92d5 3541 }
mluis 2:14a5d6ad92d5 3542 else
mluis 2:14a5d6ad92d5 3543 {
mluis 2:14a5d6ad92d5 3544 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3545 }
mluis 2:14a5d6ad92d5 3546 break;
mluis 2:14a5d6ad92d5 3547 }
mluis 2:14a5d6ad92d5 3548 case MIB_CHANNELS_NB_REP:
mluis 2:14a5d6ad92d5 3549 {
mluis 2:14a5d6ad92d5 3550 if( ( mibSet->Param.ChannelNbRep >= 1 ) &&
mluis 2:14a5d6ad92d5 3551 ( mibSet->Param.ChannelNbRep <= 15 ) )
mluis 2:14a5d6ad92d5 3552 {
mluis 7:c16969e0f70f 3553 LoRaMacParams.ChannelsNbRep = mibSet->Param.ChannelNbRep;
mluis 2:14a5d6ad92d5 3554 }
mluis 2:14a5d6ad92d5 3555 else
mluis 2:14a5d6ad92d5 3556 {
mluis 2:14a5d6ad92d5 3557 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3558 }
mluis 2:14a5d6ad92d5 3559 break;
mluis 2:14a5d6ad92d5 3560 }
mluis 2:14a5d6ad92d5 3561 case MIB_MAX_RX_WINDOW_DURATION:
mluis 2:14a5d6ad92d5 3562 {
mluis 7:c16969e0f70f 3563 LoRaMacParams.MaxRxWindow = mibSet->Param.MaxRxWindow;
mluis 2:14a5d6ad92d5 3564 break;
mluis 2:14a5d6ad92d5 3565 }
mluis 2:14a5d6ad92d5 3566 case MIB_RECEIVE_DELAY_1:
mluis 2:14a5d6ad92d5 3567 {
mluis 7:c16969e0f70f 3568 LoRaMacParams.ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
mluis 2:14a5d6ad92d5 3569 break;
mluis 2:14a5d6ad92d5 3570 }
mluis 2:14a5d6ad92d5 3571 case MIB_RECEIVE_DELAY_2:
mluis 2:14a5d6ad92d5 3572 {
mluis 7:c16969e0f70f 3573 LoRaMacParams.ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
mluis 2:14a5d6ad92d5 3574 break;
mluis 2:14a5d6ad92d5 3575 }
mluis 2:14a5d6ad92d5 3576 case MIB_JOIN_ACCEPT_DELAY_1:
mluis 2:14a5d6ad92d5 3577 {
mluis 7:c16969e0f70f 3578 LoRaMacParams.JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
mluis 2:14a5d6ad92d5 3579 break;
mluis 2:14a5d6ad92d5 3580 }
mluis 2:14a5d6ad92d5 3581 case MIB_JOIN_ACCEPT_DELAY_2:
mluis 2:14a5d6ad92d5 3582 {
mluis 7:c16969e0f70f 3583 LoRaMacParams.JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
mluis 2:14a5d6ad92d5 3584 break;
mluis 2:14a5d6ad92d5 3585 }
mluis 4:37c12dbc8dc7 3586 case MIB_CHANNELS_DEFAULT_DATARATE:
mluis 4:37c12dbc8dc7 3587 {
mluis 4:37c12dbc8dc7 3588 if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
mluis 4:37c12dbc8dc7 3589 LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
mluis 4:37c12dbc8dc7 3590 {
mluis 7:c16969e0f70f 3591 LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
mluis 4:37c12dbc8dc7 3592 }
mluis 4:37c12dbc8dc7 3593 else
mluis 4:37c12dbc8dc7 3594 {
mluis 4:37c12dbc8dc7 3595 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 4:37c12dbc8dc7 3596 }
mluis 4:37c12dbc8dc7 3597 break;
mluis 4:37c12dbc8dc7 3598 }
mluis 2:14a5d6ad92d5 3599 case MIB_CHANNELS_DATARATE:
mluis 2:14a5d6ad92d5 3600 {
mluis 2:14a5d6ad92d5 3601 if( ValueInRange( mibSet->Param.ChannelsDatarate,
mluis 4:37c12dbc8dc7 3602 LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
mluis 2:14a5d6ad92d5 3603 {
mluis 7:c16969e0f70f 3604 LoRaMacParams.ChannelsDatarate = mibSet->Param.ChannelsDatarate;
mluis 2:14a5d6ad92d5 3605 }
mluis 2:14a5d6ad92d5 3606 else
mluis 2:14a5d6ad92d5 3607 {
mluis 2:14a5d6ad92d5 3608 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3609 }
mluis 2:14a5d6ad92d5 3610 break;
mluis 2:14a5d6ad92d5 3611 }
mluis 2:14a5d6ad92d5 3612 case MIB_CHANNELS_TX_POWER:
mluis 2:14a5d6ad92d5 3613 {
mluis 2:14a5d6ad92d5 3614 if( ValueInRange( mibSet->Param.ChannelsTxPower,
mluis 2:14a5d6ad92d5 3615 LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
mluis 2:14a5d6ad92d5 3616 {
mluis 7:c16969e0f70f 3617 LoRaMacParams.ChannelsTxPower = mibSet->Param.ChannelsTxPower;
mluis 2:14a5d6ad92d5 3618 }
mluis 2:14a5d6ad92d5 3619 else
mluis 2:14a5d6ad92d5 3620 {
mluis 2:14a5d6ad92d5 3621 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3622 }
mluis 2:14a5d6ad92d5 3623 break;
mluis 2:14a5d6ad92d5 3624 }
mluis 4:37c12dbc8dc7 3625 case MIB_UPLINK_COUNTER:
mluis 4:37c12dbc8dc7 3626 {
mluis 4:37c12dbc8dc7 3627 UpLinkCounter = mibSet->Param.UpLinkCounter;
mluis 4:37c12dbc8dc7 3628 break;
mluis 4:37c12dbc8dc7 3629 }
mluis 4:37c12dbc8dc7 3630 case MIB_DOWNLINK_COUNTER:
mluis 4:37c12dbc8dc7 3631 {
mluis 4:37c12dbc8dc7 3632 DownLinkCounter = mibSet->Param.DownLinkCounter;
mluis 4:37c12dbc8dc7 3633 break;
mluis 4:37c12dbc8dc7 3634 }
mluis 2:14a5d6ad92d5 3635 default:
mluis 2:14a5d6ad92d5 3636 status = LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 2:14a5d6ad92d5 3637 break;
mluis 0:91d1a7783bb9 3638 }
mluis 0:91d1a7783bb9 3639
mluis 2:14a5d6ad92d5 3640 return status;
mluis 0:91d1a7783bb9 3641 }
mluis 0:91d1a7783bb9 3642
mluis 2:14a5d6ad92d5 3643 LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
mluis 0:91d1a7783bb9 3644 {
mluis 3:b9d87593a8ae 3645 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 3:b9d87593a8ae 3646 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 3:b9d87593a8ae 3647 #else
mluis 3:b9d87593a8ae 3648 bool datarateInvalid = false;
mluis 3:b9d87593a8ae 3649 bool frequencyInvalid = false;
mluis 3:b9d87593a8ae 3650 uint8_t band = 0;
mluis 3:b9d87593a8ae 3651
mluis 3:b9d87593a8ae 3652 // The id must not exceed LORA_MAX_NB_CHANNELS
mluis 2:14a5d6ad92d5 3653 if( id >= LORA_MAX_NB_CHANNELS )
mluis 0:91d1a7783bb9 3654 {
mluis 2:14a5d6ad92d5 3655 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 0:91d1a7783bb9 3656 }
mluis 3:b9d87593a8ae 3657 // Validate if the MAC is in a correct state
mluis 2:14a5d6ad92d5 3658 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 0:91d1a7783bb9 3659 {
mluis 3:b9d87593a8ae 3660 if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
mluis 3:b9d87593a8ae 3661 {
mluis 3:b9d87593a8ae 3662 return LORAMAC_STATUS_BUSY;
mluis 3:b9d87593a8ae 3663 }
mluis 0:91d1a7783bb9 3664 }
mluis 3:b9d87593a8ae 3665 // Validate the datarate
mluis 2:14a5d6ad92d5 3666 if( ( params.DrRange.Fields.Min > params.DrRange.Fields.Max ) ||
mluis 4:37c12dbc8dc7 3667 ( ValueInRange( params.DrRange.Fields.Min, LORAMAC_TX_MIN_DATARATE,
mluis 4:37c12dbc8dc7 3668 LORAMAC_TX_MAX_DATARATE ) == false ) ||
mluis 4:37c12dbc8dc7 3669 ( ValueInRange( params.DrRange.Fields.Max, LORAMAC_TX_MIN_DATARATE,
mluis 4:37c12dbc8dc7 3670 LORAMAC_TX_MAX_DATARATE ) == false ) )
mluis 0:91d1a7783bb9 3671 {
mluis 3:b9d87593a8ae 3672 datarateInvalid = true;
mluis 0:91d1a7783bb9 3673 }
mluis 2:14a5d6ad92d5 3674
mluis 3:b9d87593a8ae 3675 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 3:b9d87593a8ae 3676 if( id < 3 )
mluis 0:91d1a7783bb9 3677 {
mluis 3:b9d87593a8ae 3678 if( params.Frequency != Channels[id].Frequency )
mluis 0:91d1a7783bb9 3679 {
mluis 3:b9d87593a8ae 3680 frequencyInvalid = true;
mluis 3:b9d87593a8ae 3681 }
mluis 3:b9d87593a8ae 3682
mluis 7:c16969e0f70f 3683 if( params.DrRange.Fields.Min > LoRaMacParamsDefaults.ChannelsDatarate )
mluis 3:b9d87593a8ae 3684 {
mluis 3:b9d87593a8ae 3685 datarateInvalid = true;
mluis 3:b9d87593a8ae 3686 }
mluis 4:37c12dbc8dc7 3687 if( ValueInRange( params.DrRange.Fields.Max, DR_5, LORAMAC_TX_MAX_DATARATE ) == false )
mluis 3:b9d87593a8ae 3688 {
mluis 3:b9d87593a8ae 3689 datarateInvalid = true;
mluis 0:91d1a7783bb9 3690 }
mluis 0:91d1a7783bb9 3691 }
mluis 3:b9d87593a8ae 3692 #endif
mluis 3:b9d87593a8ae 3693
mluis 3:b9d87593a8ae 3694 // Validate the frequency
mluis 3:b9d87593a8ae 3695 if( ( Radio.CheckRfFrequency( params.Frequency ) == true ) && ( params.Frequency > 0 ) && ( frequencyInvalid == false ) )
mluis 0:91d1a7783bb9 3696 {
mluis 3:b9d87593a8ae 3697 #if defined( USE_BAND_868 )
mluis 3:b9d87593a8ae 3698 if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
mluis 0:91d1a7783bb9 3699 {
mluis 3:b9d87593a8ae 3700 band = BAND_G1_0;
mluis 0:91d1a7783bb9 3701 }
mluis 3:b9d87593a8ae 3702 else if( ( params.Frequency > 868000000 ) && ( params.Frequency <= 868600000 ) )
mluis 0:91d1a7783bb9 3703 {
mluis 3:b9d87593a8ae 3704 band = BAND_G1_1;
mluis 0:91d1a7783bb9 3705 }
mluis 3:b9d87593a8ae 3706 else if( ( params.Frequency >= 868700000 ) && ( params.Frequency <= 869200000 ) )
mluis 0:91d1a7783bb9 3707 {
mluis 3:b9d87593a8ae 3708 band = BAND_G1_2;
mluis 3:b9d87593a8ae 3709 }
mluis 3:b9d87593a8ae 3710 else if( ( params.Frequency >= 869400000 ) && ( params.Frequency <= 869650000 ) )
mluis 3:b9d87593a8ae 3711 {
mluis 3:b9d87593a8ae 3712 band = BAND_G1_3;
mluis 0:91d1a7783bb9 3713 }
mluis 3:b9d87593a8ae 3714 else if( ( params.Frequency >= 869700000 ) && ( params.Frequency <= 870000000 ) )
mluis 0:91d1a7783bb9 3715 {
mluis 3:b9d87593a8ae 3716 band = BAND_G1_4;
mluis 0:91d1a7783bb9 3717 }
mluis 3:b9d87593a8ae 3718 else
mluis 3:b9d87593a8ae 3719 {
mluis 3:b9d87593a8ae 3720 frequencyInvalid = true;
mluis 3:b9d87593a8ae 3721 }
mluis 3:b9d87593a8ae 3722 #endif
mluis 0:91d1a7783bb9 3723 }
mluis 0:91d1a7783bb9 3724 else
mluis 0:91d1a7783bb9 3725 {
mluis 3:b9d87593a8ae 3726 frequencyInvalid = true;
mluis 3:b9d87593a8ae 3727 }
mluis 3:b9d87593a8ae 3728
mluis 3:b9d87593a8ae 3729 if( ( datarateInvalid == true ) && ( frequencyInvalid == true ) )
mluis 3:b9d87593a8ae 3730 {
mluis 3:b9d87593a8ae 3731 return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
mluis 0:91d1a7783bb9 3732 }
mluis 3:b9d87593a8ae 3733 if( datarateInvalid == true )
mluis 3:b9d87593a8ae 3734 {
mluis 3:b9d87593a8ae 3735 return LORAMAC_STATUS_DATARATE_INVALID;
mluis 3:b9d87593a8ae 3736 }
mluis 3:b9d87593a8ae 3737 if( frequencyInvalid == true )
mluis 0:91d1a7783bb9 3738 {
mluis 3:b9d87593a8ae 3739 return LORAMAC_STATUS_FREQUENCY_INVALID;
mluis 2:14a5d6ad92d5 3740 }
mluis 2:14a5d6ad92d5 3741
mluis 3:b9d87593a8ae 3742 // Every parameter is valid, activate the channel
mluis 3:b9d87593a8ae 3743 Channels[id] = params;
mluis 3:b9d87593a8ae 3744 Channels[id].Band = band;
mluis 7:c16969e0f70f 3745 LoRaMacParams.ChannelsMask[0] |= ( 1 << id );
mluis 3:b9d87593a8ae 3746
mluis 2:14a5d6ad92d5 3747 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 3748 #endif
mluis 0:91d1a7783bb9 3749 }
mluis 0:91d1a7783bb9 3750
mluis 2:14a5d6ad92d5 3751 LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
mluis 0:91d1a7783bb9 3752 {
mluis 3:b9d87593a8ae 3753 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 2:14a5d6ad92d5 3754 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 0:91d1a7783bb9 3755 {
mluis 3:b9d87593a8ae 3756 if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
mluis 3:b9d87593a8ae 3757 {
mluis 3:b9d87593a8ae 3758 return LORAMAC_STATUS_BUSY;
mluis 3:b9d87593a8ae 3759 }
mluis 0:91d1a7783bb9 3760 }
mluis 3:b9d87593a8ae 3761
mluis 4:37c12dbc8dc7 3762 if( ( id < 3 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
mluis 0:91d1a7783bb9 3763 {
mluis 3:b9d87593a8ae 3764 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 3:b9d87593a8ae 3765 }
mluis 3:b9d87593a8ae 3766 else
mluis 3:b9d87593a8ae 3767 {
mluis 3:b9d87593a8ae 3768 // Remove the channel from the list of channels
mluis 3:b9d87593a8ae 3769 Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 };
mluis 4:37c12dbc8dc7 3770
mluis 3:b9d87593a8ae 3771 // Disable the channel as it doesn't exist anymore
mluis 7:c16969e0f70f 3772 if( DisableChannelInMask( id, LoRaMacParams.ChannelsMask ) == false )
mluis 2:14a5d6ad92d5 3773 {
mluis 2:14a5d6ad92d5 3774 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3775 }
mluis 0:91d1a7783bb9 3776 }
mluis 3:b9d87593a8ae 3777 return LORAMAC_STATUS_OK;
mluis 3:b9d87593a8ae 3778 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 3:b9d87593a8ae 3779 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3780 #endif
mluis 2:14a5d6ad92d5 3781 }
mluis 2:14a5d6ad92d5 3782
mluis 2:14a5d6ad92d5 3783 LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam )
mluis 2:14a5d6ad92d5 3784 {
mluis 2:14a5d6ad92d5 3785 if( channelParam == NULL )
mluis 2:14a5d6ad92d5 3786 {
mluis 2:14a5d6ad92d5 3787 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3788 }
mluis 2:14a5d6ad92d5 3789 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 2:14a5d6ad92d5 3790 {
mluis 2:14a5d6ad92d5 3791 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 3792 }
mluis 2:14a5d6ad92d5 3793
mluis 2:14a5d6ad92d5 3794 // Reset downlink counter
mluis 2:14a5d6ad92d5 3795 channelParam->DownLinkCounter = 0;
mluis 2:14a5d6ad92d5 3796
mluis 2:14a5d6ad92d5 3797 if( MulticastChannels == NULL )
mluis 2:14a5d6ad92d5 3798 {
mluis 2:14a5d6ad92d5 3799 // New node is the fist element
mluis 2:14a5d6ad92d5 3800 MulticastChannels = channelParam;
mluis 0:91d1a7783bb9 3801 }
mluis 0:91d1a7783bb9 3802 else
mluis 0:91d1a7783bb9 3803 {
mluis 2:14a5d6ad92d5 3804 MulticastParams_t *cur = MulticastChannels;
mluis 2:14a5d6ad92d5 3805
mluis 2:14a5d6ad92d5 3806 // Search the last node in the list
mluis 2:14a5d6ad92d5 3807 while( cur->Next != NULL )
mluis 2:14a5d6ad92d5 3808 {
mluis 2:14a5d6ad92d5 3809 cur = cur->Next;
mluis 2:14a5d6ad92d5 3810 }
mluis 2:14a5d6ad92d5 3811 // This function always finds the last node
mluis 2:14a5d6ad92d5 3812 cur->Next = channelParam;
mluis 0:91d1a7783bb9 3813 }
mluis 2:14a5d6ad92d5 3814
mluis 2:14a5d6ad92d5 3815 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 3816 }
mluis 0:91d1a7783bb9 3817
mluis 2:14a5d6ad92d5 3818 LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam )
mluis 0:91d1a7783bb9 3819 {
mluis 2:14a5d6ad92d5 3820 if( channelParam == NULL )
mluis 0:91d1a7783bb9 3821 {
mluis 2:14a5d6ad92d5 3822 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 0:91d1a7783bb9 3823 }
mluis 2:14a5d6ad92d5 3824 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 2:14a5d6ad92d5 3825 {
mluis 2:14a5d6ad92d5 3826 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 3827 }
mluis 2:14a5d6ad92d5 3828
mluis 2:14a5d6ad92d5 3829 if( MulticastChannels != NULL )
mluis 0:91d1a7783bb9 3830 {
mluis 2:14a5d6ad92d5 3831 if( MulticastChannels == channelParam )
mluis 2:14a5d6ad92d5 3832 {
mluis 2:14a5d6ad92d5 3833 // First element
mluis 2:14a5d6ad92d5 3834 MulticastChannels = channelParam->Next;
mluis 2:14a5d6ad92d5 3835 }
mluis 2:14a5d6ad92d5 3836 else
mluis 2:14a5d6ad92d5 3837 {
mluis 2:14a5d6ad92d5 3838 MulticastParams_t *cur = MulticastChannels;
mluis 2:14a5d6ad92d5 3839
mluis 2:14a5d6ad92d5 3840 // Search the node in the list
mluis 2:14a5d6ad92d5 3841 while( cur->Next && cur->Next != channelParam )
mluis 2:14a5d6ad92d5 3842 {
mluis 2:14a5d6ad92d5 3843 cur = cur->Next;
mluis 2:14a5d6ad92d5 3844 }
mluis 2:14a5d6ad92d5 3845 // If we found the node, remove it
mluis 2:14a5d6ad92d5 3846 if( cur->Next )
mluis 2:14a5d6ad92d5 3847 {
mluis 2:14a5d6ad92d5 3848 cur->Next = channelParam->Next;
mluis 2:14a5d6ad92d5 3849 }
mluis 2:14a5d6ad92d5 3850 }
mluis 2:14a5d6ad92d5 3851 channelParam->Next = NULL;
mluis 0:91d1a7783bb9 3852 }
mluis 2:14a5d6ad92d5 3853
mluis 2:14a5d6ad92d5 3854 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 3855 }
mluis 0:91d1a7783bb9 3856
mluis 2:14a5d6ad92d5 3857 LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest )
mluis 0:91d1a7783bb9 3858 {
mluis 2:14a5d6ad92d5 3859 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 2:14a5d6ad92d5 3860 LoRaMacHeader_t macHdr;
mluis 2:14a5d6ad92d5 3861
mluis 2:14a5d6ad92d5 3862 if( mlmeRequest == NULL )
mluis 2:14a5d6ad92d5 3863 {
mluis 2:14a5d6ad92d5 3864 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3865 }
mluis 2:14a5d6ad92d5 3866 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 2:14a5d6ad92d5 3867 {
mluis 2:14a5d6ad92d5 3868 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 3869 }
mluis 2:14a5d6ad92d5 3870
mluis 2:14a5d6ad92d5 3871 memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) );
mluis 2:14a5d6ad92d5 3872
mluis 2:14a5d6ad92d5 3873 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 2:14a5d6ad92d5 3874
mluis 2:14a5d6ad92d5 3875 switch( mlmeRequest->Type )
mluis 2:14a5d6ad92d5 3876 {
mluis 2:14a5d6ad92d5 3877 case MLME_JOIN:
mluis 2:14a5d6ad92d5 3878 {
mluis 2:14a5d6ad92d5 3879 if( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED )
mluis 2:14a5d6ad92d5 3880 {
mluis 6:d7a34ded7c87 3881 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 3882 }
mluis 2:14a5d6ad92d5 3883
mluis 2:14a5d6ad92d5 3884 MlmeConfirm.MlmeRequest = mlmeRequest->Type;
mluis 2:14a5d6ad92d5 3885
mluis 2:14a5d6ad92d5 3886 if( ( mlmeRequest->Req.Join.DevEui == NULL ) ||
mluis 2:14a5d6ad92d5 3887 ( mlmeRequest->Req.Join.AppEui == NULL ) ||
mluis 2:14a5d6ad92d5 3888 ( mlmeRequest->Req.Join.AppKey == NULL ) )
mluis 2:14a5d6ad92d5 3889 {
mluis 2:14a5d6ad92d5 3890 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3891 }
mluis 2:14a5d6ad92d5 3892
mluis 2:14a5d6ad92d5 3893 LoRaMacFlags.Bits.MlmeReq = 1;
mluis 2:14a5d6ad92d5 3894
mluis 2:14a5d6ad92d5 3895 LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
mluis 2:14a5d6ad92d5 3896 LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
mluis 2:14a5d6ad92d5 3897 LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
mluis 2:14a5d6ad92d5 3898
mluis 2:14a5d6ad92d5 3899 macHdr.Value = 0;
mluis 2:14a5d6ad92d5 3900 macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
mluis 2:14a5d6ad92d5 3901
mluis 7:c16969e0f70f 3902 ResetMacParameters( );
mluis 7:c16969e0f70f 3903
mluis 7:c16969e0f70f 3904 JoinRequestTrials++;
mluis 7:c16969e0f70f 3905 LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials );
mluis 2:14a5d6ad92d5 3906
mluis 2:14a5d6ad92d5 3907 status = Send( &macHdr, 0, NULL, 0 );
mluis 2:14a5d6ad92d5 3908 break;
mluis 2:14a5d6ad92d5 3909 }
mluis 2:14a5d6ad92d5 3910 case MLME_LINK_CHECK:
mluis 2:14a5d6ad92d5 3911 {
mluis 2:14a5d6ad92d5 3912 LoRaMacFlags.Bits.MlmeReq = 1;
mluis 2:14a5d6ad92d5 3913 // LoRaMac will send this command piggy-pack
mluis 2:14a5d6ad92d5 3914 MlmeConfirm.MlmeRequest = mlmeRequest->Type;
mluis 2:14a5d6ad92d5 3915
mluis 2:14a5d6ad92d5 3916 status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
mluis 2:14a5d6ad92d5 3917 break;
mluis 2:14a5d6ad92d5 3918 }
mluis 2:14a5d6ad92d5 3919 default:
mluis 2:14a5d6ad92d5 3920 break;
mluis 2:14a5d6ad92d5 3921 }
mluis 2:14a5d6ad92d5 3922
mluis 2:14a5d6ad92d5 3923 if( status != LORAMAC_STATUS_OK )
mluis 2:14a5d6ad92d5 3924 {
mluis 2:14a5d6ad92d5 3925 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 3926 LoRaMacFlags.Bits.MlmeReq = 0;
mluis 2:14a5d6ad92d5 3927 }
mluis 2:14a5d6ad92d5 3928
mluis 2:14a5d6ad92d5 3929 return status;
mluis 0:91d1a7783bb9 3930 }
mluis 0:91d1a7783bb9 3931
mluis 2:14a5d6ad92d5 3932 LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
mluis 0:91d1a7783bb9 3933 {
mluis 2:14a5d6ad92d5 3934 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 2:14a5d6ad92d5 3935 LoRaMacHeader_t macHdr;
mluis 2:14a5d6ad92d5 3936 uint8_t fPort = 0;
mluis 2:14a5d6ad92d5 3937 void *fBuffer;
mluis 2:14a5d6ad92d5 3938 uint16_t fBufferSize;
mluis 2:14a5d6ad92d5 3939 int8_t datarate;
mluis 2:14a5d6ad92d5 3940 bool readyToSend = false;
mluis 2:14a5d6ad92d5 3941
mluis 2:14a5d6ad92d5 3942 if( mcpsRequest == NULL )
mluis 2:14a5d6ad92d5 3943 {
mluis 2:14a5d6ad92d5 3944 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3945 }
mluis 2:14a5d6ad92d5 3946 if( ( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING ) ||
mluis 2:14a5d6ad92d5 3947 ( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED ) )
mluis 2:14a5d6ad92d5 3948 {
mluis 2:14a5d6ad92d5 3949 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 3950 }
mluis 2:14a5d6ad92d5 3951
mluis 2:14a5d6ad92d5 3952 macHdr.Value = 0;
mluis 2:14a5d6ad92d5 3953 memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) );
mluis 2:14a5d6ad92d5 3954 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 2:14a5d6ad92d5 3955
mluis 2:14a5d6ad92d5 3956 switch( mcpsRequest->Type )
mluis 2:14a5d6ad92d5 3957 {
mluis 2:14a5d6ad92d5 3958 case MCPS_UNCONFIRMED:
mluis 2:14a5d6ad92d5 3959 {
mluis 2:14a5d6ad92d5 3960 readyToSend = true;
mluis 2:14a5d6ad92d5 3961 AckTimeoutRetries = 1;
mluis 2:14a5d6ad92d5 3962
mluis 2:14a5d6ad92d5 3963 macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP;
mluis 2:14a5d6ad92d5 3964 fPort = mcpsRequest->Req.Unconfirmed.fPort;
mluis 2:14a5d6ad92d5 3965 fBuffer = mcpsRequest->Req.Unconfirmed.fBuffer;
mluis 2:14a5d6ad92d5 3966 fBufferSize = mcpsRequest->Req.Unconfirmed.fBufferSize;
mluis 2:14a5d6ad92d5 3967 datarate = mcpsRequest->Req.Unconfirmed.Datarate;
mluis 2:14a5d6ad92d5 3968 break;
mluis 2:14a5d6ad92d5 3969 }
mluis 2:14a5d6ad92d5 3970 case MCPS_CONFIRMED:
mluis 2:14a5d6ad92d5 3971 {
mluis 2:14a5d6ad92d5 3972 readyToSend = true;
mluis 2:14a5d6ad92d5 3973 AckTimeoutRetriesCounter = 1;
mluis 3:b9d87593a8ae 3974 AckTimeoutRetries = mcpsRequest->Req.Confirmed.NbTrials;
mluis 2:14a5d6ad92d5 3975
mluis 2:14a5d6ad92d5 3976 macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
mluis 2:14a5d6ad92d5 3977 fPort = mcpsRequest->Req.Confirmed.fPort;
mluis 2:14a5d6ad92d5 3978 fBuffer = mcpsRequest->Req.Confirmed.fBuffer;
mluis 2:14a5d6ad92d5 3979 fBufferSize = mcpsRequest->Req.Confirmed.fBufferSize;
mluis 2:14a5d6ad92d5 3980 datarate = mcpsRequest->Req.Confirmed.Datarate;
mluis 2:14a5d6ad92d5 3981 break;
mluis 2:14a5d6ad92d5 3982 }
mluis 2:14a5d6ad92d5 3983 case MCPS_PROPRIETARY:
mluis 2:14a5d6ad92d5 3984 {
mluis 2:14a5d6ad92d5 3985 readyToSend = true;
mluis 2:14a5d6ad92d5 3986 AckTimeoutRetries = 1;
mluis 2:14a5d6ad92d5 3987
mluis 2:14a5d6ad92d5 3988 macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY;
mluis 2:14a5d6ad92d5 3989 fBuffer = mcpsRequest->Req.Proprietary.fBuffer;
mluis 2:14a5d6ad92d5 3990 fBufferSize = mcpsRequest->Req.Proprietary.fBufferSize;
mluis 2:14a5d6ad92d5 3991 datarate = mcpsRequest->Req.Proprietary.Datarate;
mluis 2:14a5d6ad92d5 3992 break;
mluis 2:14a5d6ad92d5 3993 }
mluis 2:14a5d6ad92d5 3994 default:
mluis 2:14a5d6ad92d5 3995 break;
mluis 2:14a5d6ad92d5 3996 }
mluis 2:14a5d6ad92d5 3997
mluis 2:14a5d6ad92d5 3998 if( readyToSend == true )
mluis 2:14a5d6ad92d5 3999 {
mluis 2:14a5d6ad92d5 4000 if( AdrCtrlOn == false )
mluis 2:14a5d6ad92d5 4001 {
mluis 4:37c12dbc8dc7 4002 if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true )
mluis 2:14a5d6ad92d5 4003 {
mluis 7:c16969e0f70f 4004 LoRaMacParams.ChannelsDatarate = datarate;
mluis 2:14a5d6ad92d5 4005 }
mluis 2:14a5d6ad92d5 4006 else
mluis 2:14a5d6ad92d5 4007 {
mluis 2:14a5d6ad92d5 4008 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4009 }
mluis 2:14a5d6ad92d5 4010 }
mluis 2:14a5d6ad92d5 4011
mluis 2:14a5d6ad92d5 4012 status = Send( &macHdr, fPort, fBuffer, fBufferSize );
mluis 2:14a5d6ad92d5 4013 if( status == LORAMAC_STATUS_OK )
mluis 2:14a5d6ad92d5 4014 {
mluis 2:14a5d6ad92d5 4015 McpsConfirm.McpsRequest = mcpsRequest->Type;
mluis 2:14a5d6ad92d5 4016 LoRaMacFlags.Bits.McpsReq = 1;
mluis 2:14a5d6ad92d5 4017 }
mluis 2:14a5d6ad92d5 4018 else
mluis 2:14a5d6ad92d5 4019 {
mluis 2:14a5d6ad92d5 4020 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 4021 }
mluis 2:14a5d6ad92d5 4022 }
mluis 2:14a5d6ad92d5 4023
mluis 2:14a5d6ad92d5 4024 return status;
mluis 0:91d1a7783bb9 4025 }
mluis 0:91d1a7783bb9 4026
mluis 0:91d1a7783bb9 4027 void LoRaMacTestRxWindowsOn( bool enable )
mluis 0:91d1a7783bb9 4028 {
mluis 0:91d1a7783bb9 4029 IsRxWindowsEnabled = enable;
mluis 0:91d1a7783bb9 4030 }
mluis 0:91d1a7783bb9 4031
mluis 2:14a5d6ad92d5 4032 void LoRaMacTestSetMic( uint16_t txPacketCounter )
mluis 0:91d1a7783bb9 4033 {
mluis 2:14a5d6ad92d5 4034 UpLinkCounter = txPacketCounter;
mluis 0:91d1a7783bb9 4035 IsUpLinkCounterFixed = true;
mluis 0:91d1a7783bb9 4036 }
mluis 2:14a5d6ad92d5 4037
mluis 2:14a5d6ad92d5 4038 void LoRaMacTestSetDutyCycleOn( bool enable )
mluis 2:14a5d6ad92d5 4039 {
mluis 2:14a5d6ad92d5 4040 DutyCycleOn = enable;
mluis 2:14a5d6ad92d5 4041 }