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

