LoRaWAN MAC layer implementation

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

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

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

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

The example projects are:

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

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

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


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433
Committer:
mluis
Date:
Tue Oct 20 13:21:26 2015 +0000
Revision:
0:91d1a7783bb9
Child:
1:91e4e6c60d1e
Library creation synchronized with GitHub LoRaMac-node v3.4 (https://github.com/Lora-net/LoRaMac-node)

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 0:91d1a7783bb9 8
mluis 0:91d1a7783bb9 9 Description: LoRa MAC layer implementation
mluis 0:91d1a7783bb9 10
mluis 0:91d1a7783bb9 11 License: Revised BSD License, see LICENSE.TXT file include in the project
mluis 0:91d1a7783bb9 12
mluis 0:91d1a7783bb9 13 Maintainer: Miguel Luis and Gregory Cristian
mluis 0:91d1a7783bb9 14 */
mluis 0:91d1a7783bb9 15 #include "mbed.h"
mluis 0:91d1a7783bb9 16 #include "board.h"
mluis 0:91d1a7783bb9 17 #include "utilities.h"
mluis 0:91d1a7783bb9 18 #include "sx1276-hal.h"
mluis 0:91d1a7783bb9 19
mluis 0:91d1a7783bb9 20 #include "LoRaMacCrypto.h"
mluis 0:91d1a7783bb9 21 #include "LoRaMac.h"
mluis 0:91d1a7783bb9 22
mluis 0:91d1a7783bb9 23 /*!
mluis 0:91d1a7783bb9 24 * Maximum PHY layer payload size
mluis 0:91d1a7783bb9 25 */
mluis 0:91d1a7783bb9 26 #define LORAMAC_PHY_MAXPAYLOAD 250
mluis 0:91d1a7783bb9 27
mluis 0:91d1a7783bb9 28 /*!
mluis 0:91d1a7783bb9 29 * Device IEEE EUI
mluis 0:91d1a7783bb9 30 */
mluis 0:91d1a7783bb9 31 static uint8_t *LoRaMacDevEui;
mluis 0:91d1a7783bb9 32
mluis 0:91d1a7783bb9 33 /*!
mluis 0:91d1a7783bb9 34 * Application IEEE EUI
mluis 0:91d1a7783bb9 35 */
mluis 0:91d1a7783bb9 36 static uint8_t *LoRaMacAppEui;
mluis 0:91d1a7783bb9 37
mluis 0:91d1a7783bb9 38 /*!
mluis 0:91d1a7783bb9 39 * AES encryption/decryption cipher application key
mluis 0:91d1a7783bb9 40 */
mluis 0:91d1a7783bb9 41 static uint8_t *LoRaMacAppKey;
mluis 0:91d1a7783bb9 42
mluis 0:91d1a7783bb9 43 /*!
mluis 0:91d1a7783bb9 44 * AES encryption/decryption cipher network session key
mluis 0:91d1a7783bb9 45 */
mluis 0:91d1a7783bb9 46 static uint8_t LoRaMacNwkSKey[] =
mluis 0:91d1a7783bb9 47 {
mluis 0:91d1a7783bb9 48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mluis 0:91d1a7783bb9 49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:91d1a7783bb9 50 };
mluis 0:91d1a7783bb9 51
mluis 0:91d1a7783bb9 52 /*!
mluis 0:91d1a7783bb9 53 * AES encryption/decryption cipher application session key
mluis 0:91d1a7783bb9 54 */
mluis 0:91d1a7783bb9 55 static uint8_t LoRaMacAppSKey[] =
mluis 0:91d1a7783bb9 56 {
mluis 0:91d1a7783bb9 57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
mluis 0:91d1a7783bb9 58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
mluis 0:91d1a7783bb9 59 };
mluis 0:91d1a7783bb9 60
mluis 0:91d1a7783bb9 61 /*!
mluis 0:91d1a7783bb9 62 * Device nonce is a random value extracted by issuing a sequence of RSSI
mluis 0:91d1a7783bb9 63 * measurements
mluis 0:91d1a7783bb9 64 */
mluis 0:91d1a7783bb9 65 static uint16_t LoRaMacDevNonce;
mluis 0:91d1a7783bb9 66
mluis 0:91d1a7783bb9 67 /*!
mluis 0:91d1a7783bb9 68 * Network ID ( 3 bytes )
mluis 0:91d1a7783bb9 69 */
mluis 0:91d1a7783bb9 70 static uint32_t LoRaMacNetID;
mluis 0:91d1a7783bb9 71
mluis 0:91d1a7783bb9 72 /*!
mluis 0:91d1a7783bb9 73 * Mote Address
mluis 0:91d1a7783bb9 74 */
mluis 0:91d1a7783bb9 75 static uint32_t LoRaMacDevAddr;
mluis 0:91d1a7783bb9 76
mluis 0:91d1a7783bb9 77 /*!
mluis 0:91d1a7783bb9 78 * Mutlicast channels linked list
mluis 0:91d1a7783bb9 79 */
mluis 0:91d1a7783bb9 80 static MulticastParams_t *MulticastChannels = NULL;
mluis 0:91d1a7783bb9 81
mluis 0:91d1a7783bb9 82 /*!
mluis 0:91d1a7783bb9 83 * Actual device class
mluis 0:91d1a7783bb9 84 */
mluis 0:91d1a7783bb9 85 static DeviceClass_t LoRaMacDeviceClass;
mluis 0:91d1a7783bb9 86
mluis 0:91d1a7783bb9 87 /*!
mluis 0:91d1a7783bb9 88 * Indicates if the node is connected to a private or public network
mluis 0:91d1a7783bb9 89 */
mluis 0:91d1a7783bb9 90 static bool PublicNetwork;
mluis 0:91d1a7783bb9 91
mluis 0:91d1a7783bb9 92 /*!
mluis 0:91d1a7783bb9 93 * Indicates if the node supports repeaters
mluis 0:91d1a7783bb9 94 */
mluis 0:91d1a7783bb9 95 static bool RepeaterSupport;
mluis 0:91d1a7783bb9 96
mluis 0:91d1a7783bb9 97 /*!
mluis 0:91d1a7783bb9 98 * Buffer containing the data to be sent or received.
mluis 0:91d1a7783bb9 99 */
mluis 0:91d1a7783bb9 100 static uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD];
mluis 0:91d1a7783bb9 101
mluis 0:91d1a7783bb9 102 /*!
mluis 0:91d1a7783bb9 103 * Length of packet in LoRaMacBuffer
mluis 0:91d1a7783bb9 104 */
mluis 0:91d1a7783bb9 105 static uint16_t LoRaMacBufferPktLen = 0;
mluis 0:91d1a7783bb9 106
mluis 0:91d1a7783bb9 107 /*!
mluis 0:91d1a7783bb9 108 * Buffer containing the upper layer data.
mluis 0:91d1a7783bb9 109 */
mluis 0:91d1a7783bb9 110 static uint8_t LoRaMacPayload[LORAMAC_PHY_MAXPAYLOAD];
mluis 0:91d1a7783bb9 111 static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];
mluis 0:91d1a7783bb9 112
mluis 0:91d1a7783bb9 113 /*!
mluis 0:91d1a7783bb9 114 * LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
mluis 0:91d1a7783bb9 115 * Only the 16 LSB bits are sent
mluis 0:91d1a7783bb9 116 */
mluis 0:91d1a7783bb9 117 static uint32_t UpLinkCounter = 1;
mluis 0:91d1a7783bb9 118
mluis 0:91d1a7783bb9 119 /*!
mluis 0:91d1a7783bb9 120 * LoRaMAC frame counter. Each time a packet is received the counter is incremented.
mluis 0:91d1a7783bb9 121 * Only the 16 LSB bits are received
mluis 0:91d1a7783bb9 122 */
mluis 0:91d1a7783bb9 123 static uint32_t DownLinkCounter = 0;
mluis 0:91d1a7783bb9 124
mluis 0:91d1a7783bb9 125 /*!
mluis 0:91d1a7783bb9 126 * IsPacketCounterFixed enables the MIC field tests by fixing the
mluis 0:91d1a7783bb9 127 * UpLinkCounter value
mluis 0:91d1a7783bb9 128 */
mluis 0:91d1a7783bb9 129 static bool IsUpLinkCounterFixed = false;
mluis 0:91d1a7783bb9 130
mluis 0:91d1a7783bb9 131 /*!
mluis 0:91d1a7783bb9 132 * Used for test purposes. Disables the opening of the reception windows.
mluis 0:91d1a7783bb9 133 */
mluis 0:91d1a7783bb9 134 static bool IsRxWindowsEnabled = true;
mluis 0:91d1a7783bb9 135
mluis 0:91d1a7783bb9 136 /*!
mluis 0:91d1a7783bb9 137 * Indicates if the MAC layer has already joined a network.
mluis 0:91d1a7783bb9 138 */
mluis 0:91d1a7783bb9 139 static bool IsLoRaMacNetworkJoined = false;
mluis 0:91d1a7783bb9 140
mluis 0:91d1a7783bb9 141 /*!
mluis 0:91d1a7783bb9 142 * LoRaMac ADR control status
mluis 0:91d1a7783bb9 143 */
mluis 0:91d1a7783bb9 144 static bool AdrCtrlOn = false;
mluis 0:91d1a7783bb9 145
mluis 0:91d1a7783bb9 146 /*!
mluis 0:91d1a7783bb9 147 * Counts the number of missed ADR acknowledgements
mluis 0:91d1a7783bb9 148 */
mluis 0:91d1a7783bb9 149 static uint32_t AdrAckCounter = 0;
mluis 0:91d1a7783bb9 150
mluis 0:91d1a7783bb9 151 /*!
mluis 0:91d1a7783bb9 152 * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
mluis 0:91d1a7783bb9 153 * if the nodes needs to manage the server acknowledgement.
mluis 0:91d1a7783bb9 154 */
mluis 0:91d1a7783bb9 155 static bool NodeAckRequested = false;
mluis 0:91d1a7783bb9 156
mluis 0:91d1a7783bb9 157 /*!
mluis 0:91d1a7783bb9 158 * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
mluis 0:91d1a7783bb9 159 * if the ACK bit must be set for the next transmission
mluis 0:91d1a7783bb9 160 */
mluis 0:91d1a7783bb9 161 static bool SrvAckRequested = false;
mluis 0:91d1a7783bb9 162
mluis 0:91d1a7783bb9 163 /*!
mluis 0:91d1a7783bb9 164 * Indicates if the MAC layer wants to send MAC commands
mluis 0:91d1a7783bb9 165 */
mluis 0:91d1a7783bb9 166 static bool MacCommandsInNextTx = false;
mluis 0:91d1a7783bb9 167
mluis 0:91d1a7783bb9 168 /*!
mluis 0:91d1a7783bb9 169 * Contains the current MacCommandsBuffer index
mluis 0:91d1a7783bb9 170 */
mluis 0:91d1a7783bb9 171 static uint8_t MacCommandsBufferIndex = 0;
mluis 0:91d1a7783bb9 172
mluis 0:91d1a7783bb9 173 /*!
mluis 0:91d1a7783bb9 174 * Buffer containing the MAC layer commands
mluis 0:91d1a7783bb9 175 */
mluis 0:91d1a7783bb9 176 static uint8_t MacCommandsBuffer[15];
mluis 0:91d1a7783bb9 177
mluis 0:91d1a7783bb9 178 #if defined( USE_BAND_433 )
mluis 0:91d1a7783bb9 179 /*!
mluis 0:91d1a7783bb9 180 * Data rates table definition
mluis 0:91d1a7783bb9 181 */
mluis 0:91d1a7783bb9 182 const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
mluis 0:91d1a7783bb9 183
mluis 0:91d1a7783bb9 184 /*!
mluis 0:91d1a7783bb9 185 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
mluis 0:91d1a7783bb9 186 */
mluis 0:91d1a7783bb9 187 const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
mluis 0:91d1a7783bb9 188
mluis 0:91d1a7783bb9 189 /*!
mluis 0:91d1a7783bb9 190 * Maximum payload with respect to the datarate index. Can operate with repeater.
mluis 0:91d1a7783bb9 191 */
mluis 0:91d1a7783bb9 192 const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
mluis 0:91d1a7783bb9 193
mluis 0:91d1a7783bb9 194 /*!
mluis 0:91d1a7783bb9 195 * Tx output powers table definition
mluis 0:91d1a7783bb9 196 */
mluis 0:91d1a7783bb9 197 const int8_t TxPowers[] = { 20, 14, 11, 8, 5, 2 };
mluis 0:91d1a7783bb9 198
mluis 0:91d1a7783bb9 199 /*!
mluis 0:91d1a7783bb9 200 * LoRaMac bands
mluis 0:91d1a7783bb9 201 */
mluis 0:91d1a7783bb9 202 static Band_t Bands[LORA_MAX_NB_BANDS] =
mluis 0:91d1a7783bb9 203 {
mluis 0:91d1a7783bb9 204 BAND0,
mluis 0:91d1a7783bb9 205 };
mluis 0:91d1a7783bb9 206
mluis 0:91d1a7783bb9 207 /*!
mluis 0:91d1a7783bb9 208 * LoRaMAC channels
mluis 0:91d1a7783bb9 209 */
mluis 0:91d1a7783bb9 210 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
mluis 0:91d1a7783bb9 211 {
mluis 0:91d1a7783bb9 212 LC1,
mluis 0:91d1a7783bb9 213 LC2,
mluis 0:91d1a7783bb9 214 LC3,
mluis 0:91d1a7783bb9 215 };
mluis 0:91d1a7783bb9 216 #elif defined( USE_BAND_780 )
mluis 0:91d1a7783bb9 217 /*!
mluis 0:91d1a7783bb9 218 * Data rates table definition
mluis 0:91d1a7783bb9 219 */
mluis 0:91d1a7783bb9 220 const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
mluis 0:91d1a7783bb9 221
mluis 0:91d1a7783bb9 222 /*!
mluis 0:91d1a7783bb9 223 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
mluis 0:91d1a7783bb9 224 */
mluis 0:91d1a7783bb9 225 const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
mluis 0:91d1a7783bb9 226
mluis 0:91d1a7783bb9 227 /*!
mluis 0:91d1a7783bb9 228 * Maximum payload with respect to the datarate index. Can operate with repeater.
mluis 0:91d1a7783bb9 229 */
mluis 0:91d1a7783bb9 230 const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
mluis 0:91d1a7783bb9 231
mluis 0:91d1a7783bb9 232 /*!
mluis 0:91d1a7783bb9 233 * Tx output powers table definition
mluis 0:91d1a7783bb9 234 */
mluis 0:91d1a7783bb9 235 const int8_t TxPowers[] = { 20, 14, 11, 8, 5, 2 };
mluis 0:91d1a7783bb9 236
mluis 0:91d1a7783bb9 237 /*!
mluis 0:91d1a7783bb9 238 * LoRaMac bands
mluis 0:91d1a7783bb9 239 */
mluis 0:91d1a7783bb9 240 static Band_t Bands[LORA_MAX_NB_BANDS] =
mluis 0:91d1a7783bb9 241 {
mluis 0:91d1a7783bb9 242 BAND0,
mluis 0:91d1a7783bb9 243 };
mluis 0:91d1a7783bb9 244
mluis 0:91d1a7783bb9 245 /*!
mluis 0:91d1a7783bb9 246 * LoRaMAC channels
mluis 0:91d1a7783bb9 247 */
mluis 0:91d1a7783bb9 248 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
mluis 0:91d1a7783bb9 249 {
mluis 0:91d1a7783bb9 250 LC1,
mluis 0:91d1a7783bb9 251 LC2,
mluis 0:91d1a7783bb9 252 LC3,
mluis 0:91d1a7783bb9 253 };
mluis 0:91d1a7783bb9 254 #elif defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 255 /*!
mluis 0:91d1a7783bb9 256 * Data rates table definition
mluis 0:91d1a7783bb9 257 */
mluis 0:91d1a7783bb9 258 const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
mluis 0:91d1a7783bb9 259
mluis 0:91d1a7783bb9 260 /*!
mluis 0:91d1a7783bb9 261 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
mluis 0:91d1a7783bb9 262 */
mluis 0:91d1a7783bb9 263 const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
mluis 0:91d1a7783bb9 264
mluis 0:91d1a7783bb9 265 /*!
mluis 0:91d1a7783bb9 266 * Maximum payload with respect to the datarate index. Can operate with repeater.
mluis 0:91d1a7783bb9 267 */
mluis 0:91d1a7783bb9 268 const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
mluis 0:91d1a7783bb9 269
mluis 0:91d1a7783bb9 270 /*!
mluis 0:91d1a7783bb9 271 * Tx output powers table definition
mluis 0:91d1a7783bb9 272 */
mluis 0:91d1a7783bb9 273 const int8_t TxPowers[] = { 20, 14, 11, 8, 5, 2 };
mluis 0:91d1a7783bb9 274
mluis 0:91d1a7783bb9 275 /*!
mluis 0:91d1a7783bb9 276 * LoRaMac bands
mluis 0:91d1a7783bb9 277 */
mluis 0:91d1a7783bb9 278 static Band_t Bands[LORA_MAX_NB_BANDS] =
mluis 0:91d1a7783bb9 279 {
mluis 0:91d1a7783bb9 280 BAND0,
mluis 0:91d1a7783bb9 281 BAND1,
mluis 0:91d1a7783bb9 282 BAND2,
mluis 0:91d1a7783bb9 283 BAND3,
mluis 0:91d1a7783bb9 284 BAND4,
mluis 0:91d1a7783bb9 285 };
mluis 0:91d1a7783bb9 286
mluis 0:91d1a7783bb9 287 /*!
mluis 0:91d1a7783bb9 288 * LoRaMAC channels
mluis 0:91d1a7783bb9 289 */
mluis 0:91d1a7783bb9 290 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
mluis 0:91d1a7783bb9 291 {
mluis 0:91d1a7783bb9 292 LC1,
mluis 0:91d1a7783bb9 293 LC2,
mluis 0:91d1a7783bb9 294 LC3,
mluis 0:91d1a7783bb9 295 LC4,
mluis 0:91d1a7783bb9 296 LC5,
mluis 0:91d1a7783bb9 297 LC6,
mluis 0:91d1a7783bb9 298 LC7,
mluis 0:91d1a7783bb9 299 LC8,
mluis 0:91d1a7783bb9 300 LC9,
mluis 0:91d1a7783bb9 301 };
mluis 0:91d1a7783bb9 302 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 303 /*!
mluis 0:91d1a7783bb9 304 * Data rates table definition
mluis 0:91d1a7783bb9 305 */
mluis 0:91d1a7783bb9 306 const uint8_t Datarates[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
mluis 0:91d1a7783bb9 307
mluis 0:91d1a7783bb9 308 /*!
mluis 0:91d1a7783bb9 309 * Up/Down link data rates offset definition
mluis 0:91d1a7783bb9 310 */
mluis 0:91d1a7783bb9 311 const int8_t datarateOffsets[16][4] =
mluis 0:91d1a7783bb9 312 {
mluis 0:91d1a7783bb9 313 { DR_10, DR_9 , DR_8 , DR_8 }, // DR_0
mluis 0:91d1a7783bb9 314 { DR_11, DR_10, DR_9 , DR_8 }, // DR_1
mluis 0:91d1a7783bb9 315 { DR_12, DR_11, DR_10, DR_9 }, // DR_2
mluis 0:91d1a7783bb9 316 { DR_13, DR_12, DR_11, DR_10 }, // DR_3
mluis 0:91d1a7783bb9 317 { DR_13, DR_13, DR_12, DR_11 }, // DR_4
mluis 0:91d1a7783bb9 318 { 0xFF , 0xFF , 0xFF , 0xFF },
mluis 0:91d1a7783bb9 319 { 0xFF , 0xFF , 0xFF , 0xFF },
mluis 0:91d1a7783bb9 320 { 0xFF , 0xFF , 0xFF , 0xFF },
mluis 0:91d1a7783bb9 321 { DR_8 , DR_8 , DR_8 , DR_8 },
mluis 0:91d1a7783bb9 322 { DR_9 , DR_8 , DR_8 , DR_8 },
mluis 0:91d1a7783bb9 323 { DR_10, DR_9 , DR_8 , DR_8 },
mluis 0:91d1a7783bb9 324 { DR_11, DR_10, DR_9 , DR_8 },
mluis 0:91d1a7783bb9 325 { DR_12, DR_11, DR_10, DR_9 },
mluis 0:91d1a7783bb9 326 { DR_13, DR_12, DR_11, DR_10 },
mluis 0:91d1a7783bb9 327 { 0xFF , 0xFF , 0xFF , 0xFF },
mluis 0:91d1a7783bb9 328 { 0xFF , 0xFF , 0xFF , 0xFF },
mluis 0:91d1a7783bb9 329 };
mluis 0:91d1a7783bb9 330
mluis 0:91d1a7783bb9 331 /*!
mluis 0:91d1a7783bb9 332 * Maximum payload with respect to the datarate index. Cannot operate with repeater.
mluis 0:91d1a7783bb9 333 */
mluis 0:91d1a7783bb9 334 const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 129, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
mluis 0:91d1a7783bb9 335
mluis 0:91d1a7783bb9 336 /*!
mluis 0:91d1a7783bb9 337 * Maximum payload with respect to the datarate index. Can operate with repeater.
mluis 0:91d1a7783bb9 338 */
mluis 0:91d1a7783bb9 339 const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 129, 242, 242, 0, 0, 0, 33, 103, 222, 222, 222, 222, 0, 0 };
mluis 0:91d1a7783bb9 340
mluis 0:91d1a7783bb9 341 /*!
mluis 0:91d1a7783bb9 342 * Tx output powers table definition
mluis 0:91d1a7783bb9 343 */
mluis 0:91d1a7783bb9 344 const int8_t TxPowers[] = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 };
mluis 0:91d1a7783bb9 345
mluis 0:91d1a7783bb9 346 /*!
mluis 0:91d1a7783bb9 347 * LoRaMac bands
mluis 0:91d1a7783bb9 348 */
mluis 0:91d1a7783bb9 349 static Band_t Bands[LORA_MAX_NB_BANDS] =
mluis 0:91d1a7783bb9 350 {
mluis 0:91d1a7783bb9 351 BAND0,
mluis 0:91d1a7783bb9 352 };
mluis 0:91d1a7783bb9 353
mluis 0:91d1a7783bb9 354 /*!
mluis 0:91d1a7783bb9 355 * LoRaMAC channels
mluis 0:91d1a7783bb9 356 */
mluis 0:91d1a7783bb9 357 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS];
mluis 0:91d1a7783bb9 358
mluis 0:91d1a7783bb9 359 #else
mluis 0:91d1a7783bb9 360 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 361 #endif
mluis 0:91d1a7783bb9 362
mluis 0:91d1a7783bb9 363 /*!
mluis 0:91d1a7783bb9 364 * LoRaMAC 2nd reception window settings
mluis 0:91d1a7783bb9 365 */
mluis 0:91d1a7783bb9 366 static Rx2ChannelParams_t Rx2Channel = RX_WND_2_CHANNEL;
mluis 0:91d1a7783bb9 367
mluis 0:91d1a7783bb9 368 /*!
mluis 0:91d1a7783bb9 369 * Datarate offset between uplink and downlink on first window
mluis 0:91d1a7783bb9 370 */
mluis 0:91d1a7783bb9 371 static uint8_t Rx1DrOffset = 0;
mluis 0:91d1a7783bb9 372
mluis 0:91d1a7783bb9 373 /*!
mluis 0:91d1a7783bb9 374 * Mask indicating which channels are enabled
mluis 0:91d1a7783bb9 375 */
mluis 0:91d1a7783bb9 376 static uint16_t ChannelsMask[6];
mluis 0:91d1a7783bb9 377
mluis 0:91d1a7783bb9 378 /*!
mluis 0:91d1a7783bb9 379 * Channels Tx output power
mluis 0:91d1a7783bb9 380 */
mluis 0:91d1a7783bb9 381 static int8_t ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
mluis 0:91d1a7783bb9 382
mluis 0:91d1a7783bb9 383 /*!
mluis 0:91d1a7783bb9 384 * Channels datarate
mluis 0:91d1a7783bb9 385 */
mluis 0:91d1a7783bb9 386 static int8_t ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
mluis 0:91d1a7783bb9 387
mluis 0:91d1a7783bb9 388 /*!
mluis 0:91d1a7783bb9 389 * Channels default datarate
mluis 0:91d1a7783bb9 390 */
mluis 0:91d1a7783bb9 391 static int8_t ChannelsDefaultDatarate = LORAMAC_DEFAULT_DATARATE;
mluis 0:91d1a7783bb9 392
mluis 0:91d1a7783bb9 393 /*!
mluis 0:91d1a7783bb9 394 * Number of uplink messages repetitions [1:15] (unconfirmed messages only)
mluis 0:91d1a7783bb9 395 */
mluis 0:91d1a7783bb9 396 static uint8_t ChannelsNbRep = 1;
mluis 0:91d1a7783bb9 397
mluis 0:91d1a7783bb9 398 /*!
mluis 0:91d1a7783bb9 399 * Uplink messages repetitions counter
mluis 0:91d1a7783bb9 400 */
mluis 0:91d1a7783bb9 401 static uint8_t ChannelsNbRepCounter = 0;
mluis 0:91d1a7783bb9 402
mluis 0:91d1a7783bb9 403 /*!
mluis 0:91d1a7783bb9 404 * Maximum duty cycle
mluis 0:91d1a7783bb9 405 * \remark Possibility to shutdown the device.
mluis 0:91d1a7783bb9 406 */
mluis 0:91d1a7783bb9 407 static uint8_t MaxDCycle = 0;
mluis 0:91d1a7783bb9 408
mluis 0:91d1a7783bb9 409 /*!
mluis 0:91d1a7783bb9 410 * Agregated duty cycle management
mluis 0:91d1a7783bb9 411 */
mluis 0:91d1a7783bb9 412 static uint16_t AggregatedDCycle;
mluis 0:91d1a7783bb9 413 static TimerTime_t AggregatedLastTxDoneTime;
mluis 0:91d1a7783bb9 414 static TimerTime_t AggregatedTimeOff;
mluis 0:91d1a7783bb9 415
mluis 0:91d1a7783bb9 416 /*!
mluis 0:91d1a7783bb9 417 * Enables/Disables duty cycle management (Test only)
mluis 0:91d1a7783bb9 418 */
mluis 0:91d1a7783bb9 419 static bool DutyCycleOn;
mluis 0:91d1a7783bb9 420
mluis 0:91d1a7783bb9 421 /*!
mluis 0:91d1a7783bb9 422 * Current channel index
mluis 0:91d1a7783bb9 423 */
mluis 0:91d1a7783bb9 424 static uint8_t Channel;
mluis 0:91d1a7783bb9 425
mluis 0:91d1a7783bb9 426 /*!
mluis 0:91d1a7783bb9 427 * LoRaMac internal states
mluis 0:91d1a7783bb9 428 */
mluis 0:91d1a7783bb9 429 enum LoRaMacState_e
mluis 0:91d1a7783bb9 430 {
mluis 0:91d1a7783bb9 431 MAC_IDLE = 0x00000000,
mluis 0:91d1a7783bb9 432 MAC_TX_RUNNING = 0x00000001,
mluis 0:91d1a7783bb9 433 MAC_RX = 0x00000002,
mluis 0:91d1a7783bb9 434 MAC_ACK_REQ = 0x00000004,
mluis 0:91d1a7783bb9 435 MAC_ACK_RETRY = 0x00000008,
mluis 0:91d1a7783bb9 436 MAC_CHANNEL_CHECK = 0x00000010,
mluis 0:91d1a7783bb9 437 };
mluis 0:91d1a7783bb9 438
mluis 0:91d1a7783bb9 439 /*!
mluis 0:91d1a7783bb9 440 * LoRaMac internal state
mluis 0:91d1a7783bb9 441 */
mluis 0:91d1a7783bb9 442 uint32_t LoRaMacState = MAC_IDLE;
mluis 0:91d1a7783bb9 443
mluis 0:91d1a7783bb9 444 /*!
mluis 0:91d1a7783bb9 445 * LoRaMac timer used to check the LoRaMacState (runs every second)
mluis 0:91d1a7783bb9 446 */
mluis 0:91d1a7783bb9 447 static TimerEvent_t MacStateCheckTimer;
mluis 0:91d1a7783bb9 448
mluis 0:91d1a7783bb9 449 /*!
mluis 0:91d1a7783bb9 450 * LoRaMac upper layer event functions
mluis 0:91d1a7783bb9 451 */
mluis 0:91d1a7783bb9 452 static LoRaMacEvent_t *LoRaMacEvents;
mluis 0:91d1a7783bb9 453
mluis 0:91d1a7783bb9 454 /*!
mluis 0:91d1a7783bb9 455 * LoRaMac notification event flags
mluis 0:91d1a7783bb9 456 */
mluis 0:91d1a7783bb9 457 LoRaMacEventFlags_t LoRaMacEventFlags;
mluis 0:91d1a7783bb9 458
mluis 0:91d1a7783bb9 459 /*!
mluis 0:91d1a7783bb9 460 * LoRaMac notification event info
mluis 0:91d1a7783bb9 461 */
mluis 0:91d1a7783bb9 462 LoRaMacEventInfo_t LoRaMacEventInfo;
mluis 0:91d1a7783bb9 463
mluis 0:91d1a7783bb9 464 /*!
mluis 0:91d1a7783bb9 465 * LoRaMac channel check timer
mluis 0:91d1a7783bb9 466 */
mluis 0:91d1a7783bb9 467 static TimerEvent_t ChannelCheckTimer;
mluis 0:91d1a7783bb9 468
mluis 0:91d1a7783bb9 469 /*!
mluis 0:91d1a7783bb9 470 * LoRaMac duty cycle delayed Tx timer
mluis 0:91d1a7783bb9 471 */
mluis 0:91d1a7783bb9 472 static TimerEvent_t TxDelayedTimer;
mluis 0:91d1a7783bb9 473
mluis 0:91d1a7783bb9 474 /*!
mluis 0:91d1a7783bb9 475 * LoRaMac reception windows timers
mluis 0:91d1a7783bb9 476 */
mluis 0:91d1a7783bb9 477 static TimerEvent_t RxWindowTimer1;
mluis 0:91d1a7783bb9 478 static TimerEvent_t RxWindowTimer2;
mluis 0:91d1a7783bb9 479
mluis 0:91d1a7783bb9 480 /*!
mluis 0:91d1a7783bb9 481 * LoRaMac reception windows delay from end of Tx
mluis 0:91d1a7783bb9 482 */
mluis 0:91d1a7783bb9 483 static uint32_t ReceiveDelay1;
mluis 0:91d1a7783bb9 484 static uint32_t ReceiveDelay2;
mluis 0:91d1a7783bb9 485 static uint32_t JoinAcceptDelay1;
mluis 0:91d1a7783bb9 486 static uint32_t JoinAcceptDelay2;
mluis 0:91d1a7783bb9 487
mluis 0:91d1a7783bb9 488 /*!
mluis 0:91d1a7783bb9 489 * LoRaMac reception windows delay
mluis 0:91d1a7783bb9 490 * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
mluis 0:91d1a7783bb9 491 * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
mluis 0:91d1a7783bb9 492 */
mluis 0:91d1a7783bb9 493 static uint32_t RxWindow1Delay;
mluis 0:91d1a7783bb9 494 static uint32_t RxWindow2Delay;
mluis 0:91d1a7783bb9 495
mluis 0:91d1a7783bb9 496 /*!
mluis 0:91d1a7783bb9 497 * LoRaMac maximum time a reception window stays open
mluis 0:91d1a7783bb9 498 */
mluis 0:91d1a7783bb9 499 static uint32_t MaxRxWindow;
mluis 0:91d1a7783bb9 500
mluis 0:91d1a7783bb9 501 /*!
mluis 0:91d1a7783bb9 502 * Acknowledge timeout timer. Used for packet retransmissions.
mluis 0:91d1a7783bb9 503 */
mluis 0:91d1a7783bb9 504 static TimerEvent_t AckTimeoutTimer;
mluis 0:91d1a7783bb9 505
mluis 0:91d1a7783bb9 506 /*!
mluis 0:91d1a7783bb9 507 * Number of trials to get a frame acknowledged
mluis 0:91d1a7783bb9 508 */
mluis 0:91d1a7783bb9 509 static uint8_t AckTimeoutRetries = 1;
mluis 0:91d1a7783bb9 510
mluis 0:91d1a7783bb9 511 /*!
mluis 0:91d1a7783bb9 512 * Number of trials to get a frame acknowledged
mluis 0:91d1a7783bb9 513 */
mluis 0:91d1a7783bb9 514 static uint8_t AckTimeoutRetriesCounter = 1;
mluis 0:91d1a7783bb9 515
mluis 0:91d1a7783bb9 516 /*!
mluis 0:91d1a7783bb9 517 * Indicates if the AckTimeout timer has expired or not
mluis 0:91d1a7783bb9 518 */
mluis 0:91d1a7783bb9 519 static bool AckTimeoutRetry = false;
mluis 0:91d1a7783bb9 520
mluis 0:91d1a7783bb9 521 /*!
mluis 0:91d1a7783bb9 522 * Last transmission time on air
mluis 0:91d1a7783bb9 523 */
mluis 0:91d1a7783bb9 524 TimerTime_t TxTimeOnAir = 0;
mluis 0:91d1a7783bb9 525
mluis 0:91d1a7783bb9 526 /*!
mluis 0:91d1a7783bb9 527 * Function to be executed on Radio Tx Done event
mluis 0:91d1a7783bb9 528 */
mluis 0:91d1a7783bb9 529 static void OnRadioTxDone( void );
mluis 0:91d1a7783bb9 530
mluis 0:91d1a7783bb9 531 /*!
mluis 0:91d1a7783bb9 532 * Function to be executed on Radio Rx Done event
mluis 0:91d1a7783bb9 533 */
mluis 0:91d1a7783bb9 534 static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
mluis 0:91d1a7783bb9 535
mluis 0:91d1a7783bb9 536 /*!
mluis 0:91d1a7783bb9 537 * Function executed on Radio Tx Timeout event
mluis 0:91d1a7783bb9 538 */
mluis 0:91d1a7783bb9 539 static void OnRadioTxTimeout( void );
mluis 0:91d1a7783bb9 540
mluis 0:91d1a7783bb9 541 /*!
mluis 0:91d1a7783bb9 542 * Function executed on Radio Rx error event
mluis 0:91d1a7783bb9 543 */
mluis 0:91d1a7783bb9 544 static void OnRadioRxError( void );
mluis 0:91d1a7783bb9 545
mluis 0:91d1a7783bb9 546 /*!
mluis 0:91d1a7783bb9 547 * Function executed on Radio Rx Timeout event
mluis 0:91d1a7783bb9 548 */
mluis 0:91d1a7783bb9 549 static void OnRadioRxTimeout( void );
mluis 0:91d1a7783bb9 550
mluis 0:91d1a7783bb9 551 /*!
mluis 0:91d1a7783bb9 552 * Function executed on Resend Frame timer event.
mluis 0:91d1a7783bb9 553 */
mluis 0:91d1a7783bb9 554 static void OnMacStateCheckTimerEvent( void );
mluis 0:91d1a7783bb9 555
mluis 0:91d1a7783bb9 556 /*!
mluis 0:91d1a7783bb9 557 * Function executed on duty cycle delayed Tx timer event
mluis 0:91d1a7783bb9 558 */
mluis 0:91d1a7783bb9 559 static void OnTxDelayedTimerEvent( void );
mluis 0:91d1a7783bb9 560
mluis 0:91d1a7783bb9 561 /*!
mluis 0:91d1a7783bb9 562 * Function executed on channel check timer event
mluis 0:91d1a7783bb9 563 */
mluis 0:91d1a7783bb9 564 static void OnChannelCheckTimerEvent( void );
mluis 0:91d1a7783bb9 565
mluis 0:91d1a7783bb9 566 /*!
mluis 0:91d1a7783bb9 567 * Function executed on first Rx window timer event
mluis 0:91d1a7783bb9 568 */
mluis 0:91d1a7783bb9 569 static void OnRxWindow1TimerEvent( void );
mluis 0:91d1a7783bb9 570
mluis 0:91d1a7783bb9 571 /*!
mluis 0:91d1a7783bb9 572 * Function executed on second Rx window timer event
mluis 0:91d1a7783bb9 573 */
mluis 0:91d1a7783bb9 574 static void OnRxWindow2TimerEvent( void );
mluis 0:91d1a7783bb9 575
mluis 0:91d1a7783bb9 576 /*!
mluis 0:91d1a7783bb9 577 * Function executed on AckTimeout timer event
mluis 0:91d1a7783bb9 578 */
mluis 0:91d1a7783bb9 579 static void OnAckTimeoutTimerEvent( void );
mluis 0:91d1a7783bb9 580
mluis 0:91d1a7783bb9 581 /*!
mluis 0:91d1a7783bb9 582 * Radio events function pointer
mluis 0:91d1a7783bb9 583 */
mluis 0:91d1a7783bb9 584 //static RadioEvents_t RadioEvents;
mluis 0:91d1a7783bb9 585 SX1276MB1xAS Radio( OnRadioTxDone, OnRadioTxTimeout, OnRadioRxDone, OnRadioRxTimeout, OnRadioRxError, NULL, NULL );
mluis 0:91d1a7783bb9 586
mluis 0:91d1a7783bb9 587 /*!
mluis 0:91d1a7783bb9 588 * \brief Validates if the payload fits into the frame, taking the datarate
mluis 0:91d1a7783bb9 589 * into account.
mluis 0:91d1a7783bb9 590 *
mluis 0:91d1a7783bb9 591 * \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
mluis 0:91d1a7783bb9 592 *
mluis 0:91d1a7783bb9 593 * \param lenN Length of the application payload. The length depends on the
mluis 0:91d1a7783bb9 594 * datarate and is region specific
mluis 0:91d1a7783bb9 595 *
mluis 0:91d1a7783bb9 596 * \param datarate Current datarate
mluis 0:91d1a7783bb9 597 *
mluis 0:91d1a7783bb9 598 * \retval [false: payload does not fit into the frame, true: payload fits into
mluis 0:91d1a7783bb9 599 * the frame]
mluis 0:91d1a7783bb9 600 */
mluis 0:91d1a7783bb9 601 static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate );
mluis 0:91d1a7783bb9 602
mluis 0:91d1a7783bb9 603 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 604 /*!
mluis 0:91d1a7783bb9 605 * \brief Counts the number of enabled 125 kHz channels in the channel mask.
mluis 0:91d1a7783bb9 606 * This function can only be applied to US915 band.
mluis 0:91d1a7783bb9 607 *
mluis 0:91d1a7783bb9 608 * \param channelsMask Pointer to the first element of the channel mask
mluis 0:91d1a7783bb9 609 *
mluis 0:91d1a7783bb9 610 * \retval Number of enabled channels in the channel mask
mluis 0:91d1a7783bb9 611 */
mluis 0:91d1a7783bb9 612 static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask );
mluis 0:91d1a7783bb9 613 #endif
mluis 0:91d1a7783bb9 614
mluis 0:91d1a7783bb9 615 /*!
mluis 0:91d1a7783bb9 616 * \brief Limits the Tx power according to the number of enabled channels
mluis 0:91d1a7783bb9 617 *
mluis 0:91d1a7783bb9 618 * \retval Returns the maximum valid tx power
mluis 0:91d1a7783bb9 619 */
mluis 0:91d1a7783bb9 620 static int8_t LimitTxPower( int8_t txPower );
mluis 0:91d1a7783bb9 621
mluis 0:91d1a7783bb9 622 /*!
mluis 0:91d1a7783bb9 623 * Searches and set the next random available channel
mluis 0:91d1a7783bb9 624 *
mluis 0:91d1a7783bb9 625 * \retval status Function status [0: OK, 1: Unable to find a free channel]
mluis 0:91d1a7783bb9 626 */
mluis 0:91d1a7783bb9 627 static uint8_t LoRaMacSetNextChannel( void )
mluis 0:91d1a7783bb9 628 {
mluis 0:91d1a7783bb9 629 uint8_t i = 0;
mluis 0:91d1a7783bb9 630 uint8_t j = 0;
mluis 0:91d1a7783bb9 631 uint8_t k = 0;
mluis 0:91d1a7783bb9 632 uint8_t nbEnabledChannels = 0;
mluis 0:91d1a7783bb9 633 uint8_t enabledChannels[LORA_MAX_NB_CHANNELS];
mluis 0:91d1a7783bb9 634 TimerTime_t curTime = TimerGetCurrentTime( );
mluis 0:91d1a7783bb9 635
mluis 0:91d1a7783bb9 636 memset( enabledChannels, 0, LORA_MAX_NB_CHANNELS );
mluis 0:91d1a7783bb9 637
mluis 0:91d1a7783bb9 638 // Update Aggregated duty cycle
mluis 0:91d1a7783bb9 639 if( AggregatedTimeOff < ( curTime - AggregatedLastTxDoneTime ) )
mluis 0:91d1a7783bb9 640 {
mluis 0:91d1a7783bb9 641 AggregatedTimeOff = 0;
mluis 0:91d1a7783bb9 642 }
mluis 0:91d1a7783bb9 643
mluis 0:91d1a7783bb9 644 // Update bands Time OFF
mluis 0:91d1a7783bb9 645 TimerTime_t minTime = ( TimerTime_t )( -1 );
mluis 0:91d1a7783bb9 646 for( i = 0; i < LORA_MAX_NB_BANDS; i++ )
mluis 0:91d1a7783bb9 647 {
mluis 0:91d1a7783bb9 648 if( DutyCycleOn == true )
mluis 0:91d1a7783bb9 649 {
mluis 0:91d1a7783bb9 650 if( Bands[i].TimeOff < ( curTime - Bands[i].LastTxDoneTime ) )
mluis 0:91d1a7783bb9 651 {
mluis 0:91d1a7783bb9 652 Bands[i].TimeOff = 0;
mluis 0:91d1a7783bb9 653 }
mluis 0:91d1a7783bb9 654 if( Bands[i].TimeOff != 0 )
mluis 0:91d1a7783bb9 655 {
mluis 0:91d1a7783bb9 656 minTime = MIN( Bands[i].TimeOff, minTime );
mluis 0:91d1a7783bb9 657 }
mluis 0:91d1a7783bb9 658 }
mluis 0:91d1a7783bb9 659 else
mluis 0:91d1a7783bb9 660 {
mluis 0:91d1a7783bb9 661 minTime = 0;
mluis 0:91d1a7783bb9 662 Bands[i].TimeOff = 0;
mluis 0:91d1a7783bb9 663 }
mluis 0:91d1a7783bb9 664 }
mluis 0:91d1a7783bb9 665
mluis 0:91d1a7783bb9 666 // Search how many channels are enabled
mluis 0:91d1a7783bb9 667 for( i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
mluis 0:91d1a7783bb9 668 {
mluis 0:91d1a7783bb9 669 for( j = 0; j < 16; j++ )
mluis 0:91d1a7783bb9 670 {
mluis 0:91d1a7783bb9 671 if( ( ChannelsMask[k] & ( 1 << j ) ) != 0 )
mluis 0:91d1a7783bb9 672 {
mluis 0:91d1a7783bb9 673 if( Channels[i + j].Frequency == 0 )
mluis 0:91d1a7783bb9 674 { // Check if the channel is enabled
mluis 0:91d1a7783bb9 675 continue;
mluis 0:91d1a7783bb9 676 }
mluis 0:91d1a7783bb9 677 if( ( ( Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate ) &&
mluis 0:91d1a7783bb9 678 ( ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false )
mluis 0:91d1a7783bb9 679 { // Check if the current channel selection supports the given datarate
mluis 0:91d1a7783bb9 680 continue;
mluis 0:91d1a7783bb9 681 }
mluis 0:91d1a7783bb9 682 if( Bands[Channels[i + j].Band].TimeOff > 0 )
mluis 0:91d1a7783bb9 683 { // Check if the band is available for transmission
mluis 0:91d1a7783bb9 684 continue;
mluis 0:91d1a7783bb9 685 }
mluis 0:91d1a7783bb9 686 if( AggregatedTimeOff > 0 )
mluis 0:91d1a7783bb9 687 { // Check if there is time available for transmission
mluis 0:91d1a7783bb9 688 continue;
mluis 0:91d1a7783bb9 689 }
mluis 0:91d1a7783bb9 690 enabledChannels[nbEnabledChannels++] = i + j;
mluis 0:91d1a7783bb9 691 }
mluis 0:91d1a7783bb9 692 }
mluis 0:91d1a7783bb9 693 }
mluis 0:91d1a7783bb9 694 if( nbEnabledChannels > 0 )
mluis 0:91d1a7783bb9 695 {
mluis 0:91d1a7783bb9 696 Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
mluis 0:91d1a7783bb9 697 LoRaMacState &= ~MAC_CHANNEL_CHECK;
mluis 0:91d1a7783bb9 698 TimerStop( &ChannelCheckTimer );
mluis 0:91d1a7783bb9 699 return 0;
mluis 0:91d1a7783bb9 700 }
mluis 0:91d1a7783bb9 701 // No free channel found.
mluis 0:91d1a7783bb9 702 // Check again
mluis 0:91d1a7783bb9 703 if( ( LoRaMacState & MAC_CHANNEL_CHECK ) == 0 )
mluis 0:91d1a7783bb9 704 {
mluis 0:91d1a7783bb9 705 TimerSetValue( &ChannelCheckTimer, minTime );
mluis 0:91d1a7783bb9 706 TimerStart( &ChannelCheckTimer );
mluis 0:91d1a7783bb9 707 LoRaMacState |= MAC_CHANNEL_CHECK;
mluis 0:91d1a7783bb9 708 }
mluis 0:91d1a7783bb9 709 return 1;
mluis 0:91d1a7783bb9 710 }
mluis 0:91d1a7783bb9 711
mluis 0:91d1a7783bb9 712 /*
mluis 0:91d1a7783bb9 713 * TODO: Add documentation
mluis 0:91d1a7783bb9 714 */
mluis 0:91d1a7783bb9 715 void OnChannelCheckTimerEvent( void )
mluis 0:91d1a7783bb9 716 {
mluis 0:91d1a7783bb9 717 TimerStop( &ChannelCheckTimer );
mluis 0:91d1a7783bb9 718
mluis 0:91d1a7783bb9 719 LoRaMacState &= ~MAC_CHANNEL_CHECK;
mluis 0:91d1a7783bb9 720 if( LoRaMacSetNextChannel( ) == 0 )
mluis 0:91d1a7783bb9 721 {
mluis 0:91d1a7783bb9 722 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 0:91d1a7783bb9 723 {
mluis 0:91d1a7783bb9 724 LoRaMacSendFrameOnChannel( Channels[Channel] );
mluis 0:91d1a7783bb9 725 }
mluis 0:91d1a7783bb9 726 }
mluis 0:91d1a7783bb9 727 }
mluis 0:91d1a7783bb9 728
mluis 0:91d1a7783bb9 729 /*!
mluis 0:91d1a7783bb9 730 * Adds a new MAC command to be sent.
mluis 0:91d1a7783bb9 731 *
mluis 0:91d1a7783bb9 732 * \Remark MAC layer internal function
mluis 0:91d1a7783bb9 733 *
mluis 0:91d1a7783bb9 734 * \param [in] cmd MAC command to be added
mluis 0:91d1a7783bb9 735 * [MOTE_MAC_LINK_CHECK_REQ,
mluis 0:91d1a7783bb9 736 * MOTE_MAC_LINK_ADR_ANS,
mluis 0:91d1a7783bb9 737 * MOTE_MAC_DUTY_CYCLE_ANS,
mluis 0:91d1a7783bb9 738 * MOTE_MAC_RX2_PARAM_SET_ANS,
mluis 0:91d1a7783bb9 739 * MOTE_MAC_DEV_STATUS_ANS
mluis 0:91d1a7783bb9 740 * MOTE_MAC_NEW_CHANNEL_ANS]
mluis 0:91d1a7783bb9 741 * \param [in] p1 1st parameter ( optional depends on the command )
mluis 0:91d1a7783bb9 742 * \param [in] p2 2nd parameter ( optional depends on the command )
mluis 0:91d1a7783bb9 743 *
mluis 0:91d1a7783bb9 744 * \retval status Function status [0: OK, 1: Unknown command, 2: Buffer full]
mluis 0:91d1a7783bb9 745 */
mluis 0:91d1a7783bb9 746 static uint8_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
mluis 0:91d1a7783bb9 747 {
mluis 0:91d1a7783bb9 748 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
mluis 0:91d1a7783bb9 749 switch( cmd )
mluis 0:91d1a7783bb9 750 {
mluis 0:91d1a7783bb9 751 case MOTE_MAC_LINK_CHECK_REQ:
mluis 0:91d1a7783bb9 752 // No payload for this command
mluis 0:91d1a7783bb9 753 break;
mluis 0:91d1a7783bb9 754 case MOTE_MAC_LINK_ADR_ANS:
mluis 0:91d1a7783bb9 755 // Margin
mluis 0:91d1a7783bb9 756 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
mluis 0:91d1a7783bb9 757 break;
mluis 0:91d1a7783bb9 758 case MOTE_MAC_DUTY_CYCLE_ANS:
mluis 0:91d1a7783bb9 759 // No payload for this answer
mluis 0:91d1a7783bb9 760 break;
mluis 0:91d1a7783bb9 761 case MOTE_MAC_RX_PARAM_SETUP_ANS:
mluis 0:91d1a7783bb9 762 // Status: Datarate ACK, Channel ACK
mluis 0:91d1a7783bb9 763 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
mluis 0:91d1a7783bb9 764 break;
mluis 0:91d1a7783bb9 765 case MOTE_MAC_DEV_STATUS_ANS:
mluis 0:91d1a7783bb9 766 // 1st byte Battery
mluis 0:91d1a7783bb9 767 // 2nd byte Margin
mluis 0:91d1a7783bb9 768 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
mluis 0:91d1a7783bb9 769 MacCommandsBuffer[MacCommandsBufferIndex++] = p2;
mluis 0:91d1a7783bb9 770 break;
mluis 0:91d1a7783bb9 771 case MOTE_MAC_NEW_CHANNEL_ANS:
mluis 0:91d1a7783bb9 772 // Status: Datarate range OK, Channel frequency OK
mluis 0:91d1a7783bb9 773 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
mluis 0:91d1a7783bb9 774 break;
mluis 0:91d1a7783bb9 775 case MOTE_MAC_RX_TIMING_SETUP_ANS:
mluis 0:91d1a7783bb9 776 // No payload for this answer
mluis 0:91d1a7783bb9 777 break;
mluis 0:91d1a7783bb9 778 default:
mluis 0:91d1a7783bb9 779 return 1;
mluis 0:91d1a7783bb9 780 }
mluis 0:91d1a7783bb9 781 if( MacCommandsBufferIndex <= 15 )
mluis 0:91d1a7783bb9 782 {
mluis 0:91d1a7783bb9 783 MacCommandsInNextTx = true;
mluis 0:91d1a7783bb9 784 return 0;
mluis 0:91d1a7783bb9 785 }
mluis 0:91d1a7783bb9 786 else
mluis 0:91d1a7783bb9 787 {
mluis 0:91d1a7783bb9 788 return 2;
mluis 0:91d1a7783bb9 789 }
mluis 0:91d1a7783bb9 790 }
mluis 0:91d1a7783bb9 791
mluis 0:91d1a7783bb9 792 // TODO: Add Documentation
mluis 0:91d1a7783bb9 793 static void LoRaMacNotify( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info )
mluis 0:91d1a7783bb9 794 {
mluis 0:91d1a7783bb9 795 if( ( LoRaMacEvents != NULL ) && ( LoRaMacEvents->MacEvent != NULL ) )
mluis 0:91d1a7783bb9 796 {
mluis 0:91d1a7783bb9 797 LoRaMacEvents->MacEvent( flags, info );
mluis 0:91d1a7783bb9 798 }
mluis 0:91d1a7783bb9 799 flags->Value = 0;
mluis 0:91d1a7783bb9 800 }
mluis 0:91d1a7783bb9 801
mluis 0:91d1a7783bb9 802 typedef uint8_t ( *GetBatteryLevel )( );
mluis 0:91d1a7783bb9 803 GetBatteryLevel LoRaMacGetBatteryLevel;
mluis 0:91d1a7783bb9 804
mluis 0:91d1a7783bb9 805 void LoRaMacInit( LoRaMacEvent_t *events, uint8_t ( *getBatteryLevel )( ) )
mluis 0:91d1a7783bb9 806 {
mluis 0:91d1a7783bb9 807 LoRaMacEvents = events;
mluis 0:91d1a7783bb9 808
mluis 0:91d1a7783bb9 809 LoRaMacEventFlags.Value = 0;
mluis 0:91d1a7783bb9 810
mluis 0:91d1a7783bb9 811 LoRaMacEventInfo.TxAckReceived = false;
mluis 0:91d1a7783bb9 812 LoRaMacEventInfo.TxNbRetries = 0;
mluis 0:91d1a7783bb9 813 LoRaMacEventInfo.TxDatarate = 7;
mluis 0:91d1a7783bb9 814 LoRaMacEventInfo.RxPort = 1;
mluis 0:91d1a7783bb9 815 LoRaMacEventInfo.RxBuffer = NULL;
mluis 0:91d1a7783bb9 816 LoRaMacEventInfo.RxBufferSize = 0;
mluis 0:91d1a7783bb9 817 LoRaMacEventInfo.RxRssi = 0;
mluis 0:91d1a7783bb9 818 LoRaMacEventInfo.RxSnr = 0;
mluis 0:91d1a7783bb9 819 LoRaMacEventInfo.Energy = 0;
mluis 0:91d1a7783bb9 820 LoRaMacEventInfo.DemodMargin = 0;
mluis 0:91d1a7783bb9 821 LoRaMacEventInfo.NbGateways = 0;
mluis 0:91d1a7783bb9 822 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 0:91d1a7783bb9 823
mluis 0:91d1a7783bb9 824 LoRaMacGetBatteryLevel = getBatteryLevel;
mluis 0:91d1a7783bb9 825
mluis 0:91d1a7783bb9 826 LoRaMacDeviceClass = CLASS_A;
mluis 0:91d1a7783bb9 827
mluis 0:91d1a7783bb9 828 UpLinkCounter = 1;
mluis 0:91d1a7783bb9 829 DownLinkCounter = 0;
mluis 0:91d1a7783bb9 830
mluis 0:91d1a7783bb9 831 IsLoRaMacNetworkJoined = false;
mluis 0:91d1a7783bb9 832 LoRaMacState = MAC_IDLE;
mluis 0:91d1a7783bb9 833
mluis 0:91d1a7783bb9 834 #if defined( USE_BAND_433 )
mluis 0:91d1a7783bb9 835 ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 0:91d1a7783bb9 836 #elif defined( USE_BAND_780 )
mluis 0:91d1a7783bb9 837 ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 0:91d1a7783bb9 838 #elif defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 839 ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
mluis 0:91d1a7783bb9 840 #elif defined( USE_BAND_915 )
mluis 0:91d1a7783bb9 841 ChannelsMask[0] = 0xFFFF;
mluis 0:91d1a7783bb9 842 ChannelsMask[1] = 0xFFFF;
mluis 0:91d1a7783bb9 843 ChannelsMask[2] = 0xFFFF;
mluis 0:91d1a7783bb9 844 ChannelsMask[3] = 0xFFFF;
mluis 0:91d1a7783bb9 845 ChannelsMask[4] = 0x00FF;
mluis 0:91d1a7783bb9 846 ChannelsMask[5] = 0x0000;
mluis 0:91d1a7783bb9 847 #elif defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 848 ChannelsMask[0] = 0x00FF;
mluis 0:91d1a7783bb9 849 ChannelsMask[1] = 0x0000;
mluis 0:91d1a7783bb9 850 ChannelsMask[2] = 0x0000;
mluis 0:91d1a7783bb9 851 ChannelsMask[3] = 0x0000;
mluis 0:91d1a7783bb9 852 ChannelsMask[4] = 0x0001;
mluis 0:91d1a7783bb9 853 ChannelsMask[5] = 0x0000;
mluis 0:91d1a7783bb9 854 #else
mluis 0:91d1a7783bb9 855 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 856 #endif
mluis 0:91d1a7783bb9 857
mluis 0:91d1a7783bb9 858 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 859 // 125 kHz channels
mluis 0:91d1a7783bb9 860 for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ )
mluis 0:91d1a7783bb9 861 {
mluis 0:91d1a7783bb9 862 Channels[i].Frequency = 902.3e6 + i * 200e3;
mluis 0:91d1a7783bb9 863 Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
mluis 0:91d1a7783bb9 864 Channels[i].Band = 0;
mluis 0:91d1a7783bb9 865 }
mluis 0:91d1a7783bb9 866 // 500 kHz channels
mluis 0:91d1a7783bb9 867 for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ )
mluis 0:91d1a7783bb9 868 {
mluis 0:91d1a7783bb9 869 Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6;
mluis 0:91d1a7783bb9 870 Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
mluis 0:91d1a7783bb9 871 Channels[i].Band = 0;
mluis 0:91d1a7783bb9 872 }
mluis 0:91d1a7783bb9 873 #endif
mluis 0:91d1a7783bb9 874
mluis 0:91d1a7783bb9 875 ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
mluis 0:91d1a7783bb9 876 ChannelsDefaultDatarate = ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
mluis 0:91d1a7783bb9 877 ChannelsNbRep = 1;
mluis 0:91d1a7783bb9 878 ChannelsNbRepCounter = 0;
mluis 0:91d1a7783bb9 879
mluis 0:91d1a7783bb9 880 MaxDCycle = 0;
mluis 0:91d1a7783bb9 881 AggregatedDCycle = 1;
mluis 0:91d1a7783bb9 882 AggregatedLastTxDoneTime = 0;
mluis 0:91d1a7783bb9 883 AggregatedTimeOff = 0;
mluis 0:91d1a7783bb9 884
mluis 0:91d1a7783bb9 885 #if defined( USE_BAND_433 )
mluis 0:91d1a7783bb9 886 DutyCycleOn = false;
mluis 0:91d1a7783bb9 887 #elif defined( USE_BAND_780 )
mluis 0:91d1a7783bb9 888 DutyCycleOn = false;
mluis 0:91d1a7783bb9 889 #elif defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 890 DutyCycleOn = true;
mluis 0:91d1a7783bb9 891 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 892 DutyCycleOn = false;
mluis 0:91d1a7783bb9 893 #else
mluis 0:91d1a7783bb9 894 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 895 #endif
mluis 0:91d1a7783bb9 896
mluis 0:91d1a7783bb9 897 MaxRxWindow = MAX_RX_WINDOW;
mluis 0:91d1a7783bb9 898 ReceiveDelay1 = RECEIVE_DELAY1;
mluis 0:91d1a7783bb9 899 ReceiveDelay2 = RECEIVE_DELAY2;
mluis 0:91d1a7783bb9 900 JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
mluis 0:91d1a7783bb9 901 JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
mluis 0:91d1a7783bb9 902
mluis 0:91d1a7783bb9 903 TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent );
mluis 0:91d1a7783bb9 904 TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
mluis 0:91d1a7783bb9 905
mluis 0:91d1a7783bb9 906 TimerInit( &ChannelCheckTimer, OnChannelCheckTimerEvent );
mluis 0:91d1a7783bb9 907 TimerInit( &TxDelayedTimer, OnTxDelayedTimerEvent );
mluis 0:91d1a7783bb9 908 TimerInit( &RxWindowTimer1, OnRxWindow1TimerEvent );
mluis 0:91d1a7783bb9 909 TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
mluis 0:91d1a7783bb9 910 TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
mluis 0:91d1a7783bb9 911
mluis 0:91d1a7783bb9 912 // Random seed initialization
mluis 0:91d1a7783bb9 913 srand( Radio.Random( ) );
mluis 0:91d1a7783bb9 914
mluis 0:91d1a7783bb9 915 // Initialize channel index.
mluis 0:91d1a7783bb9 916 Channel = LORA_MAX_NB_CHANNELS;
mluis 0:91d1a7783bb9 917
mluis 0:91d1a7783bb9 918 PublicNetwork = true;
mluis 0:91d1a7783bb9 919 LoRaMacSetPublicNetwork( PublicNetwork );
mluis 0:91d1a7783bb9 920 Radio.Sleep( );
mluis 0:91d1a7783bb9 921 }
mluis 0:91d1a7783bb9 922
mluis 0:91d1a7783bb9 923 void LoRaMacSetAdrOn( bool enable )
mluis 0:91d1a7783bb9 924 {
mluis 0:91d1a7783bb9 925 AdrCtrlOn = enable;
mluis 0:91d1a7783bb9 926 }
mluis 0:91d1a7783bb9 927
mluis 0:91d1a7783bb9 928 void LoRaMacInitNwkIds( uint32_t netID, uint32_t devAddr, uint8_t *nwkSKey, uint8_t *appSKey )
mluis 0:91d1a7783bb9 929 {
mluis 0:91d1a7783bb9 930 LoRaMacNetID = netID;
mluis 0:91d1a7783bb9 931 LoRaMacDevAddr = devAddr;
mluis 0:91d1a7783bb9 932 LoRaMacMemCpy( nwkSKey, LoRaMacNwkSKey, 16 );
mluis 0:91d1a7783bb9 933 LoRaMacMemCpy( appSKey, LoRaMacAppSKey, 16 );
mluis 0:91d1a7783bb9 934
mluis 0:91d1a7783bb9 935 IsLoRaMacNetworkJoined = true;
mluis 0:91d1a7783bb9 936 }
mluis 0:91d1a7783bb9 937
mluis 0:91d1a7783bb9 938 void LoRaMacMulticastChannelAdd( MulticastParams_t *channelParam )
mluis 0:91d1a7783bb9 939 {
mluis 0:91d1a7783bb9 940 // Reset downlink counter
mluis 0:91d1a7783bb9 941 channelParam->DownLinkCounter = 0;
mluis 0:91d1a7783bb9 942
mluis 0:91d1a7783bb9 943 if( MulticastChannels == NULL )
mluis 0:91d1a7783bb9 944 {
mluis 0:91d1a7783bb9 945 MulticastChannels = channelParam;
mluis 0:91d1a7783bb9 946 }
mluis 0:91d1a7783bb9 947 else
mluis 0:91d1a7783bb9 948 {
mluis 0:91d1a7783bb9 949 MulticastParams_t *cur = MulticastChannels;
mluis 0:91d1a7783bb9 950 while( cur->Next != NULL )
mluis 0:91d1a7783bb9 951 {
mluis 0:91d1a7783bb9 952 cur = cur->Next;
mluis 0:91d1a7783bb9 953 }
mluis 0:91d1a7783bb9 954 cur->Next = channelParam;
mluis 0:91d1a7783bb9 955 }
mluis 0:91d1a7783bb9 956 }
mluis 0:91d1a7783bb9 957
mluis 0:91d1a7783bb9 958 void LoRaMacMulticastChannelRemove( MulticastParams_t *channelParam )
mluis 0:91d1a7783bb9 959 {
mluis 0:91d1a7783bb9 960 MulticastParams_t *cur = NULL;
mluis 0:91d1a7783bb9 961
mluis 0:91d1a7783bb9 962 // Remove the front element
mluis 0:91d1a7783bb9 963 if( MulticastChannels == channelParam )
mluis 0:91d1a7783bb9 964 {
mluis 0:91d1a7783bb9 965 if( MulticastChannels != NULL )
mluis 0:91d1a7783bb9 966 {
mluis 0:91d1a7783bb9 967 cur = MulticastChannels;
mluis 0:91d1a7783bb9 968 MulticastChannels = MulticastChannels->Next;
mluis 0:91d1a7783bb9 969 cur->Next = NULL;
mluis 0:91d1a7783bb9 970 // Last node in the list
mluis 0:91d1a7783bb9 971 if( cur == MulticastChannels )
mluis 0:91d1a7783bb9 972 {
mluis 0:91d1a7783bb9 973 MulticastChannels = NULL;
mluis 0:91d1a7783bb9 974 }
mluis 0:91d1a7783bb9 975 }
mluis 0:91d1a7783bb9 976 return;
mluis 0:91d1a7783bb9 977 }
mluis 0:91d1a7783bb9 978
mluis 0:91d1a7783bb9 979 // Remove last element
mluis 0:91d1a7783bb9 980 if( channelParam->Next == NULL )
mluis 0:91d1a7783bb9 981 {
mluis 0:91d1a7783bb9 982 if( MulticastChannels != NULL )
mluis 0:91d1a7783bb9 983 {
mluis 0:91d1a7783bb9 984 cur = MulticastChannels;
mluis 0:91d1a7783bb9 985 MulticastParams_t *last = NULL;
mluis 0:91d1a7783bb9 986 while( cur->Next != NULL )
mluis 0:91d1a7783bb9 987 {
mluis 0:91d1a7783bb9 988 last = cur;
mluis 0:91d1a7783bb9 989 cur = cur->Next;
mluis 0:91d1a7783bb9 990 }
mluis 0:91d1a7783bb9 991 if( last != NULL )
mluis 0:91d1a7783bb9 992 {
mluis 0:91d1a7783bb9 993 last->Next = NULL;
mluis 0:91d1a7783bb9 994 }
mluis 0:91d1a7783bb9 995 // Last node in the list
mluis 0:91d1a7783bb9 996 if( cur == last )
mluis 0:91d1a7783bb9 997 {
mluis 0:91d1a7783bb9 998 MulticastChannels = NULL;
mluis 0:91d1a7783bb9 999 }
mluis 0:91d1a7783bb9 1000 }
mluis 0:91d1a7783bb9 1001 return;
mluis 0:91d1a7783bb9 1002 }
mluis 0:91d1a7783bb9 1003
mluis 0:91d1a7783bb9 1004 // Remove a middle element
mluis 0:91d1a7783bb9 1005 cur = MulticastChannels;
mluis 0:91d1a7783bb9 1006 while( cur != NULL )
mluis 0:91d1a7783bb9 1007 {
mluis 0:91d1a7783bb9 1008 if( cur->Next == channelParam )
mluis 0:91d1a7783bb9 1009 {
mluis 0:91d1a7783bb9 1010 break;
mluis 0:91d1a7783bb9 1011 }
mluis 0:91d1a7783bb9 1012 cur = cur->Next;
mluis 0:91d1a7783bb9 1013 }
mluis 0:91d1a7783bb9 1014 if( cur != NULL )
mluis 0:91d1a7783bb9 1015 {
mluis 0:91d1a7783bb9 1016 MulticastParams_t *tmp = cur ->Next;
mluis 0:91d1a7783bb9 1017 cur->Next = tmp->Next;
mluis 0:91d1a7783bb9 1018 tmp->Next = NULL;
mluis 0:91d1a7783bb9 1019 }
mluis 0:91d1a7783bb9 1020 }
mluis 0:91d1a7783bb9 1021
mluis 0:91d1a7783bb9 1022 uint8_t LoRaMacJoinReq( uint8_t *devEui, uint8_t *appEui, uint8_t *appKey )
mluis 0:91d1a7783bb9 1023 {
mluis 0:91d1a7783bb9 1024 LoRaMacHeader_t macHdr;
mluis 0:91d1a7783bb9 1025
mluis 0:91d1a7783bb9 1026 LoRaMacDevEui = devEui;
mluis 0:91d1a7783bb9 1027 LoRaMacAppEui = appEui;
mluis 0:91d1a7783bb9 1028 LoRaMacAppKey = appKey;
mluis 0:91d1a7783bb9 1029
mluis 0:91d1a7783bb9 1030 macHdr.Value = 0;
mluis 0:91d1a7783bb9 1031 macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
mluis 0:91d1a7783bb9 1032
mluis 0:91d1a7783bb9 1033 IsLoRaMacNetworkJoined = false;
mluis 0:91d1a7783bb9 1034
mluis 0:91d1a7783bb9 1035 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 1036 static uint8_t drSwitch = 0;
mluis 0:91d1a7783bb9 1037
mluis 0:91d1a7783bb9 1038 if( drSwitch == 0 )
mluis 0:91d1a7783bb9 1039 {
mluis 0:91d1a7783bb9 1040 ChannelsDatarate = DR_0;
mluis 0:91d1a7783bb9 1041 }
mluis 0:91d1a7783bb9 1042 else
mluis 0:91d1a7783bb9 1043 {
mluis 0:91d1a7783bb9 1044 ChannelsDatarate = DR_4;
mluis 0:91d1a7783bb9 1045 }
mluis 0:91d1a7783bb9 1046 drSwitch = ( drSwitch + 1 ) % 2;
mluis 0:91d1a7783bb9 1047 #endif
mluis 0:91d1a7783bb9 1048 return LoRaMacSend( &macHdr, NULL, 0, NULL, 0 );
mluis 0:91d1a7783bb9 1049 }
mluis 0:91d1a7783bb9 1050
mluis 0:91d1a7783bb9 1051 uint8_t LoRaMacLinkCheckReq( void )
mluis 0:91d1a7783bb9 1052 {
mluis 0:91d1a7783bb9 1053 return AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
mluis 0:91d1a7783bb9 1054 }
mluis 0:91d1a7783bb9 1055
mluis 0:91d1a7783bb9 1056 uint8_t LoRaMacSendFrame( uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
mluis 0:91d1a7783bb9 1057 {
mluis 0:91d1a7783bb9 1058 LoRaMacHeader_t macHdr;
mluis 0:91d1a7783bb9 1059
mluis 0:91d1a7783bb9 1060 macHdr.Value = 0;
mluis 0:91d1a7783bb9 1061
mluis 0:91d1a7783bb9 1062 macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP;
mluis 0:91d1a7783bb9 1063 return LoRaMacSend( &macHdr, NULL, fPort, fBuffer, fBufferSize );
mluis 0:91d1a7783bb9 1064 }
mluis 0:91d1a7783bb9 1065
mluis 0:91d1a7783bb9 1066 uint8_t LoRaMacSendConfirmedFrame( uint8_t fPort, void *fBuffer, uint16_t fBufferSize, uint8_t retries )
mluis 0:91d1a7783bb9 1067 {
mluis 0:91d1a7783bb9 1068 LoRaMacHeader_t macHdr;
mluis 0:91d1a7783bb9 1069
mluis 0:91d1a7783bb9 1070 if( AdrCtrlOn == false )
mluis 0:91d1a7783bb9 1071 {
mluis 0:91d1a7783bb9 1072 ChannelsDatarate = ChannelsDefaultDatarate;
mluis 0:91d1a7783bb9 1073 }
mluis 0:91d1a7783bb9 1074 AckTimeoutRetries = retries;
mluis 0:91d1a7783bb9 1075 AckTimeoutRetriesCounter = 1;
mluis 0:91d1a7783bb9 1076
mluis 0:91d1a7783bb9 1077 macHdr.Value = 0;
mluis 0:91d1a7783bb9 1078
mluis 0:91d1a7783bb9 1079 macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
mluis 0:91d1a7783bb9 1080 return LoRaMacSend( &macHdr, NULL, fPort, fBuffer, fBufferSize );
mluis 0:91d1a7783bb9 1081 }
mluis 0:91d1a7783bb9 1082
mluis 0:91d1a7783bb9 1083 uint8_t LoRaMacSend( LoRaMacHeader_t *macHdr, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
mluis 0:91d1a7783bb9 1084 {
mluis 0:91d1a7783bb9 1085 LoRaMacFrameCtrl_t fCtrl;
mluis 0:91d1a7783bb9 1086
mluis 0:91d1a7783bb9 1087 fCtrl.Value = 0;
mluis 0:91d1a7783bb9 1088
mluis 0:91d1a7783bb9 1089 fCtrl.Bits.FOptsLen = 0;
mluis 0:91d1a7783bb9 1090 fCtrl.Bits.FPending = 0;
mluis 0:91d1a7783bb9 1091 fCtrl.Bits.Ack = false;
mluis 0:91d1a7783bb9 1092 fCtrl.Bits.AdrAckReq = false;
mluis 0:91d1a7783bb9 1093 fCtrl.Bits.Adr = AdrCtrlOn;
mluis 0:91d1a7783bb9 1094
mluis 0:91d1a7783bb9 1095 if( LoRaMacSetNextChannel( ) == 0 )
mluis 0:91d1a7783bb9 1096 {
mluis 0:91d1a7783bb9 1097 return LoRaMacSendOnChannel( Channels[Channel], macHdr, &fCtrl, fOpts, fPort, fBuffer, fBufferSize );
mluis 0:91d1a7783bb9 1098 }
mluis 0:91d1a7783bb9 1099 return 5;
mluis 0:91d1a7783bb9 1100 }
mluis 0:91d1a7783bb9 1101
mluis 0:91d1a7783bb9 1102 uint8_t LoRaMacPrepareFrame( ChannelParams_t channel, LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
mluis 0:91d1a7783bb9 1103 {
mluis 0:91d1a7783bb9 1104 uint16_t i;
mluis 0:91d1a7783bb9 1105 uint8_t pktHeaderLen = 0;
mluis 0:91d1a7783bb9 1106 uint32_t mic = 0;
mluis 0:91d1a7783bb9 1107
mluis 0:91d1a7783bb9 1108 LoRaMacBufferPktLen = 0;
mluis 0:91d1a7783bb9 1109
mluis 0:91d1a7783bb9 1110 NodeAckRequested = false;
mluis 0:91d1a7783bb9 1111
mluis 0:91d1a7783bb9 1112 if( fBuffer == NULL )
mluis 0:91d1a7783bb9 1113 {
mluis 0:91d1a7783bb9 1114 fBufferSize = 0;
mluis 0:91d1a7783bb9 1115 }
mluis 0:91d1a7783bb9 1116 else
mluis 0:91d1a7783bb9 1117 {
mluis 0:91d1a7783bb9 1118 if( ValidatePayloadLength( fBufferSize, ChannelsDatarate ) == false )
mluis 0:91d1a7783bb9 1119 {
mluis 0:91d1a7783bb9 1120 return 3;
mluis 0:91d1a7783bb9 1121 }
mluis 0:91d1a7783bb9 1122 }
mluis 0:91d1a7783bb9 1123
mluis 0:91d1a7783bb9 1124 LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
mluis 0:91d1a7783bb9 1125
mluis 0:91d1a7783bb9 1126 switch( macHdr->Bits.MType )
mluis 0:91d1a7783bb9 1127 {
mluis 0:91d1a7783bb9 1128 case FRAME_TYPE_JOIN_REQ:
mluis 0:91d1a7783bb9 1129 RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
mluis 0:91d1a7783bb9 1130 RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
mluis 0:91d1a7783bb9 1131
mluis 0:91d1a7783bb9 1132 LoRaMacBufferPktLen = pktHeaderLen;
mluis 0:91d1a7783bb9 1133
mluis 0:91d1a7783bb9 1134 LoRaMacMemCpy( LoRaMacAppEui, LoRaMacBuffer + LoRaMacBufferPktLen, 8 );
mluis 0:91d1a7783bb9 1135 LoRaMacBufferPktLen += 8;
mluis 0:91d1a7783bb9 1136 LoRaMacMemCpy( LoRaMacDevEui, LoRaMacBuffer + LoRaMacBufferPktLen, 8 );
mluis 0:91d1a7783bb9 1137 LoRaMacBufferPktLen += 8;
mluis 0:91d1a7783bb9 1138
mluis 0:91d1a7783bb9 1139 LoRaMacDevNonce = Radio.Random( );
mluis 0:91d1a7783bb9 1140
mluis 0:91d1a7783bb9 1141 LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF;
mluis 0:91d1a7783bb9 1142 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( LoRaMacDevNonce >> 8 ) & 0xFF;
mluis 0:91d1a7783bb9 1143
mluis 0:91d1a7783bb9 1144 LoRaMacJoinComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic );
mluis 0:91d1a7783bb9 1145
mluis 0:91d1a7783bb9 1146 LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF;
mluis 0:91d1a7783bb9 1147 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF;
mluis 0:91d1a7783bb9 1148 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF;
mluis 0:91d1a7783bb9 1149 LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF;
mluis 0:91d1a7783bb9 1150
mluis 0:91d1a7783bb9 1151 break;
mluis 0:91d1a7783bb9 1152 case FRAME_TYPE_DATA_CONFIRMED_UP:
mluis 0:91d1a7783bb9 1153 NodeAckRequested = true;
mluis 0:91d1a7783bb9 1154 //Intentional falltrough
mluis 0:91d1a7783bb9 1155 case FRAME_TYPE_DATA_UNCONFIRMED_UP:
mluis 0:91d1a7783bb9 1156 if( IsLoRaMacNetworkJoined == false )
mluis 0:91d1a7783bb9 1157 {
mluis 0:91d1a7783bb9 1158 return 2; // No network has been joined yet
mluis 0:91d1a7783bb9 1159 }
mluis 0:91d1a7783bb9 1160
mluis 0:91d1a7783bb9 1161 RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME;
mluis 0:91d1a7783bb9 1162 RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME;
mluis 0:91d1a7783bb9 1163
mluis 0:91d1a7783bb9 1164 if( fOpts == NULL )
mluis 0:91d1a7783bb9 1165 {
mluis 0:91d1a7783bb9 1166 fCtrl->Bits.FOptsLen = 0;
mluis 0:91d1a7783bb9 1167 }
mluis 0:91d1a7783bb9 1168
mluis 0:91d1a7783bb9 1169 if( SrvAckRequested == true )
mluis 0:91d1a7783bb9 1170 {
mluis 0:91d1a7783bb9 1171 SrvAckRequested = false;
mluis 0:91d1a7783bb9 1172 fCtrl->Bits.Ack = 1;
mluis 0:91d1a7783bb9 1173 }
mluis 0:91d1a7783bb9 1174
mluis 0:91d1a7783bb9 1175 if( fCtrl->Bits.Adr == true )
mluis 0:91d1a7783bb9 1176 {
mluis 0:91d1a7783bb9 1177 if( ChannelsDatarate == LORAMAC_MIN_DATARATE )
mluis 0:91d1a7783bb9 1178 {
mluis 0:91d1a7783bb9 1179 AdrAckCounter = 0;
mluis 0:91d1a7783bb9 1180 fCtrl->Bits.AdrAckReq = false;
mluis 0:91d1a7783bb9 1181 }
mluis 0:91d1a7783bb9 1182 else
mluis 0:91d1a7783bb9 1183 {
mluis 0:91d1a7783bb9 1184 if( AdrAckCounter > ADR_ACK_LIMIT )
mluis 0:91d1a7783bb9 1185 {
mluis 0:91d1a7783bb9 1186 fCtrl->Bits.AdrAckReq = true;
mluis 0:91d1a7783bb9 1187 }
mluis 0:91d1a7783bb9 1188 else
mluis 0:91d1a7783bb9 1189 {
mluis 0:91d1a7783bb9 1190 fCtrl->Bits.AdrAckReq = false;
mluis 0:91d1a7783bb9 1191 }
mluis 0:91d1a7783bb9 1192 if( AdrAckCounter > ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) )
mluis 0:91d1a7783bb9 1193 {
mluis 0:91d1a7783bb9 1194 AdrAckCounter = 0;
mluis 0:91d1a7783bb9 1195 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 1196 if( ChannelsDatarate > LORAMAC_MIN_DATARATE )
mluis 0:91d1a7783bb9 1197 {
mluis 0:91d1a7783bb9 1198 ChannelsDatarate--;
mluis 0:91d1a7783bb9 1199 }
mluis 0:91d1a7783bb9 1200 else
mluis 0:91d1a7783bb9 1201 {
mluis 0:91d1a7783bb9 1202 // Re-enable default channels LC1, LC2, LC3
mluis 0:91d1a7783bb9 1203 ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
mluis 0:91d1a7783bb9 1204 }
mluis 0:91d1a7783bb9 1205 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 1206 if( ( ChannelsDatarate > LORAMAC_MIN_DATARATE ) && ( ChannelsDatarate == DR_8 ) )
mluis 0:91d1a7783bb9 1207 {
mluis 0:91d1a7783bb9 1208 ChannelsDatarate = DR_4;
mluis 0:91d1a7783bb9 1209 }
mluis 0:91d1a7783bb9 1210 if( ChannelsDatarate > LORAMAC_MIN_DATARATE )
mluis 0:91d1a7783bb9 1211 {
mluis 0:91d1a7783bb9 1212 ChannelsDatarate--;
mluis 0:91d1a7783bb9 1213 }
mluis 0:91d1a7783bb9 1214 else
mluis 0:91d1a7783bb9 1215 {
mluis 0:91d1a7783bb9 1216 #if defined( USE_BAND_915 )
mluis 0:91d1a7783bb9 1217 // Re-enable default channels
mluis 0:91d1a7783bb9 1218 ChannelsMask[0] = 0xFFFF;
mluis 0:91d1a7783bb9 1219 ChannelsMask[1] = 0xFFFF;
mluis 0:91d1a7783bb9 1220 ChannelsMask[2] = 0xFFFF;
mluis 0:91d1a7783bb9 1221 ChannelsMask[3] = 0xFFFF;
mluis 0:91d1a7783bb9 1222 ChannelsMask[4] = 0x00FF;
mluis 0:91d1a7783bb9 1223 ChannelsMask[5] = 0x0000;
mluis 0:91d1a7783bb9 1224 #else // defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 1225 // Re-enable default channels
mluis 0:91d1a7783bb9 1226 ChannelsMask[0] = 0x00FF;
mluis 0:91d1a7783bb9 1227 ChannelsMask[1] = 0x0000;
mluis 0:91d1a7783bb9 1228 ChannelsMask[2] = 0x0000;
mluis 0:91d1a7783bb9 1229 ChannelsMask[3] = 0x0000;
mluis 0:91d1a7783bb9 1230 ChannelsMask[4] = 0x0001;
mluis 0:91d1a7783bb9 1231 ChannelsMask[5] = 0x0000;
mluis 0:91d1a7783bb9 1232 #endif
mluis 0:91d1a7783bb9 1233 }
mluis 0:91d1a7783bb9 1234 #else
mluis 0:91d1a7783bb9 1235 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 1236 #endif
mluis 0:91d1a7783bb9 1237 }
mluis 0:91d1a7783bb9 1238 }
mluis 0:91d1a7783bb9 1239 }
mluis 0:91d1a7783bb9 1240
mluis 0:91d1a7783bb9 1241 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;
mluis 0:91d1a7783bb9 1242 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;
mluis 0:91d1a7783bb9 1243 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;
mluis 0:91d1a7783bb9 1244 LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF;
mluis 0:91d1a7783bb9 1245
mluis 0:91d1a7783bb9 1246 LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value;
mluis 0:91d1a7783bb9 1247
mluis 0:91d1a7783bb9 1248 LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
mluis 0:91d1a7783bb9 1249 LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
mluis 0:91d1a7783bb9 1250
mluis 0:91d1a7783bb9 1251 if( fOpts != NULL )
mluis 0:91d1a7783bb9 1252 {
mluis 0:91d1a7783bb9 1253 for( i = 0; i < fCtrl->Bits.FOptsLen; i++ )
mluis 0:91d1a7783bb9 1254 {
mluis 0:91d1a7783bb9 1255 LoRaMacBuffer[pktHeaderLen++] = fOpts[i];
mluis 0:91d1a7783bb9 1256 }
mluis 0:91d1a7783bb9 1257 }
mluis 0:91d1a7783bb9 1258 if( ( MacCommandsBufferIndex + fCtrl->Bits.FOptsLen ) <= 15 )
mluis 0:91d1a7783bb9 1259 {
mluis 0:91d1a7783bb9 1260 if( MacCommandsInNextTx == true )
mluis 0:91d1a7783bb9 1261 {
mluis 0:91d1a7783bb9 1262 fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
mluis 0:91d1a7783bb9 1263
mluis 0:91d1a7783bb9 1264 // Update FCtrl field with new value of OptionsLength
mluis 0:91d1a7783bb9 1265 LoRaMacBuffer[0x05] = fCtrl->Value;
mluis 0:91d1a7783bb9 1266 for( i = 0; i < MacCommandsBufferIndex; i++ )
mluis 0:91d1a7783bb9 1267 {
mluis 0:91d1a7783bb9 1268 LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
mluis 0:91d1a7783bb9 1269 }
mluis 0:91d1a7783bb9 1270 }
mluis 0:91d1a7783bb9 1271 MacCommandsInNextTx = false;
mluis 0:91d1a7783bb9 1272 MacCommandsBufferIndex = 0;
mluis 0:91d1a7783bb9 1273 }
mluis 0:91d1a7783bb9 1274
mluis 0:91d1a7783bb9 1275 if( ( pktHeaderLen + fBufferSize ) > LORAMAC_PHY_MAXPAYLOAD )
mluis 0:91d1a7783bb9 1276 {
mluis 0:91d1a7783bb9 1277 return 3;
mluis 0:91d1a7783bb9 1278 }
mluis 0:91d1a7783bb9 1279
mluis 0:91d1a7783bb9 1280 if( fBuffer != NULL )
mluis 0:91d1a7783bb9 1281 {
mluis 0:91d1a7783bb9 1282 LoRaMacBuffer[pktHeaderLen++] = fPort;
mluis 0:91d1a7783bb9 1283
mluis 0:91d1a7783bb9 1284 if( fPort == 0 )
mluis 0:91d1a7783bb9 1285 {
mluis 0:91d1a7783bb9 1286 LoRaMacPayloadEncrypt( ( uint8_t* )fBuffer, fBufferSize, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
mluis 0:91d1a7783bb9 1287 }
mluis 0:91d1a7783bb9 1288 else
mluis 0:91d1a7783bb9 1289 {
mluis 0:91d1a7783bb9 1290 LoRaMacPayloadEncrypt( ( uint8_t* )fBuffer, fBufferSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
mluis 0:91d1a7783bb9 1291 }
mluis 0:91d1a7783bb9 1292 LoRaMacMemCpy( LoRaMacPayload, LoRaMacBuffer + pktHeaderLen, fBufferSize );
mluis 0:91d1a7783bb9 1293 }
mluis 0:91d1a7783bb9 1294 LoRaMacBufferPktLen = pktHeaderLen + fBufferSize;
mluis 0:91d1a7783bb9 1295
mluis 0:91d1a7783bb9 1296 LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
mluis 0:91d1a7783bb9 1297
mluis 0:91d1a7783bb9 1298 if( ( LoRaMacBufferPktLen + LORAMAC_MFR_LEN ) > LORAMAC_PHY_MAXPAYLOAD )
mluis 0:91d1a7783bb9 1299 {
mluis 0:91d1a7783bb9 1300 return 3;
mluis 0:91d1a7783bb9 1301 }
mluis 0:91d1a7783bb9 1302 LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;
mluis 0:91d1a7783bb9 1303 LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xFF;
mluis 0:91d1a7783bb9 1304 LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0xFF;
mluis 0:91d1a7783bb9 1305 LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF;
mluis 0:91d1a7783bb9 1306
mluis 0:91d1a7783bb9 1307 LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
mluis 0:91d1a7783bb9 1308 break;
mluis 0:91d1a7783bb9 1309 default:
mluis 0:91d1a7783bb9 1310 return 4;
mluis 0:91d1a7783bb9 1311 }
mluis 0:91d1a7783bb9 1312
mluis 0:91d1a7783bb9 1313 return 0;
mluis 0:91d1a7783bb9 1314 }
mluis 0:91d1a7783bb9 1315
mluis 0:91d1a7783bb9 1316 uint8_t LoRaMacSendFrameOnChannel( ChannelParams_t channel )
mluis 0:91d1a7783bb9 1317 {
mluis 0:91d1a7783bb9 1318 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 0:91d1a7783bb9 1319 LoRaMacEventInfo.TxDatarate = ChannelsDatarate;
mluis 0:91d1a7783bb9 1320
mluis 0:91d1a7783bb9 1321 ChannelsTxPower = LimitTxPower( ChannelsTxPower );
mluis 0:91d1a7783bb9 1322
mluis 0:91d1a7783bb9 1323 Radio.SetChannel( channel.Frequency );
mluis 0:91d1a7783bb9 1324 Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 1325
mluis 0:91d1a7783bb9 1326 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 1327 if( ChannelsDatarate == DR_7 )
mluis 0:91d1a7783bb9 1328 { // High Speed FSK channel
mluis 0:91d1a7783bb9 1329 Radio.SetTxConfig( MODEM_FSK, TxPowers[ChannelsTxPower], 25e3, 0, Datarates[ChannelsDatarate] * 1e3, 0, 5, false, true, 0, 0, false, 3e6 );
mluis 0:91d1a7783bb9 1330 TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 1331 }
mluis 0:91d1a7783bb9 1332 else if( ChannelsDatarate == DR_6 )
mluis 0:91d1a7783bb9 1333 { // High speed LoRa channel
mluis 0:91d1a7783bb9 1334 Radio.SetTxConfig( MODEM_LORA, TxPowers[ChannelsTxPower], 0, 1, Datarates[ChannelsDatarate], 1, 8, false, true, 0, 0, false, 3e6 );
mluis 0:91d1a7783bb9 1335 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 1336 }
mluis 0:91d1a7783bb9 1337 else
mluis 0:91d1a7783bb9 1338 { // Normal LoRa channel
mluis 0:91d1a7783bb9 1339 Radio.SetTxConfig( MODEM_LORA, TxPowers[ChannelsTxPower], 0, 0, Datarates[ChannelsDatarate], 1, 8, false, true, 0, 0, false, 3e6 );
mluis 0:91d1a7783bb9 1340 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 1341 }
mluis 0:91d1a7783bb9 1342 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 1343 if( ChannelsDatarate >= DR_4 )
mluis 0:91d1a7783bb9 1344 { // High speed LoRa channel BW500 kHz
mluis 0:91d1a7783bb9 1345 Radio.SetTxConfig( MODEM_LORA, TxPowers[ChannelsTxPower], 0, 2, Datarates[ChannelsDatarate], 1, 8, false, true, 0, 0, false, 3e6 );
mluis 0:91d1a7783bb9 1346 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 1347 }
mluis 0:91d1a7783bb9 1348 else
mluis 0:91d1a7783bb9 1349 { // Normal LoRa channel
mluis 0:91d1a7783bb9 1350 Radio.SetTxConfig( MODEM_LORA, TxPowers[ChannelsTxPower], 0, 0, Datarates[ChannelsDatarate], 1, 8, false, true, 0, 0, false, 3e6 );
mluis 0:91d1a7783bb9 1351 TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 1352 }
mluis 0:91d1a7783bb9 1353 #else
mluis 0:91d1a7783bb9 1354 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 1355 #endif
mluis 0:91d1a7783bb9 1356
mluis 0:91d1a7783bb9 1357 if( MaxDCycle == 255 )
mluis 0:91d1a7783bb9 1358 {
mluis 0:91d1a7783bb9 1359 return 6;
mluis 0:91d1a7783bb9 1360 }
mluis 0:91d1a7783bb9 1361 if( MaxDCycle == 0 )
mluis 0:91d1a7783bb9 1362 {
mluis 0:91d1a7783bb9 1363 AggregatedTimeOff = 0;
mluis 0:91d1a7783bb9 1364 }
mluis 0:91d1a7783bb9 1365
mluis 0:91d1a7783bb9 1366 LoRaMacState |= MAC_TX_RUNNING;
mluis 0:91d1a7783bb9 1367 // Starts the MAC layer status check timer
mluis 0:91d1a7783bb9 1368 TimerStart( &MacStateCheckTimer );
mluis 0:91d1a7783bb9 1369
mluis 0:91d1a7783bb9 1370 if( MAX( Bands[channel.Band].TimeOff, AggregatedTimeOff ) > ( TimerGetCurrentTime( ) ) )
mluis 0:91d1a7783bb9 1371 {
mluis 0:91d1a7783bb9 1372 // Schedule transmission
mluis 0:91d1a7783bb9 1373 TimerSetValue( &TxDelayedTimer, MAX( Bands[channel.Band].TimeOff, AggregatedTimeOff ) );
mluis 0:91d1a7783bb9 1374 TimerStart( &TxDelayedTimer );
mluis 0:91d1a7783bb9 1375 }
mluis 0:91d1a7783bb9 1376 else
mluis 0:91d1a7783bb9 1377 {
mluis 0:91d1a7783bb9 1378 // Send now
mluis 0:91d1a7783bb9 1379 Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 1380 }
mluis 0:91d1a7783bb9 1381 return 0;
mluis 0:91d1a7783bb9 1382 }
mluis 0:91d1a7783bb9 1383
mluis 0:91d1a7783bb9 1384
mluis 0:91d1a7783bb9 1385 void OnTxDelayedTimerEvent( void )
mluis 0:91d1a7783bb9 1386 {
mluis 0:91d1a7783bb9 1387 TimerStop( &TxDelayedTimer );
mluis 0:91d1a7783bb9 1388 Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
mluis 0:91d1a7783bb9 1389 }
mluis 0:91d1a7783bb9 1390
mluis 0:91d1a7783bb9 1391 uint8_t LoRaMacSendOnChannel( ChannelParams_t channel, LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
mluis 0:91d1a7783bb9 1392 {
mluis 0:91d1a7783bb9 1393 uint8_t status = 0;
mluis 0:91d1a7783bb9 1394
mluis 0:91d1a7783bb9 1395 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 0:91d1a7783bb9 1396 {
mluis 0:91d1a7783bb9 1397 return 1; // MAC is busy transmitting a previous frame
mluis 0:91d1a7783bb9 1398 }
mluis 0:91d1a7783bb9 1399
mluis 0:91d1a7783bb9 1400 status = LoRaMacPrepareFrame( channel, macHdr, fCtrl, fOpts, fPort, fBuffer, fBufferSize );
mluis 0:91d1a7783bb9 1401 if( status != 0 )
mluis 0:91d1a7783bb9 1402 {
mluis 0:91d1a7783bb9 1403 return status;
mluis 0:91d1a7783bb9 1404 }
mluis 0:91d1a7783bb9 1405
mluis 0:91d1a7783bb9 1406 LoRaMacEventInfo.TxNbRetries = 0;
mluis 0:91d1a7783bb9 1407 LoRaMacEventInfo.TxAckReceived = false;
mluis 0:91d1a7783bb9 1408
mluis 0:91d1a7783bb9 1409 return LoRaMacSendFrameOnChannel( channel );
mluis 0:91d1a7783bb9 1410 }
mluis 0:91d1a7783bb9 1411
mluis 0:91d1a7783bb9 1412 static void LoRaMacProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize )
mluis 0:91d1a7783bb9 1413 {
mluis 0:91d1a7783bb9 1414 while( macIndex < commandsSize )
mluis 0:91d1a7783bb9 1415 {
mluis 0:91d1a7783bb9 1416 // Decode Frame MAC commands
mluis 0:91d1a7783bb9 1417 switch( payload[macIndex++] )
mluis 0:91d1a7783bb9 1418 {
mluis 0:91d1a7783bb9 1419 case SRV_MAC_LINK_CHECK_ANS:
mluis 0:91d1a7783bb9 1420 LoRaMacEventFlags.Bits.LinkCheck = 1;
mluis 0:91d1a7783bb9 1421 LoRaMacEventInfo.DemodMargin = payload[macIndex++];
mluis 0:91d1a7783bb9 1422 LoRaMacEventInfo.NbGateways = payload[macIndex++];
mluis 0:91d1a7783bb9 1423 break;
mluis 0:91d1a7783bb9 1424 case SRV_MAC_LINK_ADR_REQ:
mluis 0:91d1a7783bb9 1425 {
mluis 0:91d1a7783bb9 1426 uint8_t status = 0x07;
mluis 0:91d1a7783bb9 1427 uint16_t chMask;
mluis 0:91d1a7783bb9 1428 int8_t txPower = 0;
mluis 0:91d1a7783bb9 1429 int8_t datarate = 0;
mluis 0:91d1a7783bb9 1430 uint8_t nbRep = 0;
mluis 0:91d1a7783bb9 1431 uint8_t chMaskCntl = 0;
mluis 0:91d1a7783bb9 1432 uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
mluis 0:91d1a7783bb9 1433
mluis 0:91d1a7783bb9 1434 // Initialize local copy of the channels mask array
mluis 0:91d1a7783bb9 1435 for( uint8_t i = 0; i < 6; i++ )
mluis 0:91d1a7783bb9 1436 {
mluis 0:91d1a7783bb9 1437 channelsMask[i] = ChannelsMask[i];
mluis 0:91d1a7783bb9 1438 }
mluis 0:91d1a7783bb9 1439 datarate = payload[macIndex++];
mluis 0:91d1a7783bb9 1440 txPower = datarate & 0x0F;
mluis 0:91d1a7783bb9 1441 datarate = ( datarate >> 4 ) & 0x0F;
mluis 0:91d1a7783bb9 1442
mluis 0:91d1a7783bb9 1443 if( ( AdrCtrlOn == false ) &&
mluis 0:91d1a7783bb9 1444 ( ( ChannelsDatarate != datarate ) || ( ChannelsTxPower != txPower ) ) )
mluis 0:91d1a7783bb9 1445 { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower
mluis 0:91d1a7783bb9 1446 // Answer the server with fail status
mluis 0:91d1a7783bb9 1447 // Power ACK = 0
mluis 0:91d1a7783bb9 1448 // Data rate ACK = 0
mluis 0:91d1a7783bb9 1449 // Channel mask = 0
mluis 0:91d1a7783bb9 1450 AddMacCommand( MOTE_MAC_LINK_ADR_ANS, 0, 0 );
mluis 0:91d1a7783bb9 1451 break;
mluis 0:91d1a7783bb9 1452 }
mluis 0:91d1a7783bb9 1453 chMask = payload[macIndex++];
mluis 0:91d1a7783bb9 1454 chMask |= payload[macIndex++] << 8;
mluis 0:91d1a7783bb9 1455
mluis 0:91d1a7783bb9 1456 nbRep = payload[macIndex++];
mluis 0:91d1a7783bb9 1457 chMaskCntl = ( nbRep >> 4 ) & 0x07;
mluis 0:91d1a7783bb9 1458 nbRep &= 0x0F;
mluis 0:91d1a7783bb9 1459 if( nbRep == 0 )
mluis 0:91d1a7783bb9 1460 {
mluis 0:91d1a7783bb9 1461 nbRep = 1;
mluis 0:91d1a7783bb9 1462 }
mluis 0:91d1a7783bb9 1463 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 1464 if( ( chMaskCntl == 0 ) && ( chMask == 0 ) )
mluis 0:91d1a7783bb9 1465 {
mluis 0:91d1a7783bb9 1466 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 1467 }
mluis 0:91d1a7783bb9 1468 else if( ( chMaskCntl >= 1 ) && ( chMaskCntl <= 5 ) )
mluis 0:91d1a7783bb9 1469 {
mluis 0:91d1a7783bb9 1470 // RFU
mluis 0:91d1a7783bb9 1471 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 1472 }
mluis 0:91d1a7783bb9 1473 else
mluis 0:91d1a7783bb9 1474 {
mluis 0:91d1a7783bb9 1475 for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
mluis 0:91d1a7783bb9 1476 {
mluis 0:91d1a7783bb9 1477 if( chMaskCntl == 6 )
mluis 0:91d1a7783bb9 1478 {
mluis 0:91d1a7783bb9 1479 if( Channels[i].Frequency != 0 )
mluis 0:91d1a7783bb9 1480 {
mluis 0:91d1a7783bb9 1481 chMask |= 1 << i;
mluis 0:91d1a7783bb9 1482 }
mluis 0:91d1a7783bb9 1483 }
mluis 0:91d1a7783bb9 1484 else
mluis 0:91d1a7783bb9 1485 {
mluis 0:91d1a7783bb9 1486 if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
mluis 0:91d1a7783bb9 1487 ( Channels[i].Frequency == 0 ) )
mluis 0:91d1a7783bb9 1488 {// Trying to enable an undefined channel
mluis 0:91d1a7783bb9 1489 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 1490 }
mluis 0:91d1a7783bb9 1491 }
mluis 0:91d1a7783bb9 1492 }
mluis 0:91d1a7783bb9 1493 channelsMask[0] = chMask;
mluis 0:91d1a7783bb9 1494 }
mluis 0:91d1a7783bb9 1495 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 1496 if( chMaskCntl == 6 )
mluis 0:91d1a7783bb9 1497 {
mluis 0:91d1a7783bb9 1498 // Enable all 125 kHz channels
mluis 0:91d1a7783bb9 1499 for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
mluis 0:91d1a7783bb9 1500 {
mluis 0:91d1a7783bb9 1501 for( uint8_t j = 0; j < 16; j++ )
mluis 0:91d1a7783bb9 1502 {
mluis 0:91d1a7783bb9 1503 if( Channels[i + j].Frequency != 0 )
mluis 0:91d1a7783bb9 1504 {
mluis 0:91d1a7783bb9 1505 channelsMask[k] |= 1 << j;
mluis 0:91d1a7783bb9 1506 }
mluis 0:91d1a7783bb9 1507 }
mluis 0:91d1a7783bb9 1508 }
mluis 0:91d1a7783bb9 1509 }
mluis 0:91d1a7783bb9 1510 else if( chMaskCntl == 7 )
mluis 0:91d1a7783bb9 1511 {
mluis 0:91d1a7783bb9 1512 // Disable all 125 kHz channels
mluis 0:91d1a7783bb9 1513 channelsMask[0] = 0x0000;
mluis 0:91d1a7783bb9 1514 channelsMask[1] = 0x0000;
mluis 0:91d1a7783bb9 1515 channelsMask[2] = 0x0000;
mluis 0:91d1a7783bb9 1516 channelsMask[3] = 0x0000;
mluis 0:91d1a7783bb9 1517 }
mluis 0:91d1a7783bb9 1518 else if( chMaskCntl == 5 )
mluis 0:91d1a7783bb9 1519 {
mluis 0:91d1a7783bb9 1520 // RFU
mluis 0:91d1a7783bb9 1521 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 1522 }
mluis 0:91d1a7783bb9 1523 else
mluis 0:91d1a7783bb9 1524 {
mluis 0:91d1a7783bb9 1525 for( uint8_t i = 0; i < 16; i++ )
mluis 0:91d1a7783bb9 1526 {
mluis 0:91d1a7783bb9 1527 if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
mluis 0:91d1a7783bb9 1528 ( Channels[chMaskCntl * 16 + i].Frequency == 0 ) )
mluis 0:91d1a7783bb9 1529 {// Trying to enable an undefined channel
mluis 0:91d1a7783bb9 1530 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 1531 }
mluis 0:91d1a7783bb9 1532 }
mluis 0:91d1a7783bb9 1533 channelsMask[chMaskCntl] = chMask;
mluis 0:91d1a7783bb9 1534
mluis 0:91d1a7783bb9 1535 if( CountNbEnabled125kHzChannels( channelsMask ) < 6 )
mluis 0:91d1a7783bb9 1536 {
mluis 0:91d1a7783bb9 1537 status &= 0xFE; // Channel mask KO
mluis 0:91d1a7783bb9 1538 }
mluis 0:91d1a7783bb9 1539 }
mluis 0:91d1a7783bb9 1540 #else
mluis 0:91d1a7783bb9 1541 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 1542 #endif
mluis 0:91d1a7783bb9 1543 if( ( ( datarate < LORAMAC_MIN_DATARATE ) ||
mluis 0:91d1a7783bb9 1544 ( datarate > LORAMAC_MAX_DATARATE ) ) == true )
mluis 0:91d1a7783bb9 1545 {
mluis 0:91d1a7783bb9 1546 status &= 0xFD; // Datarate KO
mluis 0:91d1a7783bb9 1547 }
mluis 0:91d1a7783bb9 1548
mluis 0:91d1a7783bb9 1549 //
mluis 0:91d1a7783bb9 1550 // Remark MaxTxPower = 0 and MinTxPower = 5
mluis 0:91d1a7783bb9 1551 //
mluis 0:91d1a7783bb9 1552 if( ( ( LORAMAC_MAX_TX_POWER <= txPower ) &&
mluis 0:91d1a7783bb9 1553 ( txPower <= LORAMAC_MIN_TX_POWER ) ) == false )
mluis 0:91d1a7783bb9 1554 {
mluis 0:91d1a7783bb9 1555 status &= 0xFB; // TxPower KO
mluis 0:91d1a7783bb9 1556 }
mluis 0:91d1a7783bb9 1557 if( ( status & 0x07 ) == 0x07 )
mluis 0:91d1a7783bb9 1558 {
mluis 0:91d1a7783bb9 1559 ChannelsDatarate = datarate;
mluis 0:91d1a7783bb9 1560 ChannelsTxPower = txPower;
mluis 0:91d1a7783bb9 1561 #if defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 1562 ChannelsMask[0] = channelsMask[0] & 0x00FF;
mluis 0:91d1a7783bb9 1563 ChannelsMask[1] = channelsMask[1] & 0x0000;
mluis 0:91d1a7783bb9 1564 ChannelsMask[2] = channelsMask[2] & 0x0000;
mluis 0:91d1a7783bb9 1565 ChannelsMask[3] = channelsMask[3] & 0x0000;
mluis 0:91d1a7783bb9 1566 ChannelsMask[4] = channelsMask[4] & 0x0001;
mluis 0:91d1a7783bb9 1567 ChannelsMask[5] = channelsMask[5] & 0x0000;
mluis 0:91d1a7783bb9 1568 #else
mluis 0:91d1a7783bb9 1569 ChannelsMask[0] = channelsMask[0];
mluis 0:91d1a7783bb9 1570 ChannelsMask[1] = channelsMask[1];
mluis 0:91d1a7783bb9 1571 ChannelsMask[2] = channelsMask[2];
mluis 0:91d1a7783bb9 1572 ChannelsMask[3] = channelsMask[3];
mluis 0:91d1a7783bb9 1573 ChannelsMask[4] = channelsMask[4];
mluis 0:91d1a7783bb9 1574 ChannelsMask[5] = channelsMask[5];
mluis 0:91d1a7783bb9 1575 #endif
mluis 0:91d1a7783bb9 1576 ChannelsNbRep = nbRep;
mluis 0:91d1a7783bb9 1577 }
mluis 0:91d1a7783bb9 1578 AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
mluis 0:91d1a7783bb9 1579 }
mluis 0:91d1a7783bb9 1580 break;
mluis 0:91d1a7783bb9 1581 case SRV_MAC_DUTY_CYCLE_REQ:
mluis 0:91d1a7783bb9 1582 MaxDCycle = payload[macIndex++];
mluis 0:91d1a7783bb9 1583 AggregatedDCycle = 1 << MaxDCycle;
mluis 0:91d1a7783bb9 1584 AddMacCommand( MOTE_MAC_DUTY_CYCLE_ANS, 0, 0 );
mluis 0:91d1a7783bb9 1585 break;
mluis 0:91d1a7783bb9 1586 case SRV_MAC_RX_PARAM_SETUP_REQ:
mluis 0:91d1a7783bb9 1587 {
mluis 0:91d1a7783bb9 1588 uint8_t status = 0x07;
mluis 0:91d1a7783bb9 1589 int8_t datarate = 0;
mluis 0:91d1a7783bb9 1590 int8_t drOffset = 0;
mluis 0:91d1a7783bb9 1591 uint32_t freq = 0;
mluis 0:91d1a7783bb9 1592
mluis 0:91d1a7783bb9 1593 drOffset = payload[macIndex++];
mluis 0:91d1a7783bb9 1594 datarate = drOffset & 0x0F;
mluis 0:91d1a7783bb9 1595 drOffset = ( drOffset >> 4 ) & 0x0F;
mluis 0:91d1a7783bb9 1596
mluis 0:91d1a7783bb9 1597 freq = ( uint32_t )payload[macIndex++];
mluis 0:91d1a7783bb9 1598 freq |= ( uint32_t )payload[macIndex++] << 8;
mluis 0:91d1a7783bb9 1599 freq |= ( uint32_t )payload[macIndex++] << 16;
mluis 0:91d1a7783bb9 1600 freq *= 100;
mluis 0:91d1a7783bb9 1601
mluis 0:91d1a7783bb9 1602 if( Radio.CheckRfFrequency( freq ) == false )
mluis 0:91d1a7783bb9 1603 {
mluis 0:91d1a7783bb9 1604 status &= 0xFE; // Channel frequency KO
mluis 0:91d1a7783bb9 1605 }
mluis 0:91d1a7783bb9 1606
mluis 0:91d1a7783bb9 1607 if( ( ( datarate < LORAMAC_MIN_DATARATE ) ||
mluis 0:91d1a7783bb9 1608 ( datarate > LORAMAC_MAX_DATARATE ) ) == true )
mluis 0:91d1a7783bb9 1609 {
mluis 0:91d1a7783bb9 1610 status &= 0xFD; // Datarate KO
mluis 0:91d1a7783bb9 1611 }
mluis 0:91d1a7783bb9 1612
mluis 0:91d1a7783bb9 1613 if( ( ( drOffset < 0 ) || ( drOffset > 5 ) ) == true )
mluis 0:91d1a7783bb9 1614 {
mluis 0:91d1a7783bb9 1615 status &= 0xFB; // Rx1DrOffset range KO
mluis 0:91d1a7783bb9 1616 }
mluis 0:91d1a7783bb9 1617
mluis 0:91d1a7783bb9 1618 if( ( status & 0x07 ) == 0x07 )
mluis 0:91d1a7783bb9 1619 {
mluis 0:91d1a7783bb9 1620 Rx2Channel.Datarate = datarate;
mluis 0:91d1a7783bb9 1621 Rx2Channel.Frequency = freq;
mluis 0:91d1a7783bb9 1622 Rx1DrOffset = drOffset;
mluis 0:91d1a7783bb9 1623 }
mluis 0:91d1a7783bb9 1624 AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
mluis 0:91d1a7783bb9 1625 }
mluis 0:91d1a7783bb9 1626 break;
mluis 0:91d1a7783bb9 1627 case SRV_MAC_DEV_STATUS_REQ:
mluis 0:91d1a7783bb9 1628 AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, LoRaMacGetBatteryLevel( ), LoRaMacEventInfo.RxSnr );
mluis 0:91d1a7783bb9 1629 break;
mluis 0:91d1a7783bb9 1630 case SRV_MAC_NEW_CHANNEL_REQ:
mluis 0:91d1a7783bb9 1631 {
mluis 0:91d1a7783bb9 1632 uint8_t status = 0x03;
mluis 0:91d1a7783bb9 1633 int8_t channelIndex = 0;
mluis 0:91d1a7783bb9 1634 ChannelParams_t chParam;
mluis 0:91d1a7783bb9 1635
mluis 0:91d1a7783bb9 1636 channelIndex = payload[macIndex++];
mluis 0:91d1a7783bb9 1637 chParam.Frequency = ( uint32_t )payload[macIndex++];
mluis 0:91d1a7783bb9 1638 chParam.Frequency |= ( uint32_t )payload[macIndex++] << 8;
mluis 0:91d1a7783bb9 1639 chParam.Frequency |= ( uint32_t )payload[macIndex++] << 16;
mluis 0:91d1a7783bb9 1640 chParam.Frequency *= 100;
mluis 0:91d1a7783bb9 1641 chParam.DrRange.Value = payload[macIndex++];
mluis 0:91d1a7783bb9 1642
mluis 0:91d1a7783bb9 1643 if( ( channelIndex < 3 ) || ( channelIndex > LORA_MAX_NB_CHANNELS ) )
mluis 0:91d1a7783bb9 1644 {
mluis 0:91d1a7783bb9 1645 status &= 0xFE; // Channel frequency KO
mluis 0:91d1a7783bb9 1646 }
mluis 0:91d1a7783bb9 1647
mluis 0:91d1a7783bb9 1648 if( Radio.CheckRfFrequency( chParam.Frequency ) == false )
mluis 0:91d1a7783bb9 1649 {
mluis 0:91d1a7783bb9 1650 status &= 0xFE; // Channel frequency KO
mluis 0:91d1a7783bb9 1651 }
mluis 0:91d1a7783bb9 1652
mluis 0:91d1a7783bb9 1653 if( ( chParam.DrRange.Fields.Min > chParam.DrRange.Fields.Max ) ||
mluis 0:91d1a7783bb9 1654 ( ( ( LORAMAC_MIN_DATARATE <= chParam.DrRange.Fields.Min ) &&
mluis 0:91d1a7783bb9 1655 ( chParam.DrRange.Fields.Min <= LORAMAC_MAX_DATARATE ) ) == false ) ||
mluis 0:91d1a7783bb9 1656 ( ( ( LORAMAC_MIN_DATARATE <= chParam.DrRange.Fields.Max ) &&
mluis 0:91d1a7783bb9 1657 ( chParam.DrRange.Fields.Max <= LORAMAC_MAX_DATARATE ) ) == false ) )
mluis 0:91d1a7783bb9 1658 {
mluis 0:91d1a7783bb9 1659 status &= 0xFD; // Datarate range KO
mluis 0:91d1a7783bb9 1660 }
mluis 0:91d1a7783bb9 1661 if( ( status & 0x03 ) == 0x03 )
mluis 0:91d1a7783bb9 1662 {
mluis 0:91d1a7783bb9 1663 LoRaMacSetChannel( channelIndex, chParam );
mluis 0:91d1a7783bb9 1664 }
mluis 0:91d1a7783bb9 1665 AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
mluis 0:91d1a7783bb9 1666 }
mluis 0:91d1a7783bb9 1667 break;
mluis 0:91d1a7783bb9 1668 case SRV_MAC_RX_TIMING_SETUP_REQ:
mluis 0:91d1a7783bb9 1669 {
mluis 0:91d1a7783bb9 1670 uint8_t delay = payload[macIndex++] & 0x0F;
mluis 0:91d1a7783bb9 1671
mluis 0:91d1a7783bb9 1672 if( delay == 0 )
mluis 0:91d1a7783bb9 1673 {
mluis 0:91d1a7783bb9 1674 delay++;
mluis 0:91d1a7783bb9 1675 }
mluis 0:91d1a7783bb9 1676 ReceiveDelay1 = delay * 1e6;
mluis 0:91d1a7783bb9 1677 ReceiveDelay2 = ReceiveDelay1 + 1e6;
mluis 0:91d1a7783bb9 1678 AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
mluis 0:91d1a7783bb9 1679 }
mluis 0:91d1a7783bb9 1680 break;
mluis 0:91d1a7783bb9 1681 default:
mluis 0:91d1a7783bb9 1682 // Unknown command. ABORT MAC commands processing
mluis 0:91d1a7783bb9 1683 return;
mluis 0:91d1a7783bb9 1684 }
mluis 0:91d1a7783bb9 1685 }
mluis 0:91d1a7783bb9 1686 }
mluis 0:91d1a7783bb9 1687
mluis 0:91d1a7783bb9 1688 /*!
mluis 0:91d1a7783bb9 1689 * Function to be executed on Tx Done event
mluis 0:91d1a7783bb9 1690 */
mluis 0:91d1a7783bb9 1691 static void OnRadioTxDone( void )
mluis 0:91d1a7783bb9 1692 {
mluis 0:91d1a7783bb9 1693 TimerTime_t curTime = TimerGetCurrentTime( );
mluis 0:91d1a7783bb9 1694 if( LoRaMacDeviceClass != CLASS_C )
mluis 0:91d1a7783bb9 1695 {
mluis 0:91d1a7783bb9 1696 Radio.Sleep( );
mluis 0:91d1a7783bb9 1697 }
mluis 0:91d1a7783bb9 1698 else
mluis 0:91d1a7783bb9 1699 {
mluis 0:91d1a7783bb9 1700 OnRxWindow2TimerEvent( );
mluis 0:91d1a7783bb9 1701 }
mluis 0:91d1a7783bb9 1702
mluis 0:91d1a7783bb9 1703 // Update Band Time OFF
mluis 0:91d1a7783bb9 1704 Bands[Channels[Channel].Band].LastTxDoneTime = curTime;
mluis 0:91d1a7783bb9 1705 if( DutyCycleOn == true )
mluis 0:91d1a7783bb9 1706 {
mluis 0:91d1a7783bb9 1707 Bands[Channels[Channel].Band].TimeOff = TxTimeOnAir * Bands[Channels[Channel].Band].DCycle - TxTimeOnAir;
mluis 0:91d1a7783bb9 1708 }
mluis 0:91d1a7783bb9 1709 else
mluis 0:91d1a7783bb9 1710 {
mluis 0:91d1a7783bb9 1711 Bands[Channels[Channel].Band].TimeOff = 0;
mluis 0:91d1a7783bb9 1712 }
mluis 0:91d1a7783bb9 1713 // Update Agregated Time OFF
mluis 0:91d1a7783bb9 1714 AggregatedLastTxDoneTime = curTime;
mluis 0:91d1a7783bb9 1715 AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
mluis 0:91d1a7783bb9 1716
mluis 0:91d1a7783bb9 1717 if( IsRxWindowsEnabled == true )
mluis 0:91d1a7783bb9 1718 {
mluis 0:91d1a7783bb9 1719 TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
mluis 0:91d1a7783bb9 1720 TimerStart( &RxWindowTimer1 );
mluis 0:91d1a7783bb9 1721 if( LoRaMacDeviceClass != CLASS_C )
mluis 0:91d1a7783bb9 1722 {
mluis 0:91d1a7783bb9 1723 TimerSetValue( &RxWindowTimer2, RxWindow2Delay );
mluis 0:91d1a7783bb9 1724 TimerStart( &RxWindowTimer2 );
mluis 0:91d1a7783bb9 1725 }
mluis 0:91d1a7783bb9 1726 }
mluis 0:91d1a7783bb9 1727 else
mluis 0:91d1a7783bb9 1728 {
mluis 0:91d1a7783bb9 1729 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 1730 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 0:91d1a7783bb9 1731 }
mluis 0:91d1a7783bb9 1732
mluis 0:91d1a7783bb9 1733 if( NodeAckRequested == false )
mluis 0:91d1a7783bb9 1734 {
mluis 0:91d1a7783bb9 1735 ChannelsNbRepCounter++;
mluis 0:91d1a7783bb9 1736 }
mluis 0:91d1a7783bb9 1737 }
mluis 0:91d1a7783bb9 1738
mluis 0:91d1a7783bb9 1739 /*!
mluis 0:91d1a7783bb9 1740 * Function to be executed on Rx Done event
mluis 0:91d1a7783bb9 1741 */
mluis 0:91d1a7783bb9 1742 static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
mluis 0:91d1a7783bb9 1743 {
mluis 0:91d1a7783bb9 1744 LoRaMacHeader_t macHdr;
mluis 0:91d1a7783bb9 1745 LoRaMacFrameCtrl_t fCtrl;
mluis 0:91d1a7783bb9 1746
mluis 0:91d1a7783bb9 1747 uint8_t pktHeaderLen = 0;
mluis 0:91d1a7783bb9 1748 uint32_t address = 0;
mluis 0:91d1a7783bb9 1749 uint16_t sequenceCounter = 0;
mluis 0:91d1a7783bb9 1750 int32_t sequence = 0;
mluis 0:91d1a7783bb9 1751 uint8_t appPayloadStartIndex = 0;
mluis 0:91d1a7783bb9 1752 uint8_t port = 0xFF;
mluis 0:91d1a7783bb9 1753 uint8_t frameLen = 0;
mluis 0:91d1a7783bb9 1754 uint32_t mic = 0;
mluis 0:91d1a7783bb9 1755 uint32_t micRx = 0;
mluis 0:91d1a7783bb9 1756
mluis 0:91d1a7783bb9 1757 MulticastParams_t *curMulticastParams = NULL;
mluis 0:91d1a7783bb9 1758 uint8_t *nwkSKey = LoRaMacNwkSKey;
mluis 0:91d1a7783bb9 1759 uint8_t *appSKey = LoRaMacAppSKey;
mluis 0:91d1a7783bb9 1760 uint32_t downLinkCounter = 0;
mluis 0:91d1a7783bb9 1761
mluis 0:91d1a7783bb9 1762 bool isMicOk = false;
mluis 0:91d1a7783bb9 1763
mluis 0:91d1a7783bb9 1764 if( LoRaMacDeviceClass != CLASS_C )
mluis 0:91d1a7783bb9 1765 {
mluis 0:91d1a7783bb9 1766 Radio.Sleep( );
mluis 0:91d1a7783bb9 1767 }
mluis 0:91d1a7783bb9 1768 else
mluis 0:91d1a7783bb9 1769 {
mluis 0:91d1a7783bb9 1770 if( LoRaMacEventFlags.Bits.RxSlot == 0 )
mluis 0:91d1a7783bb9 1771 {
mluis 0:91d1a7783bb9 1772 OnRxWindow2TimerEvent( );
mluis 0:91d1a7783bb9 1773 }
mluis 0:91d1a7783bb9 1774 }
mluis 0:91d1a7783bb9 1775 TimerStop( &RxWindowTimer2 );
mluis 0:91d1a7783bb9 1776
mluis 0:91d1a7783bb9 1777 macHdr.Value = payload[pktHeaderLen++];
mluis 0:91d1a7783bb9 1778
mluis 0:91d1a7783bb9 1779 switch( macHdr.Bits.MType )
mluis 0:91d1a7783bb9 1780 {
mluis 0:91d1a7783bb9 1781 case FRAME_TYPE_JOIN_ACCEPT:
mluis 0:91d1a7783bb9 1782 if( IsLoRaMacNetworkJoined == true )
mluis 0:91d1a7783bb9 1783 {
mluis 0:91d1a7783bb9 1784 break;
mluis 0:91d1a7783bb9 1785 }
mluis 0:91d1a7783bb9 1786 LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
mluis 0:91d1a7783bb9 1787
mluis 0:91d1a7783bb9 1788 LoRaMacRxPayload[0] = macHdr.Value;
mluis 0:91d1a7783bb9 1789
mluis 0:91d1a7783bb9 1790 LoRaMacJoinComputeMic( LoRaMacRxPayload, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic );
mluis 0:91d1a7783bb9 1791
mluis 0:91d1a7783bb9 1792 micRx |= ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN];
mluis 0:91d1a7783bb9 1793 micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 1] << 8 );
mluis 0:91d1a7783bb9 1794 micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16 );
mluis 0:91d1a7783bb9 1795 micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24 );
mluis 0:91d1a7783bb9 1796
mluis 0:91d1a7783bb9 1797 if( micRx == mic )
mluis 0:91d1a7783bb9 1798 {
mluis 0:91d1a7783bb9 1799 LoRaMacEventFlags.Bits.Rx = 1;
mluis 0:91d1a7783bb9 1800 LoRaMacEventInfo.RxSnr = snr;
mluis 0:91d1a7783bb9 1801 LoRaMacEventInfo.RxRssi = rssi;
mluis 0:91d1a7783bb9 1802
mluis 0:91d1a7783bb9 1803 LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
mluis 0:91d1a7783bb9 1804
mluis 0:91d1a7783bb9 1805 LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
mluis 0:91d1a7783bb9 1806 LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
mluis 0:91d1a7783bb9 1807 LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );
mluis 0:91d1a7783bb9 1808
mluis 0:91d1a7783bb9 1809 LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
mluis 0:91d1a7783bb9 1810 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
mluis 0:91d1a7783bb9 1811 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
mluis 0:91d1a7783bb9 1812 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
mluis 0:91d1a7783bb9 1813
mluis 0:91d1a7783bb9 1814 // DLSettings
mluis 0:91d1a7783bb9 1815 Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
mluis 0:91d1a7783bb9 1816 Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
mluis 0:91d1a7783bb9 1817
mluis 0:91d1a7783bb9 1818 // RxDelay
mluis 0:91d1a7783bb9 1819 ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
mluis 0:91d1a7783bb9 1820 if( ReceiveDelay1 == 0 )
mluis 0:91d1a7783bb9 1821 {
mluis 0:91d1a7783bb9 1822 ReceiveDelay1 = 1;
mluis 0:91d1a7783bb9 1823 }
mluis 0:91d1a7783bb9 1824 ReceiveDelay1 *= 1e6;
mluis 0:91d1a7783bb9 1825 ReceiveDelay2 = ReceiveDelay1 + 1e6;
mluis 0:91d1a7783bb9 1826
mluis 0:91d1a7783bb9 1827 #if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 0:91d1a7783bb9 1828 //CFList
mluis 0:91d1a7783bb9 1829 if( ( size - 1 ) > 16 )
mluis 0:91d1a7783bb9 1830 {
mluis 0:91d1a7783bb9 1831 ChannelParams_t param;
mluis 0:91d1a7783bb9 1832 param.DrRange.Value = ( DR_5 << 4 ) | DR_0;
mluis 0:91d1a7783bb9 1833
mluis 0:91d1a7783bb9 1834 for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 )
mluis 0:91d1a7783bb9 1835 {
mluis 0:91d1a7783bb9 1836 param.Frequency = ( ( uint32_t )LoRaMacRxPayload[13 + j] | ( ( uint32_t )LoRaMacRxPayload[14 + j] << 8 ) | ( ( uint32_t )LoRaMacRxPayload[15 + j] << 16 ) ) * 100;
mluis 0:91d1a7783bb9 1837 LoRaMacSetChannel( i, param );
mluis 0:91d1a7783bb9 1838 }
mluis 0:91d1a7783bb9 1839 }
mluis 0:91d1a7783bb9 1840 #endif
mluis 0:91d1a7783bb9 1841 LoRaMacEventFlags.Bits.JoinAccept = 1;
mluis 0:91d1a7783bb9 1842 IsLoRaMacNetworkJoined = true;
mluis 0:91d1a7783bb9 1843 ChannelsDatarate = ChannelsDefaultDatarate;
mluis 0:91d1a7783bb9 1844 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 0:91d1a7783bb9 1845 }
mluis 0:91d1a7783bb9 1846 else
mluis 0:91d1a7783bb9 1847 {
mluis 0:91d1a7783bb9 1848 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
mluis 0:91d1a7783bb9 1849 }
mluis 0:91d1a7783bb9 1850
mluis 0:91d1a7783bb9 1851 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 1852 break;
mluis 0:91d1a7783bb9 1853 case FRAME_TYPE_DATA_CONFIRMED_DOWN:
mluis 0:91d1a7783bb9 1854 case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
mluis 0:91d1a7783bb9 1855 {
mluis 0:91d1a7783bb9 1856 address = payload[pktHeaderLen++];
mluis 0:91d1a7783bb9 1857 address |= ( (uint32_t)payload[pktHeaderLen++] << 8 );
mluis 0:91d1a7783bb9 1858 address |= ( (uint32_t)payload[pktHeaderLen++] << 16 );
mluis 0:91d1a7783bb9 1859 address |= ( (uint32_t)payload[pktHeaderLen++] << 24 );
mluis 0:91d1a7783bb9 1860
mluis 0:91d1a7783bb9 1861 if( address != LoRaMacDevAddr )
mluis 0:91d1a7783bb9 1862 {
mluis 0:91d1a7783bb9 1863 curMulticastParams = MulticastChannels;
mluis 0:91d1a7783bb9 1864 while( curMulticastParams != NULL )
mluis 0:91d1a7783bb9 1865 {
mluis 0:91d1a7783bb9 1866 if( address == curMulticastParams->Address )
mluis 0:91d1a7783bb9 1867 {
mluis 0:91d1a7783bb9 1868 LoRaMacEventFlags.Bits.Multicast = 1;
mluis 0:91d1a7783bb9 1869 nwkSKey = curMulticastParams->NwkSKey;
mluis 0:91d1a7783bb9 1870 appSKey = curMulticastParams->AppSKey;
mluis 0:91d1a7783bb9 1871 downLinkCounter = curMulticastParams->DownLinkCounter;
mluis 0:91d1a7783bb9 1872 break;
mluis 0:91d1a7783bb9 1873 }
mluis 0:91d1a7783bb9 1874 curMulticastParams = curMulticastParams->Next;
mluis 0:91d1a7783bb9 1875 }
mluis 0:91d1a7783bb9 1876 if( LoRaMacEventFlags.Bits.Multicast == 0 )
mluis 0:91d1a7783bb9 1877 {
mluis 0:91d1a7783bb9 1878 // We are not the destination of this frame.
mluis 0:91d1a7783bb9 1879 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 1880 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
mluis 0:91d1a7783bb9 1881 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 0:91d1a7783bb9 1882 return;
mluis 0:91d1a7783bb9 1883 }
mluis 0:91d1a7783bb9 1884 }
mluis 0:91d1a7783bb9 1885 else
mluis 0:91d1a7783bb9 1886 {
mluis 0:91d1a7783bb9 1887 LoRaMacEventFlags.Bits.Multicast = 0;
mluis 0:91d1a7783bb9 1888 nwkSKey = LoRaMacNwkSKey;
mluis 0:91d1a7783bb9 1889 appSKey = LoRaMacAppSKey;
mluis 0:91d1a7783bb9 1890 downLinkCounter = DownLinkCounter;
mluis 0:91d1a7783bb9 1891 }
mluis 0:91d1a7783bb9 1892
mluis 0:91d1a7783bb9 1893 if( LoRaMacDeviceClass != CLASS_A )
mluis 0:91d1a7783bb9 1894 {
mluis 0:91d1a7783bb9 1895 LoRaMacState |= MAC_RX;
mluis 0:91d1a7783bb9 1896 // Starts the MAC layer status check timer
mluis 0:91d1a7783bb9 1897 TimerStart( &MacStateCheckTimer );
mluis 0:91d1a7783bb9 1898 }
mluis 0:91d1a7783bb9 1899 fCtrl.Value = payload[pktHeaderLen++];
mluis 0:91d1a7783bb9 1900
mluis 0:91d1a7783bb9 1901 sequenceCounter |= ( uint32_t )payload[pktHeaderLen++];
mluis 0:91d1a7783bb9 1902 sequenceCounter |= ( uint32_t )payload[pktHeaderLen++] << 8;
mluis 0:91d1a7783bb9 1903
mluis 0:91d1a7783bb9 1904 appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen;
mluis 0:91d1a7783bb9 1905
mluis 0:91d1a7783bb9 1906 micRx |= ( uint32_t )payload[size - LORAMAC_MFR_LEN];
mluis 0:91d1a7783bb9 1907 micRx |= ( (uint32_t)payload[size - LORAMAC_MFR_LEN + 1] << 8 );
mluis 0:91d1a7783bb9 1908 micRx |= ( (uint32_t)payload[size - LORAMAC_MFR_LEN + 2] << 16 );
mluis 0:91d1a7783bb9 1909 micRx |= ( (uint32_t)payload[size - LORAMAC_MFR_LEN + 3] << 24 );
mluis 0:91d1a7783bb9 1910
mluis 0:91d1a7783bb9 1911 sequence = ( int32_t )sequenceCounter - ( int32_t )( downLinkCounter & 0xFFFF );
mluis 0:91d1a7783bb9 1912 if( sequence < 0 )
mluis 0:91d1a7783bb9 1913 {
mluis 0:91d1a7783bb9 1914 // sequence reset or roll over happened
mluis 0:91d1a7783bb9 1915 downLinkCounter = ( downLinkCounter & 0xFFFF0000 ) | ( sequenceCounter + ( uint32_t )0x10000 );
mluis 0:91d1a7783bb9 1916 LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
mluis 0:91d1a7783bb9 1917 if( micRx == mic )
mluis 0:91d1a7783bb9 1918 {
mluis 0:91d1a7783bb9 1919 isMicOk = true;
mluis 0:91d1a7783bb9 1920 }
mluis 0:91d1a7783bb9 1921 else
mluis 0:91d1a7783bb9 1922 {
mluis 0:91d1a7783bb9 1923 isMicOk = false;
mluis 0:91d1a7783bb9 1924 // sequence reset
mluis 0:91d1a7783bb9 1925 if( LoRaMacEventFlags.Bits.Multicast == 1 )
mluis 0:91d1a7783bb9 1926 {
mluis 0:91d1a7783bb9 1927 curMulticastParams->DownLinkCounter = downLinkCounter = sequenceCounter;
mluis 0:91d1a7783bb9 1928 }
mluis 0:91d1a7783bb9 1929 else
mluis 0:91d1a7783bb9 1930 {
mluis 0:91d1a7783bb9 1931 DownLinkCounter = downLinkCounter = sequenceCounter;
mluis 0:91d1a7783bb9 1932 }
mluis 0:91d1a7783bb9 1933 LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
mluis 0:91d1a7783bb9 1934 }
mluis 0:91d1a7783bb9 1935 }
mluis 0:91d1a7783bb9 1936 else
mluis 0:91d1a7783bb9 1937 {
mluis 0:91d1a7783bb9 1938 downLinkCounter = ( downLinkCounter & 0xFFFF0000 ) | sequenceCounter;
mluis 0:91d1a7783bb9 1939 LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
mluis 0:91d1a7783bb9 1940 }
mluis 0:91d1a7783bb9 1941
mluis 0:91d1a7783bb9 1942 if( ( isMicOk == true ) ||
mluis 0:91d1a7783bb9 1943 ( micRx == mic ) )
mluis 0:91d1a7783bb9 1944 {
mluis 0:91d1a7783bb9 1945 LoRaMacEventFlags.Bits.Rx = 1;
mluis 0:91d1a7783bb9 1946 LoRaMacEventInfo.RxSnr = snr;
mluis 0:91d1a7783bb9 1947 LoRaMacEventInfo.RxRssi = rssi;
mluis 0:91d1a7783bb9 1948 LoRaMacEventInfo.RxBufferSize = 0;
mluis 0:91d1a7783bb9 1949 AdrAckCounter = 0;
mluis 0:91d1a7783bb9 1950 if( LoRaMacEventFlags.Bits.Multicast == 1 )
mluis 0:91d1a7783bb9 1951 {
mluis 0:91d1a7783bb9 1952 curMulticastParams->DownLinkCounter = downLinkCounter;
mluis 0:91d1a7783bb9 1953 }
mluis 0:91d1a7783bb9 1954 else
mluis 0:91d1a7783bb9 1955 {
mluis 0:91d1a7783bb9 1956 DownLinkCounter = downLinkCounter;
mluis 0:91d1a7783bb9 1957 }
mluis 0:91d1a7783bb9 1958
mluis 0:91d1a7783bb9 1959 if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN )
mluis 0:91d1a7783bb9 1960 {
mluis 0:91d1a7783bb9 1961 SrvAckRequested = true;
mluis 0:91d1a7783bb9 1962 }
mluis 0:91d1a7783bb9 1963 else
mluis 0:91d1a7783bb9 1964 {
mluis 0:91d1a7783bb9 1965 SrvAckRequested = false;
mluis 0:91d1a7783bb9 1966 }
mluis 0:91d1a7783bb9 1967 // Check if the frame is an acknowledgement
mluis 0:91d1a7783bb9 1968 if( fCtrl.Bits.Ack == 1 )
mluis 0:91d1a7783bb9 1969 {
mluis 0:91d1a7783bb9 1970 LoRaMacEventInfo.TxAckReceived = true;
mluis 0:91d1a7783bb9 1971
mluis 0:91d1a7783bb9 1972 // Stop the AckTimeout timer as no more retransmissions
mluis 0:91d1a7783bb9 1973 // are needed.
mluis 0:91d1a7783bb9 1974 TimerStop( &AckTimeoutTimer );
mluis 0:91d1a7783bb9 1975 }
mluis 0:91d1a7783bb9 1976 else
mluis 0:91d1a7783bb9 1977 {
mluis 0:91d1a7783bb9 1978 LoRaMacEventInfo.TxAckReceived = false;
mluis 0:91d1a7783bb9 1979 if( AckTimeoutRetriesCounter > AckTimeoutRetries )
mluis 0:91d1a7783bb9 1980 {
mluis 0:91d1a7783bb9 1981 // Stop the AckTimeout timer as no more retransmissions
mluis 0:91d1a7783bb9 1982 // are needed.
mluis 0:91d1a7783bb9 1983 TimerStop( &AckTimeoutTimer );
mluis 0:91d1a7783bb9 1984 }
mluis 0:91d1a7783bb9 1985 }
mluis 0:91d1a7783bb9 1986
mluis 0:91d1a7783bb9 1987 if( fCtrl.Bits.FOptsLen > 0 )
mluis 0:91d1a7783bb9 1988 {
mluis 0:91d1a7783bb9 1989 // Decode Options field MAC commands
mluis 0:91d1a7783bb9 1990 LoRaMacProcessMacCommands( payload, 8, appPayloadStartIndex );
mluis 0:91d1a7783bb9 1991 }
mluis 0:91d1a7783bb9 1992
mluis 0:91d1a7783bb9 1993 if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
mluis 0:91d1a7783bb9 1994 {
mluis 0:91d1a7783bb9 1995 port = payload[appPayloadStartIndex++];
mluis 0:91d1a7783bb9 1996 frameLen = ( size - 4 ) - appPayloadStartIndex;
mluis 0:91d1a7783bb9 1997
mluis 0:91d1a7783bb9 1998 if( port == 0 )
mluis 0:91d1a7783bb9 1999 {
mluis 0:91d1a7783bb9 2000 LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
mluis 0:91d1a7783bb9 2001 frameLen,
mluis 0:91d1a7783bb9 2002 nwkSKey,
mluis 0:91d1a7783bb9 2003 address,
mluis 0:91d1a7783bb9 2004 DOWN_LINK,
mluis 0:91d1a7783bb9 2005 downLinkCounter,
mluis 0:91d1a7783bb9 2006 LoRaMacRxPayload );
mluis 0:91d1a7783bb9 2007
mluis 0:91d1a7783bb9 2008 // Decode frame payload MAC commands
mluis 0:91d1a7783bb9 2009 LoRaMacProcessMacCommands( LoRaMacRxPayload, 0, frameLen );
mluis 0:91d1a7783bb9 2010 }
mluis 0:91d1a7783bb9 2011 else
mluis 0:91d1a7783bb9 2012 {
mluis 0:91d1a7783bb9 2013 LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
mluis 0:91d1a7783bb9 2014 frameLen,
mluis 0:91d1a7783bb9 2015 appSKey,
mluis 0:91d1a7783bb9 2016 address,
mluis 0:91d1a7783bb9 2017 DOWN_LINK,
mluis 0:91d1a7783bb9 2018 downLinkCounter,
mluis 0:91d1a7783bb9 2019 LoRaMacRxPayload );
mluis 0:91d1a7783bb9 2020
mluis 0:91d1a7783bb9 2021 LoRaMacEventFlags.Bits.RxData = 1;
mluis 0:91d1a7783bb9 2022 LoRaMacEventInfo.RxPort = port;
mluis 0:91d1a7783bb9 2023 LoRaMacEventInfo.RxBuffer = LoRaMacRxPayload;
mluis 0:91d1a7783bb9 2024 LoRaMacEventInfo.RxBufferSize = frameLen;
mluis 0:91d1a7783bb9 2025 }
mluis 0:91d1a7783bb9 2026 }
mluis 0:91d1a7783bb9 2027
mluis 0:91d1a7783bb9 2028 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 2029 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 0:91d1a7783bb9 2030 }
mluis 0:91d1a7783bb9 2031 else
mluis 0:91d1a7783bb9 2032 {
mluis 0:91d1a7783bb9 2033 LoRaMacEventInfo.TxAckReceived = false;
mluis 0:91d1a7783bb9 2034
mluis 0:91d1a7783bb9 2035 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 2036 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
mluis 0:91d1a7783bb9 2037 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 0:91d1a7783bb9 2038 }
mluis 0:91d1a7783bb9 2039 }
mluis 0:91d1a7783bb9 2040 break;
mluis 0:91d1a7783bb9 2041 case FRAME_TYPE_PROPRIETARY:
mluis 0:91d1a7783bb9 2042 //Intentional falltrough
mluis 0:91d1a7783bb9 2043 default:
mluis 0:91d1a7783bb9 2044 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 2045 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
mluis 0:91d1a7783bb9 2046 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 0:91d1a7783bb9 2047 break;
mluis 0:91d1a7783bb9 2048 }
mluis 0:91d1a7783bb9 2049 }
mluis 0:91d1a7783bb9 2050
mluis 0:91d1a7783bb9 2051 /*!
mluis 0:91d1a7783bb9 2052 * Function executed on Radio Tx Timeout event
mluis 0:91d1a7783bb9 2053 */
mluis 0:91d1a7783bb9 2054 static void OnRadioTxTimeout( void )
mluis 0:91d1a7783bb9 2055 {
mluis 0:91d1a7783bb9 2056 if( LoRaMacDeviceClass != CLASS_C )
mluis 0:91d1a7783bb9 2057 {
mluis 0:91d1a7783bb9 2058 Radio.Sleep( );
mluis 0:91d1a7783bb9 2059 }
mluis 0:91d1a7783bb9 2060 else
mluis 0:91d1a7783bb9 2061 {
mluis 0:91d1a7783bb9 2062 OnRxWindow2TimerEvent( );
mluis 0:91d1a7783bb9 2063 }
mluis 0:91d1a7783bb9 2064
mluis 0:91d1a7783bb9 2065 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 2066 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
mluis 0:91d1a7783bb9 2067 }
mluis 0:91d1a7783bb9 2068
mluis 0:91d1a7783bb9 2069 /*!
mluis 0:91d1a7783bb9 2070 * Function executed on Radio Rx Timeout event
mluis 0:91d1a7783bb9 2071 */
mluis 0:91d1a7783bb9 2072 static void OnRadioRxTimeout( void )
mluis 0:91d1a7783bb9 2073 {
mluis 0:91d1a7783bb9 2074 if( LoRaMacDeviceClass != CLASS_C )
mluis 0:91d1a7783bb9 2075 {
mluis 0:91d1a7783bb9 2076 Radio.Sleep( );
mluis 0:91d1a7783bb9 2077 }
mluis 0:91d1a7783bb9 2078 if( LoRaMacEventFlags.Bits.RxSlot == 1 )
mluis 0:91d1a7783bb9 2079 {
mluis 0:91d1a7783bb9 2080 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 2081 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
mluis 0:91d1a7783bb9 2082 }
mluis 0:91d1a7783bb9 2083 }
mluis 0:91d1a7783bb9 2084
mluis 0:91d1a7783bb9 2085 /*!
mluis 0:91d1a7783bb9 2086 * Function executed on Radio Rx Error event
mluis 0:91d1a7783bb9 2087 */
mluis 0:91d1a7783bb9 2088 static void OnRadioRxError( void )
mluis 0:91d1a7783bb9 2089 {
mluis 0:91d1a7783bb9 2090 if( LoRaMacDeviceClass != CLASS_C )
mluis 0:91d1a7783bb9 2091 {
mluis 0:91d1a7783bb9 2092 Radio.Sleep( );
mluis 0:91d1a7783bb9 2093 }
mluis 0:91d1a7783bb9 2094 if( LoRaMacEventFlags.Bits.RxSlot == 1 )
mluis 0:91d1a7783bb9 2095 {
mluis 0:91d1a7783bb9 2096 LoRaMacEventFlags.Bits.Tx = 1;
mluis 0:91d1a7783bb9 2097 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
mluis 0:91d1a7783bb9 2098 }
mluis 0:91d1a7783bb9 2099 }
mluis 0:91d1a7783bb9 2100
mluis 0:91d1a7783bb9 2101 /*!
mluis 0:91d1a7783bb9 2102 * Initializes and opens the reception window
mluis 0:91d1a7783bb9 2103 *
mluis 0:91d1a7783bb9 2104 * \param [IN] freq window channel frequency
mluis 0:91d1a7783bb9 2105 * \param [IN] datarate window channel datarate
mluis 0:91d1a7783bb9 2106 * \param [IN] bandwidth window channel bandwidth
mluis 0:91d1a7783bb9 2107 * \param [IN] timeout window channel timeout
mluis 0:91d1a7783bb9 2108 */
mluis 0:91d1a7783bb9 2109 void LoRaMacRxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
mluis 0:91d1a7783bb9 2110 {
mluis 0:91d1a7783bb9 2111 if( Radio.GetStatus( ) == IDLE )
mluis 0:91d1a7783bb9 2112 {
mluis 0:91d1a7783bb9 2113 Radio.SetChannel( freq );
mluis 0:91d1a7783bb9 2114 if( datarate == DR_7 )
mluis 0:91d1a7783bb9 2115 {
mluis 0:91d1a7783bb9 2116 Radio.SetRxConfig( MODEM_FSK, 50e3, Datarates[datarate] * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, rxContinuous );
mluis 0:91d1a7783bb9 2117 }
mluis 0:91d1a7783bb9 2118 else
mluis 0:91d1a7783bb9 2119 {
mluis 0:91d1a7783bb9 2120 Radio.SetRxConfig( MODEM_LORA, bandwidth, Datarates[datarate], 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
mluis 0:91d1a7783bb9 2121 }
mluis 0:91d1a7783bb9 2122 if( rxContinuous == false )
mluis 0:91d1a7783bb9 2123 {
mluis 0:91d1a7783bb9 2124 Radio.Rx( MaxRxWindow );
mluis 0:91d1a7783bb9 2125 }
mluis 0:91d1a7783bb9 2126 else
mluis 0:91d1a7783bb9 2127 {
mluis 0:91d1a7783bb9 2128 Radio.Rx( 0 ); // Continuous mode
mluis 0:91d1a7783bb9 2129 }
mluis 0:91d1a7783bb9 2130 }
mluis 0:91d1a7783bb9 2131 }
mluis 0:91d1a7783bb9 2132
mluis 0:91d1a7783bb9 2133 /*!
mluis 0:91d1a7783bb9 2134 * Function executed on first Rx window timer event
mluis 0:91d1a7783bb9 2135 */
mluis 0:91d1a7783bb9 2136 static void OnRxWindow1TimerEvent( void )
mluis 0:91d1a7783bb9 2137 {
mluis 0:91d1a7783bb9 2138 uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
mluis 0:91d1a7783bb9 2139 int8_t datarate = 0;
mluis 0:91d1a7783bb9 2140 uint32_t bandwidth = 0; // LoRa 125 kHz
mluis 0:91d1a7783bb9 2141
mluis 0:91d1a7783bb9 2142 TimerStop( &RxWindowTimer1 );
mluis 0:91d1a7783bb9 2143 LoRaMacEventFlags.Bits.RxSlot = 0;
mluis 0:91d1a7783bb9 2144
mluis 0:91d1a7783bb9 2145 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 2146 datarate = ChannelsDatarate - Rx1DrOffset;
mluis 0:91d1a7783bb9 2147 if( datarate < 0 )
mluis 0:91d1a7783bb9 2148 {
mluis 0:91d1a7783bb9 2149 datarate = DR_0;
mluis 0:91d1a7783bb9 2150 }
mluis 0:91d1a7783bb9 2151
mluis 0:91d1a7783bb9 2152 // For higher datarates, we increase the number of symbols generating a Rx Timeout
mluis 0:91d1a7783bb9 2153 if( datarate >= DR_3 )
mluis 0:91d1a7783bb9 2154 { // DR_6, DR_5, DR_4, DR_3
mluis 0:91d1a7783bb9 2155 symbTimeout = 8;
mluis 0:91d1a7783bb9 2156 }
mluis 0:91d1a7783bb9 2157 if( datarate == DR_6 )
mluis 0:91d1a7783bb9 2158 {// LoRa 250 kHz
mluis 0:91d1a7783bb9 2159 bandwidth = 1;
mluis 0:91d1a7783bb9 2160 }
mluis 0:91d1a7783bb9 2161 LoRaMacRxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
mluis 0:91d1a7783bb9 2162 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 0:91d1a7783bb9 2163 datarate = datarateOffsets[ChannelsDatarate][Rx1DrOffset];
mluis 0:91d1a7783bb9 2164 if( datarate < 0 )
mluis 0:91d1a7783bb9 2165 {
mluis 0:91d1a7783bb9 2166 datarate = DR_0;
mluis 0:91d1a7783bb9 2167 }
mluis 0:91d1a7783bb9 2168 // For higher datarates, we increase the number of symbols generating a Rx Timeout
mluis 0:91d1a7783bb9 2169 if( datarate > DR_0 )
mluis 0:91d1a7783bb9 2170 { // DR_1, DR_2, DR_3, DR_4, DR_8, DR_9, DR_10, DR_11, DR_12, DR_13
mluis 0:91d1a7783bb9 2171 symbTimeout = 8;
mluis 0:91d1a7783bb9 2172 }
mluis 0:91d1a7783bb9 2173 if( datarate >= DR_4 )
mluis 0:91d1a7783bb9 2174 {// LoRa 500 kHz
mluis 0:91d1a7783bb9 2175 bandwidth = 2;
mluis 0:91d1a7783bb9 2176 }
mluis 0:91d1a7783bb9 2177 //LoRaMacRxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
mluis 0:91d1a7783bb9 2178 LoRaMacRxWindowSetup( 923.3e6 + ( Channel % 8 ) * 600e3, datarate, bandwidth, symbTimeout, false );
mluis 0:91d1a7783bb9 2179 #else
mluis 0:91d1a7783bb9 2180 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 2181 #endif
mluis 0:91d1a7783bb9 2182 }
mluis 0:91d1a7783bb9 2183
mluis 0:91d1a7783bb9 2184 /*!
mluis 0:91d1a7783bb9 2185 * Function executed on second Rx window timer event
mluis 0:91d1a7783bb9 2186 */
mluis 0:91d1a7783bb9 2187 static void OnRxWindow2TimerEvent( void )
mluis 0:91d1a7783bb9 2188 {
mluis 0:91d1a7783bb9 2189 uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
mluis 0:91d1a7783bb9 2190 uint32_t bandwidth = 0; // LoRa 125 kHz
mluis 0:91d1a7783bb9 2191
mluis 0:91d1a7783bb9 2192 TimerStop( &RxWindowTimer2 );
mluis 0:91d1a7783bb9 2193 LoRaMacEventFlags.Bits.RxSlot = 1;
mluis 0:91d1a7783bb9 2194
mluis 0:91d1a7783bb9 2195 if( NodeAckRequested == true )
mluis 0:91d1a7783bb9 2196 {
mluis 0:91d1a7783bb9 2197 TimerSetValue( &AckTimeoutTimer, ACK_TIMEOUT + randr( -ACK_TIMEOUT_RND, ACK_TIMEOUT_RND ) );
mluis 0:91d1a7783bb9 2198 TimerStart( &AckTimeoutTimer );
mluis 0:91d1a7783bb9 2199 }
mluis 0:91d1a7783bb9 2200
mluis 0:91d1a7783bb9 2201 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 2202 // For higher datarates, we increase the number of symbols generating a Rx Timeout
mluis 0:91d1a7783bb9 2203 if( Rx2Channel.Datarate >= DR_3 )
mluis 0:91d1a7783bb9 2204 { // DR_6, DR_5, DR_4, DR_3
mluis 0:91d1a7783bb9 2205 symbTimeout = 8;
mluis 0:91d1a7783bb9 2206 }
mluis 0:91d1a7783bb9 2207 if( Rx2Channel.Datarate == DR_6 )
mluis 0:91d1a7783bb9 2208 {// LoRa 250 kHz
mluis 0:91d1a7783bb9 2209 bandwidth = 1;
mluis 0:91d1a7783bb9 2210 }
mluis 0:91d1a7783bb9 2211 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 0:91d1a7783bb9 2212 // For higher datarates, we increase the number of symbols generating a Rx Timeout
mluis 0:91d1a7783bb9 2213 if( Rx2Channel.Datarate > DR_0 )
mluis 0:91d1a7783bb9 2214 { // DR_1, DR_2, DR_3, DR_4, DR_8, DR_9, DR_10, DR_11, DR_12, DR_13
mluis 0:91d1a7783bb9 2215 symbTimeout = 8;
mluis 0:91d1a7783bb9 2216 }
mluis 0:91d1a7783bb9 2217 if( Rx2Channel.Datarate >= DR_4 )
mluis 0:91d1a7783bb9 2218 {// LoRa 500 kHz
mluis 0:91d1a7783bb9 2219 bandwidth = 2;
mluis 0:91d1a7783bb9 2220 }
mluis 0:91d1a7783bb9 2221 #else
mluis 0:91d1a7783bb9 2222 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 2223 #endif
mluis 0:91d1a7783bb9 2224 if( LoRaMacDeviceClass != CLASS_C )
mluis 0:91d1a7783bb9 2225 {
mluis 0:91d1a7783bb9 2226 LoRaMacRxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, false );
mluis 0:91d1a7783bb9 2227 }
mluis 0:91d1a7783bb9 2228 else
mluis 0:91d1a7783bb9 2229 {
mluis 0:91d1a7783bb9 2230 LoRaMacRxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, true );
mluis 0:91d1a7783bb9 2231 }
mluis 0:91d1a7783bb9 2232 }
mluis 0:91d1a7783bb9 2233
mluis 0:91d1a7783bb9 2234 /*!
mluis 0:91d1a7783bb9 2235 * Function executed on MacStateCheck timer event
mluis 0:91d1a7783bb9 2236 */
mluis 0:91d1a7783bb9 2237 static void OnMacStateCheckTimerEvent( void )
mluis 0:91d1a7783bb9 2238 {
mluis 0:91d1a7783bb9 2239 TimerStop( &MacStateCheckTimer );
mluis 0:91d1a7783bb9 2240
mluis 0:91d1a7783bb9 2241 if( LoRaMacEventFlags.Bits.Tx == 1 )
mluis 0:91d1a7783bb9 2242 {
mluis 0:91d1a7783bb9 2243 if( NodeAckRequested == false )
mluis 0:91d1a7783bb9 2244 {
mluis 0:91d1a7783bb9 2245 if( LoRaMacEventFlags.Bits.JoinAccept == true )
mluis 0:91d1a7783bb9 2246 {
mluis 0:91d1a7783bb9 2247 // Join messages aren't repeated automatically
mluis 0:91d1a7783bb9 2248 ChannelsNbRepCounter = ChannelsNbRep;
mluis 0:91d1a7783bb9 2249 UpLinkCounter = 0;
mluis 0:91d1a7783bb9 2250 }
mluis 0:91d1a7783bb9 2251 if( ChannelsNbRepCounter >= ChannelsNbRep )
mluis 0:91d1a7783bb9 2252 {
mluis 0:91d1a7783bb9 2253 ChannelsNbRepCounter = 0;
mluis 0:91d1a7783bb9 2254
mluis 0:91d1a7783bb9 2255 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 0:91d1a7783bb9 2256
mluis 0:91d1a7783bb9 2257 AdrAckCounter++;
mluis 0:91d1a7783bb9 2258 if( IsUpLinkCounterFixed == false )
mluis 0:91d1a7783bb9 2259 {
mluis 0:91d1a7783bb9 2260 UpLinkCounter++;
mluis 0:91d1a7783bb9 2261 }
mluis 0:91d1a7783bb9 2262
mluis 0:91d1a7783bb9 2263 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 0:91d1a7783bb9 2264 }
mluis 0:91d1a7783bb9 2265 else
mluis 0:91d1a7783bb9 2266 {
mluis 0:91d1a7783bb9 2267 LoRaMacEventFlags.Bits.Tx = 0;
mluis 0:91d1a7783bb9 2268 // Sends the same frame again
mluis 0:91d1a7783bb9 2269 if( LoRaMacSetNextChannel( ) == 0 )
mluis 0:91d1a7783bb9 2270 {
mluis 0:91d1a7783bb9 2271 LoRaMacSendFrameOnChannel( Channels[Channel] );
mluis 0:91d1a7783bb9 2272 }
mluis 0:91d1a7783bb9 2273 }
mluis 0:91d1a7783bb9 2274 }
mluis 0:91d1a7783bb9 2275
mluis 0:91d1a7783bb9 2276 if( LoRaMacEventFlags.Bits.Rx == 1 )
mluis 0:91d1a7783bb9 2277 {
mluis 0:91d1a7783bb9 2278 if( ( LoRaMacEventInfo.TxAckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) )
mluis 0:91d1a7783bb9 2279 {
mluis 0:91d1a7783bb9 2280 AckTimeoutRetry = false;
mluis 0:91d1a7783bb9 2281 if( IsUpLinkCounterFixed == false )
mluis 0:91d1a7783bb9 2282 {
mluis 0:91d1a7783bb9 2283 UpLinkCounter++;
mluis 0:91d1a7783bb9 2284 }
mluis 0:91d1a7783bb9 2285 LoRaMacEventInfo.TxNbRetries = AckTimeoutRetriesCounter;
mluis 0:91d1a7783bb9 2286
mluis 0:91d1a7783bb9 2287 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 0:91d1a7783bb9 2288 }
mluis 0:91d1a7783bb9 2289 }
mluis 0:91d1a7783bb9 2290
mluis 0:91d1a7783bb9 2291 if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & MAC_CHANNEL_CHECK ) == 0 ) )
mluis 0:91d1a7783bb9 2292 {
mluis 0:91d1a7783bb9 2293 AckTimeoutRetry = false;
mluis 0:91d1a7783bb9 2294 if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) )
mluis 0:91d1a7783bb9 2295 {
mluis 0:91d1a7783bb9 2296 AckTimeoutRetriesCounter++;
mluis 0:91d1a7783bb9 2297
mluis 0:91d1a7783bb9 2298 if( ( AckTimeoutRetriesCounter % 2 ) == 1 )
mluis 0:91d1a7783bb9 2299 {
mluis 0:91d1a7783bb9 2300 ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_MIN_DATARATE );
mluis 0:91d1a7783bb9 2301 }
mluis 0:91d1a7783bb9 2302 LoRaMacEventFlags.Bits.Tx = 0;
mluis 0:91d1a7783bb9 2303 // Sends the same frame again
mluis 0:91d1a7783bb9 2304 if( LoRaMacSetNextChannel( ) == 0 )
mluis 0:91d1a7783bb9 2305 {
mluis 0:91d1a7783bb9 2306 LoRaMacSendFrameOnChannel( Channels[Channel] );
mluis 0:91d1a7783bb9 2307 }
mluis 0:91d1a7783bb9 2308 }
mluis 0:91d1a7783bb9 2309 else
mluis 0:91d1a7783bb9 2310 {
mluis 0:91d1a7783bb9 2311 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 2312 // Re-enable default channels LC1, LC2, LC3
mluis 0:91d1a7783bb9 2313 ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
mluis 0:91d1a7783bb9 2314 #elif defined( USE_BAND_915 )
mluis 0:91d1a7783bb9 2315 // Re-enable default channels
mluis 0:91d1a7783bb9 2316 ChannelsMask[0] = 0xFFFF;
mluis 0:91d1a7783bb9 2317 ChannelsMask[1] = 0xFFFF;
mluis 0:91d1a7783bb9 2318 ChannelsMask[2] = 0xFFFF;
mluis 0:91d1a7783bb9 2319 ChannelsMask[3] = 0xFFFF;
mluis 0:91d1a7783bb9 2320 ChannelsMask[4] = 0x00FF;
mluis 0:91d1a7783bb9 2321 ChannelsMask[5] = 0x0000;
mluis 0:91d1a7783bb9 2322 #elif defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 2323 // Re-enable default channels
mluis 0:91d1a7783bb9 2324 ChannelsMask[0] = 0x00FF;
mluis 0:91d1a7783bb9 2325 ChannelsMask[1] = 0x0000;
mluis 0:91d1a7783bb9 2326 ChannelsMask[2] = 0x0000;
mluis 0:91d1a7783bb9 2327 ChannelsMask[3] = 0x0000;
mluis 0:91d1a7783bb9 2328 ChannelsMask[4] = 0x0001;
mluis 0:91d1a7783bb9 2329 ChannelsMask[5] = 0x0000;
mluis 0:91d1a7783bb9 2330 #else
mluis 0:91d1a7783bb9 2331 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 2332 #endif
mluis 0:91d1a7783bb9 2333 LoRaMacState &= ~MAC_TX_RUNNING;
mluis 0:91d1a7783bb9 2334
mluis 0:91d1a7783bb9 2335 LoRaMacEventInfo.TxAckReceived = false;
mluis 0:91d1a7783bb9 2336 LoRaMacEventInfo.TxNbRetries = AckTimeoutRetriesCounter;
mluis 0:91d1a7783bb9 2337 if( IsUpLinkCounterFixed == false )
mluis 0:91d1a7783bb9 2338 {
mluis 0:91d1a7783bb9 2339 UpLinkCounter++;
mluis 0:91d1a7783bb9 2340 }
mluis 0:91d1a7783bb9 2341 LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_OK;
mluis 0:91d1a7783bb9 2342 }
mluis 0:91d1a7783bb9 2343 }
mluis 0:91d1a7783bb9 2344 }
mluis 0:91d1a7783bb9 2345 // Handle reception for Class B and Class C
mluis 0:91d1a7783bb9 2346 if( ( LoRaMacState & MAC_RX ) == MAC_RX )
mluis 0:91d1a7783bb9 2347 {
mluis 0:91d1a7783bb9 2348 LoRaMacState &= ~MAC_RX;
mluis 0:91d1a7783bb9 2349 }
mluis 0:91d1a7783bb9 2350 if( LoRaMacState == MAC_IDLE )
mluis 0:91d1a7783bb9 2351 {
mluis 0:91d1a7783bb9 2352 LoRaMacNotify( &LoRaMacEventFlags, &LoRaMacEventInfo );
mluis 0:91d1a7783bb9 2353 }
mluis 0:91d1a7783bb9 2354 else
mluis 0:91d1a7783bb9 2355 {
mluis 0:91d1a7783bb9 2356 // Operation not finished restart timer
mluis 0:91d1a7783bb9 2357 TimerStart( &MacStateCheckTimer );
mluis 0:91d1a7783bb9 2358 }
mluis 0:91d1a7783bb9 2359 }
mluis 0:91d1a7783bb9 2360
mluis 0:91d1a7783bb9 2361 static void OnAckTimeoutTimerEvent( void )
mluis 0:91d1a7783bb9 2362 {
mluis 0:91d1a7783bb9 2363 TimerStop( &AckTimeoutTimer );
mluis 0:91d1a7783bb9 2364
mluis 0:91d1a7783bb9 2365 AckTimeoutRetry = true;
mluis 0:91d1a7783bb9 2366 LoRaMacState &= ~MAC_ACK_REQ;
mluis 0:91d1a7783bb9 2367 }
mluis 0:91d1a7783bb9 2368
mluis 0:91d1a7783bb9 2369 /*!
mluis 0:91d1a7783bb9 2370 * ============================================================================
mluis 0:91d1a7783bb9 2371 * = LoRaMac utility functions =
mluis 0:91d1a7783bb9 2372 * ============================================================================
mluis 0:91d1a7783bb9 2373 */
mluis 0:91d1a7783bb9 2374 static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate )
mluis 0:91d1a7783bb9 2375 {
mluis 0:91d1a7783bb9 2376 bool payloadSizeOk = false;
mluis 0:91d1a7783bb9 2377 uint8_t maxN = 0;
mluis 0:91d1a7783bb9 2378
mluis 0:91d1a7783bb9 2379 // Get the maximum payload length
mluis 0:91d1a7783bb9 2380 if( RepeaterSupport == true )
mluis 0:91d1a7783bb9 2381 {
mluis 0:91d1a7783bb9 2382 maxN = MaxPayloadOfDatarateRepeater[datarate];
mluis 0:91d1a7783bb9 2383 }
mluis 0:91d1a7783bb9 2384 else
mluis 0:91d1a7783bb9 2385 {
mluis 0:91d1a7783bb9 2386 maxN = MaxPayloadOfDatarate[datarate];
mluis 0:91d1a7783bb9 2387 }
mluis 0:91d1a7783bb9 2388
mluis 0:91d1a7783bb9 2389 // Validation of the application payload size
mluis 0:91d1a7783bb9 2390 if( lenN <= maxN )
mluis 0:91d1a7783bb9 2391 {
mluis 0:91d1a7783bb9 2392 payloadSizeOk = true;
mluis 0:91d1a7783bb9 2393 }
mluis 0:91d1a7783bb9 2394
mluis 0:91d1a7783bb9 2395 return payloadSizeOk;
mluis 0:91d1a7783bb9 2396 }
mluis 0:91d1a7783bb9 2397
mluis 0:91d1a7783bb9 2398 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 2399 static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask )
mluis 0:91d1a7783bb9 2400 {
mluis 0:91d1a7783bb9 2401 uint8_t nb125kHzChannels = 0;
mluis 0:91d1a7783bb9 2402
mluis 0:91d1a7783bb9 2403 for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
mluis 0:91d1a7783bb9 2404 {
mluis 0:91d1a7783bb9 2405 for( uint8_t j = 0; j < 16; j++ )
mluis 0:91d1a7783bb9 2406 {// Verify if the channel is active
mluis 0:91d1a7783bb9 2407 if( ( channelsMask[k] & ( 1 << j ) ) == ( 1 << j ) )
mluis 0:91d1a7783bb9 2408 {
mluis 0:91d1a7783bb9 2409 nb125kHzChannels++;
mluis 0:91d1a7783bb9 2410 }
mluis 0:91d1a7783bb9 2411 }
mluis 0:91d1a7783bb9 2412 }
mluis 0:91d1a7783bb9 2413
mluis 0:91d1a7783bb9 2414 return nb125kHzChannels;
mluis 0:91d1a7783bb9 2415 }
mluis 0:91d1a7783bb9 2416 #endif
mluis 0:91d1a7783bb9 2417
mluis 0:91d1a7783bb9 2418 static int8_t LimitTxPower( int8_t txPower )
mluis 0:91d1a7783bb9 2419 {
mluis 0:91d1a7783bb9 2420 int8_t resultTxPower = txPower;
mluis 0:91d1a7783bb9 2421 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 2422 if( ( ChannelsDatarate == DR_4 ) ||
mluis 0:91d1a7783bb9 2423 ( ( ChannelsDatarate >= DR_8 ) && ( ChannelsDatarate <= DR_13 ) ) )
mluis 0:91d1a7783bb9 2424 {// Limit tx power to max 26dBm
mluis 0:91d1a7783bb9 2425 resultTxPower = MAX( txPower, TX_POWER_26_DBM );
mluis 0:91d1a7783bb9 2426 }
mluis 0:91d1a7783bb9 2427 else
mluis 0:91d1a7783bb9 2428 {
mluis 0:91d1a7783bb9 2429 if( CountNbEnabled125kHzChannels( ChannelsMask ) < 50 )
mluis 0:91d1a7783bb9 2430 {// Limit tx power to max 21dBm
mluis 0:91d1a7783bb9 2431 resultTxPower = MAX( txPower, TX_POWER_20_DBM );
mluis 0:91d1a7783bb9 2432 }
mluis 0:91d1a7783bb9 2433 }
mluis 0:91d1a7783bb9 2434 #endif
mluis 0:91d1a7783bb9 2435 return resultTxPower;
mluis 0:91d1a7783bb9 2436 }
mluis 0:91d1a7783bb9 2437
mluis 0:91d1a7783bb9 2438 void LoRaMacChannelRemove( uint8_t id )
mluis 0:91d1a7783bb9 2439 {
mluis 0:91d1a7783bb9 2440 if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
mluis 0:91d1a7783bb9 2441 {
mluis 0:91d1a7783bb9 2442 return;
mluis 0:91d1a7783bb9 2443 }
mluis 0:91d1a7783bb9 2444 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 0:91d1a7783bb9 2445 if( id < 64 )
mluis 0:91d1a7783bb9 2446 {
mluis 0:91d1a7783bb9 2447 if( CountNbEnabled125kHzChannels( ChannelsMask ) <= 6 )
mluis 0:91d1a7783bb9 2448 {
mluis 0:91d1a7783bb9 2449 return;
mluis 0:91d1a7783bb9 2450 }
mluis 0:91d1a7783bb9 2451 }
mluis 0:91d1a7783bb9 2452 #else
mluis 0:91d1a7783bb9 2453 if( id < 3 )
mluis 0:91d1a7783bb9 2454 {
mluis 0:91d1a7783bb9 2455 return;
mluis 0:91d1a7783bb9 2456 }
mluis 0:91d1a7783bb9 2457 #endif
mluis 0:91d1a7783bb9 2458
mluis 0:91d1a7783bb9 2459 uint8_t index = 0;
mluis 0:91d1a7783bb9 2460 index = id / 16;
mluis 0:91d1a7783bb9 2461
mluis 0:91d1a7783bb9 2462 if( ( index > 4 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
mluis 0:91d1a7783bb9 2463 {
mluis 0:91d1a7783bb9 2464 return;
mluis 0:91d1a7783bb9 2465 }
mluis 0:91d1a7783bb9 2466
mluis 0:91d1a7783bb9 2467 // Deactivate channel
mluis 0:91d1a7783bb9 2468 ChannelsMask[index] &= ~( 1 << ( id % 16 ) );
mluis 0:91d1a7783bb9 2469
mluis 0:91d1a7783bb9 2470 return;
mluis 0:91d1a7783bb9 2471 }
mluis 0:91d1a7783bb9 2472
mluis 0:91d1a7783bb9 2473 /*!
mluis 0:91d1a7783bb9 2474 * ============================================================================
mluis 0:91d1a7783bb9 2475 * = LoRaMac setup functions =
mluis 0:91d1a7783bb9 2476 * ============================================================================
mluis 0:91d1a7783bb9 2477 */
mluis 0:91d1a7783bb9 2478 void LoRaMacSetDeviceClass( DeviceClass_t deviceClass )
mluis 0:91d1a7783bb9 2479 {
mluis 0:91d1a7783bb9 2480 LoRaMacDeviceClass = deviceClass;
mluis 0:91d1a7783bb9 2481 }
mluis 0:91d1a7783bb9 2482
mluis 0:91d1a7783bb9 2483 void LoRaMacSetPublicNetwork( bool enable )
mluis 0:91d1a7783bb9 2484 {
mluis 0:91d1a7783bb9 2485 PublicNetwork = enable;
mluis 0:91d1a7783bb9 2486 Radio.SetModem( MODEM_LORA );
mluis 0:91d1a7783bb9 2487 if( PublicNetwork == true )
mluis 0:91d1a7783bb9 2488 {
mluis 0:91d1a7783bb9 2489 // Change LoRa modem SyncWord
mluis 0:91d1a7783bb9 2490 Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD );
mluis 0:91d1a7783bb9 2491 }
mluis 0:91d1a7783bb9 2492 else
mluis 0:91d1a7783bb9 2493 {
mluis 0:91d1a7783bb9 2494 // Change LoRa modem SyncWord
mluis 0:91d1a7783bb9 2495 Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD );
mluis 0:91d1a7783bb9 2496 }
mluis 0:91d1a7783bb9 2497 }
mluis 0:91d1a7783bb9 2498
mluis 0:91d1a7783bb9 2499 void LoRaMacSetChannel( uint8_t id, ChannelParams_t params )
mluis 0:91d1a7783bb9 2500 {
mluis 0:91d1a7783bb9 2501 params.Band = 0;
mluis 0:91d1a7783bb9 2502 Channels[id] = params;
mluis 0:91d1a7783bb9 2503 // Activate the newly created channel
mluis 0:91d1a7783bb9 2504 if( id < 16 )
mluis 0:91d1a7783bb9 2505 {
mluis 0:91d1a7783bb9 2506 ChannelsMask[0] |= 1 << id;
mluis 0:91d1a7783bb9 2507 }
mluis 0:91d1a7783bb9 2508 else if( id < 32 )
mluis 0:91d1a7783bb9 2509 {
mluis 0:91d1a7783bb9 2510 ChannelsMask[1] |= 1 << ( id - 16 );
mluis 0:91d1a7783bb9 2511 }
mluis 0:91d1a7783bb9 2512 else if( id < 48 )
mluis 0:91d1a7783bb9 2513 {
mluis 0:91d1a7783bb9 2514 ChannelsMask[2] |= 1 << ( id - 32 );
mluis 0:91d1a7783bb9 2515 }
mluis 0:91d1a7783bb9 2516 else if( id < 64 )
mluis 0:91d1a7783bb9 2517 {
mluis 0:91d1a7783bb9 2518 ChannelsMask[3] |= 1 << ( id - 48 );
mluis 0:91d1a7783bb9 2519 }
mluis 0:91d1a7783bb9 2520 else if( id < 72 )
mluis 0:91d1a7783bb9 2521 {
mluis 0:91d1a7783bb9 2522 ChannelsMask[4] |= 1 << ( id - 64 );
mluis 0:91d1a7783bb9 2523 }
mluis 0:91d1a7783bb9 2524 else
mluis 0:91d1a7783bb9 2525 {
mluis 0:91d1a7783bb9 2526 // Don't activate the channel
mluis 0:91d1a7783bb9 2527 }
mluis 0:91d1a7783bb9 2528 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 )
mluis 0:91d1a7783bb9 2529 Channels[id].Band = 0; // 1% duty cycle on EU433 and CN780 bands
mluis 0:91d1a7783bb9 2530 #elif defined( USE_BAND_868 )
mluis 0:91d1a7783bb9 2531 if( ( Channels[id].Frequency >= 865000000 ) && ( Channels[id].Frequency <= 868000000 ) )
mluis 0:91d1a7783bb9 2532 {
mluis 0:91d1a7783bb9 2533 if( Channels[id].Band != BAND_G1_0 )
mluis 0:91d1a7783bb9 2534 {
mluis 0:91d1a7783bb9 2535 Channels[id].Band = BAND_G1_0;
mluis 0:91d1a7783bb9 2536 }
mluis 0:91d1a7783bb9 2537 }
mluis 0:91d1a7783bb9 2538 else if( ( Channels[id].Frequency > 868000000 ) && ( Channels[id].Frequency <= 868600000 ) )
mluis 0:91d1a7783bb9 2539 {
mluis 0:91d1a7783bb9 2540 if( Channels[id].Band != BAND_G1_1 )
mluis 0:91d1a7783bb9 2541 {
mluis 0:91d1a7783bb9 2542 Channels[id].Band = BAND_G1_1;
mluis 0:91d1a7783bb9 2543 }
mluis 0:91d1a7783bb9 2544 }
mluis 0:91d1a7783bb9 2545 else if( ( Channels[id].Frequency >= 868700000 ) && ( Channels[id].Frequency <= 869200000 ) )
mluis 0:91d1a7783bb9 2546 {
mluis 0:91d1a7783bb9 2547 if( Channels[id].Band != BAND_G1_2 )
mluis 0:91d1a7783bb9 2548 {
mluis 0:91d1a7783bb9 2549 Channels[id].Band = BAND_G1_2;
mluis 0:91d1a7783bb9 2550 }
mluis 0:91d1a7783bb9 2551 }
mluis 0:91d1a7783bb9 2552 else if( ( Channels[id].Frequency >= 869400000 ) && ( Channels[id].Frequency <= 869650000 ) )
mluis 0:91d1a7783bb9 2553 {
mluis 0:91d1a7783bb9 2554 if( Channels[id].Band != BAND_G1_3 )
mluis 0:91d1a7783bb9 2555 {
mluis 0:91d1a7783bb9 2556 Channels[id].Band = BAND_G1_3;
mluis 0:91d1a7783bb9 2557 }
mluis 0:91d1a7783bb9 2558 }
mluis 0:91d1a7783bb9 2559 else if( ( Channels[id].Frequency >= 869700000 ) && ( Channels[id].Frequency <= 870000000 ) )
mluis 0:91d1a7783bb9 2560 {
mluis 0:91d1a7783bb9 2561 if( Channels[id].Band != BAND_G1_4 )
mluis 0:91d1a7783bb9 2562 {
mluis 0:91d1a7783bb9 2563 Channels[id].Band = BAND_G1_4;
mluis 0:91d1a7783bb9 2564 }
mluis 0:91d1a7783bb9 2565 }
mluis 0:91d1a7783bb9 2566 else
mluis 0:91d1a7783bb9 2567 {
mluis 0:91d1a7783bb9 2568 Channels[id].Frequency = 0;
mluis 0:91d1a7783bb9 2569 Channels[id].DrRange.Value = 0;
mluis 0:91d1a7783bb9 2570 }
mluis 0:91d1a7783bb9 2571 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
mluis 0:91d1a7783bb9 2572 Channels[id].Band = 0; // No duty cycle on US915 band
mluis 0:91d1a7783bb9 2573 #else
mluis 0:91d1a7783bb9 2574 #error "Please define a frequency band in the compiler options."
mluis 0:91d1a7783bb9 2575 #endif
mluis 0:91d1a7783bb9 2576 // Check if it is a valid channel
mluis 0:91d1a7783bb9 2577 if( Channels[id].Frequency == 0 )
mluis 0:91d1a7783bb9 2578 {
mluis 0:91d1a7783bb9 2579 LoRaMacChannelRemove( id );
mluis 0:91d1a7783bb9 2580 }
mluis 0:91d1a7783bb9 2581 }
mluis 0:91d1a7783bb9 2582
mluis 0:91d1a7783bb9 2583 void LoRaMacSetRx2Channel( Rx2ChannelParams_t param )
mluis 0:91d1a7783bb9 2584 {
mluis 0:91d1a7783bb9 2585 Rx2Channel = param;
mluis 0:91d1a7783bb9 2586 }
mluis 0:91d1a7783bb9 2587
mluis 0:91d1a7783bb9 2588 void LoRaMacSetChannelsTxPower( int8_t txPower )
mluis 0:91d1a7783bb9 2589 {
mluis 0:91d1a7783bb9 2590 if( ( txPower >= LORAMAC_MAX_TX_POWER ) &&
mluis 0:91d1a7783bb9 2591 ( txPower <= LORAMAC_MIN_TX_POWER ) )
mluis 0:91d1a7783bb9 2592 {
mluis 0:91d1a7783bb9 2593 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 2594 int8_t txPwr = LimitTxPower( txPower );
mluis 0:91d1a7783bb9 2595 if( txPwr == txPower )
mluis 0:91d1a7783bb9 2596 {
mluis 0:91d1a7783bb9 2597 ChannelsTxPower = txPower;
mluis 0:91d1a7783bb9 2598 }
mluis 0:91d1a7783bb9 2599 #else
mluis 0:91d1a7783bb9 2600 ChannelsTxPower = txPower;
mluis 0:91d1a7783bb9 2601 #endif
mluis 0:91d1a7783bb9 2602 }
mluis 0:91d1a7783bb9 2603 }
mluis 0:91d1a7783bb9 2604
mluis 0:91d1a7783bb9 2605 void LoRaMacSetChannelsDatarate( int8_t datarate )
mluis 0:91d1a7783bb9 2606 {
mluis 0:91d1a7783bb9 2607 ChannelsDefaultDatarate = ChannelsDatarate = datarate;
mluis 0:91d1a7783bb9 2608 }
mluis 0:91d1a7783bb9 2609
mluis 0:91d1a7783bb9 2610 void LoRaMacSetChannelsMask( uint16_t *mask )
mluis 0:91d1a7783bb9 2611 {
mluis 0:91d1a7783bb9 2612 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
mluis 0:91d1a7783bb9 2613 if( ( CountNbEnabled125kHzChannels( mask ) < 6 ) &&
mluis 0:91d1a7783bb9 2614 ( CountNbEnabled125kHzChannels( mask ) > 0 ) )
mluis 0:91d1a7783bb9 2615 {
mluis 0:91d1a7783bb9 2616
mluis 0:91d1a7783bb9 2617 }
mluis 0:91d1a7783bb9 2618 else
mluis 0:91d1a7783bb9 2619 {
mluis 0:91d1a7783bb9 2620 LoRaMacMemCpy( (uint8_t* ) mask,
mluis 0:91d1a7783bb9 2621 ( uint8_t* ) ChannelsMask, 10 );
mluis 0:91d1a7783bb9 2622 }
mluis 0:91d1a7783bb9 2623 #else
mluis 0:91d1a7783bb9 2624 if( ( mask[0] & 0x0007 ) != 0x0007 )
mluis 0:91d1a7783bb9 2625 {
mluis 0:91d1a7783bb9 2626 }
mluis 0:91d1a7783bb9 2627 else
mluis 0:91d1a7783bb9 2628 {
mluis 0:91d1a7783bb9 2629 LoRaMacMemCpy( ( uint8_t* ) mask,
mluis 0:91d1a7783bb9 2630 ( uint8_t* ) ChannelsMask, 2 );
mluis 0:91d1a7783bb9 2631 }
mluis 0:91d1a7783bb9 2632 #endif
mluis 0:91d1a7783bb9 2633 }
mluis 0:91d1a7783bb9 2634
mluis 0:91d1a7783bb9 2635 void LoRaMacSetChannelsNbRep( uint8_t nbRep )
mluis 0:91d1a7783bb9 2636 {
mluis 0:91d1a7783bb9 2637 if( nbRep < 1 )
mluis 0:91d1a7783bb9 2638 {
mluis 0:91d1a7783bb9 2639 nbRep = 1;
mluis 0:91d1a7783bb9 2640 }
mluis 0:91d1a7783bb9 2641 if( nbRep > 15 )
mluis 0:91d1a7783bb9 2642 {
mluis 0:91d1a7783bb9 2643 nbRep = 15;
mluis 0:91d1a7783bb9 2644 }
mluis 0:91d1a7783bb9 2645 ChannelsNbRep = nbRep;
mluis 0:91d1a7783bb9 2646 }
mluis 0:91d1a7783bb9 2647
mluis 0:91d1a7783bb9 2648 void LoRaMacSetMaxRxWindow( uint32_t delay )
mluis 0:91d1a7783bb9 2649 {
mluis 0:91d1a7783bb9 2650 MaxRxWindow = delay;
mluis 0:91d1a7783bb9 2651 }
mluis 0:91d1a7783bb9 2652
mluis 0:91d1a7783bb9 2653 void LoRaMacSetReceiveDelay1( uint32_t delay )
mluis 0:91d1a7783bb9 2654 {
mluis 0:91d1a7783bb9 2655 ReceiveDelay1 = delay;
mluis 0:91d1a7783bb9 2656 }
mluis 0:91d1a7783bb9 2657
mluis 0:91d1a7783bb9 2658 void LoRaMacSetReceiveDelay2( uint32_t delay )
mluis 0:91d1a7783bb9 2659 {
mluis 0:91d1a7783bb9 2660 ReceiveDelay2 = delay;
mluis 0:91d1a7783bb9 2661 }
mluis 0:91d1a7783bb9 2662
mluis 0:91d1a7783bb9 2663 void LoRaMacSetJoinAcceptDelay1( uint32_t delay )
mluis 0:91d1a7783bb9 2664 {
mluis 0:91d1a7783bb9 2665 JoinAcceptDelay1 = delay;
mluis 0:91d1a7783bb9 2666 }
mluis 0:91d1a7783bb9 2667
mluis 0:91d1a7783bb9 2668 void LoRaMacSetJoinAcceptDelay2( uint32_t delay )
mluis 0:91d1a7783bb9 2669 {
mluis 0:91d1a7783bb9 2670 JoinAcceptDelay2 = delay;
mluis 0:91d1a7783bb9 2671 }
mluis 0:91d1a7783bb9 2672
mluis 0:91d1a7783bb9 2673 uint32_t LoRaMacGetUpLinkCounter( void )
mluis 0:91d1a7783bb9 2674 {
mluis 0:91d1a7783bb9 2675 return UpLinkCounter;
mluis 0:91d1a7783bb9 2676 }
mluis 0:91d1a7783bb9 2677
mluis 0:91d1a7783bb9 2678 uint32_t LoRaMacGetDownLinkCounter( void )
mluis 0:91d1a7783bb9 2679 {
mluis 0:91d1a7783bb9 2680 return DownLinkCounter;
mluis 0:91d1a7783bb9 2681 }
mluis 0:91d1a7783bb9 2682
mluis 0:91d1a7783bb9 2683 /*!
mluis 0:91d1a7783bb9 2684 * ============================================================================
mluis 0:91d1a7783bb9 2685 * = LoRaMac test functions =
mluis 0:91d1a7783bb9 2686 * ============================================================================
mluis 0:91d1a7783bb9 2687 */
mluis 0:91d1a7783bb9 2688 void LoRaMacTestSetDutyCycleOn( bool enable )
mluis 0:91d1a7783bb9 2689 {
mluis 0:91d1a7783bb9 2690 DutyCycleOn = enable;
mluis 0:91d1a7783bb9 2691 }
mluis 0:91d1a7783bb9 2692
mluis 0:91d1a7783bb9 2693 void LoRaMacTestRxWindowsOn( bool enable )
mluis 0:91d1a7783bb9 2694 {
mluis 0:91d1a7783bb9 2695 IsRxWindowsEnabled = enable;
mluis 0:91d1a7783bb9 2696 }
mluis 0:91d1a7783bb9 2697
mluis 0:91d1a7783bb9 2698 void LoRaMacTestSetMic( uint16_t upLinkCounter )
mluis 0:91d1a7783bb9 2699 {
mluis 0:91d1a7783bb9 2700 UpLinkCounter = upLinkCounter;
mluis 0:91d1a7783bb9 2701 IsUpLinkCounterFixed = true;
mluis 0:91d1a7783bb9 2702 }