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:
terence304
Date:
Wed Jul 26 00:56:14 2017 +0000
Revision:
9:db4900d60c37
Parent:
8:26002607de9c
Child:
10:1ac668ce2b15
Fix length error bug

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 RxWindow1Delay = LoRaMacParams.ReceiveDelay1 + RxWindowsParams[0].RxOffset;
mluis 8:26002607de9c 2927 RxWindow2Delay = LoRaMacParams.ReceiveDelay2 + RxWindowsParams[1].RxOffset;
mluis 8:26002607de9c 2928 }
mluis 8:26002607de9c 2929
mluis 2:14a5d6ad92d5 2930 // Schedule transmission of frame
mluis 2:14a5d6ad92d5 2931 if( dutyCycleTimeOff == 0 )
mluis 2:14a5d6ad92d5 2932 {
mluis 2:14a5d6ad92d5 2933 // Try to send now
mluis 2:14a5d6ad92d5 2934 return SendFrameOnChannel( Channels[Channel] );
mluis 0:91d1a7783bb9 2935 }
mluis 0:91d1a7783bb9 2936 else
mluis 0:91d1a7783bb9 2937 {
mluis 2:14a5d6ad92d5 2938 // Send later - prepare timer
mluis 8:26002607de9c 2939 LoRaMacState |= LORAMAC_TX_DELAYED;
mluis 2:14a5d6ad92d5 2940 TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
mluis 2:14a5d6ad92d5 2941 TimerStart( &TxDelayedTimer );
mluis 2:14a5d6ad92d5 2942
mluis 2:14a5d6ad92d5 2943 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 2944 }
mluis 2:14a5d6ad92d5 2945 }
mluis 2:14a5d6ad92d5 2946
mluis 8:26002607de9c 2947 static uint16_t JoinDutyCycle( void )
mluis 7:c16969e0f70f 2948 {
mluis 7:c16969e0f70f 2949 uint16_t dutyCycle = 0;
mluis 8:26002607de9c 2950 TimerTime_t timeElapsed = TimerGetElapsedTime( LoRaMacInitializationTime );
mluis 8:26002607de9c 2951
mluis 8:26002607de9c 2952 if( timeElapsed < 3600e3 )
mluis 7:c16969e0f70f 2953 {
mluis 7:c16969e0f70f 2954 dutyCycle = BACKOFF_DC_1_HOUR;
mluis 7:c16969e0f70f 2955 }
mluis 8:26002607de9c 2956 else if( timeElapsed < ( 3600e3 + 36000e3 ) )
mluis 7:c16969e0f70f 2957 {
mluis 7:c16969e0f70f 2958 dutyCycle = BACKOFF_DC_10_HOURS;
mluis 7:c16969e0f70f 2959 }
mluis 7:c16969e0f70f 2960 else
mluis 7:c16969e0f70f 2961 {
mluis 7:c16969e0f70f 2962 dutyCycle = BACKOFF_DC_24_HOURS;
mluis 7:c16969e0f70f 2963 }
mluis 7:c16969e0f70f 2964 return dutyCycle;
mluis 7:c16969e0f70f 2965 }
mluis 7:c16969e0f70f 2966
mluis 4:37c12dbc8dc7 2967 static void CalculateBackOff( uint8_t channel )
mluis 4:37c12dbc8dc7 2968 {
mluis 4:37c12dbc8dc7 2969 uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
mluis 7:c16969e0f70f 2970 uint16_t joinDutyCycle = 0;
mluis 8:26002607de9c 2971
mluis 8:26002607de9c 2972 // Reset time-off to initial value.
mluis 8:26002607de9c 2973 Bands[Channels[channel].Band].TimeOff = 0;
mluis 4:37c12dbc8dc7 2974
mluis 4:37c12dbc8dc7 2975 if( IsLoRaMacNetworkJoined == false )
mluis 4:37c12dbc8dc7 2976 {
mluis 8:26002607de9c 2977 // The node has not joined yet. Apply join duty cycle to all regions.
mluis 8:26002607de9c 2978 joinDutyCycle = JoinDutyCycle( );
mluis 7:c16969e0f70f 2979 dutyCycle = MAX( dutyCycle, joinDutyCycle );
mluis 7:c16969e0f70f 2980
mluis 8:26002607de9c 2981 // Update Band time-off.
mluis 4:37c12dbc8dc7 2982 Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
mluis 4:37c12dbc8dc7 2983 }
mluis 4:37c12dbc8dc7 2984 else
mluis 4:37c12dbc8dc7 2985 {
mluis 8:26002607de9c 2986 if( DutyCycleOn == true )
mluis 8:26002607de9c 2987 {
mluis 8:26002607de9c 2988 Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
mluis 8:26002607de9c 2989 }
mluis 7:c16969e0f70f 2990 }
mluis 7:c16969e0f70f 2991
mluis 4:37c12dbc8dc7 2992 // Update Aggregated Time OFF
mluis 4:37c12dbc8dc7 2993 AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
mluis 4:37c12dbc8dc7 2994 }
mluis 4:37c12dbc8dc7 2995
mluis 7:c16969e0f70f 2996 static int8_t AlternateDatarate( uint16_t nbTrials )
mluis 7:c16969e0f70f 2997 {
mluis 7:c16969e0f70f 2998 int8_t datarate = LORAMAC_TX_MIN_DATARATE;
mluis 7:c16969e0f70f 2999 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 3000 #if defined( USE_BAND_915 )
mluis 7:c16969e0f70f 3001 // Re-enable 500 kHz default channels
mluis 7:c16969e0f70f 3002 LoRaMacParams.ChannelsMask[4] = 0x00FF;
mluis 7:c16969e0f70f 3003 #else // defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 3004 // Re-enable 500 kHz default channels
mluis 8:26002607de9c 3005 ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask );
mluis 7:c16969e0f70f 3006 #endif
mluis 7:c16969e0f70f 3007
mluis 7:c16969e0f70f 3008 if( ( nbTrials & 0x01 ) == 0x01 )
mluis 7:c16969e0f70f 3009 {
mluis 7:c16969e0f70f 3010 datarate = DR_4;
mluis 7:c16969e0f70f 3011 }
mluis 7:c16969e0f70f 3012 else
mluis 7:c16969e0f70f 3013 {
mluis 8:26002607de9c 3014 datarate = DR_0;
mluis 7:c16969e0f70f 3015 }
mluis 7:c16969e0f70f 3016 #else
mluis 7:c16969e0f70f 3017 if( ( nbTrials % 48 ) == 0 )
mluis 7:c16969e0f70f 3018 {
mluis 7:c16969e0f70f 3019 datarate = DR_0;
mluis 7:c16969e0f70f 3020 }
mluis 7:c16969e0f70f 3021 else if( ( nbTrials % 32 ) == 0 )
mluis 7:c16969e0f70f 3022 {
mluis 7:c16969e0f70f 3023 datarate = DR_1;
mluis 7:c16969e0f70f 3024 }
mluis 7:c16969e0f70f 3025 else if( ( nbTrials % 24 ) == 0 )
mluis 7:c16969e0f70f 3026 {
mluis 7:c16969e0f70f 3027 datarate = DR_2;
mluis 7:c16969e0f70f 3028 }
mluis 7:c16969e0f70f 3029 else if( ( nbTrials % 16 ) == 0 )
mluis 7:c16969e0f70f 3030 {
mluis 7:c16969e0f70f 3031 datarate = DR_3;
mluis 7:c16969e0f70f 3032 }
mluis 7:c16969e0f70f 3033 else if( ( nbTrials % 8 ) == 0 )
mluis 7:c16969e0f70f 3034 {
mluis 7:c16969e0f70f 3035 datarate = DR_4;
mluis 7:c16969e0f70f 3036 }
mluis 7:c16969e0f70f 3037 else
mluis 7:c16969e0f70f 3038 {
mluis 7:c16969e0f70f 3039 datarate = DR_5;
mluis 7:c16969e0f70f 3040 }
mluis 7:c16969e0f70f 3041 #endif
mluis 7:c16969e0f70f 3042 return datarate;
mluis 7:c16969e0f70f 3043 }
mluis 7:c16969e0f70f 3044
mluis 7:c16969e0f70f 3045 static void ResetMacParameters( void )
mluis 7:c16969e0f70f 3046 {
mluis 7:c16969e0f70f 3047 IsLoRaMacNetworkJoined = false;
mluis 7:c16969e0f70f 3048
mluis 7:c16969e0f70f 3049 // Counters
mluis 8:26002607de9c 3050 UpLinkCounter = 0;
mluis 7:c16969e0f70f 3051 DownLinkCounter = 0;
mluis 7:c16969e0f70f 3052 AdrAckCounter = 0;
mluis 7:c16969e0f70f 3053
mluis 7:c16969e0f70f 3054 ChannelsNbRepCounter = 0;
mluis 7:c16969e0f70f 3055
mluis 7:c16969e0f70f 3056 AckTimeoutRetries = 1;
mluis 7:c16969e0f70f 3057 AckTimeoutRetriesCounter = 1;
mluis 7:c16969e0f70f 3058 AckTimeoutRetry = false;
mluis 7:c16969e0f70f 3059
mluis 7:c16969e0f70f 3060 MaxDCycle = 0;
mluis 7:c16969e0f70f 3061 AggregatedDCycle = 1;
mluis 7:c16969e0f70f 3062
mluis 7:c16969e0f70f 3063 MacCommandsBufferIndex = 0;
mluis 7:c16969e0f70f 3064 MacCommandsBufferToRepeatIndex = 0;
mluis 7:c16969e0f70f 3065
mluis 7:c16969e0f70f 3066 IsRxWindowsEnabled = true;
mluis 7:c16969e0f70f 3067
mluis 7:c16969e0f70f 3068 LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
mluis 7:c16969e0f70f 3069 LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
mluis 7:c16969e0f70f 3070
mluis 7:c16969e0f70f 3071 LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset;
mluis 7:c16969e0f70f 3072 LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
mluis 7:c16969e0f70f 3073
mluis 7:c16969e0f70f 3074 memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
mluis 7:c16969e0f70f 3075
mluis 7:c16969e0f70f 3076 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 3077 memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
mluis 7:c16969e0f70f 3078 #endif
mluis 7:c16969e0f70f 3079
mluis 7:c16969e0f70f 3080
mluis 7:c16969e0f70f 3081 NodeAckRequested = false;
mluis 7:c16969e0f70f 3082 SrvAckRequested = false;
mluis 7:c16969e0f70f 3083 MacCommandsInNextTx = false;
mluis 7:c16969e0f70f 3084
mluis 7:c16969e0f70f 3085 // Reset Multicast downlink counters
mluis 7:c16969e0f70f 3086 MulticastParams_t *cur = MulticastChannels;
mluis 7:c16969e0f70f 3087 while( cur != NULL )
mluis 7:c16969e0f70f 3088 {
mluis 7:c16969e0f70f 3089 cur->DownLinkCounter = 0;
mluis 7:c16969e0f70f 3090 cur = cur->Next;
mluis 7:c16969e0f70f 3091 }
mluis 7:c16969e0f70f 3092
mluis 7:c16969e0f70f 3093 // Initialize channel index.
mluis 7:c16969e0f70f 3094 Channel = LORA_MAX_NB_CHANNELS;
mluis 7:c16969e0f70f 3095 }
mluis 7:c16969e0f70f 3096
mluis 2:14a5d6ad92d5 3097 LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
mluis 2:14a5d6ad92d5 3098 {
mluis 2:14a5d6ad92d5 3099 uint16_t i;
mluis 2:14a5d6ad92d5 3100 uint8_t pktHeaderLen = 0;
mluis 2:14a5d6ad92d5 3101 uint32_t mic = 0;
mluis 2:14a5d6ad92d5 3102 const void* payload = fBuffer;
mluis 2:14a5d6ad92d5 3103 uint8_t framePort = fPort;
mluis 2:14a5d6ad92d5 3104
mluis 2:14a5d6ad92d5 3105 LoRaMacBufferPktLen = 0;
mluis 2:14a5d6ad92d5 3106
mluis 2:14a5d6ad92d5 3107 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 3108
mluis 2:14a5d6ad92d5 3109 if( fBuffer == NULL )
mluis 0:91d1a7783bb9 3110 {
mluis 2:14a5d6ad92d5 3111 fBufferSize = 0;
mluis 2:14a5d6ad92d5 3112 }
mluis 2:14a5d6ad92d5 3113
mluis 8:26002607de9c 3114 LoRaMacTxPayloadLen = fBufferSize;
mluis 8:26002607de9c 3115
mluis 2:14a5d6ad92d5 3116 LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
mluis 2:14a5d6ad92d5 3117
mluis 2:14a5d6ad92d5 3118 switch( macHdr->Bits.MType )
mluis 2:14a5d6ad92d5 3119 {
mluis 2:14a5d6ad92d5 3120 case FRAME_TYPE_JOIN_REQ:
mluis 2:14a5d6ad92d5 3121 LoRaMacBufferPktLen = pktHeaderLen;
mluis 2:14a5d6ad92d5 3122
mluis 2:14a5d6ad92d5 3123 memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
mluis 2:14a5d6ad92d5 3124 LoRaMacBufferPktLen += 8;
mluis 2:14a5d6ad92d5 3125 memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacDevEui, 8 );
mluis 2:14a5d6ad92d5 3126 LoRaMacBufferPktLen += 8;
mluis 2:14a5d6ad92d5 3127
mluis 2:14a5d6ad92d5 3128 LoRaMacDevNonce = Radio.Random( );
mluis 2:14a5d6ad92d5 3129
mluis 2:14a5d6ad92d5 3130 LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF;
mluis 2:14a5d6ad92d5 3131 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( LoRaMacDevNonce >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 3132
mluis 2:14a5d6ad92d5 3133 LoRaMacJoinComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic );
mluis 2:14a5d6ad92d5 3134
mluis 2:14a5d6ad92d5 3135 LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF;
mluis 2:14a5d6ad92d5 3136 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 3137 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF;
mluis 2:14a5d6ad92d5 3138 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF;
mluis 2:14a5d6ad92d5 3139
mluis 2:14a5d6ad92d5 3140 break;
mluis 2:14a5d6ad92d5 3141 case FRAME_TYPE_DATA_CONFIRMED_UP:
mluis 2:14a5d6ad92d5 3142 NodeAckRequested = true;
mluis 8:26002607de9c 3143 //Intentional fallthrough
mluis 2:14a5d6ad92d5 3144 case FRAME_TYPE_DATA_UNCONFIRMED_UP:
mluis 2:14a5d6ad92d5 3145 if( IsLoRaMacNetworkJoined == false )
mluis 0:91d1a7783bb9 3146 {
mluis 2:14a5d6ad92d5 3147 return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet
mluis 2:14a5d6ad92d5 3148 }
mluis 2:14a5d6ad92d5 3149
mluis 7:c16969e0f70f 3150 fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate );
terence304 9:db4900d60c37 3151
terence304 9:db4900d60c37 3152 if( ValidatePayloadLength( LoRaMacTxPayloadLen, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false )
terence304 9:db4900d60c37 3153 {
terence304 9:db4900d60c37 3154 return LORAMAC_STATUS_LENGTH_ERROR;
terence304 9:db4900d60c37 3155 }
mluis 7:c16969e0f70f 3156
mluis 2:14a5d6ad92d5 3157 if( SrvAckRequested == true )
mluis 2:14a5d6ad92d5 3158 {
mluis 2:14a5d6ad92d5 3159 SrvAckRequested = false;
mluis 2:14a5d6ad92d5 3160 fCtrl->Bits.Ack = 1;
mluis 2:14a5d6ad92d5 3161 }
mluis 2:14a5d6ad92d5 3162
mluis 2:14a5d6ad92d5 3163 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;
mluis 2:14a5d6ad92d5 3164 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 3165 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;
mluis 2:14a5d6ad92d5 3166 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF;
mluis 2:14a5d6ad92d5 3167
mluis 2:14a5d6ad92d5 3168 LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value;
mluis 2:14a5d6ad92d5 3169
mluis 2:14a5d6ad92d5 3170 LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
mluis 2:14a5d6ad92d5 3171 LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 3172
mluis 7:c16969e0f70f 3173 // Copy the MAC commands which must be re-send into the MAC command buffer
mluis 7:c16969e0f70f 3174 memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
mluis 7:c16969e0f70f 3175 MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
mluis 7:c16969e0f70f 3176
mluis 8:26002607de9c 3177 if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
mluis 2:14a5d6ad92d5 3178 {
mluis 2:14a5d6ad92d5 3179 if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
mluis 1:91e4e6c60d1e 3180 {
mluis 2:14a5d6ad92d5 3181 fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
mluis 2:14a5d6ad92d5 3182
mluis 2:14a5d6ad92d5 3183 // Update FCtrl field with new value of OptionsLength
mluis 2:14a5d6ad92d5 3184 LoRaMacBuffer[0x05] = fCtrl->Value;
mluis 2:14a5d6ad92d5 3185 for( i = 0; i < MacCommandsBufferIndex; i++ )
mluis 0:91d1a7783bb9 3186 {
mluis 2:14a5d6ad92d5 3187 LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
mluis 0:91d1a7783bb9 3188 }
mluis 0:91d1a7783bb9 3189 }
mluis 0:91d1a7783bb9 3190 }
mluis 0:91d1a7783bb9 3191 else
mluis 0:91d1a7783bb9 3192 {
mluis 2:14a5d6ad92d5 3193 if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
mluis 0:91d1a7783bb9 3194 {
mluis 8:26002607de9c 3195 LoRaMacTxPayloadLen = MacCommandsBufferIndex;
mluis 2:14a5d6ad92d5 3196 payload = MacCommandsBuffer;
mluis 2:14a5d6ad92d5 3197 framePort = 0;
mluis 0:91d1a7783bb9 3198 }
mluis 2:14a5d6ad92d5 3199 }
mluis 2:14a5d6ad92d5 3200 MacCommandsInNextTx = false;
mluis 7:c16969e0f70f 3201 // Store MAC commands which must be re-send in case the device does not receive a downlink anymore
mluis 7:c16969e0f70f 3202 MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat );
mluis 7:c16969e0f70f 3203 if( MacCommandsBufferToRepeatIndex > 0 )
mluis 7:c16969e0f70f 3204 {
mluis 7:c16969e0f70f 3205 MacCommandsInNextTx = true;
mluis 7:c16969e0f70f 3206 }
mluis 8:26002607de9c 3207
mluis 8:26002607de9c 3208 if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
mluis 2:14a5d6ad92d5 3209 {
mluis 2:14a5d6ad92d5 3210 LoRaMacBuffer[pktHeaderLen++] = framePort;
mluis 2:14a5d6ad92d5 3211
mluis 2:14a5d6ad92d5 3212 if( framePort == 0 )
mluis 0:91d1a7783bb9 3213 {
mluis 8:26002607de9c 3214 LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
mluis 0:91d1a7783bb9 3215 }
mluis 0:91d1a7783bb9 3216 else
mluis 0:91d1a7783bb9 3217 {
mluis 8:26002607de9c 3218 LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
mluis 0:91d1a7783bb9 3219 }
mluis 2:14a5d6ad92d5 3220 }
mluis 8:26002607de9c 3221 LoRaMacBufferPktLen = pktHeaderLen + LoRaMacTxPayloadLen;
mluis 2:14a5d6ad92d5 3222
mluis 2:14a5d6ad92d5 3223 LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
mluis 2:14a5d6ad92d5 3224
mluis 2:14a5d6ad92d5 3225 LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;
mluis 2:14a5d6ad92d5 3226 LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xFF;
mluis 2:14a5d6ad92d5 3227 LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0xFF;
mluis 2:14a5d6ad92d5 3228 LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF;
mluis 2:14a5d6ad92d5 3229
mluis 2:14a5d6ad92d5 3230 LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
mluis 2:14a5d6ad92d5 3231
mluis 2:14a5d6ad92d5 3232 break;
mluis 2:14a5d6ad92d5 3233 case FRAME_TYPE_PROPRIETARY:
mluis 8:26002607de9c 3234 if( ( fBuffer != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
mluis 2:14a5d6ad92d5 3235 {
mluis 8:26002607de9c 3236 memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, LoRaMacTxPayloadLen );
mluis 8:26002607de9c 3237 LoRaMacBufferPktLen = pktHeaderLen + LoRaMacTxPayloadLen;
mluis 0:91d1a7783bb9 3238 }
mluis 0:91d1a7783bb9 3239 break;
mluis 0:91d1a7783bb9 3240 default:
mluis 2:14a5d6ad92d5 3241 return LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 0:91d1a7783bb9 3242 }
mluis 2:14a5d6ad92d5 3243
mluis 2:14a5d6ad92d5 3244 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 3245 }
mluis 0:91d1a7783bb9 3246
mluis 2:14a5d6ad92d5 3247 LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel )
mluis 0:91d1a7783bb9 3248 {
mluis 7:c16969e0f70f 3249 int8_t datarate = Datarates[LoRaMacParams.ChannelsDatarate];
mluis 4:37c12dbc8dc7 3250 int8_t txPowerIndex = 0;
mluis 2:14a5d6ad92d5 3251 int8_t txPower = 0;
mluis 2:14a5d6ad92d5 3252
mluis 8:26002607de9c 3253 txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower, Bands[channel.Band].TxMaxPower );
mluis 4:37c12dbc8dc7 3254 txPower = TxPowers[txPowerIndex];
mluis 2:14a5d6ad92d5 3255
mluis 2:14a5d6ad92d5 3256 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 2:14a5d6ad92d5 3257 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 7:c16969e0f70f 3258 McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
mluis 4:37c12dbc8dc7 3259 McpsConfirm.TxPower = txPowerIndex;
mluis 8:26002607de9c 3260 McpsConfirm.UpLinkFrequency = channel.Frequency;
mluis 2:14a5d6ad92d5 3261
mluis 2:14a5d6ad92d5 3262 Radio.SetChannel( channel.Frequency );
mluis 2:14a5d6ad92d5 3263
mluis 2:14a5d6ad92d5 3264 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 7:c16969e0f70f 3265 if( LoRaMacParams.ChannelsDatarate == DR_7 )
mluis 2:14a5d6ad92d5 3266 { // High Speed FSK channel
mluis 2:14a5d6ad92d5 3267 Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen );
mluis 8:26002607de9c 3268 Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e3 );
mluis 2:14a5d6ad92d5 3269 TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
mluis 2:14a5d6ad92d5 3270
mluis 0:91d1a7783bb9 3271 }
mluis 7:c16969e0f70f 3272 else if( LoRaMacParams.ChannelsDatarate == DR_6 )
mluis 2:14a5d6ad92d5 3273 { // High speed LoRa channel
mluis 2:14a5d6ad92d5 3274 Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
mluis 8:26002607de9c 3275 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
mluis 2:14a5d6ad92d5 3276 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3277 }
mluis 1:91e4e6c60d1e 3278 else
mluis 2:14a5d6ad92d5 3279 { // Normal LoRa channel
mluis 2:14a5d6ad92d5 3280 Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
mluis 8:26002607de9c 3281 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
mluis 2:14a5d6ad92d5 3282 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3283 }
mluis 2:14a5d6ad92d5 3284 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 3285 Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
mluis 7:c16969e0f70f 3286 if( LoRaMacParams.ChannelsDatarate >= DR_4 )
mluis 2:14a5d6ad92d5 3287 { // High speed LoRa channel BW500 kHz
mluis 8:26002607de9c 3288 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
mluis 2:14a5d6ad92d5 3289 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3290 }
mluis 1:91e4e6c60d1e 3291 else
mluis 2:14a5d6ad92d5 3292 { // Normal LoRa channel
mluis 8:26002607de9c 3293 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
mluis 2:14a5d6ad92d5 3294 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3295 }
mluis 8:26002607de9c 3296 #elif defined( USE_BAND_470 )
mluis 8:26002607de9c 3297 Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
mluis 8:26002607de9c 3298 Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e3 );
mluis 8:26002607de9c 3299 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 3300 #else
mluis 0:91d1a7783bb9 3301 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 3302 #endif
mluis 2:14a5d6ad92d5 3303
mluis 2:14a5d6ad92d5 3304 // Store the time on air
mluis 2:14a5d6ad92d5 3305 McpsConfirm.TxTimeOnAir = TxTimeOnAir;
mluis 2:14a5d6ad92d5 3306 MlmeConfirm.TxTimeOnAir = TxTimeOnAir;
mluis 2:14a5d6ad92d5 3307
mluis 2:14a5d6ad92d5 3308 // Starts the MAC layer status check timer
mluis 3:b9d87593a8ae 3309 TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
mluis 2:14a5d6ad92d5 3310 TimerStart( &MacStateCheckTimer );
mluis 2:14a5d6ad92d5 3311
mluis 8:26002607de9c 3312 if( IsLoRaMacNetworkJoined == false )
mluis 8:26002607de9c 3313 {
mluis 8:26002607de9c 3314 JoinRequestTrials++;
mluis 8:26002607de9c 3315 }
mluis 8:26002607de9c 3316
mluis 2:14a5d6ad92d5 3317 // Send now
mluis 2:14a5d6ad92d5 3318 Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
mluis 2:14a5d6ad92d5 3319
mluis 8:26002607de9c 3320 LoRaMacState |= LORAMAC_TX_RUNNING;
mluis 8:26002607de9c 3321
mluis 8:26002607de9c 3322 return LORAMAC_STATUS_OK;
mluis 8:26002607de9c 3323 }
mluis 8:26002607de9c 3324
mluis 8:26002607de9c 3325 LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout )
mluis 8:26002607de9c 3326 {
mluis 8:26002607de9c 3327 int8_t txPowerIndex = 0;
mluis 8:26002607de9c 3328 int8_t txPower = 0;
mluis 8:26002607de9c 3329
mluis 8:26002607de9c 3330 txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower, Bands[Channels[Channel].Band].TxMaxPower );
mluis 8:26002607de9c 3331 txPower = TxPowers[txPowerIndex];
mluis 8:26002607de9c 3332
mluis 8:26002607de9c 3333 // Starts the MAC layer status check timer
mluis 8:26002607de9c 3334 TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
mluis 8:26002607de9c 3335 TimerStart( &MacStateCheckTimer );
mluis 8:26002607de9c 3336
mluis 8:26002607de9c 3337 Radio.SetTxContinuousWave( Channels[Channel].Frequency, txPower, timeout );
mluis 8:26002607de9c 3338
mluis 8:26002607de9c 3339 LoRaMacState |= LORAMAC_TX_RUNNING;
mluis 8:26002607de9c 3340
mluis 8:26002607de9c 3341 return LORAMAC_STATUS_OK;
mluis 8:26002607de9c 3342 }
mluis 8:26002607de9c 3343
mluis 8:26002607de9c 3344 LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power )
mluis 8:26002607de9c 3345 {
mluis 8:26002607de9c 3346 Radio.SetTxContinuousWave( frequency, power, timeout );
mluis 8:26002607de9c 3347
mluis 8:26002607de9c 3348 // Starts the MAC layer status check timer
mluis 8:26002607de9c 3349 TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
mluis 8:26002607de9c 3350 TimerStart( &MacStateCheckTimer );
mluis 8:26002607de9c 3351
mluis 8:26002607de9c 3352 LoRaMacState |= LORAMAC_TX_RUNNING;
mluis 2:14a5d6ad92d5 3353
mluis 2:14a5d6ad92d5 3354 return LORAMAC_STATUS_OK;
mluis 2:14a5d6ad92d5 3355 }
mluis 2:14a5d6ad92d5 3356
mluis 2:14a5d6ad92d5 3357 LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks )
mluis 2:14a5d6ad92d5 3358 {
mluis 2:14a5d6ad92d5 3359 if( primitives == NULL )
mluis 2:14a5d6ad92d5 3360 {
mluis 2:14a5d6ad92d5 3361 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3362 }
mluis 2:14a5d6ad92d5 3363
mluis 2:14a5d6ad92d5 3364 if( ( primitives->MacMcpsConfirm == NULL ) ||
mluis 2:14a5d6ad92d5 3365 ( primitives->MacMcpsIndication == NULL ) ||
mluis 8:26002607de9c 3366 ( primitives->MacMlmeConfirm == NULL ) )
mluis 2:14a5d6ad92d5 3367 {
mluis 2:14a5d6ad92d5 3368 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3369 }
mluis 2:14a5d6ad92d5 3370
mluis 2:14a5d6ad92d5 3371 LoRaMacPrimitives = primitives;
mluis 2:14a5d6ad92d5 3372 LoRaMacCallbacks = callbacks;
mluis 2:14a5d6ad92d5 3373
mluis 2:14a5d6ad92d5 3374 LoRaMacFlags.Value = 0;
mluis 2:14a5d6ad92d5 3375
mluis 2:14a5d6ad92d5 3376 LoRaMacDeviceClass = CLASS_A;
mluis 8:26002607de9c 3377 LoRaMacState = LORAMAC_IDLE;
mluis 7:c16969e0f70f 3378
mluis 7:c16969e0f70f 3379 JoinRequestTrials = 0;
mluis 8:26002607de9c 3380 MaxJoinRequestTrials = 1;
mluis 2:14a5d6ad92d5 3381 RepeaterSupport = false;
mluis 7:c16969e0f70f 3382
mluis 7:c16969e0f70f 3383 // Reset duty cycle times
mluis 7:c16969e0f70f 3384 AggregatedLastTxDoneTime = 0;
mluis 7:c16969e0f70f 3385 AggregatedTimeOff = 0;
mluis 7:c16969e0f70f 3386
mluis 7:c16969e0f70f 3387 // Duty cycle
mluis 2:14a5d6ad92d5 3388 #if defined( USE_BAND_433 )
mluis 8:26002607de9c 3389 DutyCycleOn = true;
mluis 8:26002607de9c 3390 #elif defined( USE_BAND_470 )
mluis 7:c16969e0f70f 3391 DutyCycleOn = false;
mluis 2:14a5d6ad92d5 3392 #elif defined( USE_BAND_780 )
mluis 8:26002607de9c 3393 DutyCycleOn = true;
mluis 2:14a5d6ad92d5 3394 #elif defined( USE_BAND_868 )
mluis 7:c16969e0f70f 3395 DutyCycleOn = true;
mluis 7:c16969e0f70f 3396 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 3397 DutyCycleOn = false;
mluis 7:c16969e0f70f 3398 #else
mluis 7:c16969e0f70f 3399 #error "Please define a frequency band in the compiler options."
mluis 7:c16969e0f70f 3400 #endif
mluis 7:c16969e0f70f 3401
mluis 7:c16969e0f70f 3402 // Reset to defaults
mluis 7:c16969e0f70f 3403 LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
mluis 7:c16969e0f70f 3404 LoRaMacParamsDefaults.ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
mluis 7:c16969e0f70f 3405
mluis 8:26002607de9c 3406 LoRaMacParamsDefaults.SystemMaxRxError = 10;
mluis 8:26002607de9c 3407 LoRaMacParamsDefaults.MinRxSymbols = 6;
mluis 7:c16969e0f70f 3408 LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW;
mluis 7:c16969e0f70f 3409 LoRaMacParamsDefaults.ReceiveDelay1 = RECEIVE_DELAY1;
mluis 7:c16969e0f70f 3410 LoRaMacParamsDefaults.ReceiveDelay2 = RECEIVE_DELAY2;
mluis 7:c16969e0f70f 3411 LoRaMacParamsDefaults.JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
mluis 7:c16969e0f70f 3412 LoRaMacParamsDefaults.JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
mluis 7:c16969e0f70f 3413
mluis 7:c16969e0f70f 3414 LoRaMacParamsDefaults.ChannelsNbRep = 1;
mluis 7:c16969e0f70f 3415 LoRaMacParamsDefaults.Rx1DrOffset = 0;
mluis 7:c16969e0f70f 3416
mluis 7:c16969e0f70f 3417 LoRaMacParamsDefaults.Rx2Channel = ( Rx2ChannelParams_t )RX_WND_2_CHANNEL;
mluis 7:c16969e0f70f 3418
mluis 7:c16969e0f70f 3419 // Channel mask
mluis 7:c16969e0f70f 3420 #if defined( USE_BAND_433 )
mluis 7:c16969e0f70f 3421 LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 8:26002607de9c 3422 #elif defined ( USE_BAND_470 )
mluis 8:26002607de9c 3423 LoRaMacParamsDefaults.ChannelsMask[0] = 0xFFFF;
mluis 8:26002607de9c 3424 LoRaMacParamsDefaults.ChannelsMask[1] = 0xFFFF;
mluis 8:26002607de9c 3425 LoRaMacParamsDefaults.ChannelsMask[2] = 0xFFFF;
mluis 8:26002607de9c 3426 LoRaMacParamsDefaults.ChannelsMask[3] = 0xFFFF;
mluis 8:26002607de9c 3427 LoRaMacParamsDefaults.ChannelsMask[4] = 0xFFFF;
mluis 8:26002607de9c 3428 LoRaMacParamsDefaults.ChannelsMask[5] = 0xFFFF;
mluis 7:c16969e0f70f 3429 #elif defined( USE_BAND_780 )
mluis 7:c16969e0f70f 3430 LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 7:c16969e0f70f 3431 #elif defined( USE_BAND_868 )
mluis 7:c16969e0f70f 3432 LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 2:14a5d6ad92d5 3433 #elif defined( USE_BAND_915 )
mluis 7:c16969e0f70f 3434 LoRaMacParamsDefaults.ChannelsMask[0] = 0xFFFF;
mluis 7:c16969e0f70f 3435 LoRaMacParamsDefaults.ChannelsMask[1] = 0xFFFF;
mluis 7:c16969e0f70f 3436 LoRaMacParamsDefaults.ChannelsMask[2] = 0xFFFF;
mluis 7:c16969e0f70f 3437 LoRaMacParamsDefaults.ChannelsMask[3] = 0xFFFF;
mluis 7:c16969e0f70f 3438 LoRaMacParamsDefaults.ChannelsMask[4] = 0x00FF;
mluis 7:c16969e0f70f 3439 LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000;
mluis 2:14a5d6ad92d5 3440 #elif defined( USE_BAND_915_HYBRID )
mluis 7:c16969e0f70f 3441 LoRaMacParamsDefaults.ChannelsMask[0] = 0x00FF;
mluis 7:c16969e0f70f 3442 LoRaMacParamsDefaults.ChannelsMask[1] = 0x0000;
mluis 7:c16969e0f70f 3443 LoRaMacParamsDefaults.ChannelsMask[2] = 0x0000;
mluis 7:c16969e0f70f 3444 LoRaMacParamsDefaults.ChannelsMask[3] = 0x0000;
mluis 7:c16969e0f70f 3445 LoRaMacParamsDefaults.ChannelsMask[4] = 0x0001;
mluis 7:c16969e0f70f 3446 LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000;
mluis 2:14a5d6ad92d5 3447 #else
mluis 2:14a5d6ad92d5 3448 #error "Please define a frequency band in the compiler options."
mluis 2:14a5d6ad92d5 3449 #endif
mluis 2:14a5d6ad92d5 3450
mluis 2:14a5d6ad92d5 3451 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 2:14a5d6ad92d5 3452 // 125 kHz channels
mluis 2:14a5d6ad92d5 3453 for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ )
mluis 0:91d1a7783bb9 3454 {
mluis 2:14a5d6ad92d5 3455 Channels[i].Frequency = 902.3e6 + i * 200e3;
mluis 2:14a5d6ad92d5 3456 Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
mluis 2:14a5d6ad92d5 3457 Channels[i].Band = 0;
mluis 2:14a5d6ad92d5 3458 }
mluis 2:14a5d6ad92d5 3459 // 500 kHz channels
mluis 2:14a5d6ad92d5 3460 for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ )
mluis 2:14a5d6ad92d5 3461 {
mluis 2:14a5d6ad92d5 3462 Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6;
mluis 2:14a5d6ad92d5 3463 Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
mluis 2:14a5d6ad92d5 3464 Channels[i].Band = 0;
mluis 2:14a5d6ad92d5 3465 }
mluis 8:26002607de9c 3466 #elif defined( USE_BAND_470 )
mluis 8:26002607de9c 3467 // 125 kHz channels
mluis 8:26002607de9c 3468 for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
mluis 8:26002607de9c 3469 {
mluis 8:26002607de9c 3470 Channels[i].Frequency = 470.3e6 + i * 200e3;
mluis 8:26002607de9c 3471 Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
mluis 8:26002607de9c 3472 Channels[i].Band = 0;
mluis 8:26002607de9c 3473 }
mluis 2:14a5d6ad92d5 3474 #endif
mluis 2:14a5d6ad92d5 3475
mluis 8:26002607de9c 3476 // Init parameters which are not set in function ResetMacParameters
mluis 8:26002607de9c 3477 LoRaMacParams.SystemMaxRxError = LoRaMacParamsDefaults.SystemMaxRxError;
mluis 8:26002607de9c 3478 LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols;
mluis 8:26002607de9c 3479 LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow;
mluis 8:26002607de9c 3480 LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1;
mluis 8:26002607de9c 3481 LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2;
mluis 8:26002607de9c 3482 LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1;
mluis 8:26002607de9c 3483 LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2;
mluis 8:26002607de9c 3484 LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep;
mluis 8:26002607de9c 3485
mluis 7:c16969e0f70f 3486 ResetMacParameters( );
mluis 7:c16969e0f70f 3487
mluis 7:c16969e0f70f 3488 // Initialize timers
mluis 2:14a5d6ad92d5 3489 TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent );
mluis 2:14a5d6ad92d5 3490 TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
mluis 2:14a5d6ad92d5 3491
mluis 2:14a5d6ad92d5 3492 TimerInit( &TxDelayedTimer, OnTxDelayedTimerEvent );
mluis 2:14a5d6ad92d5 3493 TimerInit( &RxWindowTimer1, OnRxWindow1TimerEvent );
mluis 2:14a5d6ad92d5 3494 TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
mluis 2:14a5d6ad92d5 3495 TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
mluis 2:14a5d6ad92d5 3496
mluis 8:26002607de9c 3497 // Store the current initialization time
mluis 8:26002607de9c 3498 LoRaMacInitializationTime = TimerGetCurrentTime( );
mluis 8:26002607de9c 3499
mluis 2:14a5d6ad92d5 3500 // Initialize Radio driver
mluis 2:14a5d6ad92d5 3501 RadioEvents.TxDone = OnRadioTxDone;
mluis 2:14a5d6ad92d5 3502 RadioEvents.RxDone = OnRadioRxDone;
mluis 2:14a5d6ad92d5 3503 RadioEvents.RxError = OnRadioRxError;
mluis 2:14a5d6ad92d5 3504 RadioEvents.TxTimeout = OnRadioTxTimeout;
mluis 2:14a5d6ad92d5 3505 RadioEvents.RxTimeout = OnRadioRxTimeout;
mluis 2:14a5d6ad92d5 3506 Radio.Init( &RadioEvents );
mluis 2:14a5d6ad92d5 3507
mluis 2:14a5d6ad92d5 3508 // Random seed initialization
mluis 2:14a5d6ad92d5 3509 srand1( Radio.Random( ) );
mluis 2:14a5d6ad92d5 3510
mluis 2:14a5d6ad92d5 3511 PublicNetwork = true;
mluis 8:26002607de9c 3512 Radio.SetPublicNetwork( PublicNetwork );
mluis 2:14a5d6ad92d5 3513 Radio.Sleep( );
mluis 2:14a5d6ad92d5 3514
mluis 2:14a5d6ad92d5 3515 return LORAMAC_STATUS_OK;
mluis 2:14a5d6ad92d5 3516 }
mluis 2:14a5d6ad92d5 3517
mluis 2:14a5d6ad92d5 3518 LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
mluis 2:14a5d6ad92d5 3519 {
mluis 7:c16969e0f70f 3520 int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate;
mluis 7:c16969e0f70f 3521 uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
mluis 2:14a5d6ad92d5 3522
mluis 2:14a5d6ad92d5 3523 if( txInfo == NULL )
mluis 2:14a5d6ad92d5 3524 {
mluis 2:14a5d6ad92d5 3525 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3526 }
mluis 2:14a5d6ad92d5 3527
mluis 2:14a5d6ad92d5 3528 AdrNextDr( AdrCtrlOn, false, &datarate );
mluis 2:14a5d6ad92d5 3529
mluis 2:14a5d6ad92d5 3530 if( RepeaterSupport == true )
mluis 2:14a5d6ad92d5 3531 {
mluis 2:14a5d6ad92d5 3532 txInfo->CurrentPayloadSize = MaxPayloadOfDatarateRepeater[datarate];
mluis 0:91d1a7783bb9 3533 }
mluis 0:91d1a7783bb9 3534 else
mluis 0:91d1a7783bb9 3535 {
mluis 2:14a5d6ad92d5 3536 txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate];
mluis 0:91d1a7783bb9 3537 }
mluis 2:14a5d6ad92d5 3538
mluis 7:c16969e0f70f 3539 if( txInfo->CurrentPayloadSize >= fOptLen )
mluis 0:91d1a7783bb9 3540 {
mluis 7:c16969e0f70f 3541 txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
mluis 0:91d1a7783bb9 3542 }
mluis 0:91d1a7783bb9 3543 else
mluis 0:91d1a7783bb9 3544 {
mluis 2:14a5d6ad92d5 3545 return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
mluis 2:14a5d6ad92d5 3546 }
mluis 2:14a5d6ad92d5 3547
mluis 2:14a5d6ad92d5 3548 if( ValidatePayloadLength( size, datarate, 0 ) == false )
mluis 2:14a5d6ad92d5 3549 {
mluis 2:14a5d6ad92d5 3550 return LORAMAC_STATUS_LENGTH_ERROR;
mluis 0:91d1a7783bb9 3551 }
mluis 2:14a5d6ad92d5 3552
mluis 7:c16969e0f70f 3553 if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
mluis 0:91d1a7783bb9 3554 {
mluis 2:14a5d6ad92d5 3555 return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
mluis 0:91d1a7783bb9 3556 }
mluis 0:91d1a7783bb9 3557
mluis 2:14a5d6ad92d5 3558 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 3559 }
mluis 0:91d1a7783bb9 3560
mluis 2:14a5d6ad92d5 3561 LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
mluis 0:91d1a7783bb9 3562 {
mluis 2:14a5d6ad92d5 3563 LoRaMacStatus_t status = LORAMAC_STATUS_OK;
mluis 2:14a5d6ad92d5 3564
mluis 2:14a5d6ad92d5 3565 if( mibGet == NULL )
mluis 2:14a5d6ad92d5 3566 {
mluis 2:14a5d6ad92d5 3567 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3568 }
mluis 2:14a5d6ad92d5 3569
mluis 2:14a5d6ad92d5 3570 switch( mibGet->Type )
mluis 0:91d1a7783bb9 3571 {
mluis 2:14a5d6ad92d5 3572 case MIB_DEVICE_CLASS:
mluis 2:14a5d6ad92d5 3573 {
mluis 2:14a5d6ad92d5 3574 mibGet->Param.Class = LoRaMacDeviceClass;
mluis 2:14a5d6ad92d5 3575 break;
mluis 2:14a5d6ad92d5 3576 }
mluis 2:14a5d6ad92d5 3577 case MIB_NETWORK_JOINED:
mluis 2:14a5d6ad92d5 3578 {
mluis 2:14a5d6ad92d5 3579 mibGet->Param.IsNetworkJoined = IsLoRaMacNetworkJoined;
mluis 2:14a5d6ad92d5 3580 break;
mluis 2:14a5d6ad92d5 3581 }
mluis 2:14a5d6ad92d5 3582 case MIB_ADR:
mluis 2:14a5d6ad92d5 3583 {
mluis 2:14a5d6ad92d5 3584 mibGet->Param.AdrEnable = AdrCtrlOn;
mluis 2:14a5d6ad92d5 3585 break;
mluis 2:14a5d6ad92d5 3586 }
mluis 2:14a5d6ad92d5 3587 case MIB_NET_ID:
mluis 2:14a5d6ad92d5 3588 {
mluis 2:14a5d6ad92d5 3589 mibGet->Param.NetID = LoRaMacNetID;
mluis 2:14a5d6ad92d5 3590 break;
mluis 2:14a5d6ad92d5 3591 }
mluis 2:14a5d6ad92d5 3592 case MIB_DEV_ADDR:
mluis 2:14a5d6ad92d5 3593 {
mluis 2:14a5d6ad92d5 3594 mibGet->Param.DevAddr = LoRaMacDevAddr;
mluis 2:14a5d6ad92d5 3595 break;
mluis 2:14a5d6ad92d5 3596 }
mluis 2:14a5d6ad92d5 3597 case MIB_NWK_SKEY:
mluis 2:14a5d6ad92d5 3598 {
mluis 2:14a5d6ad92d5 3599 mibGet->Param.NwkSKey = LoRaMacNwkSKey;
mluis 2:14a5d6ad92d5 3600 break;
mluis 2:14a5d6ad92d5 3601 }
mluis 2:14a5d6ad92d5 3602 case MIB_APP_SKEY:
mluis 2:14a5d6ad92d5 3603 {
mluis 2:14a5d6ad92d5 3604 mibGet->Param.AppSKey = LoRaMacAppSKey;
mluis 2:14a5d6ad92d5 3605 break;
mluis 2:14a5d6ad92d5 3606 }
mluis 2:14a5d6ad92d5 3607 case MIB_PUBLIC_NETWORK:
mluis 2:14a5d6ad92d5 3608 {
mluis 2:14a5d6ad92d5 3609 mibGet->Param.EnablePublicNetwork = PublicNetwork;
mluis 2:14a5d6ad92d5 3610 break;
mluis 2:14a5d6ad92d5 3611 }
mluis 2:14a5d6ad92d5 3612 case MIB_REPEATER_SUPPORT:
mluis 2:14a5d6ad92d5 3613 {
mluis 2:14a5d6ad92d5 3614 mibGet->Param.EnableRepeaterSupport = RepeaterSupport;
mluis 2:14a5d6ad92d5 3615 break;
mluis 2:14a5d6ad92d5 3616 }
mluis 2:14a5d6ad92d5 3617 case MIB_CHANNELS:
mluis 2:14a5d6ad92d5 3618 {
mluis 2:14a5d6ad92d5 3619 mibGet->Param.ChannelList = Channels;
mluis 2:14a5d6ad92d5 3620 break;
mluis 2:14a5d6ad92d5 3621 }
mluis 2:14a5d6ad92d5 3622 case MIB_RX2_CHANNEL:
mluis 2:14a5d6ad92d5 3623 {
mluis 7:c16969e0f70f 3624 mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel;
mluis 2:14a5d6ad92d5 3625 break;
mluis 2:14a5d6ad92d5 3626 }
mluis 8:26002607de9c 3627 case MIB_RX2_DEFAULT_CHANNEL:
mluis 8:26002607de9c 3628 {
mluis 8:26002607de9c 3629 mibGet->Param.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
mluis 8:26002607de9c 3630 break;
mluis 8:26002607de9c 3631 }
mluis 8:26002607de9c 3632 case MIB_CHANNELS_DEFAULT_MASK:
mluis 8:26002607de9c 3633 {
mluis 8:26002607de9c 3634 mibGet->Param.ChannelsDefaultMask = LoRaMacParamsDefaults.ChannelsMask;
mluis 8:26002607de9c 3635 break;
mluis 8:26002607de9c 3636 }
mluis 2:14a5d6ad92d5 3637 case MIB_CHANNELS_MASK:
mluis 2:14a5d6ad92d5 3638 {
mluis 7:c16969e0f70f 3639 mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask;
mluis 2:14a5d6ad92d5 3640 break;
mluis 0:91d1a7783bb9 3641 }
mluis 2:14a5d6ad92d5 3642 case MIB_CHANNELS_NB_REP:
mluis 2:14a5d6ad92d5 3643 {
mluis 7:c16969e0f70f 3644 mibGet->Param.ChannelNbRep = LoRaMacParams.ChannelsNbRep;
mluis 2:14a5d6ad92d5 3645 break;
mluis 2:14a5d6ad92d5 3646 }
mluis 2:14a5d6ad92d5 3647 case MIB_MAX_RX_WINDOW_DURATION:
mluis 2:14a5d6ad92d5 3648 {
mluis 7:c16969e0f70f 3649 mibGet->Param.MaxRxWindow = LoRaMacParams.MaxRxWindow;
mluis 2:14a5d6ad92d5 3650 break;
mluis 2:14a5d6ad92d5 3651 }
mluis 2:14a5d6ad92d5 3652 case MIB_RECEIVE_DELAY_1:
mluis 2:14a5d6ad92d5 3653 {
mluis 7:c16969e0f70f 3654 mibGet->Param.ReceiveDelay1 = LoRaMacParams.ReceiveDelay1;
mluis 2:14a5d6ad92d5 3655 break;
mluis 2:14a5d6ad92d5 3656 }
mluis 2:14a5d6ad92d5 3657 case MIB_RECEIVE_DELAY_2:
mluis 2:14a5d6ad92d5 3658 {
mluis 7:c16969e0f70f 3659 mibGet->Param.ReceiveDelay2 = LoRaMacParams.ReceiveDelay2;
mluis 2:14a5d6ad92d5 3660 break;
mluis 2:14a5d6ad92d5 3661 }
mluis 2:14a5d6ad92d5 3662 case MIB_JOIN_ACCEPT_DELAY_1:
mluis 2:14a5d6ad92d5 3663 {
mluis 7:c16969e0f70f 3664 mibGet->Param.JoinAcceptDelay1 = LoRaMacParams.JoinAcceptDelay1;
mluis 2:14a5d6ad92d5 3665 break;
mluis 2:14a5d6ad92d5 3666 }
mluis 2:14a5d6ad92d5 3667 case MIB_JOIN_ACCEPT_DELAY_2:
mluis 2:14a5d6ad92d5 3668 {
mluis 7:c16969e0f70f 3669 mibGet->Param.JoinAcceptDelay2 = LoRaMacParams.JoinAcceptDelay2;
mluis 2:14a5d6ad92d5 3670 break;
mluis 2:14a5d6ad92d5 3671 }
mluis 4:37c12dbc8dc7 3672 case MIB_CHANNELS_DEFAULT_DATARATE:
mluis 4:37c12dbc8dc7 3673 {
mluis 7:c16969e0f70f 3674 mibGet->Param.ChannelsDefaultDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
mluis 4:37c12dbc8dc7 3675 break;
mluis 4:37c12dbc8dc7 3676 }
mluis 2:14a5d6ad92d5 3677 case MIB_CHANNELS_DATARATE:
mluis 2:14a5d6ad92d5 3678 {
mluis 7:c16969e0f70f 3679 mibGet->Param.ChannelsDatarate = LoRaMacParams.ChannelsDatarate;
mluis 2:14a5d6ad92d5 3680 break;
mluis 2:14a5d6ad92d5 3681 }
mluis 8:26002607de9c 3682 case MIB_CHANNELS_DEFAULT_TX_POWER:
mluis 8:26002607de9c 3683 {
mluis 8:26002607de9c 3684 mibGet->Param.ChannelsDefaultTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
mluis 8:26002607de9c 3685 break;
mluis 8:26002607de9c 3686 }
mluis 2:14a5d6ad92d5 3687 case MIB_CHANNELS_TX_POWER:
mluis 2:14a5d6ad92d5 3688 {
mluis 7:c16969e0f70f 3689 mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower;
mluis 2:14a5d6ad92d5 3690 break;
mluis 2:14a5d6ad92d5 3691 }
mluis 2:14a5d6ad92d5 3692 case MIB_UPLINK_COUNTER:
mluis 2:14a5d6ad92d5 3693 {
mluis 2:14a5d6ad92d5 3694 mibGet->Param.UpLinkCounter = UpLinkCounter;
mluis 2:14a5d6ad92d5 3695 break;
mluis 2:14a5d6ad92d5 3696 }
mluis 2:14a5d6ad92d5 3697 case MIB_DOWNLINK_COUNTER:
mluis 2:14a5d6ad92d5 3698 {
mluis 2:14a5d6ad92d5 3699 mibGet->Param.DownLinkCounter = DownLinkCounter;
mluis 2:14a5d6ad92d5 3700 break;
mluis 2:14a5d6ad92d5 3701 }
mluis 2:14a5d6ad92d5 3702 case MIB_MULTICAST_CHANNEL:
mluis 2:14a5d6ad92d5 3703 {
mluis 2:14a5d6ad92d5 3704 mibGet->Param.MulticastList = MulticastChannels;
mluis 2:14a5d6ad92d5 3705 break;
mluis 2:14a5d6ad92d5 3706 }
mluis 8:26002607de9c 3707 case MIB_SYSTEM_MAX_RX_ERROR:
mluis 8:26002607de9c 3708 {
mluis 8:26002607de9c 3709 mibGet->Param.SystemMaxRxError = LoRaMacParams.SystemMaxRxError;
mluis 8:26002607de9c 3710 break;
mluis 8:26002607de9c 3711 }
mluis 8:26002607de9c 3712 case MIB_MIN_RX_SYMBOLS:
mluis 8:26002607de9c 3713 {
mluis 8:26002607de9c 3714 mibGet->Param.MinRxSymbols = LoRaMacParams.MinRxSymbols;
mluis 8:26002607de9c 3715 break;
mluis 8:26002607de9c 3716 }
mluis 2:14a5d6ad92d5 3717 default:
mluis 2:14a5d6ad92d5 3718 status = LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 2:14a5d6ad92d5 3719 break;
mluis 0:91d1a7783bb9 3720 }
mluis 0:91d1a7783bb9 3721
mluis 2:14a5d6ad92d5 3722 return status;
mluis 0:91d1a7783bb9 3723 }
mluis 2:14a5d6ad92d5 3724
mluis 2:14a5d6ad92d5 3725 LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
mluis 0:91d1a7783bb9 3726 {
mluis 2:14a5d6ad92d5 3727 LoRaMacStatus_t status = LORAMAC_STATUS_OK;
mluis 2:14a5d6ad92d5 3728
mluis 2:14a5d6ad92d5 3729 if( mibSet == NULL )
mluis 2:14a5d6ad92d5 3730 {
mluis 2:14a5d6ad92d5 3731 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 0:91d1a7783bb9 3732 }
mluis 8:26002607de9c 3733 if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
mluis 0:91d1a7783bb9 3734 {
mluis 2:14a5d6ad92d5 3735 return LORAMAC_STATUS_BUSY;
mluis 0:91d1a7783bb9 3736 }
mluis 2:14a5d6ad92d5 3737
mluis 2:14a5d6ad92d5 3738 switch( mibSet->Type )
mluis 0:91d1a7783bb9 3739 {
mluis 2:14a5d6ad92d5 3740 case MIB_DEVICE_CLASS:
mluis 2:14a5d6ad92d5 3741 {
mluis 2:14a5d6ad92d5 3742 LoRaMacDeviceClass = mibSet->Param.Class;
mluis 2:14a5d6ad92d5 3743 switch( LoRaMacDeviceClass )
mluis 2:14a5d6ad92d5 3744 {
mluis 2:14a5d6ad92d5 3745 case CLASS_A:
mluis 2:14a5d6ad92d5 3746 {
mluis 2:14a5d6ad92d5 3747 // Set the radio into sleep to setup a defined state
mluis 2:14a5d6ad92d5 3748 Radio.Sleep( );
mluis 2:14a5d6ad92d5 3749 break;
mluis 2:14a5d6ad92d5 3750 }
mluis 2:14a5d6ad92d5 3751 case CLASS_B:
mluis 2:14a5d6ad92d5 3752 {
mluis 2:14a5d6ad92d5 3753 break;
mluis 2:14a5d6ad92d5 3754 }
mluis 2:14a5d6ad92d5 3755 case CLASS_C:
mluis 2:14a5d6ad92d5 3756 {
mluis 2:14a5d6ad92d5 3757 // Set the NodeAckRequested indicator to default
mluis 2:14a5d6ad92d5 3758 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 3759 OnRxWindow2TimerEvent( );
mluis 2:14a5d6ad92d5 3760 break;
mluis 2:14a5d6ad92d5 3761 }
mluis 2:14a5d6ad92d5 3762 }
mluis 2:14a5d6ad92d5 3763 break;
mluis 2:14a5d6ad92d5 3764 }
mluis 2:14a5d6ad92d5 3765 case MIB_NETWORK_JOINED:
mluis 2:14a5d6ad92d5 3766 {
mluis 2:14a5d6ad92d5 3767 IsLoRaMacNetworkJoined = mibSet->Param.IsNetworkJoined;
mluis 2:14a5d6ad92d5 3768 break;
mluis 2:14a5d6ad92d5 3769 }
mluis 2:14a5d6ad92d5 3770 case MIB_ADR:
mluis 2:14a5d6ad92d5 3771 {
mluis 2:14a5d6ad92d5 3772 AdrCtrlOn = mibSet->Param.AdrEnable;
mluis 2:14a5d6ad92d5 3773 break;
mluis 2:14a5d6ad92d5 3774 }
mluis 2:14a5d6ad92d5 3775 case MIB_NET_ID:
mluis 2:14a5d6ad92d5 3776 {
mluis 2:14a5d6ad92d5 3777 LoRaMacNetID = mibSet->Param.NetID;
mluis 2:14a5d6ad92d5 3778 break;
mluis 2:14a5d6ad92d5 3779 }
mluis 2:14a5d6ad92d5 3780 case MIB_DEV_ADDR:
mluis 2:14a5d6ad92d5 3781 {
mluis 2:14a5d6ad92d5 3782 LoRaMacDevAddr = mibSet->Param.DevAddr;
mluis 2:14a5d6ad92d5 3783 break;
mluis 2:14a5d6ad92d5 3784 }
mluis 2:14a5d6ad92d5 3785 case MIB_NWK_SKEY:
mluis 0:91d1a7783bb9 3786 {
mluis 2:14a5d6ad92d5 3787 if( mibSet->Param.NwkSKey != NULL )
mluis 2:14a5d6ad92d5 3788 {
mluis 2:14a5d6ad92d5 3789 memcpy1( LoRaMacNwkSKey, mibSet->Param.NwkSKey,
mluis 2:14a5d6ad92d5 3790 sizeof( LoRaMacNwkSKey ) );
mluis 2:14a5d6ad92d5 3791 }
mluis 2:14a5d6ad92d5 3792 else
mluis 2:14a5d6ad92d5 3793 {
mluis 2:14a5d6ad92d5 3794 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3795 }
mluis 2:14a5d6ad92d5 3796 break;
mluis 2:14a5d6ad92d5 3797 }
mluis 2:14a5d6ad92d5 3798 case MIB_APP_SKEY:
mluis 2:14a5d6ad92d5 3799 {
mluis 2:14a5d6ad92d5 3800 if( mibSet->Param.AppSKey != NULL )
mluis 2:14a5d6ad92d5 3801 {
mluis 2:14a5d6ad92d5 3802 memcpy1( LoRaMacAppSKey, mibSet->Param.AppSKey,
mluis 2:14a5d6ad92d5 3803 sizeof( LoRaMacAppSKey ) );
mluis 2:14a5d6ad92d5 3804 }
mluis 2:14a5d6ad92d5 3805 else
mluis 2:14a5d6ad92d5 3806 {
mluis 2:14a5d6ad92d5 3807 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3808 }
mluis 2:14a5d6ad92d5 3809 break;
mluis 2:14a5d6ad92d5 3810 }
mluis 2:14a5d6ad92d5 3811 case MIB_PUBLIC_NETWORK:
mluis 2:14a5d6ad92d5 3812 {
mluis 8:26002607de9c 3813 PublicNetwork = mibSet->Param.EnablePublicNetwork;
mluis 8:26002607de9c 3814 Radio.SetPublicNetwork( PublicNetwork );
mluis 2:14a5d6ad92d5 3815 break;
mluis 0:91d1a7783bb9 3816 }
mluis 2:14a5d6ad92d5 3817 case MIB_REPEATER_SUPPORT:
mluis 2:14a5d6ad92d5 3818 {
mluis 2:14a5d6ad92d5 3819 RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
mluis 2:14a5d6ad92d5 3820 break;
mluis 2:14a5d6ad92d5 3821 }
mluis 2:14a5d6ad92d5 3822 case MIB_RX2_CHANNEL:
mluis 2:14a5d6ad92d5 3823 {
mluis 7:c16969e0f70f 3824 LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel;
mluis 2:14a5d6ad92d5 3825 break;
mluis 2:14a5d6ad92d5 3826 }
mluis 8:26002607de9c 3827 case MIB_RX2_DEFAULT_CHANNEL:
mluis 8:26002607de9c 3828 {
mluis 8:26002607de9c 3829 LoRaMacParamsDefaults.Rx2Channel = mibSet->Param.Rx2DefaultChannel;
mluis 8:26002607de9c 3830 break;
mluis 8:26002607de9c 3831 }
mluis 8:26002607de9c 3832 case MIB_CHANNELS_DEFAULT_MASK:
mluis 8:26002607de9c 3833 {
mluis 8:26002607de9c 3834 if( mibSet->Param.ChannelsDefaultMask )
mluis 8:26002607de9c 3835 {
mluis 8:26002607de9c 3836 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 8:26002607de9c 3837 bool chanMaskState = true;
mluis 8:26002607de9c 3838
mluis 8:26002607de9c 3839 #if defined( USE_BAND_915_HYBRID )
mluis 8:26002607de9c 3840 chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsDefaultMask );
mluis 8:26002607de9c 3841 #endif
mluis 8:26002607de9c 3842 if( chanMaskState == true )
mluis 8:26002607de9c 3843 {
mluis 8:26002607de9c 3844 if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) &&
mluis 8:26002607de9c 3845 ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
mluis 8:26002607de9c 3846 {
mluis 8:26002607de9c 3847 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 8:26002607de9c 3848 }
mluis 8:26002607de9c 3849 else
mluis 8:26002607de9c 3850 {
mluis 8:26002607de9c 3851 memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
mluis 8:26002607de9c 3852 ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, sizeof( LoRaMacParamsDefaults.ChannelsMask ) );
mluis 8:26002607de9c 3853 for ( uint8_t i = 0; i < sizeof( LoRaMacParamsDefaults.ChannelsMask ) / 2; i++ )
mluis 8:26002607de9c 3854 {
mluis 8:26002607de9c 3855 // Disable channels which are no longer available
mluis 8:26002607de9c 3856 ChannelsMaskRemaining[i] &= LoRaMacParamsDefaults.ChannelsMask[i];
mluis 8:26002607de9c 3857 }
mluis 8:26002607de9c 3858 }
mluis 8:26002607de9c 3859 }
mluis 8:26002607de9c 3860 else
mluis 8:26002607de9c 3861 {
mluis 8:26002607de9c 3862 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 8:26002607de9c 3863 }
mluis 8:26002607de9c 3864 #elif defined( USE_BAND_470 )
mluis 8:26002607de9c 3865 memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
mluis 8:26002607de9c 3866 ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, sizeof( LoRaMacParamsDefaults.ChannelsMask ) );
mluis 8:26002607de9c 3867 #else
mluis 8:26002607de9c 3868 memcpy1( ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask,
mluis 8:26002607de9c 3869 ( uint8_t* ) mibSet->Param.ChannelsDefaultMask, 2 );
mluis 8:26002607de9c 3870 #endif
mluis 8:26002607de9c 3871 }
mluis 8:26002607de9c 3872 else
mluis 8:26002607de9c 3873 {
mluis 8:26002607de9c 3874 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 8:26002607de9c 3875 }
mluis 8:26002607de9c 3876 break;
mluis 8:26002607de9c 3877 }
mluis 2:14a5d6ad92d5 3878 case MIB_CHANNELS_MASK:
mluis 2:14a5d6ad92d5 3879 {
mluis 2:14a5d6ad92d5 3880 if( mibSet->Param.ChannelsMask )
mluis 2:14a5d6ad92d5 3881 {
mluis 2:14a5d6ad92d5 3882 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 4:37c12dbc8dc7 3883 bool chanMaskState = true;
mluis 4:37c12dbc8dc7 3884
mluis 4:37c12dbc8dc7 3885 #if defined( USE_BAND_915_HYBRID )
mluis 4:37c12dbc8dc7 3886 chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsMask );
mluis 4:37c12dbc8dc7 3887 #endif
mluis 4:37c12dbc8dc7 3888 if( chanMaskState == true )
mluis 2:14a5d6ad92d5 3889 {
mluis 8:26002607de9c 3890 if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) &&
mluis 4:37c12dbc8dc7 3891 ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
mluis 4:37c12dbc8dc7 3892 {
mluis 4:37c12dbc8dc7 3893 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 4:37c12dbc8dc7 3894 }
mluis 4:37c12dbc8dc7 3895 else
mluis 4:37c12dbc8dc7 3896 {
mluis 7:c16969e0f70f 3897 memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
mluis 7:c16969e0f70f 3898 ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
mluis 7:c16969e0f70f 3899 for ( uint8_t i = 0; i < sizeof( LoRaMacParams.ChannelsMask ) / 2; i++ )
mluis 4:37c12dbc8dc7 3900 {
mluis 4:37c12dbc8dc7 3901 // Disable channels which are no longer available
mluis 7:c16969e0f70f 3902 ChannelsMaskRemaining[i] &= LoRaMacParams.ChannelsMask[i];
mluis 4:37c12dbc8dc7 3903 }
mluis 4:37c12dbc8dc7 3904 }
mluis 2:14a5d6ad92d5 3905 }
mluis 2:14a5d6ad92d5 3906 else
mluis 2:14a5d6ad92d5 3907 {
mluis 4:37c12dbc8dc7 3908 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3909 }
mluis 8:26002607de9c 3910 #elif defined( USE_BAND_470 )
mluis 8:26002607de9c 3911 memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
mluis 8:26002607de9c 3912 ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) );
mluis 0:91d1a7783bb9 3913 #else
mluis 7:c16969e0f70f 3914 memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask,
mluis 2:14a5d6ad92d5 3915 ( uint8_t* ) mibSet->Param.ChannelsMask, 2 );
mluis 0:91d1a7783bb9 3916 #endif
mluis 2:14a5d6ad92d5 3917 }
mluis 2:14a5d6ad92d5 3918 else
mluis 2:14a5d6ad92d5 3919 {
mluis 2:14a5d6ad92d5 3920 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3921 }
mluis 2:14a5d6ad92d5 3922 break;
mluis 2:14a5d6ad92d5 3923 }
mluis 2:14a5d6ad92d5 3924 case MIB_CHANNELS_NB_REP:
mluis 2:14a5d6ad92d5 3925 {
mluis 2:14a5d6ad92d5 3926 if( ( mibSet->Param.ChannelNbRep >= 1 ) &&
mluis 2:14a5d6ad92d5 3927 ( mibSet->Param.ChannelNbRep <= 15 ) )
mluis 2:14a5d6ad92d5 3928 {
mluis 7:c16969e0f70f 3929 LoRaMacParams.ChannelsNbRep = mibSet->Param.ChannelNbRep;
mluis 2:14a5d6ad92d5 3930 }
mluis 2:14a5d6ad92d5 3931 else
mluis 2:14a5d6ad92d5 3932 {
mluis 2:14a5d6ad92d5 3933 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3934 }
mluis 2:14a5d6ad92d5 3935 break;
mluis 2:14a5d6ad92d5 3936 }
mluis 2:14a5d6ad92d5 3937 case MIB_MAX_RX_WINDOW_DURATION:
mluis 2:14a5d6ad92d5 3938 {
mluis 7:c16969e0f70f 3939 LoRaMacParams.MaxRxWindow = mibSet->Param.MaxRxWindow;
mluis 2:14a5d6ad92d5 3940 break;
mluis 2:14a5d6ad92d5 3941 }
mluis 2:14a5d6ad92d5 3942 case MIB_RECEIVE_DELAY_1:
mluis 2:14a5d6ad92d5 3943 {
mluis 7:c16969e0f70f 3944 LoRaMacParams.ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
mluis 2:14a5d6ad92d5 3945 break;
mluis 2:14a5d6ad92d5 3946 }
mluis 2:14a5d6ad92d5 3947 case MIB_RECEIVE_DELAY_2:
mluis 2:14a5d6ad92d5 3948 {
mluis 7:c16969e0f70f 3949 LoRaMacParams.ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
mluis 2:14a5d6ad92d5 3950 break;
mluis 2:14a5d6ad92d5 3951 }
mluis 2:14a5d6ad92d5 3952 case MIB_JOIN_ACCEPT_DELAY_1:
mluis 2:14a5d6ad92d5 3953 {
mluis 7:c16969e0f70f 3954 LoRaMacParams.JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
mluis 2:14a5d6ad92d5 3955 break;
mluis 2:14a5d6ad92d5 3956 }
mluis 2:14a5d6ad92d5 3957 case MIB_JOIN_ACCEPT_DELAY_2:
mluis 2:14a5d6ad92d5 3958 {
mluis 7:c16969e0f70f 3959 LoRaMacParams.JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
mluis 2:14a5d6ad92d5 3960 break;
mluis 2:14a5d6ad92d5 3961 }
mluis 4:37c12dbc8dc7 3962 case MIB_CHANNELS_DEFAULT_DATARATE:
mluis 4:37c12dbc8dc7 3963 {
mluis 8:26002607de9c 3964 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 8:26002607de9c 3965 if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
mluis 8:26002607de9c 3966 DR_0, DR_5 ) )
mluis 8:26002607de9c 3967 {
mluis 8:26002607de9c 3968 LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
mluis 8:26002607de9c 3969 }
mluis 8:26002607de9c 3970 #else
mluis 4:37c12dbc8dc7 3971 if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
mluis 4:37c12dbc8dc7 3972 LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
mluis 4:37c12dbc8dc7 3973 {
mluis 7:c16969e0f70f 3974 LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate;
mluis 4:37c12dbc8dc7 3975 }
mluis 8:26002607de9c 3976 #endif
mluis 4:37c12dbc8dc7 3977 else
mluis 4:37c12dbc8dc7 3978 {
mluis 4:37c12dbc8dc7 3979 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 4:37c12dbc8dc7 3980 }
mluis 4:37c12dbc8dc7 3981 break;
mluis 4:37c12dbc8dc7 3982 }
mluis 2:14a5d6ad92d5 3983 case MIB_CHANNELS_DATARATE:
mluis 2:14a5d6ad92d5 3984 {
mluis 2:14a5d6ad92d5 3985 if( ValueInRange( mibSet->Param.ChannelsDatarate,
mluis 4:37c12dbc8dc7 3986 LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
mluis 2:14a5d6ad92d5 3987 {
mluis 7:c16969e0f70f 3988 LoRaMacParams.ChannelsDatarate = mibSet->Param.ChannelsDatarate;
mluis 2:14a5d6ad92d5 3989 }
mluis 2:14a5d6ad92d5 3990 else
mluis 2:14a5d6ad92d5 3991 {
mluis 2:14a5d6ad92d5 3992 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 3993 }
mluis 2:14a5d6ad92d5 3994 break;
mluis 2:14a5d6ad92d5 3995 }
mluis 8:26002607de9c 3996 case MIB_CHANNELS_DEFAULT_TX_POWER:
mluis 8:26002607de9c 3997 {
mluis 8:26002607de9c 3998 if( ValueInRange( mibSet->Param.ChannelsDefaultTxPower,
mluis 8:26002607de9c 3999 LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
mluis 8:26002607de9c 4000 {
mluis 8:26002607de9c 4001 LoRaMacParamsDefaults.ChannelsTxPower = mibSet->Param.ChannelsDefaultTxPower;
mluis 8:26002607de9c 4002 }
mluis 8:26002607de9c 4003 else
mluis 8:26002607de9c 4004 {
mluis 8:26002607de9c 4005 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 8:26002607de9c 4006 }
mluis 8:26002607de9c 4007 break;
mluis 8:26002607de9c 4008 }
mluis 2:14a5d6ad92d5 4009 case MIB_CHANNELS_TX_POWER:
mluis 2:14a5d6ad92d5 4010 {
mluis 2:14a5d6ad92d5 4011 if( ValueInRange( mibSet->Param.ChannelsTxPower,
mluis 2:14a5d6ad92d5 4012 LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
mluis 2:14a5d6ad92d5 4013 {
mluis 7:c16969e0f70f 4014 LoRaMacParams.ChannelsTxPower = mibSet->Param.ChannelsTxPower;
mluis 2:14a5d6ad92d5 4015 }
mluis 2:14a5d6ad92d5 4016 else
mluis 2:14a5d6ad92d5 4017 {
mluis 2:14a5d6ad92d5 4018 status = LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4019 }
mluis 2:14a5d6ad92d5 4020 break;
mluis 2:14a5d6ad92d5 4021 }
mluis 4:37c12dbc8dc7 4022 case MIB_UPLINK_COUNTER:
mluis 4:37c12dbc8dc7 4023 {
mluis 4:37c12dbc8dc7 4024 UpLinkCounter = mibSet->Param.UpLinkCounter;
mluis 4:37c12dbc8dc7 4025 break;
mluis 4:37c12dbc8dc7 4026 }
mluis 4:37c12dbc8dc7 4027 case MIB_DOWNLINK_COUNTER:
mluis 4:37c12dbc8dc7 4028 {
mluis 4:37c12dbc8dc7 4029 DownLinkCounter = mibSet->Param.DownLinkCounter;
mluis 4:37c12dbc8dc7 4030 break;
mluis 4:37c12dbc8dc7 4031 }
mluis 8:26002607de9c 4032 case MIB_SYSTEM_MAX_RX_ERROR:
mluis 8:26002607de9c 4033 {
mluis 8:26002607de9c 4034 LoRaMacParams.SystemMaxRxError = LoRaMacParamsDefaults.SystemMaxRxError = mibSet->Param.SystemMaxRxError;
mluis 8:26002607de9c 4035 break;
mluis 8:26002607de9c 4036 }
mluis 8:26002607de9c 4037 case MIB_MIN_RX_SYMBOLS:
mluis 8:26002607de9c 4038 {
mluis 8:26002607de9c 4039 LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols = mibSet->Param.MinRxSymbols;
mluis 8:26002607de9c 4040 break;
mluis 8:26002607de9c 4041 }
mluis 2:14a5d6ad92d5 4042 default:
mluis 2:14a5d6ad92d5 4043 status = LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 2:14a5d6ad92d5 4044 break;
mluis 0:91d1a7783bb9 4045 }
mluis 0:91d1a7783bb9 4046
mluis 2:14a5d6ad92d5 4047 return status;
mluis 0:91d1a7783bb9 4048 }
mluis 0:91d1a7783bb9 4049
mluis 2:14a5d6ad92d5 4050 LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
mluis 0:91d1a7783bb9 4051 {
mluis 8:26002607de9c 4052 #if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 3:b9d87593a8ae 4053 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 3:b9d87593a8ae 4054 #else
mluis 3:b9d87593a8ae 4055 bool datarateInvalid = false;
mluis 3:b9d87593a8ae 4056 bool frequencyInvalid = false;
mluis 3:b9d87593a8ae 4057 uint8_t band = 0;
mluis 3:b9d87593a8ae 4058
mluis 3:b9d87593a8ae 4059 // The id must not exceed LORA_MAX_NB_CHANNELS
mluis 2:14a5d6ad92d5 4060 if( id >= LORA_MAX_NB_CHANNELS )
mluis 0:91d1a7783bb9 4061 {
mluis 2:14a5d6ad92d5 4062 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 0:91d1a7783bb9 4063 }
mluis 3:b9d87593a8ae 4064 // Validate if the MAC is in a correct state
mluis 8:26002607de9c 4065 if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
mluis 0:91d1a7783bb9 4066 {
mluis 8:26002607de9c 4067 if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
mluis 3:b9d87593a8ae 4068 {
mluis 3:b9d87593a8ae 4069 return LORAMAC_STATUS_BUSY;
mluis 3:b9d87593a8ae 4070 }
mluis 0:91d1a7783bb9 4071 }
mluis 3:b9d87593a8ae 4072 // Validate the datarate
mluis 2:14a5d6ad92d5 4073 if( ( params.DrRange.Fields.Min > params.DrRange.Fields.Max ) ||
mluis 4:37c12dbc8dc7 4074 ( ValueInRange( params.DrRange.Fields.Min, LORAMAC_TX_MIN_DATARATE,
mluis 4:37c12dbc8dc7 4075 LORAMAC_TX_MAX_DATARATE ) == false ) ||
mluis 4:37c12dbc8dc7 4076 ( ValueInRange( params.DrRange.Fields.Max, LORAMAC_TX_MIN_DATARATE,
mluis 4:37c12dbc8dc7 4077 LORAMAC_TX_MAX_DATARATE ) == false ) )
mluis 0:91d1a7783bb9 4078 {
mluis 3:b9d87593a8ae 4079 datarateInvalid = true;
mluis 0:91d1a7783bb9 4080 }
mluis 2:14a5d6ad92d5 4081
mluis 3:b9d87593a8ae 4082 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 3:b9d87593a8ae 4083 if( id < 3 )
mluis 0:91d1a7783bb9 4084 {
mluis 3:b9d87593a8ae 4085 if( params.Frequency != Channels[id].Frequency )
mluis 0:91d1a7783bb9 4086 {
mluis 3:b9d87593a8ae 4087 frequencyInvalid = true;
mluis 3:b9d87593a8ae 4088 }
mluis 3:b9d87593a8ae 4089
mluis 8:26002607de9c 4090 if( params.DrRange.Fields.Min > DR_0 )
mluis 3:b9d87593a8ae 4091 {
mluis 3:b9d87593a8ae 4092 datarateInvalid = true;
mluis 3:b9d87593a8ae 4093 }
mluis 4:37c12dbc8dc7 4094 if( ValueInRange( params.DrRange.Fields.Max, DR_5, LORAMAC_TX_MAX_DATARATE ) == false )
mluis 3:b9d87593a8ae 4095 {
mluis 3:b9d87593a8ae 4096 datarateInvalid = true;
mluis 0:91d1a7783bb9 4097 }
mluis 0:91d1a7783bb9 4098 }
mluis 3:b9d87593a8ae 4099 #endif
mluis 3:b9d87593a8ae 4100
mluis 3:b9d87593a8ae 4101 // Validate the frequency
mluis 3:b9d87593a8ae 4102 if( ( Radio.CheckRfFrequency( params.Frequency ) == true ) && ( params.Frequency > 0 ) && ( frequencyInvalid == false ) )
mluis 0:91d1a7783bb9 4103 {
mluis 3:b9d87593a8ae 4104 #if defined( USE_BAND_868 )
mluis 8:26002607de9c 4105 if( ( params.Frequency >= 863000000 ) && ( params.Frequency < 865000000 ) )
mluis 8:26002607de9c 4106 {
mluis 8:26002607de9c 4107 band = BAND_G1_2;
mluis 8:26002607de9c 4108 }
mluis 8:26002607de9c 4109 else if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
mluis 0:91d1a7783bb9 4110 {
mluis 3:b9d87593a8ae 4111 band = BAND_G1_0;
mluis 0:91d1a7783bb9 4112 }
mluis 3:b9d87593a8ae 4113 else if( ( params.Frequency > 868000000 ) && ( params.Frequency <= 868600000 ) )
mluis 0:91d1a7783bb9 4114 {
mluis 3:b9d87593a8ae 4115 band = BAND_G1_1;
mluis 0:91d1a7783bb9 4116 }
mluis 3:b9d87593a8ae 4117 else if( ( params.Frequency >= 868700000 ) && ( params.Frequency <= 869200000 ) )
mluis 0:91d1a7783bb9 4118 {
mluis 3:b9d87593a8ae 4119 band = BAND_G1_2;
mluis 3:b9d87593a8ae 4120 }
mluis 3:b9d87593a8ae 4121 else if( ( params.Frequency >= 869400000 ) && ( params.Frequency <= 869650000 ) )
mluis 3:b9d87593a8ae 4122 {
mluis 3:b9d87593a8ae 4123 band = BAND_G1_3;
mluis 0:91d1a7783bb9 4124 }
mluis 3:b9d87593a8ae 4125 else if( ( params.Frequency >= 869700000 ) && ( params.Frequency <= 870000000 ) )
mluis 0:91d1a7783bb9 4126 {
mluis 3:b9d87593a8ae 4127 band = BAND_G1_4;
mluis 0:91d1a7783bb9 4128 }
mluis 3:b9d87593a8ae 4129 else
mluis 3:b9d87593a8ae 4130 {
mluis 3:b9d87593a8ae 4131 frequencyInvalid = true;
mluis 3:b9d87593a8ae 4132 }
mluis 3:b9d87593a8ae 4133 #endif
mluis 0:91d1a7783bb9 4134 }
mluis 0:91d1a7783bb9 4135 else
mluis 0:91d1a7783bb9 4136 {
mluis 3:b9d87593a8ae 4137 frequencyInvalid = true;
mluis 3:b9d87593a8ae 4138 }
mluis 3:b9d87593a8ae 4139
mluis 3:b9d87593a8ae 4140 if( ( datarateInvalid == true ) && ( frequencyInvalid == true ) )
mluis 3:b9d87593a8ae 4141 {
mluis 3:b9d87593a8ae 4142 return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
mluis 0:91d1a7783bb9 4143 }
mluis 3:b9d87593a8ae 4144 if( datarateInvalid == true )
mluis 3:b9d87593a8ae 4145 {
mluis 3:b9d87593a8ae 4146 return LORAMAC_STATUS_DATARATE_INVALID;
mluis 3:b9d87593a8ae 4147 }
mluis 3:b9d87593a8ae 4148 if( frequencyInvalid == true )
mluis 0:91d1a7783bb9 4149 {
mluis 3:b9d87593a8ae 4150 return LORAMAC_STATUS_FREQUENCY_INVALID;
mluis 2:14a5d6ad92d5 4151 }
mluis 2:14a5d6ad92d5 4152
mluis 3:b9d87593a8ae 4153 // Every parameter is valid, activate the channel
mluis 3:b9d87593a8ae 4154 Channels[id] = params;
mluis 3:b9d87593a8ae 4155 Channels[id].Band = band;
mluis 7:c16969e0f70f 4156 LoRaMacParams.ChannelsMask[0] |= ( 1 << id );
mluis 3:b9d87593a8ae 4157
mluis 2:14a5d6ad92d5 4158 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 4159 #endif
mluis 0:91d1a7783bb9 4160 }
mluis 0:91d1a7783bb9 4161
mluis 2:14a5d6ad92d5 4162 LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
mluis 0:91d1a7783bb9 4163 {
mluis 3:b9d87593a8ae 4164 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 8:26002607de9c 4165 if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
mluis 0:91d1a7783bb9 4166 {
mluis 8:26002607de9c 4167 if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
mluis 3:b9d87593a8ae 4168 {
mluis 3:b9d87593a8ae 4169 return LORAMAC_STATUS_BUSY;
mluis 3:b9d87593a8ae 4170 }
mluis 0:91d1a7783bb9 4171 }
mluis 3:b9d87593a8ae 4172
mluis 4:37c12dbc8dc7 4173 if( ( id < 3 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
mluis 0:91d1a7783bb9 4174 {
mluis 3:b9d87593a8ae 4175 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 3:b9d87593a8ae 4176 }
mluis 3:b9d87593a8ae 4177 else
mluis 3:b9d87593a8ae 4178 {
mluis 3:b9d87593a8ae 4179 // Remove the channel from the list of channels
mluis 3:b9d87593a8ae 4180 Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 };
mluis 4:37c12dbc8dc7 4181
mluis 3:b9d87593a8ae 4182 // Disable the channel as it doesn't exist anymore
mluis 7:c16969e0f70f 4183 if( DisableChannelInMask( id, LoRaMacParams.ChannelsMask ) == false )
mluis 2:14a5d6ad92d5 4184 {
mluis 2:14a5d6ad92d5 4185 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4186 }
mluis 0:91d1a7783bb9 4187 }
mluis 3:b9d87593a8ae 4188 return LORAMAC_STATUS_OK;
mluis 8:26002607de9c 4189 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) || defined( USE_BAND_470 ) )
mluis 3:b9d87593a8ae 4190 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4191 #endif
mluis 2:14a5d6ad92d5 4192 }
mluis 2:14a5d6ad92d5 4193
mluis 2:14a5d6ad92d5 4194 LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam )
mluis 2:14a5d6ad92d5 4195 {
mluis 2:14a5d6ad92d5 4196 if( channelParam == NULL )
mluis 2:14a5d6ad92d5 4197 {
mluis 2:14a5d6ad92d5 4198 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4199 }
mluis 8:26002607de9c 4200 if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
mluis 2:14a5d6ad92d5 4201 {
mluis 2:14a5d6ad92d5 4202 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 4203 }
mluis 2:14a5d6ad92d5 4204
mluis 2:14a5d6ad92d5 4205 // Reset downlink counter
mluis 2:14a5d6ad92d5 4206 channelParam->DownLinkCounter = 0;
mluis 2:14a5d6ad92d5 4207
mluis 2:14a5d6ad92d5 4208 if( MulticastChannels == NULL )
mluis 2:14a5d6ad92d5 4209 {
mluis 2:14a5d6ad92d5 4210 // New node is the fist element
mluis 2:14a5d6ad92d5 4211 MulticastChannels = channelParam;
mluis 0:91d1a7783bb9 4212 }
mluis 0:91d1a7783bb9 4213 else
mluis 0:91d1a7783bb9 4214 {
mluis 2:14a5d6ad92d5 4215 MulticastParams_t *cur = MulticastChannels;
mluis 2:14a5d6ad92d5 4216
mluis 2:14a5d6ad92d5 4217 // Search the last node in the list
mluis 2:14a5d6ad92d5 4218 while( cur->Next != NULL )
mluis 2:14a5d6ad92d5 4219 {
mluis 2:14a5d6ad92d5 4220 cur = cur->Next;
mluis 2:14a5d6ad92d5 4221 }
mluis 2:14a5d6ad92d5 4222 // This function always finds the last node
mluis 2:14a5d6ad92d5 4223 cur->Next = channelParam;
mluis 0:91d1a7783bb9 4224 }
mluis 2:14a5d6ad92d5 4225
mluis 2:14a5d6ad92d5 4226 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 4227 }
mluis 0:91d1a7783bb9 4228
mluis 2:14a5d6ad92d5 4229 LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam )
mluis 0:91d1a7783bb9 4230 {
mluis 2:14a5d6ad92d5 4231 if( channelParam == NULL )
mluis 0:91d1a7783bb9 4232 {
mluis 2:14a5d6ad92d5 4233 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 0:91d1a7783bb9 4234 }
mluis 8:26002607de9c 4235 if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
mluis 2:14a5d6ad92d5 4236 {
mluis 2:14a5d6ad92d5 4237 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 4238 }
mluis 2:14a5d6ad92d5 4239
mluis 2:14a5d6ad92d5 4240 if( MulticastChannels != NULL )
mluis 0:91d1a7783bb9 4241 {
mluis 2:14a5d6ad92d5 4242 if( MulticastChannels == channelParam )
mluis 2:14a5d6ad92d5 4243 {
mluis 2:14a5d6ad92d5 4244 // First element
mluis 2:14a5d6ad92d5 4245 MulticastChannels = channelParam->Next;
mluis 2:14a5d6ad92d5 4246 }
mluis 2:14a5d6ad92d5 4247 else
mluis 2:14a5d6ad92d5 4248 {
mluis 2:14a5d6ad92d5 4249 MulticastParams_t *cur = MulticastChannels;
mluis 2:14a5d6ad92d5 4250
mluis 2:14a5d6ad92d5 4251 // Search the node in the list
mluis 2:14a5d6ad92d5 4252 while( cur->Next && cur->Next != channelParam )
mluis 2:14a5d6ad92d5 4253 {
mluis 2:14a5d6ad92d5 4254 cur = cur->Next;
mluis 2:14a5d6ad92d5 4255 }
mluis 2:14a5d6ad92d5 4256 // If we found the node, remove it
mluis 2:14a5d6ad92d5 4257 if( cur->Next )
mluis 2:14a5d6ad92d5 4258 {
mluis 2:14a5d6ad92d5 4259 cur->Next = channelParam->Next;
mluis 2:14a5d6ad92d5 4260 }
mluis 2:14a5d6ad92d5 4261 }
mluis 2:14a5d6ad92d5 4262 channelParam->Next = NULL;
mluis 0:91d1a7783bb9 4263 }
mluis 2:14a5d6ad92d5 4264
mluis 2:14a5d6ad92d5 4265 return LORAMAC_STATUS_OK;
mluis 0:91d1a7783bb9 4266 }
mluis 0:91d1a7783bb9 4267
mluis 2:14a5d6ad92d5 4268 LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest )
mluis 0:91d1a7783bb9 4269 {
mluis 2:14a5d6ad92d5 4270 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 2:14a5d6ad92d5 4271 LoRaMacHeader_t macHdr;
mluis 2:14a5d6ad92d5 4272
mluis 2:14a5d6ad92d5 4273 if( mlmeRequest == NULL )
mluis 2:14a5d6ad92d5 4274 {
mluis 2:14a5d6ad92d5 4275 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4276 }
mluis 8:26002607de9c 4277 if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
mluis 2:14a5d6ad92d5 4278 {
mluis 2:14a5d6ad92d5 4279 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 4280 }
mluis 2:14a5d6ad92d5 4281
mluis 2:14a5d6ad92d5 4282 memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) );
mluis 2:14a5d6ad92d5 4283
mluis 2:14a5d6ad92d5 4284 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 2:14a5d6ad92d5 4285
mluis 2:14a5d6ad92d5 4286 switch( mlmeRequest->Type )
mluis 2:14a5d6ad92d5 4287 {
mluis 2:14a5d6ad92d5 4288 case MLME_JOIN:
mluis 2:14a5d6ad92d5 4289 {
mluis 8:26002607de9c 4290 if( ( LoRaMacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED )
mluis 2:14a5d6ad92d5 4291 {
mluis 6:d7a34ded7c87 4292 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 4293 }
mluis 2:14a5d6ad92d5 4294
mluis 2:14a5d6ad92d5 4295 if( ( mlmeRequest->Req.Join.DevEui == NULL ) ||
mluis 2:14a5d6ad92d5 4296 ( mlmeRequest->Req.Join.AppEui == NULL ) ||
mluis 8:26002607de9c 4297 ( mlmeRequest->Req.Join.AppKey == NULL ) ||
mluis 8:26002607de9c 4298 ( mlmeRequest->Req.Join.NbTrials == 0 ) )
mluis 2:14a5d6ad92d5 4299 {
mluis 2:14a5d6ad92d5 4300 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4301 }
mluis 2:14a5d6ad92d5 4302
mluis 8:26002607de9c 4303 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 8:26002607de9c 4304 // Enables at least the usage of the 2 datarates.
mluis 8:26002607de9c 4305 if( mlmeRequest->Req.Join.NbTrials < 2 )
mluis 8:26002607de9c 4306 {
mluis 8:26002607de9c 4307 mlmeRequest->Req.Join.NbTrials = 2;
mluis 8:26002607de9c 4308 }
mluis 8:26002607de9c 4309 #else
mluis 8:26002607de9c 4310 // Enables at least the usage of all datarates.
mluis 8:26002607de9c 4311 if( mlmeRequest->Req.Join.NbTrials < 48 )
mluis 8:26002607de9c 4312 {
mluis 8:26002607de9c 4313 mlmeRequest->Req.Join.NbTrials = 48;
mluis 8:26002607de9c 4314 }
mluis 8:26002607de9c 4315 #endif
mluis 8:26002607de9c 4316
mluis 2:14a5d6ad92d5 4317 LoRaMacFlags.Bits.MlmeReq = 1;
mluis 8:26002607de9c 4318 MlmeConfirm.MlmeRequest = mlmeRequest->Type;
mluis 2:14a5d6ad92d5 4319
mluis 2:14a5d6ad92d5 4320 LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
mluis 2:14a5d6ad92d5 4321 LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
mluis 2:14a5d6ad92d5 4322 LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
mluis 8:26002607de9c 4323 MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials;
mluis 8:26002607de9c 4324
mluis 8:26002607de9c 4325 // Reset variable JoinRequestTrials
mluis 8:26002607de9c 4326 JoinRequestTrials = 0;
mluis 8:26002607de9c 4327
mluis 8:26002607de9c 4328 // Setup header information
mluis 2:14a5d6ad92d5 4329 macHdr.Value = 0;
mluis 2:14a5d6ad92d5 4330 macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
mluis 2:14a5d6ad92d5 4331
mluis 7:c16969e0f70f 4332 ResetMacParameters( );
mluis 7:c16969e0f70f 4333
mluis 8:26002607de9c 4334 // Add a +1, since we start to count from 0
mluis 8:26002607de9c 4335 LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials + 1 );
mluis 2:14a5d6ad92d5 4336
mluis 2:14a5d6ad92d5 4337 status = Send( &macHdr, 0, NULL, 0 );
mluis 2:14a5d6ad92d5 4338 break;
mluis 2:14a5d6ad92d5 4339 }
mluis 2:14a5d6ad92d5 4340 case MLME_LINK_CHECK:
mluis 2:14a5d6ad92d5 4341 {
mluis 2:14a5d6ad92d5 4342 LoRaMacFlags.Bits.MlmeReq = 1;
mluis 2:14a5d6ad92d5 4343 // LoRaMac will send this command piggy-pack
mluis 2:14a5d6ad92d5 4344 MlmeConfirm.MlmeRequest = mlmeRequest->Type;
mluis 2:14a5d6ad92d5 4345
mluis 2:14a5d6ad92d5 4346 status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
mluis 2:14a5d6ad92d5 4347 break;
mluis 2:14a5d6ad92d5 4348 }
mluis 8:26002607de9c 4349 case MLME_TXCW:
mluis 8:26002607de9c 4350 {
mluis 8:26002607de9c 4351 MlmeConfirm.MlmeRequest = mlmeRequest->Type;
mluis 8:26002607de9c 4352 LoRaMacFlags.Bits.MlmeReq = 1;
mluis 8:26002607de9c 4353 status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout );
mluis 8:26002607de9c 4354 break;
mluis 8:26002607de9c 4355 }
mluis 8:26002607de9c 4356 case MLME_TXCW_1:
mluis 8:26002607de9c 4357 {
mluis 8:26002607de9c 4358 MlmeConfirm.MlmeRequest = mlmeRequest->Type;
mluis 8:26002607de9c 4359 LoRaMacFlags.Bits.MlmeReq = 1;
mluis 8:26002607de9c 4360 status = SetTxContinuousWave1( mlmeRequest->Req.TxCw.Timeout, mlmeRequest->Req.TxCw.Frequency, mlmeRequest->Req.TxCw.Power );
mluis 8:26002607de9c 4361 break;
mluis 8:26002607de9c 4362 }
mluis 2:14a5d6ad92d5 4363 default:
mluis 2:14a5d6ad92d5 4364 break;
mluis 2:14a5d6ad92d5 4365 }
mluis 2:14a5d6ad92d5 4366
mluis 2:14a5d6ad92d5 4367 if( status != LORAMAC_STATUS_OK )
mluis 2:14a5d6ad92d5 4368 {
mluis 2:14a5d6ad92d5 4369 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 4370 LoRaMacFlags.Bits.MlmeReq = 0;
mluis 2:14a5d6ad92d5 4371 }
mluis 2:14a5d6ad92d5 4372
mluis 2:14a5d6ad92d5 4373 return status;
mluis 0:91d1a7783bb9 4374 }
mluis 0:91d1a7783bb9 4375
mluis 2:14a5d6ad92d5 4376 LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
mluis 0:91d1a7783bb9 4377 {
mluis 2:14a5d6ad92d5 4378 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
mluis 2:14a5d6ad92d5 4379 LoRaMacHeader_t macHdr;
mluis 2:14a5d6ad92d5 4380 uint8_t fPort = 0;
mluis 2:14a5d6ad92d5 4381 void *fBuffer;
mluis 2:14a5d6ad92d5 4382 uint16_t fBufferSize;
mluis 2:14a5d6ad92d5 4383 int8_t datarate;
mluis 2:14a5d6ad92d5 4384 bool readyToSend = false;
mluis 2:14a5d6ad92d5 4385
mluis 2:14a5d6ad92d5 4386 if( mcpsRequest == NULL )
mluis 2:14a5d6ad92d5 4387 {
mluis 2:14a5d6ad92d5 4388 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4389 }
mluis 8:26002607de9c 4390 if( ( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING ) ||
mluis 8:26002607de9c 4391 ( ( LoRaMacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED ) )
mluis 2:14a5d6ad92d5 4392 {
mluis 2:14a5d6ad92d5 4393 return LORAMAC_STATUS_BUSY;
mluis 2:14a5d6ad92d5 4394 }
mluis 2:14a5d6ad92d5 4395
mluis 2:14a5d6ad92d5 4396 macHdr.Value = 0;
mluis 2:14a5d6ad92d5 4397 memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) );
mluis 2:14a5d6ad92d5 4398 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 2:14a5d6ad92d5 4399
mluis 2:14a5d6ad92d5 4400 switch( mcpsRequest->Type )
mluis 2:14a5d6ad92d5 4401 {
mluis 2:14a5d6ad92d5 4402 case MCPS_UNCONFIRMED:
mluis 2:14a5d6ad92d5 4403 {
mluis 2:14a5d6ad92d5 4404 readyToSend = true;
mluis 2:14a5d6ad92d5 4405 AckTimeoutRetries = 1;
mluis 2:14a5d6ad92d5 4406
mluis 2:14a5d6ad92d5 4407 macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP;
mluis 2:14a5d6ad92d5 4408 fPort = mcpsRequest->Req.Unconfirmed.fPort;
mluis 2:14a5d6ad92d5 4409 fBuffer = mcpsRequest->Req.Unconfirmed.fBuffer;
mluis 2:14a5d6ad92d5 4410 fBufferSize = mcpsRequest->Req.Unconfirmed.fBufferSize;
mluis 2:14a5d6ad92d5 4411 datarate = mcpsRequest->Req.Unconfirmed.Datarate;
mluis 2:14a5d6ad92d5 4412 break;
mluis 2:14a5d6ad92d5 4413 }
mluis 2:14a5d6ad92d5 4414 case MCPS_CONFIRMED:
mluis 2:14a5d6ad92d5 4415 {
mluis 2:14a5d6ad92d5 4416 readyToSend = true;
mluis 2:14a5d6ad92d5 4417 AckTimeoutRetriesCounter = 1;
mluis 3:b9d87593a8ae 4418 AckTimeoutRetries = mcpsRequest->Req.Confirmed.NbTrials;
mluis 2:14a5d6ad92d5 4419
mluis 2:14a5d6ad92d5 4420 macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
mluis 2:14a5d6ad92d5 4421 fPort = mcpsRequest->Req.Confirmed.fPort;
mluis 2:14a5d6ad92d5 4422 fBuffer = mcpsRequest->Req.Confirmed.fBuffer;
mluis 2:14a5d6ad92d5 4423 fBufferSize = mcpsRequest->Req.Confirmed.fBufferSize;
mluis 2:14a5d6ad92d5 4424 datarate = mcpsRequest->Req.Confirmed.Datarate;
mluis 2:14a5d6ad92d5 4425 break;
mluis 2:14a5d6ad92d5 4426 }
mluis 2:14a5d6ad92d5 4427 case MCPS_PROPRIETARY:
mluis 2:14a5d6ad92d5 4428 {
mluis 2:14a5d6ad92d5 4429 readyToSend = true;
mluis 2:14a5d6ad92d5 4430 AckTimeoutRetries = 1;
mluis 2:14a5d6ad92d5 4431
mluis 2:14a5d6ad92d5 4432 macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY;
mluis 2:14a5d6ad92d5 4433 fBuffer = mcpsRequest->Req.Proprietary.fBuffer;
mluis 2:14a5d6ad92d5 4434 fBufferSize = mcpsRequest->Req.Proprietary.fBufferSize;
mluis 2:14a5d6ad92d5 4435 datarate = mcpsRequest->Req.Proprietary.Datarate;
mluis 2:14a5d6ad92d5 4436 break;
mluis 2:14a5d6ad92d5 4437 }
mluis 2:14a5d6ad92d5 4438 default:
mluis 2:14a5d6ad92d5 4439 break;
mluis 2:14a5d6ad92d5 4440 }
mluis 2:14a5d6ad92d5 4441
mluis 2:14a5d6ad92d5 4442 if( readyToSend == true )
mluis 2:14a5d6ad92d5 4443 {
mluis 2:14a5d6ad92d5 4444 if( AdrCtrlOn == false )
mluis 2:14a5d6ad92d5 4445 {
mluis 4:37c12dbc8dc7 4446 if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true )
mluis 2:14a5d6ad92d5 4447 {
mluis 7:c16969e0f70f 4448 LoRaMacParams.ChannelsDatarate = datarate;
mluis 2:14a5d6ad92d5 4449 }
mluis 2:14a5d6ad92d5 4450 else
mluis 2:14a5d6ad92d5 4451 {
mluis 2:14a5d6ad92d5 4452 return LORAMAC_STATUS_PARAMETER_INVALID;
mluis 2:14a5d6ad92d5 4453 }
mluis 2:14a5d6ad92d5 4454 }
mluis 2:14a5d6ad92d5 4455
mluis 2:14a5d6ad92d5 4456 status = Send( &macHdr, fPort, fBuffer, fBufferSize );
mluis 2:14a5d6ad92d5 4457 if( status == LORAMAC_STATUS_OK )
mluis 2:14a5d6ad92d5 4458 {
mluis 2:14a5d6ad92d5 4459 McpsConfirm.McpsRequest = mcpsRequest->Type;
mluis 2:14a5d6ad92d5 4460 LoRaMacFlags.Bits.McpsReq = 1;
mluis 2:14a5d6ad92d5 4461 }
mluis 2:14a5d6ad92d5 4462 else
mluis 2:14a5d6ad92d5 4463 {
mluis 2:14a5d6ad92d5 4464 NodeAckRequested = false;
mluis 2:14a5d6ad92d5 4465 }
mluis 2:14a5d6ad92d5 4466 }
mluis 2:14a5d6ad92d5 4467
mluis 2:14a5d6ad92d5 4468 return status;
mluis 0:91d1a7783bb9 4469 }
mluis 0:91d1a7783bb9 4470
mluis 0:91d1a7783bb9 4471 void LoRaMacTestRxWindowsOn( bool enable )
mluis 0:91d1a7783bb9 4472 {
mluis 0:91d1a7783bb9 4473 IsRxWindowsEnabled = enable;
mluis 0:91d1a7783bb9 4474 }
mluis 0:91d1a7783bb9 4475
mluis 2:14a5d6ad92d5 4476 void LoRaMacTestSetMic( uint16_t txPacketCounter )
mluis 0:91d1a7783bb9 4477 {
mluis 2:14a5d6ad92d5 4478 UpLinkCounter = txPacketCounter;
mluis 0:91d1a7783bb9 4479 IsUpLinkCounterFixed = true;
mluis 0:91d1a7783bb9 4480 }
mluis 2:14a5d6ad92d5 4481
mluis 2:14a5d6ad92d5 4482 void LoRaMacTestSetDutyCycleOn( bool enable )
mluis 2:14a5d6ad92d5 4483 {
mluis 8:26002607de9c 4484 #if ( defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) )
mluis 2:14a5d6ad92d5 4485 DutyCycleOn = enable;
mluis 8:26002607de9c 4486 #else
mluis 8:26002607de9c 4487 DutyCycleOn = false;
mluis 8:26002607de9c 4488 #endif
mluis 2:14a5d6ad92d5 4489 }
mluis 8:26002607de9c 4490
mluis 8:26002607de9c 4491 void LoRaMacTestSetChannel( uint8_t channel )
mluis 8:26002607de9c 4492 {
mluis 8:26002607de9c 4493 Channel = channel;
mluis 8:26002607de9c 4494 }
mluis 8:26002607de9c 4495
mluis 8:26002607de9c 4496 static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError )
mluis 8:26002607de9c 4497 {
mluis 8:26002607de9c 4498 RxConfigParams_t rxConfigParams = { 0, 0, 0, 0 };
mluis 8:26002607de9c 4499 double tSymbol = 0.0;
mluis 8:26002607de9c 4500
mluis 8:26002607de9c 4501 rxConfigParams.Datarate = datarate;
mluis 8:26002607de9c 4502 switch( Bandwidths[datarate] )
mluis 8:26002607de9c 4503 {
mluis 8:26002607de9c 4504 default:
mluis 8:26002607de9c 4505 case 125000:
mluis 8:26002607de9c 4506 rxConfigParams.Bandwidth = 0;
mluis 8:26002607de9c 4507 break;
mluis 8:26002607de9c 4508 case 250000:
mluis 8:26002607de9c 4509 rxConfigParams.Bandwidth = 1;
mluis 8:26002607de9c 4510 break;
mluis 8:26002607de9c 4511 case 500000:
mluis 8:26002607de9c 4512 rxConfigParams.Bandwidth = 2;
mluis 8:26002607de9c 4513 break;
mluis 8:26002607de9c 4514 }
mluis 8:26002607de9c 4515
mluis 8:26002607de9c 4516 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 8:26002607de9c 4517 if( datarate == DR_7 )
mluis 8:26002607de9c 4518 { // FSK
mluis 8:26002607de9c 4519 tSymbol = ( 1.0 / ( double )Datarates[datarate] ) * 8.0; // 1 symbol equals 1 byte
mluis 8:26002607de9c 4520 }
mluis 8:26002607de9c 4521 else
mluis 8:26002607de9c 4522 #endif
mluis 8:26002607de9c 4523 { // LoRa
mluis 8:26002607de9c 4524 tSymbol = ( ( double )( 1 << Datarates[datarate] ) / ( double )Bandwidths[datarate] ) * 1e3;
mluis 8:26002607de9c 4525 }
mluis 8:26002607de9c 4526
mluis 8:26002607de9c 4527 rxConfigParams.RxWindowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * LoRaMacParams.MinRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), LoRaMacParams.MinRxSymbols ); // Computed number of symbols
mluis 8:26002607de9c 4528
mluis 8:26002607de9c 4529 rxConfigParams.RxOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( rxConfigParams.RxWindowTimeout * tSymbol ) / 2.0 ) - RADIO_WAKEUP_TIME );
mluis 8:26002607de9c 4530
mluis 8:26002607de9c 4531 return rxConfigParams;
mluis 8:26002607de9c 4532 }