20171208

Fork of LoRaWAN-lib by Semtech

Committer:
mluis
Date:
Tue Oct 20 13:21:26 2015 +0000
Revision:
0:91d1a7783bb9
Child:
1:91e4e6c60d1e
Library creation synchronized with GitHub LoRaMac-node v3.4 (https://github.com/Lora-net/LoRaMac-node)

Who changed what in which revision?

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