Espotel / Mbed 2 deprecated LoRaWAN_Semtech_stack_v41

Dependencies:   SX1272lib mbed

Fork of LoRaWAN_Semtech_stack_v4.1 by Michal Leksinski

Committer:
mleksio
Date:
Wed Dec 16 14:25:16 2015 +0000
Revision:
0:c58229885f95
Child:
1:2be292bd43f9
first commit

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