Example Tx Rx LoRa code for Multitech Conduit. Based on Semtech stack for ELMO - ver. 4.1.0.

Dependencies:   SX1272lib mbed

Committer:
Pasi
Date:
Tue Apr 19 21:48:58 2016 +0000
Revision:
6:71b489e70063
Parent:
5:be347c6040c1
Text tweaking

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