this is avaiable project

Dependents:   LoRaWAN_MBED

Fork of LoRaMacLib by LoRa All

Committer:
pzheng
Date:
Mon Nov 30 10:00:41 2015 +0000
Revision:
9:b3ddbad8c5e3
Parent:
8:19a3b4a82c69
Child:
11:29686c1ac910
This is a available project using 433MHz frequency made by pzheng in semtech 20151130

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