Semtech / LoRaWAN-lib-dev

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

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

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

The example projects are:

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

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

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


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433
Committer:
mluis
Date:
Mon Apr 24 14:11:47 2017 +0000
Revision:
2:76f59096e3a7
Parent:
1:4820e04b066c
WARNING: API timings changed from micro-seconds to milliseconds; Synchronized with https://github.com/Lora-net/LoRaMac-node git revision c82a25f9c5cc746dc2be1f8ed7f76c3707975ab2; ;

Who changed what in which revision?

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