LoRaWAN MAC layer implementation

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

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

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

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

The example projects are:

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

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

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


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433
Committer:
ubhat
Date:
Tue Jul 17 22:48:35 2018 +0000
Revision:
11:2426a05fe29e
Parent:
6:d7a34ded7c87
Fix bug where FCnt get incremented twice in the case of ADRACKReq with D/L ACK

Who changed what in which revision?

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