this is avaiable project

Dependents:   LoRaWAN_MBED

Fork of LoRaMacLib by LoRa All

Committer:
GregCr
Date:
Wed Aug 12 14:08:29 2015 +0000
Revision:
0:9be122c18509
Child:
1:0a272b37c6cd
First Implementation

Who changed what in which revision?

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