LoRaWAN MAC layer implementation

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

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

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

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

The example projects are:

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

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

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


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433
Committer:
mluis
Date:
Fri May 13 14:51:50 2016 +0000
Revision:
4:37c12dbc8dc7
Parent:
3:b9d87593a8ae
Child:
5:2477c924494a
Synchronized with https://github.com/Lora-net/LoRaMac-node git revision 55d16ca8949c09ee241c87b7600e2a8bc90d3743

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