Semtech / LoRaWAN-lib-dev

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

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

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

The example projects are:

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

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

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


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433
Committer:
mluis
Date:
Tue Jul 05 15:12:50 2016 +0000
Revision:
1:4820e04b066c
Parent:
0:66f12acb8acb
Child:
2:76f59096e3a7
Synchronized with https://github.com/Lora-net/LoRaMac-node develop branch git revision c09c3101e64d7c7f1ca5061faf470d709122c8d0

Who changed what in which revision?

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