LoRaWAN MAC layer implementation

Dependents:   LoRaWAN-demo-72_tjm LoRaWAN-demo-72_jlc LoRaWAN-demo-elmo frdm_LoRa_Connect_Woodstream_Demo_tjm ... more

LoRAWAN-lib is a port of the GitHub LoRaMac-node LoRaWAN MAC layer implementation.

This library depends on the SX1276Lib or SX1272Lib radio drivers depending on the used mbed component shield.

This library depends also on some cryptographic helper functions as well as helper functions for the timers management. These can be found on the example projects under the system directory.

The example projects are:

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

The LoRaWAN specification specifies different ISM bands operating parameters. These are all implemented under the LoRaMac-board.h file.

In order to select which band to use, please change line 24 of board.h file provided on the examples projects as follows:


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433
Committer:
mluis
Date:
Tue Jan 05 16:41:54 2016 +0000
Revision:
2:14a5d6ad92d5
Parent:
1:91e4e6c60d1e
Child:
3:b9d87593a8ae
Synchronized with https://github.com/Lora-net/LoRaMac-node git revision a2226468d470eceb251338e1acfb24cfd121effa

Who changed what in which revision?

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