LoRaWAN MAC layer implementation

Dependents:   LoRaWAN-demo-72_tjm LoRaWAN-demo-72_jlc LoRaWAN-demo-elmo frdm_LoRa_Connect_Woodstream_Demo_tjm ... more

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

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

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

The example projects are:

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

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

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


EU868

board.h

#define USE_BAND_868


US915

board.h

#define USE_BAND_915


US915 - Hybrid

board.h

#define USE_BAND_915_HYBRID


CN780

board.h

#define USE_BAND_780


EU433

board.h

#define USE_BAND_433
Committer:
mluis
Date:
Mon Mar 14 09:09:54 2016 +0000
Revision:
3:b9d87593a8ae
Parent:
2:14a5d6ad92d5
Child:
4:37c12dbc8dc7
Synchronized with https://github.com/Lora-net/LoRaMac-node git revision 5a25e2f1593bc382200e848e6db967d1c4550021

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