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:
Mon Nov 23 10:09:43 2015 +0000
Revision:
1:91e4e6c60d1e
Parent:
0:91d1a7783bb9
Child:
2:14a5d6ad92d5
Keep LoRaMac only related files in the library.; Updated files according to latest GitHub version

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