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:
Thu Jun 02 07:58:35 2016 +0000
Revision:
0:66f12acb8acb
Child:
1:4820e04b066c
Synchronized with https://github.com/Lora-net/LoRaMac-node develop branch git revision 8391d0092863c1522c395fe7e6305706a98bb11e

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