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:
Mon Apr 24 09:42:37 2017 +0000
Revision:
8:26002607de9c
Parent:
7:c16969e0f70f
Child:
9:db4900d60c37
WARNING: Radio API timings changed from micro-seconds to milliseconds; ; Synchronized with https://github.com/Lora-net/LoRaMac-node git revision e506c246652fa44c3f24cecb89d0707b49ece739;

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