Semtech stack for ELMO - ver. 4.1.0.

Dependencies:   SX1272lib mbed

Fork of LoRaWAN_Semtech_stack_v4.1 by Michal Leksinski

Committer:
mleksio
Date:
Fri Apr 22 07:37:04 2016 +0000
Revision:
5:cbb921e2a03b
Parent:
4:0aa5d153c316
Removed unused files.

Who changed what in which revision?

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