end node on synchronous star LoRa network.
Dependencies: SX127x sx12xx_hal TSL2561
radio chip selection
Radio chip driver is not included, allowing choice of radio device.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
if you're using SX1280, then import sx1280 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.
This project for use with LoRaWAN_singlechannel_gateway project.
Alternately gateway running on raspberry pi can be used as gateway.
LoRaWAN on single radio channel
Network description is at gateway project page. Synchronous star network.
Hardware Support
This project supports SX1276 and SX1272, sx126x kit, sx126x shield, and sx128x 2.4GHz. The ST board B-L072Z-LRWAN1 is also supported (TypeABZ module). When B-L072Z-LRWAN1
target is selected, TARGET_DISCO_L072CZ_LRWAN1
is defined by tools, allowing correct radio driver configuration for this platform. Alternately, any mbed board that can use LoRa radio shield board should work, but NUCLEO boards are tested.
End-node Unique ID
DevEUI is created from CPU serial number. AppEUI and AppKey are declared as software constants.
End-node Configuration
Data rate definition LORAMAC_DEFAULT_DATARATE
configured in LoRaMac-definitions.h
. See gateway project page for configuration of gateway.
LoRaWAN addressing is configured in Comissioning.h
; only OTA mode is functional.
Header file board/lora_config.h
, selects application layer options (i.e. sensors) to be compiled in.
Serial Interface
Serial port operates at 115200bps.
Application layer single_us915_main.cpp
User button triggers uplink (i.e. blue button on nucleo board), or jumper enables continuously sends repeated uplink packets. The MAC layer holds each uplink request until the allocated timeslot.
command | arguments | description |
---|---|---|
? | - | print available commands |
. (period) | - | print status (DevEUI, DevAddr, etc) |
ul | length integer | set payload length of test uplink packets |
sensor demo
Selected grove sensors may be plugged into SX1272 shield.
To enable, edit lora_config.h
to define SENSORS
.
Sensor connections on SX1272MB2xAS:
D8 D9: button | RX TX: (unused) | A3 A4: Rotary Angle Sensor |
D6 D7: RGB LED | SCL SDA: digital light sensor | A1 A2: Rotary Angle Sensor |
Digital input pin, state reported via uplink: PC8
Digital output pin, controlled via downlink: PC6
PWM out: PB_10
Jumper enables auto-repeated transmit: PC10
and PC12
on NUCLEO board, located on end of morpho headers nearby JP4.
mac/LoRaMacSingle.cpp@32:ac904adfc842, 2018-12-16 (annotated)
- Committer:
- dudmuck
- Date:
- Sun Dec 16 18:29:23 2018 +0000
- Revision:
- 32:ac904adfc842
- Parent:
- 31:6ed03f61af64
- Child:
- 33:bc0b6be19e07
ceil() requires argument type cast
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dudmuck | 0:8f0d0ae0a077 | 1 | /* |
dudmuck | 0:8f0d0ae0a077 | 2 | / _____) _ | | |
dudmuck | 0:8f0d0ae0a077 | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ |
dudmuck | 0:8f0d0ae0a077 | 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ |
dudmuck | 0:8f0d0ae0a077 | 5 | _____) ) ____| | | || |_| ____( (___| | | | |
dudmuck | 0:8f0d0ae0a077 | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| |
dudmuck | 0:8f0d0ae0a077 | 7 | (C)2013 Semtech |
dudmuck | 0:8f0d0ae0a077 | 8 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ |
dudmuck | 0:8f0d0ae0a077 | 9 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| |
dudmuck | 0:8f0d0ae0a077 | 10 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| |
dudmuck | 0:8f0d0ae0a077 | 11 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| |
dudmuck | 0:8f0d0ae0a077 | 12 | embedded.connectivity.solutions=============== |
dudmuck | 0:8f0d0ae0a077 | 13 | |
dudmuck | 0:8f0d0ae0a077 | 14 | Description: LoRa MAC layer implementation |
dudmuck | 0:8f0d0ae0a077 | 15 | |
dudmuck | 0:8f0d0ae0a077 | 16 | License: Revised BSD License, see LICENSE.TXT file include in the project |
dudmuck | 0:8f0d0ae0a077 | 17 | |
dudmuck | 0:8f0d0ae0a077 | 18 | */ |
dudmuck | 0:8f0d0ae0a077 | 19 | #include <math.h> |
dudmuck | 0:8f0d0ae0a077 | 20 | #include "board.h" |
Wayne Roberts |
29:ad409c68c0a6 | 21 | #include "radio.h" |
dudmuck | 0:8f0d0ae0a077 | 22 | |
dudmuck | 0:8f0d0ae0a077 | 23 | #include "LoRaMacCrypto.h" |
Wayne Roberts |
31:6ed03f61af64 | 24 | #include "LoRaMacSingle.h" |
dudmuck | 0:8f0d0ae0a077 | 25 | #include "LoRaMacTest.h" |
Wayne Roberts |
29:ad409c68c0a6 | 26 | #include "LowPowerTimeoutAbs.h" |
Wayne Roberts |
29:ad409c68c0a6 | 27 | |
Wayne Roberts |
29:ad409c68c0a6 | 28 | //DigitalOut pc2(PC_2); |
Wayne Roberts |
29:ad409c68c0a6 | 29 | #define BEACONS_MISSED_LIMIT 16 |
dudmuck | 16:915815632c1f | 30 | |
dudmuck | 0:8f0d0ae0a077 | 31 | #define PING_SLOT_RESOLUTION_us 30000 |
dudmuck | 0:8f0d0ae0a077 | 32 | |
Wayne Roberts |
29:ad409c68c0a6 | 33 | #define PREAMBLE_SYMBS 8 |
Wayne Roberts |
29:ad409c68c0a6 | 34 | |
Wayne Roberts |
29:ad409c68c0a6 | 35 | #define TARGET_PRECESSION_us 3000 |
Wayne Roberts |
29:ad409c68c0a6 | 36 | #define BEACON_RX_TIMEOUT_LOCKED_us 8000 |
Wayne Roberts |
29:ad409c68c0a6 | 37 | |
dudmuck | 0:8f0d0ae0a077 | 38 | /*! |
dudmuck | 0:8f0d0ae0a077 | 39 | * Maximum PHY layer payload size |
dudmuck | 0:8f0d0ae0a077 | 40 | */ |
dudmuck | 0:8f0d0ae0a077 | 41 | #define LORAMAC_PHY_MAXPAYLOAD 255 |
dudmuck | 0:8f0d0ae0a077 | 42 | |
dudmuck | 0:8f0d0ae0a077 | 43 | /*! |
dudmuck | 0:8f0d0ae0a077 | 44 | * Maximum MAC commands buffer size |
dudmuck | 0:8f0d0ae0a077 | 45 | */ |
dudmuck | 0:8f0d0ae0a077 | 46 | #define LORA_MAC_COMMAND_MAX_LENGTH 15 |
dudmuck | 0:8f0d0ae0a077 | 47 | |
Wayne Roberts |
29:ad409c68c0a6 | 48 | /*! radio timer started later by this much: */ |
Wayne Roberts |
29:ad409c68c0a6 | 49 | static volatile int lpt_offset; |
Wayne Roberts |
29:ad409c68c0a6 | 50 | |
Wayne Roberts |
29:ad409c68c0a6 | 51 | static volatile us_timestamp_t txDoneAt; |
dudmuck | 20:42839629a5dc | 52 | |
dudmuck | 0:8f0d0ae0a077 | 53 | /*! |
dudmuck | 0:8f0d0ae0a077 | 54 | * Device IEEE EUI |
dudmuck | 0:8f0d0ae0a077 | 55 | */ |
dudmuck | 0:8f0d0ae0a077 | 56 | static uint8_t *LoRaMacDevEui; |
dudmuck | 0:8f0d0ae0a077 | 57 | |
dudmuck | 0:8f0d0ae0a077 | 58 | /*! |
dudmuck | 0:8f0d0ae0a077 | 59 | * Application IEEE EUI |
dudmuck | 0:8f0d0ae0a077 | 60 | */ |
dudmuck | 0:8f0d0ae0a077 | 61 | static uint8_t *LoRaMacAppEui; |
dudmuck | 0:8f0d0ae0a077 | 62 | |
dudmuck | 0:8f0d0ae0a077 | 63 | /*! |
dudmuck | 0:8f0d0ae0a077 | 64 | * AES encryption/decryption cipher application key |
dudmuck | 0:8f0d0ae0a077 | 65 | */ |
dudmuck | 0:8f0d0ae0a077 | 66 | static uint8_t *LoRaMacAppKey; |
dudmuck | 0:8f0d0ae0a077 | 67 | |
dudmuck | 0:8f0d0ae0a077 | 68 | /*! |
dudmuck | 0:8f0d0ae0a077 | 69 | * AES encryption/decryption cipher network session key |
dudmuck | 0:8f0d0ae0a077 | 70 | */ |
dudmuck | 0:8f0d0ae0a077 | 71 | static uint8_t LoRaMacNwkSKey[] = |
dudmuck | 0:8f0d0ae0a077 | 72 | { |
dudmuck | 0:8f0d0ae0a077 | 73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
dudmuck | 0:8f0d0ae0a077 | 74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
dudmuck | 0:8f0d0ae0a077 | 75 | }; |
dudmuck | 0:8f0d0ae0a077 | 76 | |
dudmuck | 0:8f0d0ae0a077 | 77 | /*! |
dudmuck | 0:8f0d0ae0a077 | 78 | * AES encryption/decryption cipher application session key |
dudmuck | 0:8f0d0ae0a077 | 79 | */ |
dudmuck | 0:8f0d0ae0a077 | 80 | static uint8_t LoRaMacAppSKey[] = |
dudmuck | 0:8f0d0ae0a077 | 81 | { |
dudmuck | 0:8f0d0ae0a077 | 82 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
dudmuck | 0:8f0d0ae0a077 | 83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
dudmuck | 0:8f0d0ae0a077 | 84 | }; |
dudmuck | 0:8f0d0ae0a077 | 85 | |
dudmuck | 0:8f0d0ae0a077 | 86 | /*! |
dudmuck | 0:8f0d0ae0a077 | 87 | * Device nonce is a random value extracted by issuing a sequence of RSSI |
dudmuck | 0:8f0d0ae0a077 | 88 | * measurements |
dudmuck | 0:8f0d0ae0a077 | 89 | */ |
dudmuck | 0:8f0d0ae0a077 | 90 | static uint16_t LoRaMacDevNonce; |
dudmuck | 0:8f0d0ae0a077 | 91 | |
dudmuck | 0:8f0d0ae0a077 | 92 | /*! |
dudmuck | 0:8f0d0ae0a077 | 93 | * Network ID ( 3 bytes ) |
dudmuck | 0:8f0d0ae0a077 | 94 | */ |
dudmuck | 0:8f0d0ae0a077 | 95 | static uint32_t LoRaMacNetID; |
dudmuck | 0:8f0d0ae0a077 | 96 | |
dudmuck | 0:8f0d0ae0a077 | 97 | /*! |
dudmuck | 0:8f0d0ae0a077 | 98 | * Mote Address |
dudmuck | 0:8f0d0ae0a077 | 99 | */ |
dudmuck | 0:8f0d0ae0a077 | 100 | static uint32_t LoRaMacDevAddr; |
dudmuck | 0:8f0d0ae0a077 | 101 | |
dudmuck | 0:8f0d0ae0a077 | 102 | /*! |
dudmuck | 0:8f0d0ae0a077 | 103 | * Multicast channels linked list |
dudmuck | 0:8f0d0ae0a077 | 104 | */ |
dudmuck | 0:8f0d0ae0a077 | 105 | static MulticastParams_t *MulticastChannels = NULL; |
dudmuck | 0:8f0d0ae0a077 | 106 | |
dudmuck | 0:8f0d0ae0a077 | 107 | /*! |
dudmuck | 0:8f0d0ae0a077 | 108 | * Indicates if the node is connected to a private or public network |
dudmuck | 0:8f0d0ae0a077 | 109 | */ |
dudmuck | 0:8f0d0ae0a077 | 110 | static bool PublicNetwork; |
dudmuck | 0:8f0d0ae0a077 | 111 | |
Wayne Roberts |
29:ad409c68c0a6 | 112 | uint8_t tx_buf_len; |
Wayne Roberts |
29:ad409c68c0a6 | 113 | |
Wayne Roberts |
29:ad409c68c0a6 | 114 | static uint8_t rxFRMPayload[244]; |
dudmuck | 0:8f0d0ae0a077 | 115 | |
dudmuck | 0:8f0d0ae0a077 | 116 | /*! |
dudmuck | 0:8f0d0ae0a077 | 117 | * LoRaMAC frame counter. Each time a packet is sent the counter is incremented. |
dudmuck | 0:8f0d0ae0a077 | 118 | * Only the 16 LSB bits are sent |
dudmuck | 0:8f0d0ae0a077 | 119 | */ |
dudmuck | 0:8f0d0ae0a077 | 120 | static uint32_t UpLinkCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 121 | |
dudmuck | 0:8f0d0ae0a077 | 122 | /*! |
dudmuck | 0:8f0d0ae0a077 | 123 | * LoRaMAC frame counter. Each time a packet is received the counter is incremented. |
dudmuck | 0:8f0d0ae0a077 | 124 | * Only the 16 LSB bits are received |
dudmuck | 0:8f0d0ae0a077 | 125 | */ |
dudmuck | 0:8f0d0ae0a077 | 126 | static uint32_t DownLinkCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 127 | |
dudmuck | 0:8f0d0ae0a077 | 128 | /*! |
dudmuck | 0:8f0d0ae0a077 | 129 | * IsPacketCounterFixed enables the MIC field tests by fixing the |
dudmuck | 0:8f0d0ae0a077 | 130 | * UpLinkCounter value |
dudmuck | 0:8f0d0ae0a077 | 131 | */ |
dudmuck | 16:915815632c1f | 132 | //static bool IsUpLinkCounterFixed = false; |
dudmuck | 0:8f0d0ae0a077 | 133 | |
dudmuck | 0:8f0d0ae0a077 | 134 | /*! |
dudmuck | 0:8f0d0ae0a077 | 135 | * Used for test purposes. Disables the opening of the reception windows. |
dudmuck | 0:8f0d0ae0a077 | 136 | */ |
dudmuck | 0:8f0d0ae0a077 | 137 | static bool IsRxWindowsEnabled = true; |
Wayne Roberts |
29:ad409c68c0a6 | 138 | LowPowerTimeoutAbs _rx_timeout; |
Wayne Roberts |
29:ad409c68c0a6 | 139 | volatile us_timestamp_t _rx_timeout_setAt; |
dudmuck | 0:8f0d0ae0a077 | 140 | |
dudmuck | 0:8f0d0ae0a077 | 141 | /*! |
dudmuck | 0:8f0d0ae0a077 | 142 | * Indicates if the MAC layer wants to send MAC commands |
dudmuck | 0:8f0d0ae0a077 | 143 | */ |
dudmuck | 0:8f0d0ae0a077 | 144 | static bool MacCommandsInNextTx = false; |
dudmuck | 0:8f0d0ae0a077 | 145 | |
dudmuck | 0:8f0d0ae0a077 | 146 | /*! |
dudmuck | 0:8f0d0ae0a077 | 147 | * Contains the current MacCommandsBuffer index |
dudmuck | 0:8f0d0ae0a077 | 148 | */ |
dudmuck | 0:8f0d0ae0a077 | 149 | static uint8_t MacCommandsBufferIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 150 | |
dudmuck | 0:8f0d0ae0a077 | 151 | /*! |
dudmuck | 0:8f0d0ae0a077 | 152 | * Contains the current MacCommandsBuffer index for MAC commands to repeat |
dudmuck | 0:8f0d0ae0a077 | 153 | */ |
dudmuck | 0:8f0d0ae0a077 | 154 | static uint8_t MacCommandsBufferToRepeatIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 155 | |
dudmuck | 0:8f0d0ae0a077 | 156 | /*! |
dudmuck | 0:8f0d0ae0a077 | 157 | * Buffer containing the MAC layer commands |
dudmuck | 0:8f0d0ae0a077 | 158 | */ |
dudmuck | 0:8f0d0ae0a077 | 159 | static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH]; |
dudmuck | 0:8f0d0ae0a077 | 160 | |
dudmuck | 0:8f0d0ae0a077 | 161 | /*! |
dudmuck | 0:8f0d0ae0a077 | 162 | * Buffer containing the MAC layer commands which must be repeated |
dudmuck | 0:8f0d0ae0a077 | 163 | */ |
dudmuck | 0:8f0d0ae0a077 | 164 | static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH]; |
dudmuck | 0:8f0d0ae0a077 | 165 | |
dudmuck | 18:9ac71c0eb70d | 166 | #define BEACON_SIZE 6 /* bytes */ |
dudmuck | 18:9ac71c0eb70d | 167 | #define BEACON_CHANNEL_DR LORAMAC_DEFAULT_DATARATE |
dudmuck | 18:9ac71c0eb70d | 168 | |
dudmuck | 18:9ac71c0eb70d | 169 | |
Wayne Roberts |
29:ad409c68c0a6 | 170 | #ifdef SX128x_H |
Wayne Roberts |
29:ad409c68c0a6 | 171 | // 0 1 2 3 4 5 6 7 |
Wayne Roberts |
29:ad409c68c0a6 | 172 | const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 6, 5 }; |
Wayne Roberts |
29:ad409c68c0a6 | 173 | #define SF_FROM_DR0 12 /* DR0 is sf12 */ |
Wayne Roberts |
29:ad409c68c0a6 | 174 | #define SF_FROM_DR1 11 /* DR1 is sf11 */ |
Wayne Roberts |
29:ad409c68c0a6 | 175 | #define SF_FROM_DR2 10 /* DR2 is sf10 */ |
Wayne Roberts |
29:ad409c68c0a6 | 176 | #define SF_FROM_DR3 9 /* DR3 is sf9 */ |
Wayne Roberts |
29:ad409c68c0a6 | 177 | #define SF_FROM_DR4 8 /* DR4 is sf8 */ |
Wayne Roberts |
29:ad409c68c0a6 | 178 | #define SF_FROM_DR5 7 /* DR5 is sf7 */ |
Wayne Roberts |
29:ad409c68c0a6 | 179 | #define SF_FROM_DR6 6 /* DR5 is sf6 */ |
Wayne Roberts |
29:ad409c68c0a6 | 180 | #define SF_FROM_DR7 5 /* DR7 is sf5 */ |
Wayne Roberts |
29:ad409c68c0a6 | 181 | |
Wayne Roberts |
29:ad409c68c0a6 | 182 | |
Wayne Roberts |
29:ad409c68c0a6 | 183 | const int8_t TxPowers[] = { 12, 5 }; |
Wayne Roberts |
29:ad409c68c0a6 | 184 | #define LORAMAC_FIRST_CHANNEL ( (uint32_t)2486.9e6 ) |
Wayne Roberts |
29:ad409c68c0a6 | 185 | #define LORAMAC_STEPWIDTH_CHANNEL ( (uint32_t)300e3 ) |
Wayne Roberts |
30:1c35c4f56e50 | 186 | #define LORA_MAX_NB_CHANNELS 8 |
Wayne Roberts |
29:ad409c68c0a6 | 187 | |
Wayne Roberts |
29:ad409c68c0a6 | 188 | #define LORA_BANDWIDTH_KHZ 200 |
Wayne Roberts |
29:ad409c68c0a6 | 189 | |
Wayne Roberts |
29:ad409c68c0a6 | 190 | /* |
Wayne Roberts |
29:ad409c68c0a6 | 191 | #define STR_HELPER(x) #x |
Wayne Roberts |
29:ad409c68c0a6 | 192 | #define STR(x) STR_HELPER(x) |
Wayne Roberts |
29:ad409c68c0a6 | 193 | #pragma message "content of BEACON_RXDONE_LATENCY_us: " STR(BEACON_RXDONE_LATENCY_us) |
Wayne Roberts |
29:ad409c68c0a6 | 194 | */ |
Wayne Roberts |
29:ad409c68c0a6 | 195 | |
Wayne Roberts |
29:ad409c68c0a6 | 196 | /* end sx1280 */ |
Wayne Roberts |
29:ad409c68c0a6 | 197 | #elif defined( USE_BAND_915_SINGLE ) |
dudmuck | 18:9ac71c0eb70d | 198 | /*! |
dudmuck | 18:9ac71c0eb70d | 199 | * Data rates table definition |
Wayne Roberts |
29:ad409c68c0a6 | 200 | DR: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15*/ |
dudmuck | 18:9ac71c0eb70d | 201 | const uint8_t Datarates[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 }; |
Wayne Roberts |
29:ad409c68c0a6 | 202 | #define SF_FROM_DR8 12 |
Wayne Roberts |
29:ad409c68c0a6 | 203 | #define SF_FROM_DR9 11 |
Wayne Roberts |
29:ad409c68c0a6 | 204 | #define SF_FROM_DR10 10 |
Wayne Roberts |
29:ad409c68c0a6 | 205 | #define SF_FROM_DR11 9 |
Wayne Roberts |
29:ad409c68c0a6 | 206 | #define SF_FROM_DR12 8 |
Wayne Roberts |
29:ad409c68c0a6 | 207 | #define SF_FROM_DR13 7 |
dudmuck | 18:9ac71c0eb70d | 208 | |
dudmuck | 18:9ac71c0eb70d | 209 | /*! |
dudmuck | 18:9ac71c0eb70d | 210 | * Tx output powers table definition |
dudmuck | 18:9ac71c0eb70d | 211 | */ |
dudmuck | 23:a862b5601663 | 212 | // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
dudmuck | 23:a862b5601663 | 213 | const int8_t TxPowers[] = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0 }; |
dudmuck | 18:9ac71c0eb70d | 214 | #define LORAMAC_FIRST_CHANNEL ( (uint32_t)910.0e6 ) |
dudmuck | 18:9ac71c0eb70d | 215 | #define LORAMAC_STEPWIDTH_CHANNEL ( (uint32_t)800e3 ) |
dudmuck | 18:9ac71c0eb70d | 216 | #define LORA_MAX_NB_CHANNELS 8 |
dudmuck | 18:9ac71c0eb70d | 217 | |
Wayne Roberts |
29:ad409c68c0a6 | 218 | #define LORA_BANDWIDTH_KHZ 500 |
Wayne Roberts |
29:ad409c68c0a6 | 219 | /* |
Wayne Roberts |
29:ad409c68c0a6 | 220 | #define STR_HELPER(x) #x |
Wayne Roberts |
29:ad409c68c0a6 | 221 | #define STR(x) STR_HELPER(x) |
Wayne Roberts |
29:ad409c68c0a6 | 222 | #pragma message "content of BEACON_RXDONE_LATENCY_us: " STR(BEACON_RXDONE_LATENCY_us) |
Wayne Roberts |
29:ad409c68c0a6 | 223 | #pragma message "content of BEACON_TOA_us: " STR(BEACON_TOA_us) |
Wayne Roberts |
29:ad409c68c0a6 | 224 | */ |
dudmuck | 18:9ac71c0eb70d | 225 | |
dudmuck | 18:9ac71c0eb70d | 226 | /* end us915 */ |
Wayne Roberts |
29:ad409c68c0a6 | 227 | #elif defined(USE_BAND_433) |
Wayne Roberts |
29:ad409c68c0a6 | 228 | // DR: 0 1 2 3 4 5 6 7 |
dudmuck | 18:9ac71c0eb70d | 229 | const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 }; |
Wayne Roberts |
29:ad409c68c0a6 | 230 | #define SF_FROM_DR0 12 |
Wayne Roberts |
29:ad409c68c0a6 | 231 | #define SF_FROM_DR1 11 |
Wayne Roberts |
29:ad409c68c0a6 | 232 | #define SF_FROM_DR2 10 |
Wayne Roberts |
29:ad409c68c0a6 | 233 | #define SF_FROM_DR3 9 |
Wayne Roberts |
29:ad409c68c0a6 | 234 | #define SF_FROM_DR4 8 |
Wayne Roberts |
29:ad409c68c0a6 | 235 | #define SF_FROM_DR5 7 |
Wayne Roberts |
29:ad409c68c0a6 | 236 | |
dudmuck | 18:9ac71c0eb70d | 237 | const int8_t TxPowers[] = { 10, 7, 4, 1, -2, -5 }; |
Wayne Roberts |
29:ad409c68c0a6 | 238 | #define LORA_BANDWIDTH_KHZ 125 |
dudmuck | 18:9ac71c0eb70d | 239 | |
dudmuck | 18:9ac71c0eb70d | 240 | #define LORAMAC_FIRST_CHANNEL ( (uint32_t)433.32e6 ) |
dudmuck | 18:9ac71c0eb70d | 241 | #define LORAMAC_STEPWIDTH_CHANNEL ( (uint32_t)200e3 ) |
Wayne Roberts |
30:1c35c4f56e50 | 242 | #define LORA_MAX_NB_CHANNELS 7 |
dudmuck | 18:9ac71c0eb70d | 243 | |
dudmuck | 18:9ac71c0eb70d | 244 | /* end USE_BAND_433 */ |
dudmuck | 18:9ac71c0eb70d | 245 | #else |
dudmuck | 18:9ac71c0eb70d | 246 | #error "Please define a frequency band in the compiler options." |
dudmuck | 0:8f0d0ae0a077 | 247 | #endif |
dudmuck | 0:8f0d0ae0a077 | 248 | |
Wayne Roberts |
29:ad409c68c0a6 | 249 | #define _SF_FROM_DR(dr) SF_FROM_DR ## dr |
Wayne Roberts |
29:ad409c68c0a6 | 250 | #define SF_FROM_DR_(x) _SF_FROM_DR(x) |
Wayne Roberts |
29:ad409c68c0a6 | 251 | |
Wayne Roberts |
29:ad409c68c0a6 | 252 | #ifdef SX128x_H |
Wayne Roberts |
29:ad409c68c0a6 | 253 | |
Wayne Roberts |
30:1c35c4f56e50 | 254 | #define FASTEST_SF 5 |
Wayne Roberts |
30:1c35c4f56e50 | 255 | /* ratio of symbol period to time from end of packet to RxDone interrupt */ |
Wayne Roberts |
30:1c35c4f56e50 | 256 | // sp 200KHz 160 320 640 1280 2560 5120 10240 20480 |
Wayne Roberts |
30:1c35c4f56e50 | 257 | // usLatency 200KHz implicit-6byte 90 228 436 880 2020 4200 8800 19300 |
Wayne Roberts |
30:1c35c4f56e50 | 258 | // SF: 5 6 7 8 9 10 11 12 |
Wayne Roberts |
30:1c35c4f56e50 | 259 | const float rxLatencyFactorFromSF[8] = { 0.56, 0.72, 0.68, 0.69, 0.79, 0.82, 0.86, 0.94 }; |
Wayne Roberts |
29:ad409c68c0a6 | 260 | |
Wayne Roberts |
29:ad409c68c0a6 | 261 | #elif defined(SX126x_H) || defined(SX127x_H) |
Wayne Roberts |
29:ad409c68c0a6 | 262 | |
Wayne Roberts |
30:1c35c4f56e50 | 263 | #define FASTEST_SF 5 |
Wayne Roberts |
30:1c35c4f56e50 | 264 | /* ratio of symbol period to time from end of packet to RxDone interrupt */ |
Wayne Roberts |
30:1c35c4f56e50 | 265 | // sp 500KHz 64 128 256 512 1024 2048 4096 8192 |
Wayne Roberts |
30:1c35c4f56e50 | 266 | // usLatency 500KHz implicit-6byte 92 184 376 780 1680 3680 7720 |
Wayne Roberts |
30:1c35c4f56e50 | 267 | // SF: 5 6 7 8 9 10 11 12 |
Wayne Roberts |
30:1c35c4f56e50 | 268 | const float rxLatencyFactorFromSF[8] = { 0.72, 0.72, 0.72, 0.73, 0.76, 0.82, 0.90, 0.94 }; |
Wayne Roberts |
29:ad409c68c0a6 | 269 | |
Wayne Roberts |
29:ad409c68c0a6 | 270 | #endif /* SX126x_H || SX127x_H */ |
Wayne Roberts |
29:ad409c68c0a6 | 271 | |
dudmuck | 18:9ac71c0eb70d | 272 | static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS]; // populated in init |
dudmuck | 18:9ac71c0eb70d | 273 | |
dudmuck | 16:915815632c1f | 274 | #define BEACON_GUARD_us 2000000 // pre-beacon start |
dudmuck | 0:8f0d0ae0a077 | 275 | #define BEACON_RESERVED_us 2120000 // post-beacon start |
dudmuck | 0:8f0d0ae0a077 | 276 | |
Wayne Roberts |
29:ad409c68c0a6 | 277 | #define MIN_SYMBOL_TIMEOUT 8 // number of symbols to keep receiver open for |
dudmuck | 13:18de9ee3a461 | 278 | |
dudmuck | 0:8f0d0ae0a077 | 279 | /*! |
dudmuck | 0:8f0d0ae0a077 | 280 | * LoRaMac parameters |
dudmuck | 0:8f0d0ae0a077 | 281 | */ |
dudmuck | 0:8f0d0ae0a077 | 282 | LoRaMacParams_t LoRaMacParams; |
dudmuck | 0:8f0d0ae0a077 | 283 | |
dudmuck | 0:8f0d0ae0a077 | 284 | /*! |
dudmuck | 0:8f0d0ae0a077 | 285 | * LoRaMac default parameters |
dudmuck | 0:8f0d0ae0a077 | 286 | */ |
dudmuck | 0:8f0d0ae0a077 | 287 | LoRaMacParams_t LoRaMacParamsDefaults; |
dudmuck | 0:8f0d0ae0a077 | 288 | |
dudmuck | 0:8f0d0ae0a077 | 289 | /*! |
dudmuck | 0:8f0d0ae0a077 | 290 | * Uplink messages repetitions counter |
dudmuck | 0:8f0d0ae0a077 | 291 | */ |
dudmuck | 0:8f0d0ae0a077 | 292 | static uint8_t ChannelsNbRepCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 293 | |
dudmuck | 0:8f0d0ae0a077 | 294 | /*! |
dudmuck | 0:8f0d0ae0a077 | 295 | * Current channel index |
dudmuck | 0:8f0d0ae0a077 | 296 | */ |
dudmuck | 0:8f0d0ae0a077 | 297 | static uint8_t Channel; |
dudmuck | 0:8f0d0ae0a077 | 298 | |
dudmuck | 0:8f0d0ae0a077 | 299 | /*! |
dudmuck | 0:8f0d0ae0a077 | 300 | * LoRaMac upper layer event functions |
dudmuck | 0:8f0d0ae0a077 | 301 | */ |
dudmuck | 0:8f0d0ae0a077 | 302 | static LoRaMacPrimitives_t *LoRaMacPrimitives; |
dudmuck | 0:8f0d0ae0a077 | 303 | |
dudmuck | 0:8f0d0ae0a077 | 304 | /*! |
dudmuck | 0:8f0d0ae0a077 | 305 | * LoRaMac upper layer callback functions |
dudmuck | 0:8f0d0ae0a077 | 306 | */ |
dudmuck | 0:8f0d0ae0a077 | 307 | static LoRaMacCallback_t *LoRaMacCallbacks; |
dudmuck | 0:8f0d0ae0a077 | 308 | |
dudmuck | 0:8f0d0ae0a077 | 309 | /*! |
dudmuck | 0:8f0d0ae0a077 | 310 | * LoRaMac duty cycle delayed Tx timer |
dudmuck | 0:8f0d0ae0a077 | 311 | */ |
Wayne Roberts |
29:ad409c68c0a6 | 312 | LowPowerTimeoutAbs _tx_timeout; |
dudmuck | 0:8f0d0ae0a077 | 313 | |
dudmuck | 0:8f0d0ae0a077 | 314 | /*! |
dudmuck | 0:8f0d0ae0a077 | 315 | * LoRaMac reception windows delay |
dudmuck | 0:8f0d0ae0a077 | 316 | * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME |
dudmuck | 0:8f0d0ae0a077 | 317 | * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME |
dudmuck | 0:8f0d0ae0a077 | 318 | */ |
dudmuck | 0:8f0d0ae0a077 | 319 | static uint32_t RxWindowDelay_us; |
dudmuck | 0:8f0d0ae0a077 | 320 | |
dudmuck | 0:8f0d0ae0a077 | 321 | typedef enum { |
dudmuck | 0:8f0d0ae0a077 | 322 | BEACON_STATE_NONE = 0, |
dudmuck | 0:8f0d0ae0a077 | 323 | BEACON_STATE_FIRST_ACQ, |
dudmuck | 0:8f0d0ae0a077 | 324 | BEACON_STATE_ACQ_ERROR, |
dudmuck | 21:500ff43d8424 | 325 | BEACON_STATE_LOCKED, |
dudmuck | 0:8f0d0ae0a077 | 326 | } beacon_state_e; |
dudmuck | 0:8f0d0ae0a077 | 327 | |
dudmuck | 16:915815632c1f | 328 | static struct beacon_struct { |
dudmuck | 0:8f0d0ae0a077 | 329 | int rx_precession_us; // positive: rxing before tx start, negative: rxing after tx start |
Wayne Roberts |
29:ad409c68c0a6 | 330 | us_timestamp_t rx_setup_at; |
Wayne Roberts |
29:ad409c68c0a6 | 331 | us_timestamp_t LastBeaconRx_us; // updated only at beacon reception |
Wayne Roberts |
29:ad409c68c0a6 | 332 | us_timestamp_t sendAt; |
Wayne Roberts |
29:ad409c68c0a6 | 333 | int lastSendAtErr; |
dudmuck | 13:18de9ee3a461 | 334 | int last_BeaconRxTimerError_us; |
dudmuck | 13:18de9ee3a461 | 335 | int known_working_BeaconRxTimerError_us; |
dudmuck | 0:8f0d0ae0a077 | 336 | |
Wayne Roberts |
29:ad409c68c0a6 | 337 | unsigned symbol_period_us; |
dudmuck | 0:8f0d0ae0a077 | 338 | |
dudmuck | 0:8f0d0ae0a077 | 339 | uint8_t Precess_symbols; // how many symbols we want to start receiver before expected transmitter |
Wayne Roberts |
29:ad409c68c0a6 | 340 | uint16_t nSymbsTimeout; |
Wayne Roberts |
29:ad409c68c0a6 | 341 | unsigned SymbolTimeout_us; |
dudmuck | 0:8f0d0ae0a077 | 342 | uint8_t num_missed; |
Wayne Roberts |
30:1c35c4f56e50 | 343 | uint8_t num_consecutive_ok; |
dudmuck | 0:8f0d0ae0a077 | 344 | |
dudmuck | 0:8f0d0ae0a077 | 345 | beacon_state_e state; |
dudmuck | 0:8f0d0ae0a077 | 346 | |
dudmuck | 0:8f0d0ae0a077 | 347 | uint16_t tx_slot_offset; |
dudmuck | 0:8f0d0ae0a077 | 348 | uint16_t periodicity_slots; |
Wayne Roberts |
30:1c35c4f56e50 | 349 | uint32_t beaconStartToRxDone; |
Wayne Roberts |
29:ad409c68c0a6 | 350 | uint16_t sendOpportunities; |
Wayne Roberts |
29:ad409c68c0a6 | 351 | |
Wayne Roberts |
29:ad409c68c0a6 | 352 | LowPowerTimeoutAbs _timeout_rx; |
Wayne Roberts |
29:ad409c68c0a6 | 353 | LowPowerTimeoutAbs _timeout_guard; |
dudmuck | 16:915815632c1f | 354 | bool guard; |
dudmuck | 0:8f0d0ae0a077 | 355 | } BeaconCtx; |
dudmuck | 0:8f0d0ae0a077 | 356 | |
dudmuck | 0:8f0d0ae0a077 | 357 | /*! |
dudmuck | 0:8f0d0ae0a077 | 358 | * Rx window parameters |
dudmuck | 0:8f0d0ae0a077 | 359 | */ |
dudmuck | 0:8f0d0ae0a077 | 360 | typedef struct |
dudmuck | 0:8f0d0ae0a077 | 361 | { |
dudmuck | 0:8f0d0ae0a077 | 362 | int8_t Datarate; |
dudmuck | 0:8f0d0ae0a077 | 363 | uint32_t RxWindowTimeout; |
Wayne Roberts |
29:ad409c68c0a6 | 364 | } RxConfigParams_t; |
dudmuck | 0:8f0d0ae0a077 | 365 | |
dudmuck | 0:8f0d0ae0a077 | 366 | /*! |
dudmuck | 0:8f0d0ae0a077 | 367 | * Rx windows params |
dudmuck | 0:8f0d0ae0a077 | 368 | */ |
dudmuck | 0:8f0d0ae0a077 | 369 | static RxConfigParams_t RxWindowsParam; |
dudmuck | 0:8f0d0ae0a077 | 370 | |
dudmuck | 0:8f0d0ae0a077 | 371 | /*! |
dudmuck | 0:8f0d0ae0a077 | 372 | * Acknowledge timeout timer. Used for packet retransmissions. |
dudmuck | 0:8f0d0ae0a077 | 373 | */ |
dudmuck | 0:8f0d0ae0a077 | 374 | static LowPowerTimeout AckTimeoutTimer; |
dudmuck | 0:8f0d0ae0a077 | 375 | |
dudmuck | 0:8f0d0ae0a077 | 376 | /*! |
dudmuck | 0:8f0d0ae0a077 | 377 | * Number of trials for the Join Request |
dudmuck | 0:8f0d0ae0a077 | 378 | */ |
dudmuck | 0:8f0d0ae0a077 | 379 | static uint8_t JoinRequestTrials; |
dudmuck | 0:8f0d0ae0a077 | 380 | |
dudmuck | 0:8f0d0ae0a077 | 381 | /*! |
dudmuck | 0:8f0d0ae0a077 | 382 | * Maximum number of trials for the Join Request |
dudmuck | 0:8f0d0ae0a077 | 383 | */ |
dudmuck | 0:8f0d0ae0a077 | 384 | static uint8_t MaxJoinRequestTrials; |
dudmuck | 0:8f0d0ae0a077 | 385 | |
dudmuck | 0:8f0d0ae0a077 | 386 | /*! |
dudmuck | 0:8f0d0ae0a077 | 387 | * Structure to hold an MCPS indication data. |
dudmuck | 0:8f0d0ae0a077 | 388 | */ |
dudmuck | 0:8f0d0ae0a077 | 389 | static McpsIndication_t McpsIndication; |
dudmuck | 0:8f0d0ae0a077 | 390 | |
dudmuck | 0:8f0d0ae0a077 | 391 | /*! |
dudmuck | 0:8f0d0ae0a077 | 392 | * Structure to hold MCPS confirm data. |
dudmuck | 0:8f0d0ae0a077 | 393 | */ |
dudmuck | 0:8f0d0ae0a077 | 394 | static McpsConfirm_t McpsConfirm; |
dudmuck | 0:8f0d0ae0a077 | 395 | |
dudmuck | 0:8f0d0ae0a077 | 396 | /*! |
dudmuck | 0:8f0d0ae0a077 | 397 | * Structure to hold MLME confirm data. |
dudmuck | 0:8f0d0ae0a077 | 398 | */ |
dudmuck | 0:8f0d0ae0a077 | 399 | static MlmeConfirm_t MlmeConfirm; |
dudmuck | 0:8f0d0ae0a077 | 400 | |
dudmuck | 0:8f0d0ae0a077 | 401 | /*! |
dudmuck | 0:8f0d0ae0a077 | 402 | * Structure to hold MLME indication data. |
dudmuck | 0:8f0d0ae0a077 | 403 | */ |
dudmuck | 0:8f0d0ae0a077 | 404 | static MlmeIndication_t MlmeIndication; |
dudmuck | 0:8f0d0ae0a077 | 405 | |
dudmuck | 0:8f0d0ae0a077 | 406 | /*! |
dudmuck | 0:8f0d0ae0a077 | 407 | * LoRaMac tx/rx operation state |
dudmuck | 0:8f0d0ae0a077 | 408 | */ |
Wayne Roberts |
29:ad409c68c0a6 | 409 | volatile LoRaMacFlags_t LoRaMacFlags; |
dudmuck | 0:8f0d0ae0a077 | 410 | |
dudmuck | 0:8f0d0ae0a077 | 411 | /*! |
dudmuck | 0:8f0d0ae0a077 | 412 | * \brief This function prepares the MAC to abort the execution of function |
dudmuck | 0:8f0d0ae0a077 | 413 | * OnRadioRxDone in case of a reception error. |
dudmuck | 0:8f0d0ae0a077 | 414 | */ |
dudmuck | 0:8f0d0ae0a077 | 415 | static void PrepareRxDoneAbort( void ); |
dudmuck | 0:8f0d0ae0a077 | 416 | |
dudmuck | 0:8f0d0ae0a077 | 417 | /*! |
dudmuck | 0:8f0d0ae0a077 | 418 | * \brief Function executed on Radio Tx Timeout event |
dudmuck | 0:8f0d0ae0a077 | 419 | */ |
dudmuck | 0:8f0d0ae0a077 | 420 | static void OnRadioTxTimeout( void ); |
dudmuck | 0:8f0d0ae0a077 | 421 | |
dudmuck | 0:8f0d0ae0a077 | 422 | /*! |
dudmuck | 0:8f0d0ae0a077 | 423 | * \brief Function executed on Radio Rx error event |
dudmuck | 0:8f0d0ae0a077 | 424 | */ |
dudmuck | 0:8f0d0ae0a077 | 425 | static void OnRadioRxError( void ); |
dudmuck | 0:8f0d0ae0a077 | 426 | |
dudmuck | 0:8f0d0ae0a077 | 427 | /*! |
dudmuck | 0:8f0d0ae0a077 | 428 | * \brief Function executed on Radio Rx Timeout event |
dudmuck | 0:8f0d0ae0a077 | 429 | */ |
dudmuck | 0:8f0d0ae0a077 | 430 | static void OnRadioRxTimeout( void ); |
dudmuck | 0:8f0d0ae0a077 | 431 | |
dudmuck | 0:8f0d0ae0a077 | 432 | /*! |
dudmuck | 0:8f0d0ae0a077 | 433 | * \brief Function executed on AckTimeout timer event |
dudmuck | 0:8f0d0ae0a077 | 434 | */ |
dudmuck | 0:8f0d0ae0a077 | 435 | static void OnAckTimeoutTimerEvent( void ); |
dudmuck | 0:8f0d0ae0a077 | 436 | |
dudmuck | 0:8f0d0ae0a077 | 437 | /*! |
dudmuck | 0:8f0d0ae0a077 | 438 | * \brief Adds a new MAC command to be sent. |
dudmuck | 0:8f0d0ae0a077 | 439 | * |
dudmuck | 0:8f0d0ae0a077 | 440 | * \Remark MAC layer internal function |
dudmuck | 0:8f0d0ae0a077 | 441 | * |
dudmuck | 0:8f0d0ae0a077 | 442 | * \param [in] cmd MAC command to be added |
dudmuck | 0:8f0d0ae0a077 | 443 | * [MOTE_MAC_LINK_CHECK_REQ, |
dudmuck | 0:8f0d0ae0a077 | 444 | * MOTE_MAC_LINK_ADR_ANS, |
dudmuck | 0:8f0d0ae0a077 | 445 | * MOTE_MAC_DUTY_CYCLE_ANS, |
dudmuck | 0:8f0d0ae0a077 | 446 | * MOTE_MAC_RX2_PARAM_SET_ANS, |
dudmuck | 0:8f0d0ae0a077 | 447 | * MOTE_MAC_DEV_STATUS_ANS |
dudmuck | 0:8f0d0ae0a077 | 448 | * MOTE_MAC_NEW_CHANNEL_ANS] |
dudmuck | 0:8f0d0ae0a077 | 449 | * \param [in] p1 1st parameter ( optional depends on the command ) |
dudmuck | 0:8f0d0ae0a077 | 450 | * \param [in] p2 2nd parameter ( optional depends on the command ) |
dudmuck | 0:8f0d0ae0a077 | 451 | * |
dudmuck | 0:8f0d0ae0a077 | 452 | * \retval status Function status [0: OK, 1: Unknown command, 2: Buffer full] |
dudmuck | 0:8f0d0ae0a077 | 453 | */ |
dudmuck | 0:8f0d0ae0a077 | 454 | static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ); |
dudmuck | 0:8f0d0ae0a077 | 455 | |
dudmuck | 0:8f0d0ae0a077 | 456 | /*! |
dudmuck | 0:8f0d0ae0a077 | 457 | * \brief Parses the MAC commands which must be repeated. |
dudmuck | 0:8f0d0ae0a077 | 458 | * |
dudmuck | 0:8f0d0ae0a077 | 459 | * \Remark MAC layer internal function |
dudmuck | 0:8f0d0ae0a077 | 460 | * |
dudmuck | 0:8f0d0ae0a077 | 461 | * \param [IN] cmdBufIn Buffer which stores the MAC commands to send |
dudmuck | 0:8f0d0ae0a077 | 462 | * \param [IN] length Length of the input buffer to parse |
dudmuck | 0:8f0d0ae0a077 | 463 | * \param [OUT] cmdBufOut Buffer which stores the MAC commands which must be |
dudmuck | 0:8f0d0ae0a077 | 464 | * repeated. |
dudmuck | 0:8f0d0ae0a077 | 465 | * |
dudmuck | 0:8f0d0ae0a077 | 466 | * \retval Size of the MAC commands to repeat. |
dudmuck | 0:8f0d0ae0a077 | 467 | */ |
dudmuck | 0:8f0d0ae0a077 | 468 | static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ); |
dudmuck | 0:8f0d0ae0a077 | 469 | |
dudmuck | 0:8f0d0ae0a077 | 470 | /*! |
dudmuck | 0:8f0d0ae0a077 | 471 | * \brief Verifies, if a value is in a given range. |
dudmuck | 0:8f0d0ae0a077 | 472 | * |
dudmuck | 0:8f0d0ae0a077 | 473 | * \param value Value to verify, if it is in range |
dudmuck | 0:8f0d0ae0a077 | 474 | * |
dudmuck | 0:8f0d0ae0a077 | 475 | * \param min Minimum possible value |
dudmuck | 0:8f0d0ae0a077 | 476 | * |
dudmuck | 0:8f0d0ae0a077 | 477 | * \param max Maximum possible value |
dudmuck | 0:8f0d0ae0a077 | 478 | * |
dudmuck | 0:8f0d0ae0a077 | 479 | * \retval Returns the maximum valid tx power |
dudmuck | 0:8f0d0ae0a077 | 480 | */ |
dudmuck | 0:8f0d0ae0a077 | 481 | static bool ValueInRange( int8_t value, int8_t min, int8_t max ); |
dudmuck | 0:8f0d0ae0a077 | 482 | |
dudmuck | 0:8f0d0ae0a077 | 483 | |
dudmuck | 0:8f0d0ae0a077 | 484 | /*! |
dudmuck | 0:8f0d0ae0a077 | 485 | * \brief Decodes MAC commands in the fOpts field and in the payload |
dudmuck | 0:8f0d0ae0a077 | 486 | */ |
dudmuck | 0:8f0d0ae0a077 | 487 | static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr ); |
dudmuck | 0:8f0d0ae0a077 | 488 | |
dudmuck | 0:8f0d0ae0a077 | 489 | /*! |
dudmuck | 0:8f0d0ae0a077 | 490 | * \brief LoRaMAC layer generic send frame |
dudmuck | 0:8f0d0ae0a077 | 491 | * |
dudmuck | 0:8f0d0ae0a077 | 492 | * \param [IN] macHdr MAC header field |
dudmuck | 0:8f0d0ae0a077 | 493 | * \param [IN] fPort MAC payload port |
dudmuck | 0:8f0d0ae0a077 | 494 | * \param [IN] fBuffer MAC data buffer to be sent |
dudmuck | 0:8f0d0ae0a077 | 495 | * \param [IN] fBufferSize MAC data buffer size |
dudmuck | 0:8f0d0ae0a077 | 496 | * \retval status Status of the operation. |
dudmuck | 0:8f0d0ae0a077 | 497 | */ |
dudmuck | 0:8f0d0ae0a077 | 498 | LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ); |
dudmuck | 0:8f0d0ae0a077 | 499 | |
dudmuck | 0:8f0d0ae0a077 | 500 | /*! |
dudmuck | 0:8f0d0ae0a077 | 501 | * \brief LoRaMAC layer frame buffer initialization |
dudmuck | 0:8f0d0ae0a077 | 502 | * |
dudmuck | 0:8f0d0ae0a077 | 503 | * \param [IN] macHdr MAC header field |
dudmuck | 0:8f0d0ae0a077 | 504 | * \param [IN] fCtrl MAC frame control field |
dudmuck | 0:8f0d0ae0a077 | 505 | * \param [IN] fOpts MAC commands buffer |
dudmuck | 0:8f0d0ae0a077 | 506 | * \param [IN] fPort MAC payload port |
dudmuck | 0:8f0d0ae0a077 | 507 | * \param [IN] fBuffer MAC data buffer to be sent |
dudmuck | 0:8f0d0ae0a077 | 508 | * \param [IN] fBufferSize MAC data buffer size |
dudmuck | 0:8f0d0ae0a077 | 509 | * \retval status Status of the operation. |
dudmuck | 0:8f0d0ae0a077 | 510 | */ |
dudmuck | 0:8f0d0ae0a077 | 511 | LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ); |
dudmuck | 0:8f0d0ae0a077 | 512 | |
dudmuck | 0:8f0d0ae0a077 | 513 | /*! |
dudmuck | 0:8f0d0ae0a077 | 514 | * \brief Sets the radio in continuous transmission mode |
dudmuck | 0:8f0d0ae0a077 | 515 | * |
dudmuck | 0:8f0d0ae0a077 | 516 | * \remark Uses the radio parameters set on the previous transmission. |
dudmuck | 0:8f0d0ae0a077 | 517 | * |
dudmuck | 0:8f0d0ae0a077 | 518 | * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode |
dudmuck | 0:8f0d0ae0a077 | 519 | * \retval status Status of the operation. |
dudmuck | 0:8f0d0ae0a077 | 520 | */ |
dudmuck | 0:8f0d0ae0a077 | 521 | LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout ); |
dudmuck | 0:8f0d0ae0a077 | 522 | |
dudmuck | 0:8f0d0ae0a077 | 523 | /*! |
dudmuck | 0:8f0d0ae0a077 | 524 | * \brief Sets the radio in continuous transmission mode |
dudmuck | 0:8f0d0ae0a077 | 525 | * |
dudmuck | 0:8f0d0ae0a077 | 526 | * \remark Uses the radio parameters set on the previous transmission. |
dudmuck | 0:8f0d0ae0a077 | 527 | * |
dudmuck | 0:8f0d0ae0a077 | 528 | * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode |
dudmuck | 0:8f0d0ae0a077 | 529 | * \param [IN] frequency RF frequency to be set. |
dudmuck | 0:8f0d0ae0a077 | 530 | * \param [IN] power RF ouptput power to be set. |
dudmuck | 0:8f0d0ae0a077 | 531 | * \retval status Status of the operation. |
dudmuck | 0:8f0d0ae0a077 | 532 | */ |
dudmuck | 0:8f0d0ae0a077 | 533 | LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power ); |
dudmuck | 0:8f0d0ae0a077 | 534 | |
Wayne Roberts |
29:ad409c68c0a6 | 535 | #ifdef SX127x_H |
Wayne Roberts |
29:ad409c68c0a6 | 536 | void printLoraIrqs(bool clear) |
Wayne Roberts |
29:ad409c68c0a6 | 537 | { |
Wayne Roberts |
29:ad409c68c0a6 | 538 | pc.printf("\r\nIrqFlags:"); |
Wayne Roberts |
29:ad409c68c0a6 | 539 | if (Radio::lora.RegIrqFlags.bits.CadDetected) |
Wayne Roberts |
29:ad409c68c0a6 | 540 | pc.printf("CadDetected "); |
Wayne Roberts |
29:ad409c68c0a6 | 541 | if (Radio::lora.RegIrqFlags.bits.FhssChangeChannel) { |
Wayne Roberts |
29:ad409c68c0a6 | 542 | pc.printf("FhssChangeChannel:%d ", Radio::lora.RegHopChannel.bits.FhssPresentChannel); |
Wayne Roberts |
29:ad409c68c0a6 | 543 | } |
Wayne Roberts |
29:ad409c68c0a6 | 544 | if (Radio::lora.RegIrqFlags.bits.CadDone) |
Wayne Roberts |
29:ad409c68c0a6 | 545 | pc.printf("CadDone "); |
Wayne Roberts |
29:ad409c68c0a6 | 546 | if (Radio::lora.RegIrqFlags.bits.TxDone) |
Wayne Roberts |
29:ad409c68c0a6 | 547 | pc.printf("TxDone-dio0:%d ", Radio::radio.dio0.read()); |
Wayne Roberts |
29:ad409c68c0a6 | 548 | if (Radio::lora.RegIrqFlags.bits.ValidHeader) |
Wayne Roberts |
29:ad409c68c0a6 | 549 | pc.printf("[42mValidHeader[0m "); |
Wayne Roberts |
29:ad409c68c0a6 | 550 | if (Radio::lora.RegIrqFlags.bits.PayloadCrcError) |
Wayne Roberts |
29:ad409c68c0a6 | 551 | pc.printf("[41mPayloadCrcError[0m "); |
Wayne Roberts |
29:ad409c68c0a6 | 552 | if (Radio::lora.RegIrqFlags.bits.RxDone) |
Wayne Roberts |
29:ad409c68c0a6 | 553 | pc.printf("[42mRxDone[0m "); |
Wayne Roberts |
29:ad409c68c0a6 | 554 | if (Radio::lora.RegIrqFlags.bits.RxTimeout) |
Wayne Roberts |
29:ad409c68c0a6 | 555 | pc.printf("RxTimeout "); |
Wayne Roberts |
29:ad409c68c0a6 | 556 | |
Wayne Roberts |
29:ad409c68c0a6 | 557 | pc.printf("\r\n"); |
Wayne Roberts |
29:ad409c68c0a6 | 558 | |
Wayne Roberts |
29:ad409c68c0a6 | 559 | if (clear) |
Wayne Roberts |
29:ad409c68c0a6 | 560 | Radio::radio.write_reg(REG_LR_IRQFLAGS, Radio::lora.RegIrqFlags.octet); |
Wayne Roberts |
29:ad409c68c0a6 | 561 | } |
Wayne Roberts |
29:ad409c68c0a6 | 562 | |
Wayne Roberts |
29:ad409c68c0a6 | 563 | void printOpMode() |
Wayne Roberts |
29:ad409c68c0a6 | 564 | { |
Wayne Roberts |
29:ad409c68c0a6 | 565 | Radio::radio.RegOpMode.octet = Radio::radio.read_reg(REG_OPMODE); |
Wayne Roberts |
29:ad409c68c0a6 | 566 | switch (Radio::radio.RegOpMode.bits.Mode) { |
Wayne Roberts |
29:ad409c68c0a6 | 567 | case RF_OPMODE_SLEEP: pc.printf("[7msleep[0m"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 568 | case RF_OPMODE_STANDBY: pc.printf("[7mstby[0m"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 569 | case RF_OPMODE_SYNTHESIZER_TX: pc.printf("[33mfstx[0m"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 570 | case RF_OPMODE_TRANSMITTER: pc.printf("[31mtx[0m"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 571 | case RF_OPMODE_SYNTHESIZER_RX: pc.printf("[33mfsrx[0m"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 572 | case RF_OPMODE_RECEIVER: pc.printf("[32mrx[0m"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 573 | case 6: |
Wayne Roberts |
29:ad409c68c0a6 | 574 | if (Radio::radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
29:ad409c68c0a6 | 575 | pc.printf("[42mrxs[0m"); |
Wayne Roberts |
29:ad409c68c0a6 | 576 | else |
Wayne Roberts |
29:ad409c68c0a6 | 577 | pc.printf("-6-"); |
Wayne Roberts |
29:ad409c68c0a6 | 578 | break; // todo: different lora/fsk |
Wayne Roberts |
29:ad409c68c0a6 | 579 | case 7: |
Wayne Roberts |
29:ad409c68c0a6 | 580 | if (Radio::radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
29:ad409c68c0a6 | 581 | pc.printf("[45mcad[0m"); |
Wayne Roberts |
29:ad409c68c0a6 | 582 | else |
Wayne Roberts |
29:ad409c68c0a6 | 583 | pc.printf("-7-"); |
Wayne Roberts |
29:ad409c68c0a6 | 584 | break; // todo: different lora/fsk |
Wayne Roberts |
29:ad409c68c0a6 | 585 | } |
Wayne Roberts |
29:ad409c68c0a6 | 586 | } |
Wayne Roberts |
29:ad409c68c0a6 | 587 | #endif /* SX127x_H */ |
Wayne Roberts |
29:ad409c68c0a6 | 588 | |
dudmuck | 0:8f0d0ae0a077 | 589 | /*! |
dudmuck | 0:8f0d0ae0a077 | 590 | * \brief Resets MAC specific parameters to default |
dudmuck | 0:8f0d0ae0a077 | 591 | */ |
dudmuck | 0:8f0d0ae0a077 | 592 | static void ResetMacParameters( void ); |
dudmuck | 0:8f0d0ae0a077 | 593 | |
dudmuck | 0:8f0d0ae0a077 | 594 | void |
dudmuck | 0:8f0d0ae0a077 | 595 | loramac_print_status() |
dudmuck | 0:8f0d0ae0a077 | 596 | { |
Wayne Roberts |
29:ad409c68c0a6 | 597 | int until_beacon = BeaconCtx.rx_setup_at - BeaconCtx._timeout_rx.read_us(); |
Wayne Roberts |
29:ad409c68c0a6 | 598 | mac_printf("until_beacon:%d ", until_beacon); |
Wayne Roberts |
29:ad409c68c0a6 | 599 | mac_printf("DR%u=sf%u guard:%d\r\n", |
dudmuck | 16:915815632c1f | 600 | LoRaMacParams.ChannelsDatarate_fixed, |
dudmuck | 16:915815632c1f | 601 | Datarates[LoRaMacParams.ChannelsDatarate_fixed], |
dudmuck | 16:915815632c1f | 602 | BeaconCtx.guard |
dudmuck | 16:915815632c1f | 603 | ); |
Wayne Roberts |
29:ad409c68c0a6 | 604 | #ifdef SX128x_H |
Wayne Roberts |
29:ad409c68c0a6 | 605 | status_t status; |
Wayne Roberts |
29:ad409c68c0a6 | 606 | Radio::radio.xfer(OPCODE_GET_STATUS, 0, 1, &status.octet); |
Wayne Roberts |
29:ad409c68c0a6 | 607 | switch (status.bits.cmdStatus) { |
Wayne Roberts |
29:ad409c68c0a6 | 608 | case 1: pc.printf("success"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 609 | case 2: pc.printf("dataAvail"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 610 | case 3: pc.printf("cmdTimeout"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 611 | case 4: pc.printf("cmdErr"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 612 | case 5: pc.printf("exeFail"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 613 | case 6: pc.printf("txdone"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 614 | default: pc.printf("cmdStatus:<%u>", status.bits.cmdStatus); break; |
Wayne Roberts |
29:ad409c68c0a6 | 615 | } |
Wayne Roberts |
29:ad409c68c0a6 | 616 | pc.printf(" "); |
Wayne Roberts |
29:ad409c68c0a6 | 617 | switch (status.bits.chipMode) { |
Wayne Roberts |
29:ad409c68c0a6 | 618 | case 2: pc.printf("stdby_rc"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 619 | case 3: pc.printf("stdby_xosc"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 620 | case 4: pc.printf("fs"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 621 | case 5: pc.printf("\e[32mrx\e[0m"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 622 | case 6: pc.printf("\e[31mtx\e[0m"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 623 | default: pc.printf("chipMode:<%u>", status.bits.chipMode); break; |
Wayne Roberts |
29:ad409c68c0a6 | 624 | } |
Wayne Roberts |
29:ad409c68c0a6 | 625 | LoRaPktPar0_t LoRaPktPar0; |
Wayne Roberts |
29:ad409c68c0a6 | 626 | LoRaPktPar0.octet = Radio::radio.readReg(REG_ADDR_LORA_PKTPAR0, 1); |
Wayne Roberts |
29:ad409c68c0a6 | 627 | pc.printf(" bw:%u sf%u ", LoRaPktPar0.bits.modem_bw, LoRaPktPar0.bits.modem_sf); |
Wayne Roberts |
29:ad409c68c0a6 | 628 | mac_printf("loraSync:%04x\r\n", Radio::radio.readReg(REG_ADDR_LORA_SYNC, 2)); |
Wayne Roberts |
29:ad409c68c0a6 | 629 | #elif defined(SX127x_H) |
Wayne Roberts |
29:ad409c68c0a6 | 630 | Radio::radio.RegPaConfig.octet = Radio::radio.read_reg(REG_PACONFIG); |
Wayne Roberts |
29:ad409c68c0a6 | 631 | if (Radio::radio.RegPaConfig.bits.PaSelect) |
Wayne Roberts |
29:ad409c68c0a6 | 632 | pc.printf("PA_BOOST "); |
Wayne Roberts |
29:ad409c68c0a6 | 633 | else |
Wayne Roberts |
29:ad409c68c0a6 | 634 | pc.printf("RFO "); |
Wayne Roberts |
29:ad409c68c0a6 | 635 | |
Wayne Roberts |
29:ad409c68c0a6 | 636 | Radio::radio.RegOpMode.octet = Radio::radio.read_reg(REG_OPMODE); |
Wayne Roberts |
29:ad409c68c0a6 | 637 | pc.printf("%.3fMHz sf%ubw%u ", Radio::radio.get_frf_MHz(), Radio::lora.getSf(), Radio::lora.getBw()); |
Wayne Roberts |
29:ad409c68c0a6 | 638 | pc.printf("dio0pin:%u ", Radio::radio.dio0.read()); |
Wayne Roberts |
29:ad409c68c0a6 | 639 | printOpMode(); |
Wayne Roberts |
29:ad409c68c0a6 | 640 | if (!Radio::radio.RegOpMode.bits.LongRangeMode) { |
Wayne Roberts |
29:ad409c68c0a6 | 641 | pc.printf("FSK\r\n"); |
Wayne Roberts |
29:ad409c68c0a6 | 642 | return; |
Wayne Roberts |
29:ad409c68c0a6 | 643 | } |
Wayne Roberts |
29:ad409c68c0a6 | 644 | |
Wayne Roberts |
29:ad409c68c0a6 | 645 | Radio::lora.RegIrqFlags.octet = Radio::radio.read_reg(REG_LR_IRQFLAGS); |
Wayne Roberts |
29:ad409c68c0a6 | 646 | printLoraIrqs(false); |
Wayne Roberts |
29:ad409c68c0a6 | 647 | |
Wayne Roberts |
29:ad409c68c0a6 | 648 | Radio::lora.RegTest33.octet = Radio::radio.read_reg(REG_LR_TEST33); // invert_i_q |
Wayne Roberts |
29:ad409c68c0a6 | 649 | Radio::lora.RegDriftInvert.octet = Radio::radio.read_reg(REG_LR_DRIFT_INVERT); |
Wayne Roberts |
29:ad409c68c0a6 | 650 | pc.printf("modemstat:%02x, rxinv:%x,%x\r\n", Radio::radio.read_reg(REG_LR_MODEMSTAT), Radio::lora.RegTest33.octet, Radio::lora.RegDriftInvert.octet); |
Wayne Roberts |
29:ad409c68c0a6 | 651 | Radio::radio.RegDioMapping1.octet = Radio::radio.read_reg(REG_DIOMAPPING1); |
Wayne Roberts |
29:ad409c68c0a6 | 652 | pc.printf("\r\ndio0map:%u\r\n", Radio::radio.RegDioMapping1.bits.Dio0Mapping); |
Wayne Roberts |
29:ad409c68c0a6 | 653 | pc.printf("FIfoAddrPtr:%02x RxBase:%02x\r\n", Radio::radio.read_reg(REG_LR_FIFOADDRPTR), Radio::radio.read_reg(REG_LR_FIFORXBASEADDR)); |
Wayne Roberts |
29:ad409c68c0a6 | 654 | #elif defined(SX126x_H) |
Wayne Roberts |
29:ad409c68c0a6 | 655 | status_t status; |
Wayne Roberts |
29:ad409c68c0a6 | 656 | Radio::radio.xfer(OPCODE_GET_STATUS, 0, 1, &status.octet); |
Wayne Roberts |
29:ad409c68c0a6 | 657 | switch (status.bits.chipMode) { |
Wayne Roberts |
29:ad409c68c0a6 | 658 | case 2: mac_printf("STBY_RC"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 659 | case 3: mac_printf("STBY_XOSC"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 660 | case 4: mac_printf("FS"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 661 | case 5: mac_printf("RX"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 662 | case 6: mac_printf("TX"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 663 | default: mac_printf("%u", status.bits.chipMode); break; |
Wayne Roberts |
29:ad409c68c0a6 | 664 | } |
Wayne Roberts |
29:ad409c68c0a6 | 665 | pc.printf(" "); |
Wayne Roberts |
29:ad409c68c0a6 | 666 | switch (status.bits.cmdStatus) { |
Wayne Roberts |
29:ad409c68c0a6 | 667 | case 1: mac_printf("rfu"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 668 | case 2: mac_printf("dataAvail"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 669 | case 3: mac_printf("timeout"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 670 | case 4: mac_printf("err"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 671 | case 5: mac_printf("fail"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 672 | case 6: mac_printf("txdone"); break; |
Wayne Roberts |
29:ad409c68c0a6 | 673 | default: mac_printf("%u", status.bits.cmdStatus); break; |
Wayne Roberts |
29:ad409c68c0a6 | 674 | } |
Wayne Roberts |
29:ad409c68c0a6 | 675 | loraConfig0_t conf0; |
Wayne Roberts |
29:ad409c68c0a6 | 676 | conf0.octet = Radio::radio.readReg(REG_ADDR_LORA_CONFIG0, 1); |
Wayne Roberts |
29:ad409c68c0a6 | 677 | // bw7=125 bw8=250 b9=500 |
Wayne Roberts |
29:ad409c68c0a6 | 678 | mac_printf(" bw:%u sf%u\r\n", conf0.bits.modem_bw, conf0.bits.modem_sf); |
Wayne Roberts |
29:ad409c68c0a6 | 679 | loraConfig1_t conf1; |
Wayne Roberts |
29:ad409c68c0a6 | 680 | conf1.octet = Radio::radio.readReg(REG_ADDR_LORA_CONFIG1, 1); |
Wayne Roberts |
29:ad409c68c0a6 | 681 | mac_printf("inviq:%u cr%u\r\n", conf1.bits.rx_invert_iq, conf1.bits.tx_coding_rate); |
Wayne Roberts |
29:ad409c68c0a6 | 682 | mac_printf("loraSync:%04x\r\n", Radio::radio.readReg(REG_ADDR_LORA_SYNC, 2)); |
Wayne Roberts |
29:ad409c68c0a6 | 683 | #endif /* ..SX126x_H */ |
dudmuck | 0:8f0d0ae0a077 | 684 | } |
dudmuck | 0:8f0d0ae0a077 | 685 | |
Wayne Roberts |
29:ad409c68c0a6 | 686 | static void RxWindowSetup( uint32_t freq, int8_t datarate, uint16_t timeout, bool rxContinuous ) |
Wayne Roberts |
29:ad409c68c0a6 | 687 | { |
Wayne Roberts |
29:ad409c68c0a6 | 688 | uint8_t downlinkDatarate = Datarates[datarate]; |
Wayne Roberts |
29:ad409c68c0a6 | 689 | |
Wayne Roberts |
29:ad409c68c0a6 | 690 | Radio::SetChannel( freq ); |
Wayne Roberts |
29:ad409c68c0a6 | 691 | |
Wayne Roberts |
29:ad409c68c0a6 | 692 | // Store downlink datarate |
Wayne Roberts |
29:ad409c68c0a6 | 693 | McpsIndication.RxDatarate = ( uint8_t ) datarate; |
Wayne Roberts |
29:ad409c68c0a6 | 694 | |
Wayne Roberts |
29:ad409c68c0a6 | 695 | Radio::LoRaModemConfig(LORA_BANDWIDTH_KHZ, downlinkDatarate, 1); |
Wayne Roberts |
29:ad409c68c0a6 | 696 | |
Wayne Roberts |
29:ad409c68c0a6 | 697 | // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
29:ad409c68c0a6 | 698 | Radio::LoRaPacketConfig(PREAMBLE_SYMBS, false, false, true); |
Wayne Roberts |
29:ad409c68c0a6 | 699 | Radio::SetLoRaSymbolTimeout(timeout); |
Wayne Roberts |
29:ad409c68c0a6 | 700 | Radio::SetRxMaxPayloadLength(LORAMAC_PHY_MAXPAYLOAD); |
Wayne Roberts |
29:ad409c68c0a6 | 701 | |
Wayne Roberts |
29:ad409c68c0a6 | 702 | } // ..RxWindowSetup() |
Wayne Roberts |
29:ad409c68c0a6 | 703 | |
Wayne Roberts |
29:ad409c68c0a6 | 704 | static void OnRxWindowTimerEvent( void ) |
Wayne Roberts |
29:ad409c68c0a6 | 705 | { |
Wayne Roberts |
29:ad409c68c0a6 | 706 | RxWindowSetup(Channels[Channel].Frequency, RxWindowsParam.Datarate, RxWindowsParam.RxWindowTimeout, false); |
Wayne Roberts |
29:ad409c68c0a6 | 707 | Radio::Rx( LoRaMacParams.MaxRxWindow ); |
Wayne Roberts |
29:ad409c68c0a6 | 708 | //mac_printf("rxwinTo:%u\r\n", RxWindowsParam.RxWindowTimeout); |
Wayne Roberts |
29:ad409c68c0a6 | 709 | } |
Wayne Roberts |
29:ad409c68c0a6 | 710 | |
dudmuck | 0:8f0d0ae0a077 | 711 | static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError ); |
dudmuck | 0:8f0d0ae0a077 | 712 | |
Wayne Roberts |
29:ad409c68c0a6 | 713 | static void OnRadioTxDone_bh() |
dudmuck | 0:8f0d0ae0a077 | 714 | { |
dudmuck | 0:8f0d0ae0a077 | 715 | // Setup timers |
dudmuck | 16:915815632c1f | 716 | if (IsRxWindowsEnabled) |
dudmuck | 0:8f0d0ae0a077 | 717 | { |
Wayne Roberts |
29:ad409c68c0a6 | 718 | int delay = lpt_offset + RxWindowDelay_us; |
Wayne Roberts |
29:ad409c68c0a6 | 719 | _rx_timeout_setAt = Radio::irqAt + delay; |
Wayne Roberts |
29:ad409c68c0a6 | 720 | _rx_timeout.attach_us(&OnRxWindowTimerEvent, _rx_timeout_setAt); |
Wayne Roberts |
29:ad409c68c0a6 | 721 | if (LoRaMacFlags.Bits.NodeAckRequested) |
dudmuck | 0:8f0d0ae0a077 | 722 | { |
dudmuck | 0:8f0d0ae0a077 | 723 | AckTimeoutTimer.attach_us(&OnAckTimeoutTimerEvent, (RxWindowDelay_us/1000) + ACK_TIMEOUT_us + randr(-ACK_TIMEOUT_RND_us, ACK_TIMEOUT_RND_us)); |
dudmuck | 0:8f0d0ae0a077 | 724 | } |
dudmuck | 0:8f0d0ae0a077 | 725 | } |
dudmuck | 0:8f0d0ae0a077 | 726 | else |
dudmuck | 0:8f0d0ae0a077 | 727 | { |
dudmuck | 0:8f0d0ae0a077 | 728 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 729 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT; |
dudmuck | 0:8f0d0ae0a077 | 730 | |
dudmuck | 0:8f0d0ae0a077 | 731 | if( LoRaMacFlags.Value == 0 ) |
dudmuck | 0:8f0d0ae0a077 | 732 | { |
dudmuck | 0:8f0d0ae0a077 | 733 | LoRaMacFlags.Bits.McpsReq = 1; |
dudmuck | 0:8f0d0ae0a077 | 734 | } |
dudmuck | 0:8f0d0ae0a077 | 735 | LoRaMacFlags.Bits.MacDone = 1; |
dudmuck | 0:8f0d0ae0a077 | 736 | } |
Wayne Roberts |
29:ad409c68c0a6 | 737 | |
Wayne Roberts |
29:ad409c68c0a6 | 738 | if (!LoRaMacFlags.Bits.NodeAckRequested) |
dudmuck | 0:8f0d0ae0a077 | 739 | { |
dudmuck | 0:8f0d0ae0a077 | 740 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 741 | ChannelsNbRepCounter++; |
dudmuck | 0:8f0d0ae0a077 | 742 | } |
Wayne Roberts |
29:ad409c68c0a6 | 743 | |
dudmuck | 10:00997daeb0c0 | 744 | MlmeIndication.MlmeIndication = MLME_TXDONE; |
dudmuck | 10:00997daeb0c0 | 745 | MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
29:ad409c68c0a6 | 746 | LoRaMacPrimitives->MacMlmeIndication( &MlmeIndication ); |
Wayne Roberts |
29:ad409c68c0a6 | 747 | |
Wayne Roberts |
29:ad409c68c0a6 | 748 | Radio::Standby( ); |
Wayne Roberts |
29:ad409c68c0a6 | 749 | |
Wayne Roberts |
29:ad409c68c0a6 | 750 | txDoneAt = Radio::irqAt + lpt_offset; |
dudmuck | 16:915815632c1f | 751 | } |
dudmuck | 16:915815632c1f | 752 | |
dudmuck | 16:915815632c1f | 753 | |
dudmuck | 16:915815632c1f | 754 | static void application_callbacks() |
dudmuck | 16:915815632c1f | 755 | { |
dudmuck | 16:915815632c1f | 756 | if (LoRaMacFlags.Bits.McpsInd) { |
dudmuck | 16:915815632c1f | 757 | LoRaMacFlags.Bits.McpsInd = 0; |
dudmuck | 16:915815632c1f | 758 | LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); |
dudmuck | 16:915815632c1f | 759 | } |
Wayne Roberts |
29:ad409c68c0a6 | 760 | |
dudmuck | 16:915815632c1f | 761 | if (LoRaMacFlags.Bits.McpsReq) { |
dudmuck | 16:915815632c1f | 762 | LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm ); |
dudmuck | 16:915815632c1f | 763 | LoRaMacFlags.Bits.McpsReq = 0; |
Wayne Roberts |
29:ad409c68c0a6 | 764 | } |
dudmuck | 0:8f0d0ae0a077 | 765 | } |
dudmuck | 0:8f0d0ae0a077 | 766 | |
dudmuck | 0:8f0d0ae0a077 | 767 | static void PrepareRxDoneAbort( void ) |
dudmuck | 0:8f0d0ae0a077 | 768 | { |
Wayne Roberts |
29:ad409c68c0a6 | 769 | if (LoRaMacFlags.Bits.NodeAckRequested) |
dudmuck | 0:8f0d0ae0a077 | 770 | { |
dudmuck | 0:8f0d0ae0a077 | 771 | OnAckTimeoutTimerEvent( ); |
dudmuck | 0:8f0d0ae0a077 | 772 | } |
dudmuck | 0:8f0d0ae0a077 | 773 | |
dudmuck | 0:8f0d0ae0a077 | 774 | LoRaMacFlags.Bits.McpsInd = 1; |
dudmuck | 0:8f0d0ae0a077 | 775 | LoRaMacFlags.Bits.MacDone = 1; |
Wayne Roberts |
29:ad409c68c0a6 | 776 | |
dudmuck | 16:915815632c1f | 777 | application_callbacks(); |
dudmuck | 0:8f0d0ae0a077 | 778 | } |
dudmuck | 0:8f0d0ae0a077 | 779 | |
dudmuck | 20:42839629a5dc | 780 | void send_bh() |
Wayne Roberts |
29:ad409c68c0a6 | 781 | { |
dudmuck | 25:fed9d5b77183 | 782 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_SEND; |
dudmuck | 25:fed9d5b77183 | 783 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_SEND; |
Wayne Roberts |
29:ad409c68c0a6 | 784 | McpsConfirm.TxPower = LoRaMacParams.ChannelsTxPower; |
dudmuck | 25:fed9d5b77183 | 785 | McpsConfirm.UpLinkFrequency = Channels[Channel].Frequency; |
dudmuck | 25:fed9d5b77183 | 786 | |
Wayne Roberts |
29:ad409c68c0a6 | 787 | if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) // joining is channel hunting |
Wayne Roberts |
29:ad409c68c0a6 | 788 | Radio::SetChannel( Channels[Channel].Frequency ); |
Wayne Roberts |
29:ad409c68c0a6 | 789 | |
Wayne Roberts |
29:ad409c68c0a6 | 790 | if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) |
dudmuck | 25:fed9d5b77183 | 791 | { |
dudmuck | 25:fed9d5b77183 | 792 | JoinRequestTrials++; |
Wayne Roberts |
29:ad409c68c0a6 | 793 | mac_printf("join %luhz try%u DR%u\r\n", Channels[Channel].Frequency, JoinRequestTrials, LoRaMacParams.ChannelsDatarate_fixed); |
dudmuck | 25:fed9d5b77183 | 794 | } |
dudmuck | 25:fed9d5b77183 | 795 | |
Wayne Roberts |
29:ad409c68c0a6 | 796 | Radio::set_tx_dbm(TxPowers[LoRaMacParams.ChannelsTxPower]); |
Wayne Roberts |
29:ad409c68c0a6 | 797 | Radio::LoRaModemConfig(LORA_BANDWIDTH_KHZ, Datarates[LoRaMacParams.ChannelsDatarate_fixed], 1); |
Wayne Roberts |
29:ad409c68c0a6 | 798 | |
Wayne Roberts |
29:ad409c68c0a6 | 799 | // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
29:ad409c68c0a6 | 800 | Radio::LoRaPacketConfig(PREAMBLE_SYMBS, false, true, false); |
Wayne Roberts |
29:ad409c68c0a6 | 801 | Radio::Send(tx_buf_len, 0, 0, 0); |
Wayne Roberts |
29:ad409c68c0a6 | 802 | |
dudmuck | 25:fed9d5b77183 | 803 | LoRaMacFlags.Bits.uplink_pending = 0; // sent |
dudmuck | 25:fed9d5b77183 | 804 | |
dudmuck | 25:fed9d5b77183 | 805 | // Compute Rx1 windows parameters, taken at TxDone |
Wayne Roberts |
29:ad409c68c0a6 | 806 | if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) |
Wayne Roberts |
29:ad409c68c0a6 | 807 | RxWindowDelay_us = LoRaMacParams.JoinAcceptDelay_us - TARGET_PRECESSION_us; |
dudmuck | 25:fed9d5b77183 | 808 | else |
Wayne Roberts |
29:ad409c68c0a6 | 809 | RxWindowDelay_us = LoRaMacParams.ReceiveDelay_us - TARGET_PRECESSION_us; |
Wayne Roberts |
29:ad409c68c0a6 | 810 | |
Wayne Roberts |
29:ad409c68c0a6 | 811 | } // ..send_bh() |
dudmuck | 20:42839629a5dc | 812 | |
dudmuck | 20:42839629a5dc | 813 | void send_callback() |
Wayne Roberts |
29:ad409c68c0a6 | 814 | { |
Wayne Roberts |
29:ad409c68c0a6 | 815 | int err = 0; |
Wayne Roberts |
29:ad409c68c0a6 | 816 | us_timestamp_t now = BeaconCtx.sendAt + BeaconCtx.lastSendAtErr; |
Wayne Roberts |
29:ad409c68c0a6 | 817 | |
dudmuck | 20:42839629a5dc | 818 | if (BeaconCtx.guard) { |
dudmuck | 25:fed9d5b77183 | 819 | /* last send, this will be restarted after beacon sent */ |
dudmuck | 20:42839629a5dc | 820 | return; |
dudmuck | 20:42839629a5dc | 821 | } |
Wayne Roberts |
29:ad409c68c0a6 | 822 | BeaconCtx.sendOpportunities++; |
Wayne Roberts |
29:ad409c68c0a6 | 823 | |
Wayne Roberts |
29:ad409c68c0a6 | 824 | BeaconCtx.sendAt += BeaconCtx.periodicity_slots * PING_SLOT_RESOLUTION_us; |
Wayne Roberts |
29:ad409c68c0a6 | 825 | if (BeaconCtx.state == BEACON_STATE_LOCKED) { |
Wayne Roberts |
29:ad409c68c0a6 | 826 | float sinceBeacon = now - BeaconCtx.LastBeaconRx_us; |
Wayne Roberts |
29:ad409c68c0a6 | 827 | float ratio = sinceBeacon / BEACON_INTERVAL_us; |
Wayne Roberts |
29:ad409c68c0a6 | 828 | err = BeaconCtx.last_BeaconRxTimerError_us * ratio; |
Wayne Roberts |
29:ad409c68c0a6 | 829 | } |
Wayne Roberts |
29:ad409c68c0a6 | 830 | _tx_timeout.attach_us(&send_callback, BeaconCtx.sendAt + err); |
Wayne Roberts |
29:ad409c68c0a6 | 831 | BeaconCtx.lastSendAtErr = err; |
Wayne Roberts |
29:ad409c68c0a6 | 832 | |
Wayne Roberts |
30:1c35c4f56e50 | 833 | if (LoRaMacFlags.Bits.uplink_pending) { |
Wayne Roberts |
30:1c35c4f56e50 | 834 | us_timestamp_t untilGuard = (BeaconCtx.rx_setup_at - BEACON_GUARD_us) - BeaconCtx._timeout_guard.read_us(); |
Wayne Roberts |
30:1c35c4f56e50 | 835 | if (untilGuard > (RECEIVE_DELAY_us + TARGET_PRECESSION_us)) |
Wayne Roberts |
30:1c35c4f56e50 | 836 | LoRaMacFlags.Bits.send = 1; |
Wayne Roberts |
30:1c35c4f56e50 | 837 | } |
dudmuck | 0:8f0d0ae0a077 | 838 | } |
dudmuck | 0:8f0d0ae0a077 | 839 | |
dudmuck | 0:8f0d0ae0a077 | 840 | void OnRxBeaconSetup() |
dudmuck | 0:8f0d0ae0a077 | 841 | { |
Wayne Roberts |
30:1c35c4f56e50 | 842 | BeaconCtx.guard = false; |
Wayne Roberts |
29:ad409c68c0a6 | 843 | LoRaMacFlags.Bits.expecting_beacon = true; |
Wayne Roberts |
29:ad409c68c0a6 | 844 | |
Wayne Roberts |
29:ad409c68c0a6 | 845 | Radio::Rx(2000); |
Wayne Roberts |
29:ad409c68c0a6 | 846 | |
Wayne Roberts |
29:ad409c68c0a6 | 847 | BeaconCtx.lastSendAtErr = 0; |
dudmuck | 16:915815632c1f | 848 | } |
dudmuck | 16:915815632c1f | 849 | |
dudmuck | 16:915815632c1f | 850 | void guard_callback() |
dudmuck | 16:915815632c1f | 851 | { |
dudmuck | 16:915815632c1f | 852 | BeaconCtx.guard = true; |
Wayne Roberts |
30:1c35c4f56e50 | 853 | Radio::Standby( ); |
Wayne Roberts |
30:1c35c4f56e50 | 854 | Radio::SetChannel( Channels[Channel].Frequency ); |
dudmuck | 21:500ff43d8424 | 855 | |
Wayne Roberts |
29:ad409c68c0a6 | 856 | _tx_timeout.detach(); |
Wayne Roberts |
29:ad409c68c0a6 | 857 | mac_printf("sendOpportunities:%u\r\n", BeaconCtx.sendOpportunities); |
Wayne Roberts |
29:ad409c68c0a6 | 858 | BeaconCtx.sendOpportunities = 0; |
Wayne Roberts |
30:1c35c4f56e50 | 859 | |
Wayne Roberts |
30:1c35c4f56e50 | 860 | // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
30:1c35c4f56e50 | 861 | Radio::LoRaPacketConfig(PREAMBLE_SYMBS, true, false, false); |
Wayne Roberts |
30:1c35c4f56e50 | 862 | Radio::LoRaModemConfig(LORA_BANDWIDTH_KHZ, Datarates[BEACON_CHANNEL_DR], 1); |
Wayne Roberts |
30:1c35c4f56e50 | 863 | Radio::SetFixedPayloadLength(BEACON_SIZE); |
Wayne Roberts |
30:1c35c4f56e50 | 864 | |
Wayne Roberts |
30:1c35c4f56e50 | 865 | #ifdef SX128x_H |
Wayne Roberts |
30:1c35c4f56e50 | 866 | /* explicit to implicit header: does sx1280 really need this a 2nd time? */ |
Wayne Roberts |
30:1c35c4f56e50 | 867 | // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
30:1c35c4f56e50 | 868 | Radio::LoRaPacketConfig(PREAMBLE_SYMBS, true, false, false); |
Wayne Roberts |
30:1c35c4f56e50 | 869 | #endif /* SX128x_H */ |
Wayne Roberts |
30:1c35c4f56e50 | 870 | Radio::SetLoRaSymbolTimeout(BeaconCtx.nSymbsTimeout); |
dudmuck | 0:8f0d0ae0a077 | 871 | } |
dudmuck | 0:8f0d0ae0a077 | 872 | |
Wayne Roberts |
29:ad409c68c0a6 | 873 | static void us_to_nSymbTimeout(unsigned us) |
dudmuck | 0:8f0d0ae0a077 | 874 | { |
Wayne Roberts |
29:ad409c68c0a6 | 875 | mac_printf("symTo:%u ", us); |
Wayne Roberts |
29:ad409c68c0a6 | 876 | BeaconCtx.nSymbsTimeout = us / BeaconCtx.symbol_period_us; |
Wayne Roberts |
29:ad409c68c0a6 | 877 | if (BeaconCtx.nSymbsTimeout < (MIN_SYMBOL_TIMEOUT+BeaconCtx.Precess_symbols)) { |
Wayne Roberts |
29:ad409c68c0a6 | 878 | BeaconCtx.nSymbsTimeout = MIN_SYMBOL_TIMEOUT+BeaconCtx.Precess_symbols; |
Wayne Roberts |
29:ad409c68c0a6 | 879 | } else if (BeaconCtx.nSymbsTimeout > 255) |
Wayne Roberts |
29:ad409c68c0a6 | 880 | BeaconCtx.nSymbsTimeout = 255; |
Wayne Roberts |
29:ad409c68c0a6 | 881 | |
Wayne Roberts |
29:ad409c68c0a6 | 882 | BeaconCtx.SymbolTimeout_us = BeaconCtx.nSymbsTimeout * BeaconCtx.symbol_period_us; |
Wayne Roberts |
29:ad409c68c0a6 | 883 | mac_printf("%u\r\n", BeaconCtx.nSymbsTimeout); |
dudmuck | 0:8f0d0ae0a077 | 884 | } |
dudmuck | 0:8f0d0ae0a077 | 885 | |
dudmuck | 0:8f0d0ae0a077 | 886 | static uint16_t beacon_crc( uint8_t *buffer, uint16_t length ) |
dudmuck | 0:8f0d0ae0a077 | 887 | { |
dudmuck | 0:8f0d0ae0a077 | 888 | // The CRC calculation follows CCITT |
dudmuck | 0:8f0d0ae0a077 | 889 | const uint16_t polynom = 0x1021; |
dudmuck | 0:8f0d0ae0a077 | 890 | // CRC initial value |
dudmuck | 0:8f0d0ae0a077 | 891 | uint16_t crc = 0x0000; |
dudmuck | 0:8f0d0ae0a077 | 892 | |
dudmuck | 0:8f0d0ae0a077 | 893 | if( buffer == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 894 | { |
dudmuck | 0:8f0d0ae0a077 | 895 | return 0; |
dudmuck | 0:8f0d0ae0a077 | 896 | } |
dudmuck | 0:8f0d0ae0a077 | 897 | |
dudmuck | 0:8f0d0ae0a077 | 898 | for( uint16_t i = 0; i < length; ++i ) |
dudmuck | 0:8f0d0ae0a077 | 899 | { |
dudmuck | 0:8f0d0ae0a077 | 900 | crc ^= ( uint16_t ) buffer[i] << 8; |
dudmuck | 0:8f0d0ae0a077 | 901 | for( uint16_t j = 0; j < 8; ++j ) |
dudmuck | 0:8f0d0ae0a077 | 902 | { |
dudmuck | 0:8f0d0ae0a077 | 903 | crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 ); |
dudmuck | 0:8f0d0ae0a077 | 904 | } |
dudmuck | 0:8f0d0ae0a077 | 905 | } |
dudmuck | 0:8f0d0ae0a077 | 906 | |
dudmuck | 0:8f0d0ae0a077 | 907 | return crc; |
dudmuck | 0:8f0d0ae0a077 | 908 | } |
dudmuck | 0:8f0d0ae0a077 | 909 | |
Wayne Roberts |
29:ad409c68c0a6 | 910 | void rx_beacon(uint16_t size) |
dudmuck | 0:8f0d0ae0a077 | 911 | { |
dudmuck | 0:8f0d0ae0a077 | 912 | static bool compensate_precession = false; |
dudmuck | 0:8f0d0ae0a077 | 913 | int32_t compensation = 0; |
Wayne Roberts |
30:1c35c4f56e50 | 914 | us_timestamp_t ThisBeaconRx_us = Radio::irqAt + lpt_offset - BeaconCtx.beaconStartToRxDone; |
Wayne Roberts |
29:ad409c68c0a6 | 915 | |
Wayne Roberts |
30:1c35c4f56e50 | 916 | BeaconCtx.num_consecutive_ok++; |
Wayne Roberts |
29:ad409c68c0a6 | 917 | mac_printf("rx_beacon %llu ", Radio::irqAt); |
Wayne Roberts |
29:ad409c68c0a6 | 918 | BeaconCtx.rx_precession_us = ThisBeaconRx_us - BeaconCtx.rx_setup_at; |
dudmuck | 0:8f0d0ae0a077 | 919 | if (BeaconCtx.state != BEACON_STATE_FIRST_ACQ) { |
dudmuck | 13:18de9ee3a461 | 920 | BeaconCtx.known_working_BeaconRxTimerError_us = BeaconCtx.last_BeaconRxTimerError_us; |
Wayne Roberts |
29:ad409c68c0a6 | 921 | BeaconCtx.last_BeaconRxTimerError_us = (ThisBeaconRx_us - BeaconCtx.LastBeaconRx_us) - (BEACON_INTERVAL_us * (BeaconCtx.num_missed+1)); |
Wayne Roberts |
29:ad409c68c0a6 | 922 | |
Wayne Roberts |
29:ad409c68c0a6 | 923 | if (BeaconCtx.num_missed > 0) { |
Wayne Roberts |
29:ad409c68c0a6 | 924 | /* Timer error is measured over more than one beacon period. |
Wayne Roberts |
29:ad409c68c0a6 | 925 | * Scale to error seen over single beacon period */ |
Wayne Roberts |
29:ad409c68c0a6 | 926 | BeaconCtx.last_BeaconRxTimerError_us /= BeaconCtx.num_missed + 1; |
dudmuck | 0:8f0d0ae0a077 | 927 | } |
dudmuck | 0:8f0d0ae0a077 | 928 | |
dudmuck | 0:8f0d0ae0a077 | 929 | if (BeaconCtx.state == BEACON_STATE_ACQ_ERROR) { |
Wayne Roberts |
29:ad409c68c0a6 | 930 | mac_printf("-->LOCKED "); |
dudmuck | 21:500ff43d8424 | 931 | BeaconCtx.state = BEACON_STATE_LOCKED; |
dudmuck | 0:8f0d0ae0a077 | 932 | compensate_precession = true; |
dudmuck | 0:8f0d0ae0a077 | 933 | } |
dudmuck | 0:8f0d0ae0a077 | 934 | } else { |
dudmuck | 0:8f0d0ae0a077 | 935 | /* ignore precession at first acquisition because it has slot resolution added */ |
Wayne Roberts |
29:ad409c68c0a6 | 936 | mac_printf("-->ACQ_ERROR "); |
dudmuck | 0:8f0d0ae0a077 | 937 | // next beacon will give us our crystal error |
dudmuck | 0:8f0d0ae0a077 | 938 | BeaconCtx.state = BEACON_STATE_ACQ_ERROR; |
dudmuck | 0:8f0d0ae0a077 | 939 | } |
dudmuck | 0:8f0d0ae0a077 | 940 | |
Wayne Roberts |
29:ad409c68c0a6 | 941 | mac_printf("err%d=%llu-%llu ", BeaconCtx.last_BeaconRxTimerError_us, ThisBeaconRx_us, BeaconCtx.LastBeaconRx_us); |
Wayne Roberts |
29:ad409c68c0a6 | 942 | if (BeaconCtx.num_missed > 0) |
Wayne Roberts |
29:ad409c68c0a6 | 943 | mac_printf("missed%u ", BeaconCtx.num_missed); |
Wayne Roberts |
29:ad409c68c0a6 | 944 | |
Wayne Roberts |
29:ad409c68c0a6 | 945 | mac_printf(" rx-before-tx:%d ", BeaconCtx.rx_precession_us); |
Wayne Roberts |
29:ad409c68c0a6 | 946 | if (BeaconCtx.last_BeaconRxTimerError_us > 40000 || BeaconCtx.last_BeaconRxTimerError_us < -40000) { |
Wayne Roberts |
29:ad409c68c0a6 | 947 | BeaconCtx._timeout_rx.detach(); |
Wayne Roberts |
29:ad409c68c0a6 | 948 | BeaconCtx._timeout_guard.detach(); |
Wayne Roberts |
29:ad409c68c0a6 | 949 | mac_printf("halt\r\n"); |
Wayne Roberts |
29:ad409c68c0a6 | 950 | for (;;) asm("nop"); |
Wayne Roberts |
29:ad409c68c0a6 | 951 | } |
dudmuck | 0:8f0d0ae0a077 | 952 | BeaconCtx.LastBeaconRx_us = ThisBeaconRx_us; |
dudmuck | 0:8f0d0ae0a077 | 953 | |
dudmuck | 21:500ff43d8424 | 954 | if (BeaconCtx.state == BEACON_STATE_LOCKED) { |
dudmuck | 0:8f0d0ae0a077 | 955 | if (compensate_precession) { |
Wayne Roberts |
29:ad409c68c0a6 | 956 | compensation = BeaconCtx.rx_precession_us - TARGET_PRECESSION_us + BeaconCtx.last_BeaconRxTimerError_us; |
Wayne Roberts |
29:ad409c68c0a6 | 957 | mac_printf(" comp%ld", compensation); |
dudmuck | 0:8f0d0ae0a077 | 958 | } |
dudmuck | 0:8f0d0ae0a077 | 959 | } |
dudmuck | 0:8f0d0ae0a077 | 960 | |
Wayne Roberts |
29:ad409c68c0a6 | 961 | // reference tick for uplink schedule: when gateway started beacon |
Wayne Roberts |
29:ad409c68c0a6 | 962 | BeaconCtx.sendAt = BeaconCtx.rx_setup_at + BeaconCtx.rx_precession_us; |
Wayne Roberts |
29:ad409c68c0a6 | 963 | BeaconCtx.sendAt += BeaconCtx.tx_slot_offset * PING_SLOT_RESOLUTION_us; |
Wayne Roberts |
29:ad409c68c0a6 | 964 | _tx_timeout.attach_us(&send_callback, BeaconCtx.sendAt); |
Wayne Roberts |
29:ad409c68c0a6 | 965 | mac_printf("sendAt:%llu ", BeaconCtx.sendAt); |
Wayne Roberts |
29:ad409c68c0a6 | 966 | |
Wayne Roberts |
29:ad409c68c0a6 | 967 | BeaconCtx.rx_setup_at += BEACON_INTERVAL_us; |
Wayne Roberts |
29:ad409c68c0a6 | 968 | BeaconCtx.rx_setup_at += compensation; |
Wayne Roberts |
29:ad409c68c0a6 | 969 | |
Wayne Roberts |
29:ad409c68c0a6 | 970 | BeaconCtx._timeout_rx.attach_us(&OnRxBeaconSetup, BeaconCtx.rx_setup_at); |
Wayne Roberts |
29:ad409c68c0a6 | 971 | BeaconCtx._timeout_guard.attach_us(&guard_callback, BeaconCtx.rx_setup_at - BEACON_GUARD_us); |
dudmuck | 0:8f0d0ae0a077 | 972 | |
dudmuck | 0:8f0d0ae0a077 | 973 | BeaconCtx.num_missed = 0; |
dudmuck | 0:8f0d0ae0a077 | 974 | |
dudmuck | 0:8f0d0ae0a077 | 975 | MlmeIndication.MlmeIndication = MLME_BEACON; |
dudmuck | 0:8f0d0ae0a077 | 976 | MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED; |
dudmuck | 0:8f0d0ae0a077 | 977 | LoRaMacPrimitives->MacMlmeIndication( &MlmeIndication ); |
dudmuck | 0:8f0d0ae0a077 | 978 | |
dudmuck | 0:8f0d0ae0a077 | 979 | /* check beacon payload */ |
Wayne Roberts |
29:ad409c68c0a6 | 980 | uint16_t calc_crc = beacon_crc(Radio::radio.rx_buf, 4); |
Wayne Roberts |
29:ad409c68c0a6 | 981 | uint16_t rx_crc = Radio::radio.rx_buf[4]; |
Wayne Roberts |
29:ad409c68c0a6 | 982 | rx_crc |= Radio::radio.rx_buf[5] << 8; |
dudmuck | 0:8f0d0ae0a077 | 983 | if (rx_crc == calc_crc) { |
Wayne Roberts |
29:ad409c68c0a6 | 984 | unsigned int rx = Radio::radio.rx_buf[0]; |
Wayne Roberts |
29:ad409c68c0a6 | 985 | rx |= Radio::radio.rx_buf[1] << 8; |
Wayne Roberts |
29:ad409c68c0a6 | 986 | rx |= Radio::radio.rx_buf[2] << 16; |
Wayne Roberts |
29:ad409c68c0a6 | 987 | rx |= Radio::radio.rx_buf[3] << 24; |
dudmuck | 10:00997daeb0c0 | 988 | if (rx != 0) { |
Wayne Roberts |
29:ad409c68c0a6 | 989 | //mac_printf("beacon payload:%08x\r\n", rx); |
dudmuck | 10:00997daeb0c0 | 990 | McpsIndication.McpsIndication = MCPS_MULTICAST; |
dudmuck | 10:00997daeb0c0 | 991 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
29:ad409c68c0a6 | 992 | McpsIndication.Buffer = Radio::radio.rx_buf; |
dudmuck | 10:00997daeb0c0 | 993 | McpsIndication.BufferSize = 4; |
dudmuck | 10:00997daeb0c0 | 994 | McpsIndication.RxData = true; |
dudmuck | 16:915815632c1f | 995 | LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); |
dudmuck | 10:00997daeb0c0 | 996 | } |
dudmuck | 0:8f0d0ae0a077 | 997 | } else |
Wayne Roberts |
29:ad409c68c0a6 | 998 | mac_printf("calc_crc:%04x rx_crc:%04x\r\n", calc_crc, rx_crc); |
Wayne Roberts |
29:ad409c68c0a6 | 999 | } // ..rx_beacon() |
Wayne Roberts |
29:ad409c68c0a6 | 1000 | |
Wayne Roberts |
29:ad409c68c0a6 | 1001 | |
Wayne Roberts |
29:ad409c68c0a6 | 1002 | #define JOIN_ACCEPT_MAX_SIZE 34 |
Wayne Roberts |
29:ad409c68c0a6 | 1003 | static void OnRadioRxDone(uint8_t size, float rssi, float snr ) |
dudmuck | 0:8f0d0ae0a077 | 1004 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1005 | uint8_t _jaDecrypted[JOIN_ACCEPT_MAX_SIZE]; |
dudmuck | 0:8f0d0ae0a077 | 1006 | LoRaMacHeader_t macHdr; |
dudmuck | 0:8f0d0ae0a077 | 1007 | LoRaMacFrameCtrl_t fCtrl; |
dudmuck | 0:8f0d0ae0a077 | 1008 | bool skipIndication = false; |
dudmuck | 0:8f0d0ae0a077 | 1009 | |
dudmuck | 0:8f0d0ae0a077 | 1010 | uint8_t pktHeaderLen = 0; |
dudmuck | 0:8f0d0ae0a077 | 1011 | uint32_t address = 0; |
dudmuck | 0:8f0d0ae0a077 | 1012 | uint8_t appPayloadStartIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 1013 | uint8_t port = 0xFF; |
dudmuck | 0:8f0d0ae0a077 | 1014 | uint8_t frameLen = 0; |
dudmuck | 0:8f0d0ae0a077 | 1015 | uint32_t mic = 0; |
dudmuck | 0:8f0d0ae0a077 | 1016 | uint32_t micRx = 0; |
dudmuck | 0:8f0d0ae0a077 | 1017 | |
dudmuck | 0:8f0d0ae0a077 | 1018 | uint16_t sequenceCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 1019 | uint16_t sequenceCounterPrev = 0; |
dudmuck | 0:8f0d0ae0a077 | 1020 | uint16_t sequenceCounterDiff = 0; |
dudmuck | 0:8f0d0ae0a077 | 1021 | uint32_t downLinkCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 1022 | |
dudmuck | 0:8f0d0ae0a077 | 1023 | MulticastParams_t *curMulticastParams = NULL; |
dudmuck | 0:8f0d0ae0a077 | 1024 | uint8_t *nwkSKey = LoRaMacNwkSKey; |
dudmuck | 0:8f0d0ae0a077 | 1025 | uint8_t *appSKey = LoRaMacAppSKey; |
dudmuck | 0:8f0d0ae0a077 | 1026 | |
dudmuck | 0:8f0d0ae0a077 | 1027 | uint8_t multicast = 0; |
dudmuck | 0:8f0d0ae0a077 | 1028 | |
dudmuck | 0:8f0d0ae0a077 | 1029 | bool isMicOk = false; |
dudmuck | 0:8f0d0ae0a077 | 1030 | |
dudmuck | 0:8f0d0ae0a077 | 1031 | McpsConfirm.AckReceived = false; |
dudmuck | 0:8f0d0ae0a077 | 1032 | McpsIndication.Rssi = rssi; |
dudmuck | 0:8f0d0ae0a077 | 1033 | McpsIndication.Snr = snr; |
dudmuck | 0:8f0d0ae0a077 | 1034 | McpsIndication.Port = 0; |
dudmuck | 0:8f0d0ae0a077 | 1035 | McpsIndication.Multicast = 0; |
dudmuck | 0:8f0d0ae0a077 | 1036 | McpsIndication.FramePending = 0; |
dudmuck | 0:8f0d0ae0a077 | 1037 | McpsIndication.Buffer = NULL; |
dudmuck | 0:8f0d0ae0a077 | 1038 | McpsIndication.BufferSize = 0; |
dudmuck | 0:8f0d0ae0a077 | 1039 | McpsIndication.RxData = false; |
dudmuck | 0:8f0d0ae0a077 | 1040 | McpsIndication.AckReceived = false; |
dudmuck | 0:8f0d0ae0a077 | 1041 | McpsIndication.DownLinkCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 1042 | McpsIndication.McpsIndication = MCPS_UNCONFIRMED; |
dudmuck | 0:8f0d0ae0a077 | 1043 | |
Wayne Roberts |
29:ad409c68c0a6 | 1044 | Radio::Sleep( ); |
Wayne Roberts |
29:ad409c68c0a6 | 1045 | |
Wayne Roberts |
29:ad409c68c0a6 | 1046 | //mac_printf("OnRadioRxDone %u", size); |
Wayne Roberts |
29:ad409c68c0a6 | 1047 | if (LoRaMacFlags.Bits.expecting_beacon) { |
Wayne Roberts |
29:ad409c68c0a6 | 1048 | rx_beacon(size); |
Wayne Roberts |
29:ad409c68c0a6 | 1049 | LoRaMacFlags.Bits.expecting_beacon = false; |
dudmuck | 0:8f0d0ae0a077 | 1050 | return; |
dudmuck | 0:8f0d0ae0a077 | 1051 | } |
dudmuck | 0:8f0d0ae0a077 | 1052 | |
Wayne Roberts |
29:ad409c68c0a6 | 1053 | macHdr.Value = Radio::radio.rx_buf[pktHeaderLen++]; |
Wayne Roberts |
29:ad409c68c0a6 | 1054 | //mac_printf("mtype:%x\r\n", macHdr.Bits.MType); |
dudmuck | 0:8f0d0ae0a077 | 1055 | |
dudmuck | 0:8f0d0ae0a077 | 1056 | switch( macHdr.Bits.MType ) |
dudmuck | 0:8f0d0ae0a077 | 1057 | { |
dudmuck | 0:8f0d0ae0a077 | 1058 | case FRAME_TYPE_JOIN_ACCEPT: |
Wayne Roberts |
29:ad409c68c0a6 | 1059 | if (LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) |
dudmuck | 0:8f0d0ae0a077 | 1060 | { |
dudmuck | 2:f2d9aa163652 | 1061 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_JOIN_ACCEPT; |
dudmuck | 0:8f0d0ae0a077 | 1062 | PrepareRxDoneAbort( ); |
dudmuck | 0:8f0d0ae0a077 | 1063 | return; |
dudmuck | 0:8f0d0ae0a077 | 1064 | } |
Wayne Roberts |
29:ad409c68c0a6 | 1065 | LoRaMacJoinDecrypt( Radio::radio.rx_buf + 1, size - 1, LoRaMacAppKey, &_jaDecrypted[1]); |
Wayne Roberts |
29:ad409c68c0a6 | 1066 | |
Wayne Roberts |
29:ad409c68c0a6 | 1067 | _jaDecrypted[0] = macHdr.Value; |
Wayne Roberts |
29:ad409c68c0a6 | 1068 | |
Wayne Roberts |
29:ad409c68c0a6 | 1069 | LoRaMacJoinComputeMic( _jaDecrypted, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic ); |
Wayne Roberts |
29:ad409c68c0a6 | 1070 | |
Wayne Roberts |
29:ad409c68c0a6 | 1071 | micRx |= ( uint32_t )_jaDecrypted[size - LORAMAC_MFR_LEN]; |
Wayne Roberts |
29:ad409c68c0a6 | 1072 | micRx |= ( ( uint32_t )_jaDecrypted[size - LORAMAC_MFR_LEN + 1] << 8 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1073 | micRx |= ( ( uint32_t )_jaDecrypted[size - LORAMAC_MFR_LEN + 2] << 16 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1074 | micRx |= ( ( uint32_t )_jaDecrypted[size - LORAMAC_MFR_LEN + 3] << 24 ); |
dudmuck | 0:8f0d0ae0a077 | 1075 | |
dudmuck | 0:8f0d0ae0a077 | 1076 | if( micRx == mic ) |
dudmuck | 0:8f0d0ae0a077 | 1077 | { |
Wayne Roberts |
30:1c35c4f56e50 | 1078 | uint32_t beaconDur; |
Wayne Roberts |
29:ad409c68c0a6 | 1079 | LoRaMacJoinComputeSKeys( LoRaMacAppKey, _jaDecrypted + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey ); |
Wayne Roberts |
29:ad409c68c0a6 | 1080 | |
Wayne Roberts |
29:ad409c68c0a6 | 1081 | LoRaMacNetID = ( uint32_t )_jaDecrypted[4]; |
Wayne Roberts |
29:ad409c68c0a6 | 1082 | LoRaMacNetID |= ( ( uint32_t )_jaDecrypted[5] << 8 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1083 | LoRaMacNetID |= ( ( uint32_t )_jaDecrypted[6] << 16 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1084 | |
Wayne Roberts |
29:ad409c68c0a6 | 1085 | LoRaMacDevAddr = ( uint32_t )_jaDecrypted[7]; |
Wayne Roberts |
29:ad409c68c0a6 | 1086 | LoRaMacDevAddr |= ( ( uint32_t )_jaDecrypted[8] << 8 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1087 | LoRaMacDevAddr |= ( ( uint32_t )_jaDecrypted[9] << 16 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1088 | LoRaMacDevAddr |= ( ( uint32_t )_jaDecrypted[10] << 24 ); |
dudmuck | 0:8f0d0ae0a077 | 1089 | |
dudmuck | 0:8f0d0ae0a077 | 1090 | // DLSettings |
Wayne Roberts |
29:ad409c68c0a6 | 1091 | LoRaMacParams.Rx1DrOffset = ( _jaDecrypted[11] >> 4 ) & 0x07; |
Wayne Roberts |
29:ad409c68c0a6 | 1092 | |
Wayne Roberts |
29:ad409c68c0a6 | 1093 | LoRaMacParams.ReceiveDelay_us = ( _jaDecrypted[12] & 0x0F ); |
dudmuck | 0:8f0d0ae0a077 | 1094 | if( LoRaMacParams.ReceiveDelay_us == 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1095 | LoRaMacParams.ReceiveDelay_us = RECEIVE_DELAY_us; |
dudmuck | 0:8f0d0ae0a077 | 1096 | else |
dudmuck | 0:8f0d0ae0a077 | 1097 | LoRaMacParams.ReceiveDelay_us *= 10; |
dudmuck | 0:8f0d0ae0a077 | 1098 | |
Wayne Roberts |
29:ad409c68c0a6 | 1099 | uint16_t beaconTimingDelay = _jaDecrypted[13] & 0xff; |
Wayne Roberts |
29:ad409c68c0a6 | 1100 | beaconTimingDelay |= _jaDecrypted[14] << 8; |
Wayne Roberts |
29:ad409c68c0a6 | 1101 | |
Wayne Roberts |
29:ad409c68c0a6 | 1102 | mac_printf("%lx slots:%x (rxdelay %lu)", LoRaMacDevAddr, beaconTimingDelay, LoRaMacParams.ReceiveDelay_us); |
Wayne Roberts |
29:ad409c68c0a6 | 1103 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1104 | unsigned us_to_beacon = ( PING_SLOT_RESOLUTION_us * beaconTimingDelay ); |
Wayne Roberts |
29:ad409c68c0a6 | 1105 | mac_printf(" us_to_beacon:%u ", us_to_beacon); |
Wayne Roberts |
29:ad409c68c0a6 | 1106 | // time to beacon given as referenced to end of join request uplink |
Wayne Roberts |
29:ad409c68c0a6 | 1107 | BeaconCtx.rx_setup_at = txDoneAt + us_to_beacon - PPM_BEACON_INTERVAL; |
Wayne Roberts |
29:ad409c68c0a6 | 1108 | BeaconCtx._timeout_rx.attach_us(&OnRxBeaconSetup, BeaconCtx.rx_setup_at); |
Wayne Roberts |
29:ad409c68c0a6 | 1109 | BeaconCtx._timeout_guard.attach_us(&guard_callback, BeaconCtx.rx_setup_at - BEACON_GUARD_us); |
Wayne Roberts |
29:ad409c68c0a6 | 1110 | |
Wayne Roberts |
29:ad409c68c0a6 | 1111 | mac_printf("beaconIn:%llu\r\n", BeaconCtx.rx_setup_at - BeaconCtx._timeout_rx.read_us()); |
Wayne Roberts |
29:ad409c68c0a6 | 1112 | } |
Wayne Roberts |
29:ad409c68c0a6 | 1113 | |
Wayne Roberts |
29:ad409c68c0a6 | 1114 | BeaconCtx.tx_slot_offset = _jaDecrypted[15]; |
Wayne Roberts |
29:ad409c68c0a6 | 1115 | BeaconCtx.tx_slot_offset |= _jaDecrypted[16] << 8; |
Wayne Roberts |
29:ad409c68c0a6 | 1116 | BeaconCtx.periodicity_slots = _jaDecrypted[17]; |
Wayne Roberts |
29:ad409c68c0a6 | 1117 | BeaconCtx.periodicity_slots |= _jaDecrypted[18] << 8; |
Wayne Roberts |
29:ad409c68c0a6 | 1118 | |
Wayne Roberts |
30:1c35c4f56e50 | 1119 | beaconDur = _jaDecrypted[22]; |
Wayne Roberts |
30:1c35c4f56e50 | 1120 | beaconDur <<= 8; |
Wayne Roberts |
30:1c35c4f56e50 | 1121 | beaconDur |= _jaDecrypted[21]; |
Wayne Roberts |
30:1c35c4f56e50 | 1122 | beaconDur <<= 8; |
Wayne Roberts |
30:1c35c4f56e50 | 1123 | beaconDur |= _jaDecrypted[20]; |
Wayne Roberts |
30:1c35c4f56e50 | 1124 | beaconDur <<= 8; |
Wayne Roberts |
30:1c35c4f56e50 | 1125 | beaconDur |= _jaDecrypted[19]; |
Wayne Roberts |
30:1c35c4f56e50 | 1126 | BeaconCtx.beaconStartToRxDone = beaconDur + (rxLatencyFactorFromSF[SF_FROM_DR_(LORAMAC_DEFAULT_DATARATE)-FASTEST_SF] * BeaconCtx.symbol_period_us); |
Wayne Roberts |
30:1c35c4f56e50 | 1127 | |
Wayne Roberts |
30:1c35c4f56e50 | 1128 | |
Wayne Roberts |
29:ad409c68c0a6 | 1129 | /* nowSlot: now vs previous beacon */ |
Wayne Roberts |
29:ad409c68c0a6 | 1130 | BeaconCtx.LastBeaconRx_us = BeaconCtx.rx_setup_at - BEACON_INTERVAL_us; |
Wayne Roberts |
29:ad409c68c0a6 | 1131 | unsigned us_since_last_beacon = _rx_timeout.read_us() - BeaconCtx.LastBeaconRx_us; |
Wayne Roberts |
29:ad409c68c0a6 | 1132 | unsigned nowSlot = us_since_last_beacon / PING_SLOT_RESOLUTION_us; |
Wayne Roberts |
29:ad409c68c0a6 | 1133 | unsigned useSlot = BeaconCtx.tx_slot_offset; |
Wayne Roberts |
29:ad409c68c0a6 | 1134 | while (useSlot < nowSlot) |
Wayne Roberts |
29:ad409c68c0a6 | 1135 | useSlot += BeaconCtx.periodicity_slots; |
Wayne Roberts |
29:ad409c68c0a6 | 1136 | |
Wayne Roberts |
30:1c35c4f56e50 | 1137 | mac_printf("beaconDur:0x%x (%u) useSlot:%u nowSlot:%u ", beaconDur, BeaconCtx.beaconStartToRxDone, useSlot, nowSlot); |
Wayne Roberts |
29:ad409c68c0a6 | 1138 | BeaconCtx.sendAt = BeaconCtx.LastBeaconRx_us + (useSlot * PING_SLOT_RESOLUTION_us); |
Wayne Roberts |
29:ad409c68c0a6 | 1139 | mac_printf("sendIn:%u\r\n", BeaconCtx.sendAt - _tx_timeout.read_us()); |
Wayne Roberts |
29:ad409c68c0a6 | 1140 | _tx_timeout.attach_us(send_callback, BeaconCtx.sendAt); |
Wayne Roberts |
29:ad409c68c0a6 | 1141 | BeaconCtx.sendOpportunities = 0; |
Wayne Roberts |
29:ad409c68c0a6 | 1142 | |
dudmuck | 0:8f0d0ae0a077 | 1143 | BeaconCtx.state = BEACON_STATE_FIRST_ACQ; |
dudmuck | 16:915815632c1f | 1144 | BeaconCtx.guard = false; |
dudmuck | 0:8f0d0ae0a077 | 1145 | BeaconCtx.num_missed = 0; |
dudmuck | 0:8f0d0ae0a077 | 1146 | BeaconCtx.rx_precession_us = 0; |
Wayne Roberts |
30:1c35c4f56e50 | 1147 | BeaconCtx.num_consecutive_ok = 0; |
Wayne Roberts |
29:ad409c68c0a6 | 1148 | BeaconCtx.last_BeaconRxTimerError_us = -PPM_BEACON_INTERVAL; |
Wayne Roberts |
29:ad409c68c0a6 | 1149 | BeaconCtx.known_working_BeaconRxTimerError_us = -PPM_BEACON_INTERVAL; |
Wayne Roberts |
29:ad409c68c0a6 | 1150 | /* first beacon reception needs to open for 30ms timing resolution */ |
dudmuck | 32:ac904adfc842 | 1151 | BeaconCtx.Precess_symbols = ceil((float)(TARGET_PRECESSION_us / BeaconCtx.symbol_period_us)); |
Wayne Roberts |
30:1c35c4f56e50 | 1152 | BeaconCtx.SymbolTimeout_us = PING_SLOT_RESOLUTION_us + (PPM_BEACON_INTERVAL * 4); // error unknown at start |
Wayne Roberts |
29:ad409c68c0a6 | 1153 | BeaconCtx.nSymbsTimeout = BeaconCtx.SymbolTimeout_us / BeaconCtx.symbol_period_us; |
Wayne Roberts |
29:ad409c68c0a6 | 1154 | if (BeaconCtx.nSymbsTimeout < MIN_SYMBOL_TIMEOUT) |
Wayne Roberts |
29:ad409c68c0a6 | 1155 | BeaconCtx.nSymbsTimeout = MIN_SYMBOL_TIMEOUT; |
Wayne Roberts |
29:ad409c68c0a6 | 1156 | else if (BeaconCtx.nSymbsTimeout > 255) |
Wayne Roberts |
29:ad409c68c0a6 | 1157 | BeaconCtx.nSymbsTimeout = 255; |
Wayne Roberts |
29:ad409c68c0a6 | 1158 | mac_printf("startSymbTo:%u ", BeaconCtx.nSymbsTimeout); |
dudmuck | 0:8f0d0ae0a077 | 1159 | |
dudmuck | 0:8f0d0ae0a077 | 1160 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
29:ad409c68c0a6 | 1161 | LoRaMacFlags.Bits.IsLoRaMacNetworkJoined = true; |
dudmuck | 0:8f0d0ae0a077 | 1162 | LoRaMacParams.ChannelsDatarate_fixed = LoRaMacParamsDefaults.ChannelsDatarate_fixed; |
dudmuck | 0:8f0d0ae0a077 | 1163 | } |
dudmuck | 0:8f0d0ae0a077 | 1164 | else |
dudmuck | 0:8f0d0ae0a077 | 1165 | { |
dudmuck | 0:8f0d0ae0a077 | 1166 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL; |
Wayne Roberts |
30:1c35c4f56e50 | 1167 | mac_printf("join-mic-fail size:%u\r\n", size); |
dudmuck | 0:8f0d0ae0a077 | 1168 | JoinRequestTrials = MaxJoinRequestTrials; // stop trying |
dudmuck | 0:8f0d0ae0a077 | 1169 | } |
dudmuck | 16:915815632c1f | 1170 | LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm ); |
dudmuck | 16:915815632c1f | 1171 | LoRaMacFlags.Bits.MlmeReq = 0; // MacMlmeConfirm() called |
dudmuck | 0:8f0d0ae0a077 | 1172 | break; |
dudmuck | 0:8f0d0ae0a077 | 1173 | case FRAME_TYPE_DATA_CONFIRMED_DOWN: |
dudmuck | 0:8f0d0ae0a077 | 1174 | case FRAME_TYPE_DATA_UNCONFIRMED_DOWN: |
dudmuck | 0:8f0d0ae0a077 | 1175 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1176 | address = Radio::radio.rx_buf[pktHeaderLen++]; |
Wayne Roberts |
29:ad409c68c0a6 | 1177 | address |= ( (uint32_t)Radio::radio.rx_buf[pktHeaderLen++] << 8 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1178 | address |= ( (uint32_t)Radio::radio.rx_buf[pktHeaderLen++] << 16 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1179 | address |= ( (uint32_t)Radio::radio.rx_buf[pktHeaderLen++] << 24 ); |
dudmuck | 0:8f0d0ae0a077 | 1180 | |
dudmuck | 0:8f0d0ae0a077 | 1181 | if( address != LoRaMacDevAddr ) |
dudmuck | 0:8f0d0ae0a077 | 1182 | { |
dudmuck | 0:8f0d0ae0a077 | 1183 | curMulticastParams = MulticastChannels; |
dudmuck | 0:8f0d0ae0a077 | 1184 | while( curMulticastParams != NULL ) |
dudmuck | 0:8f0d0ae0a077 | 1185 | { |
dudmuck | 0:8f0d0ae0a077 | 1186 | if( address == curMulticastParams->Address ) |
dudmuck | 0:8f0d0ae0a077 | 1187 | { |
dudmuck | 0:8f0d0ae0a077 | 1188 | multicast = 1; |
dudmuck | 0:8f0d0ae0a077 | 1189 | nwkSKey = curMulticastParams->NwkSKey; |
dudmuck | 0:8f0d0ae0a077 | 1190 | appSKey = curMulticastParams->AppSKey; |
dudmuck | 0:8f0d0ae0a077 | 1191 | downLinkCounter = curMulticastParams->DownLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1192 | break; |
dudmuck | 0:8f0d0ae0a077 | 1193 | } |
dudmuck | 0:8f0d0ae0a077 | 1194 | curMulticastParams = curMulticastParams->Next; |
dudmuck | 0:8f0d0ae0a077 | 1195 | } |
dudmuck | 0:8f0d0ae0a077 | 1196 | if( multicast == 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1197 | { |
dudmuck | 0:8f0d0ae0a077 | 1198 | // We are not the destination of this frame. |
dudmuck | 0:8f0d0ae0a077 | 1199 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL; |
dudmuck | 0:8f0d0ae0a077 | 1200 | PrepareRxDoneAbort( ); |
dudmuck | 0:8f0d0ae0a077 | 1201 | return; |
dudmuck | 0:8f0d0ae0a077 | 1202 | } |
dudmuck | 0:8f0d0ae0a077 | 1203 | } |
dudmuck | 0:8f0d0ae0a077 | 1204 | else |
dudmuck | 0:8f0d0ae0a077 | 1205 | { |
dudmuck | 0:8f0d0ae0a077 | 1206 | multicast = 0; |
dudmuck | 0:8f0d0ae0a077 | 1207 | nwkSKey = LoRaMacNwkSKey; |
dudmuck | 0:8f0d0ae0a077 | 1208 | appSKey = LoRaMacAppSKey; |
dudmuck | 0:8f0d0ae0a077 | 1209 | downLinkCounter = DownLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1210 | } |
dudmuck | 0:8f0d0ae0a077 | 1211 | |
Wayne Roberts |
29:ad409c68c0a6 | 1212 | fCtrl.Value = Radio::radio.rx_buf[pktHeaderLen++]; |
Wayne Roberts |
29:ad409c68c0a6 | 1213 | |
Wayne Roberts |
29:ad409c68c0a6 | 1214 | sequenceCounter = ( uint16_t )Radio::radio.rx_buf[pktHeaderLen++]; |
Wayne Roberts |
29:ad409c68c0a6 | 1215 | sequenceCounter |= ( uint16_t )Radio::radio.rx_buf[pktHeaderLen++] << 8; |
dudmuck | 0:8f0d0ae0a077 | 1216 | |
dudmuck | 0:8f0d0ae0a077 | 1217 | appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen; |
dudmuck | 0:8f0d0ae0a077 | 1218 | |
Wayne Roberts |
29:ad409c68c0a6 | 1219 | micRx |= ( uint32_t )Radio::radio.rx_buf[size - LORAMAC_MFR_LEN]; |
Wayne Roberts |
29:ad409c68c0a6 | 1220 | micRx |= ( ( uint32_t )Radio::radio.rx_buf[size - LORAMAC_MFR_LEN + 1] << 8 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1221 | micRx |= ( ( uint32_t )Radio::radio.rx_buf[size - LORAMAC_MFR_LEN + 2] << 16 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1222 | micRx |= ( ( uint32_t )Radio::radio.rx_buf[size - LORAMAC_MFR_LEN + 3] << 24 ); |
dudmuck | 0:8f0d0ae0a077 | 1223 | |
dudmuck | 0:8f0d0ae0a077 | 1224 | sequenceCounterPrev = ( uint16_t )downLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1225 | sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev ); |
dudmuck | 0:8f0d0ae0a077 | 1226 | |
dudmuck | 0:8f0d0ae0a077 | 1227 | if( sequenceCounterDiff < ( 1 << 15 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1228 | { |
dudmuck | 0:8f0d0ae0a077 | 1229 | downLinkCounter += sequenceCounterDiff; |
Wayne Roberts |
29:ad409c68c0a6 | 1230 | LoRaMacComputeMic( Radio::radio.rx_buf, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic ); |
dudmuck | 0:8f0d0ae0a077 | 1231 | if( micRx == mic ) |
dudmuck | 0:8f0d0ae0a077 | 1232 | { |
dudmuck | 0:8f0d0ae0a077 | 1233 | isMicOk = true; |
dudmuck | 0:8f0d0ae0a077 | 1234 | } |
dudmuck | 0:8f0d0ae0a077 | 1235 | } |
dudmuck | 0:8f0d0ae0a077 | 1236 | else |
dudmuck | 0:8f0d0ae0a077 | 1237 | { |
dudmuck | 0:8f0d0ae0a077 | 1238 | // check for sequence roll-over |
dudmuck | 0:8f0d0ae0a077 | 1239 | uint32_t downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff; |
Wayne Roberts |
29:ad409c68c0a6 | 1240 | LoRaMacComputeMic( Radio::radio.rx_buf, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic ); |
dudmuck | 0:8f0d0ae0a077 | 1241 | if( micRx == mic ) |
dudmuck | 0:8f0d0ae0a077 | 1242 | { |
dudmuck | 0:8f0d0ae0a077 | 1243 | isMicOk = true; |
dudmuck | 0:8f0d0ae0a077 | 1244 | downLinkCounter = downLinkCounterTmp; |
dudmuck | 0:8f0d0ae0a077 | 1245 | } |
dudmuck | 0:8f0d0ae0a077 | 1246 | } |
dudmuck | 0:8f0d0ae0a077 | 1247 | |
dudmuck | 0:8f0d0ae0a077 | 1248 | // Check for a the maximum allowed counter difference |
dudmuck | 0:8f0d0ae0a077 | 1249 | if( sequenceCounterDiff >= MAX_FCNT_GAP ) |
dudmuck | 0:8f0d0ae0a077 | 1250 | { |
dudmuck | 0:8f0d0ae0a077 | 1251 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS; |
dudmuck | 0:8f0d0ae0a077 | 1252 | McpsIndication.DownLinkCounter = downLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1253 | PrepareRxDoneAbort( ); |
dudmuck | 0:8f0d0ae0a077 | 1254 | return; |
dudmuck | 0:8f0d0ae0a077 | 1255 | } |
dudmuck | 0:8f0d0ae0a077 | 1256 | |
dudmuck | 0:8f0d0ae0a077 | 1257 | if( isMicOk == true ) |
dudmuck | 0:8f0d0ae0a077 | 1258 | { |
dudmuck | 0:8f0d0ae0a077 | 1259 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1260 | McpsIndication.Multicast = multicast; |
dudmuck | 0:8f0d0ae0a077 | 1261 | McpsIndication.FramePending = fCtrl.Bits.FPending; |
dudmuck | 0:8f0d0ae0a077 | 1262 | McpsIndication.Buffer = NULL; |
dudmuck | 0:8f0d0ae0a077 | 1263 | McpsIndication.BufferSize = 0; |
dudmuck | 0:8f0d0ae0a077 | 1264 | McpsIndication.DownLinkCounter = downLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1265 | |
dudmuck | 0:8f0d0ae0a077 | 1266 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1267 | |
dudmuck | 0:8f0d0ae0a077 | 1268 | MacCommandsBufferToRepeatIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 1269 | |
dudmuck | 0:8f0d0ae0a077 | 1270 | // Update 32 bits downlink counter |
dudmuck | 0:8f0d0ae0a077 | 1271 | if( multicast == 1 ) |
dudmuck | 0:8f0d0ae0a077 | 1272 | { |
dudmuck | 0:8f0d0ae0a077 | 1273 | McpsIndication.McpsIndication = MCPS_MULTICAST; |
dudmuck | 0:8f0d0ae0a077 | 1274 | |
dudmuck | 0:8f0d0ae0a077 | 1275 | if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) && |
dudmuck | 0:8f0d0ae0a077 | 1276 | ( curMulticastParams->DownLinkCounter != 0 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1277 | { |
dudmuck | 0:8f0d0ae0a077 | 1278 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; |
dudmuck | 0:8f0d0ae0a077 | 1279 | McpsIndication.DownLinkCounter = downLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1280 | PrepareRxDoneAbort( ); |
dudmuck | 0:8f0d0ae0a077 | 1281 | return; |
dudmuck | 0:8f0d0ae0a077 | 1282 | } |
dudmuck | 0:8f0d0ae0a077 | 1283 | curMulticastParams->DownLinkCounter = downLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1284 | } |
dudmuck | 0:8f0d0ae0a077 | 1285 | else |
dudmuck | 0:8f0d0ae0a077 | 1286 | { |
dudmuck | 0:8f0d0ae0a077 | 1287 | if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN ) |
dudmuck | 0:8f0d0ae0a077 | 1288 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1289 | LoRaMacFlags.Bits.SrvAckRequested = true; |
dudmuck | 0:8f0d0ae0a077 | 1290 | McpsIndication.McpsIndication = MCPS_CONFIRMED; |
dudmuck | 0:8f0d0ae0a077 | 1291 | |
dudmuck | 0:8f0d0ae0a077 | 1292 | if( ( DownLinkCounter == downLinkCounter ) && |
dudmuck | 0:8f0d0ae0a077 | 1293 | ( DownLinkCounter != 0 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1294 | { |
dudmuck | 0:8f0d0ae0a077 | 1295 | // Duplicated confirmed downlink. Skip indication. |
dudmuck | 0:8f0d0ae0a077 | 1296 | // In this case, the MAC layer shall accept the MAC commands |
dudmuck | 0:8f0d0ae0a077 | 1297 | // which are included in the downlink retransmission. |
dudmuck | 0:8f0d0ae0a077 | 1298 | // It should not provide the same frame to the application |
dudmuck | 0:8f0d0ae0a077 | 1299 | // layer again. |
dudmuck | 0:8f0d0ae0a077 | 1300 | skipIndication = true; |
dudmuck | 0:8f0d0ae0a077 | 1301 | } |
dudmuck | 0:8f0d0ae0a077 | 1302 | } |
dudmuck | 0:8f0d0ae0a077 | 1303 | else |
dudmuck | 0:8f0d0ae0a077 | 1304 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1305 | LoRaMacFlags.Bits.SrvAckRequested = false; |
dudmuck | 0:8f0d0ae0a077 | 1306 | McpsIndication.McpsIndication = MCPS_UNCONFIRMED; |
dudmuck | 0:8f0d0ae0a077 | 1307 | |
dudmuck | 0:8f0d0ae0a077 | 1308 | if( ( DownLinkCounter == downLinkCounter ) && |
dudmuck | 0:8f0d0ae0a077 | 1309 | ( DownLinkCounter != 0 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1310 | { |
dudmuck | 0:8f0d0ae0a077 | 1311 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; |
dudmuck | 0:8f0d0ae0a077 | 1312 | McpsIndication.DownLinkCounter = downLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1313 | PrepareRxDoneAbort( ); |
dudmuck | 0:8f0d0ae0a077 | 1314 | return; |
dudmuck | 0:8f0d0ae0a077 | 1315 | } |
dudmuck | 0:8f0d0ae0a077 | 1316 | } |
dudmuck | 0:8f0d0ae0a077 | 1317 | DownLinkCounter = downLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1318 | } |
dudmuck | 0:8f0d0ae0a077 | 1319 | |
dudmuck | 0:8f0d0ae0a077 | 1320 | // This must be done before parsing the payload and the MAC commands. |
dudmuck | 0:8f0d0ae0a077 | 1321 | // We need to reset the MacCommandsBufferIndex here, since we need |
dudmuck | 0:8f0d0ae0a077 | 1322 | // to take retransmissions and repititions into account. Error cases |
dudmuck | 0:8f0d0ae0a077 | 1323 | // will be handled in function OnMacStateCheckTimerEvent. |
dudmuck | 0:8f0d0ae0a077 | 1324 | if( McpsConfirm.McpsRequest == MCPS_CONFIRMED ) |
dudmuck | 0:8f0d0ae0a077 | 1325 | { |
dudmuck | 0:8f0d0ae0a077 | 1326 | if( fCtrl.Bits.Ack == 1 ) |
dudmuck | 0:8f0d0ae0a077 | 1327 | {// Reset MacCommandsBufferIndex when we have received an ACK. |
dudmuck | 0:8f0d0ae0a077 | 1328 | MacCommandsBufferIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 1329 | } |
dudmuck | 0:8f0d0ae0a077 | 1330 | } |
dudmuck | 0:8f0d0ae0a077 | 1331 | else |
dudmuck | 0:8f0d0ae0a077 | 1332 | {// Reset the variable if we have received any valid frame. |
dudmuck | 0:8f0d0ae0a077 | 1333 | MacCommandsBufferIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 1334 | } |
dudmuck | 0:8f0d0ae0a077 | 1335 | |
dudmuck | 0:8f0d0ae0a077 | 1336 | // Process payload and MAC commands |
dudmuck | 0:8f0d0ae0a077 | 1337 | if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1338 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1339 | port = Radio::radio.rx_buf[appPayloadStartIndex++]; |
dudmuck | 0:8f0d0ae0a077 | 1340 | frameLen = ( size - 4 ) - appPayloadStartIndex; |
dudmuck | 0:8f0d0ae0a077 | 1341 | |
dudmuck | 0:8f0d0ae0a077 | 1342 | McpsIndication.Port = port; |
dudmuck | 0:8f0d0ae0a077 | 1343 | |
dudmuck | 0:8f0d0ae0a077 | 1344 | if( port == 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1345 | { |
dudmuck | 0:8f0d0ae0a077 | 1346 | // Only allow frames which do not have fOpts |
dudmuck | 0:8f0d0ae0a077 | 1347 | if( fCtrl.Bits.FOptsLen == 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1348 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1349 | uint8_t macDecrypt[16]; |
Wayne Roberts |
29:ad409c68c0a6 | 1350 | LoRaMacPayloadDecrypt( Radio::radio.rx_buf + appPayloadStartIndex, |
dudmuck | 0:8f0d0ae0a077 | 1351 | frameLen, |
dudmuck | 0:8f0d0ae0a077 | 1352 | nwkSKey, |
dudmuck | 0:8f0d0ae0a077 | 1353 | address, |
dudmuck | 0:8f0d0ae0a077 | 1354 | DOWN_LINK, |
dudmuck | 0:8f0d0ae0a077 | 1355 | downLinkCounter, |
Wayne Roberts |
29:ad409c68c0a6 | 1356 | macDecrypt); |
dudmuck | 0:8f0d0ae0a077 | 1357 | |
dudmuck | 0:8f0d0ae0a077 | 1358 | // Decode frame payload MAC commands |
Wayne Roberts |
29:ad409c68c0a6 | 1359 | ProcessMacCommands( macDecrypt, 0, frameLen, snr ); |
dudmuck | 0:8f0d0ae0a077 | 1360 | } |
dudmuck | 0:8f0d0ae0a077 | 1361 | else |
dudmuck | 0:8f0d0ae0a077 | 1362 | { |
dudmuck | 0:8f0d0ae0a077 | 1363 | skipIndication = true; |
dudmuck | 0:8f0d0ae0a077 | 1364 | } |
dudmuck | 0:8f0d0ae0a077 | 1365 | } |
dudmuck | 0:8f0d0ae0a077 | 1366 | else |
dudmuck | 0:8f0d0ae0a077 | 1367 | { |
dudmuck | 0:8f0d0ae0a077 | 1368 | if( fCtrl.Bits.FOptsLen > 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1369 | { |
dudmuck | 0:8f0d0ae0a077 | 1370 | // Decode Options field MAC commands. Omit the fPort. |
Wayne Roberts |
29:ad409c68c0a6 | 1371 | ProcessMacCommands( Radio::radio.rx_buf, 8, appPayloadStartIndex - 1, snr ); |
dudmuck | 0:8f0d0ae0a077 | 1372 | } |
dudmuck | 0:8f0d0ae0a077 | 1373 | |
Wayne Roberts |
29:ad409c68c0a6 | 1374 | LoRaMacPayloadDecrypt( Radio::radio.rx_buf + appPayloadStartIndex, |
dudmuck | 0:8f0d0ae0a077 | 1375 | frameLen, |
dudmuck | 0:8f0d0ae0a077 | 1376 | appSKey, |
dudmuck | 0:8f0d0ae0a077 | 1377 | address, |
dudmuck | 0:8f0d0ae0a077 | 1378 | DOWN_LINK, |
dudmuck | 0:8f0d0ae0a077 | 1379 | downLinkCounter, |
Wayne Roberts |
29:ad409c68c0a6 | 1380 | rxFRMPayload); |
dudmuck | 0:8f0d0ae0a077 | 1381 | |
dudmuck | 0:8f0d0ae0a077 | 1382 | if( skipIndication == false ) |
dudmuck | 0:8f0d0ae0a077 | 1383 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1384 | McpsIndication.Buffer = rxFRMPayload; |
dudmuck | 0:8f0d0ae0a077 | 1385 | McpsIndication.BufferSize = frameLen; |
dudmuck | 0:8f0d0ae0a077 | 1386 | McpsIndication.RxData = true; |
dudmuck | 0:8f0d0ae0a077 | 1387 | } |
dudmuck | 0:8f0d0ae0a077 | 1388 | } |
dudmuck | 0:8f0d0ae0a077 | 1389 | } |
dudmuck | 0:8f0d0ae0a077 | 1390 | else |
dudmuck | 0:8f0d0ae0a077 | 1391 | { |
dudmuck | 0:8f0d0ae0a077 | 1392 | if( fCtrl.Bits.FOptsLen > 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1393 | { |
dudmuck | 0:8f0d0ae0a077 | 1394 | // Decode Options field MAC commands |
Wayne Roberts |
29:ad409c68c0a6 | 1395 | ProcessMacCommands( Radio::radio.rx_buf, 8, appPayloadStartIndex, snr ); |
dudmuck | 0:8f0d0ae0a077 | 1396 | } |
dudmuck | 0:8f0d0ae0a077 | 1397 | } |
dudmuck | 0:8f0d0ae0a077 | 1398 | |
dudmuck | 0:8f0d0ae0a077 | 1399 | if( skipIndication == false ) |
dudmuck | 0:8f0d0ae0a077 | 1400 | { |
dudmuck | 0:8f0d0ae0a077 | 1401 | // Check if the frame is an acknowledgement |
dudmuck | 0:8f0d0ae0a077 | 1402 | if( fCtrl.Bits.Ack == 1 ) |
dudmuck | 0:8f0d0ae0a077 | 1403 | { |
dudmuck | 0:8f0d0ae0a077 | 1404 | McpsConfirm.AckReceived = true; |
dudmuck | 0:8f0d0ae0a077 | 1405 | McpsIndication.AckReceived = true; |
dudmuck | 0:8f0d0ae0a077 | 1406 | |
dudmuck | 0:8f0d0ae0a077 | 1407 | // Stop the AckTimeout timer as no more retransmissions |
dudmuck | 0:8f0d0ae0a077 | 1408 | // are needed. |
dudmuck | 0:8f0d0ae0a077 | 1409 | } |
dudmuck | 0:8f0d0ae0a077 | 1410 | else |
dudmuck | 0:8f0d0ae0a077 | 1411 | { |
dudmuck | 0:8f0d0ae0a077 | 1412 | McpsConfirm.AckReceived = false; |
dudmuck | 0:8f0d0ae0a077 | 1413 | } |
dudmuck | 0:8f0d0ae0a077 | 1414 | } |
dudmuck | 0:8f0d0ae0a077 | 1415 | // Provide always an indication, skip the callback to the user application, |
dudmuck | 0:8f0d0ae0a077 | 1416 | // in case of a confirmed downlink retransmission. |
dudmuck | 0:8f0d0ae0a077 | 1417 | LoRaMacFlags.Bits.McpsInd = 1; |
dudmuck | 0:8f0d0ae0a077 | 1418 | LoRaMacFlags.Bits.McpsIndSkip = skipIndication; |
dudmuck | 0:8f0d0ae0a077 | 1419 | } |
dudmuck | 0:8f0d0ae0a077 | 1420 | else |
dudmuck | 0:8f0d0ae0a077 | 1421 | { |
dudmuck | 0:8f0d0ae0a077 | 1422 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; |
dudmuck | 5:c108560af4c3 | 1423 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; |
dudmuck | 0:8f0d0ae0a077 | 1424 | PrepareRxDoneAbort( ); |
dudmuck | 0:8f0d0ae0a077 | 1425 | return; |
dudmuck | 0:8f0d0ae0a077 | 1426 | } |
dudmuck | 0:8f0d0ae0a077 | 1427 | } |
dudmuck | 0:8f0d0ae0a077 | 1428 | break; |
dudmuck | 0:8f0d0ae0a077 | 1429 | case FRAME_TYPE_PROPRIETARY: |
dudmuck | 0:8f0d0ae0a077 | 1430 | { |
dudmuck | 0:8f0d0ae0a077 | 1431 | McpsIndication.McpsIndication = MCPS_PROPRIETARY; |
dudmuck | 0:8f0d0ae0a077 | 1432 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
29:ad409c68c0a6 | 1433 | McpsIndication.Buffer = Radio::radio.rx_buf; |
dudmuck | 0:8f0d0ae0a077 | 1434 | McpsIndication.BufferSize = size - pktHeaderLen; |
dudmuck | 0:8f0d0ae0a077 | 1435 | |
dudmuck | 0:8f0d0ae0a077 | 1436 | LoRaMacFlags.Bits.McpsInd = 1; |
dudmuck | 0:8f0d0ae0a077 | 1437 | break; |
dudmuck | 0:8f0d0ae0a077 | 1438 | } |
dudmuck | 0:8f0d0ae0a077 | 1439 | default: |
dudmuck | 2:f2d9aa163652 | 1440 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_RX_MTYPE; |
dudmuck | 5:c108560af4c3 | 1441 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_RX_MTYPE; |
Wayne Roberts |
29:ad409c68c0a6 | 1442 | mac_printf("%d:macHdr:%02x(%d,%d) ", size, macHdr.Value, rssi, snr); |
dudmuck | 0:8f0d0ae0a077 | 1443 | PrepareRxDoneAbort( ); |
dudmuck | 0:8f0d0ae0a077 | 1444 | break; |
dudmuck | 0:8f0d0ae0a077 | 1445 | } |
dudmuck | 0:8f0d0ae0a077 | 1446 | LoRaMacFlags.Bits.MacDone = 1; |
dudmuck | 0:8f0d0ae0a077 | 1447 | |
dudmuck | 16:915815632c1f | 1448 | application_callbacks(); |
dudmuck | 16:915815632c1f | 1449 | |
Wayne Roberts |
29:ad409c68c0a6 | 1450 | } // ..OnRadioRxDone() |
dudmuck | 16:915815632c1f | 1451 | |
dudmuck | 0:8f0d0ae0a077 | 1452 | static void OnRadioTxTimeout( void ) |
dudmuck | 0:8f0d0ae0a077 | 1453 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1454 | Radio::Sleep( ); |
dudmuck | 0:8f0d0ae0a077 | 1455 | |
dudmuck | 0:8f0d0ae0a077 | 1456 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; |
dudmuck | 0:8f0d0ae0a077 | 1457 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; |
dudmuck | 0:8f0d0ae0a077 | 1458 | LoRaMacFlags.Bits.MacDone = 1; |
dudmuck | 0:8f0d0ae0a077 | 1459 | } |
dudmuck | 0:8f0d0ae0a077 | 1460 | |
dudmuck | 0:8f0d0ae0a077 | 1461 | static void OnRadioRxError( void ) |
dudmuck | 0:8f0d0ae0a077 | 1462 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1463 | Radio::Sleep( ); |
Wayne Roberts |
29:ad409c68c0a6 | 1464 | |
Wayne Roberts |
29:ad409c68c0a6 | 1465 | if (LoRaMacFlags.Bits.NodeAckRequested) |
dudmuck | 0:8f0d0ae0a077 | 1466 | { |
dudmuck | 0:8f0d0ae0a077 | 1467 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_ERROR; |
dudmuck | 0:8f0d0ae0a077 | 1468 | } |
dudmuck | 0:8f0d0ae0a077 | 1469 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_ERROR; |
dudmuck | 0:8f0d0ae0a077 | 1470 | |
Wayne Roberts |
29:ad409c68c0a6 | 1471 | LoRaMacFlags.Bits.MacDone = 1; |
dudmuck | 0:8f0d0ae0a077 | 1472 | } |
dudmuck | 0:8f0d0ae0a077 | 1473 | |
dudmuck | 16:915815632c1f | 1474 | static void |
dudmuck | 16:915815632c1f | 1475 | join_send() |
dudmuck | 16:915815632c1f | 1476 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1477 | LoRaMacFlags.Bits.join_send = 1; |
dudmuck | 20:42839629a5dc | 1478 | } |
dudmuck | 20:42839629a5dc | 1479 | |
dudmuck | 25:fed9d5b77183 | 1480 | static void ScheduleTx( void ) |
dudmuck | 25:fed9d5b77183 | 1481 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1482 | if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) |
Wayne Roberts |
29:ad409c68c0a6 | 1483 | LoRaMacFlags.Bits.send = 1; // immediately send join asychronously |
dudmuck | 25:fed9d5b77183 | 1484 | else |
dudmuck | 25:fed9d5b77183 | 1485 | LoRaMacFlags.Bits.uplink_pending = 1; // send synchronously |
dudmuck | 25:fed9d5b77183 | 1486 | } |
dudmuck | 25:fed9d5b77183 | 1487 | |
dudmuck | 20:42839629a5dc | 1488 | static void |
dudmuck | 20:42839629a5dc | 1489 | join_send_bh() |
dudmuck | 20:42839629a5dc | 1490 | { |
dudmuck | 16:915815632c1f | 1491 | if (JoinRequestTrials < MaxJoinRequestTrials) { |
dudmuck | 16:915815632c1f | 1492 | LoRaMacHeader_t macHdr; |
dudmuck | 16:915815632c1f | 1493 | LoRaMacFrameCtrl_t fCtrl; |
Wayne Roberts |
29:ad409c68c0a6 | 1494 | |
dudmuck | 16:915815632c1f | 1495 | if (++Channel == LORA_MAX_NB_CHANNELS) |
dudmuck | 16:915815632c1f | 1496 | Channel = 0; |
Wayne Roberts |
29:ad409c68c0a6 | 1497 | mac_printf("<join-ch%u>", Channel); |
Wayne Roberts |
29:ad409c68c0a6 | 1498 | |
dudmuck | 16:915815632c1f | 1499 | macHdr.Value = 0; |
dudmuck | 16:915815632c1f | 1500 | macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; |
Wayne Roberts |
29:ad409c68c0a6 | 1501 | |
dudmuck | 16:915815632c1f | 1502 | fCtrl.Value = 0; |
dudmuck | 16:915815632c1f | 1503 | fCtrl.Bits.Adr = 0; |
Wayne Roberts |
29:ad409c68c0a6 | 1504 | |
dudmuck | 16:915815632c1f | 1505 | /* In case of join request retransmissions, the stack must prepare |
dudmuck | 16:915815632c1f | 1506 | * the frame again, because the network server keeps track of the random |
dudmuck | 16:915815632c1f | 1507 | * LoRaMacDevNonce values to prevent reply attacks. */ |
dudmuck | 16:915815632c1f | 1508 | PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1509 | |
dudmuck | 16:915815632c1f | 1510 | ScheduleTx(); |
dudmuck | 16:915815632c1f | 1511 | } else { |
dudmuck | 16:915815632c1f | 1512 | MlmeConfirm.MlmeRequest = MLME_JOIN; |
dudmuck | 16:915815632c1f | 1513 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL; |
dudmuck | 16:915815632c1f | 1514 | LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm ); |
dudmuck | 16:915815632c1f | 1515 | } |
Wayne Roberts |
29:ad409c68c0a6 | 1516 | } // ..join_send_bh() |
dudmuck | 16:915815632c1f | 1517 | |
dudmuck | 0:8f0d0ae0a077 | 1518 | static void OnRadioRxTimeout( void ) |
dudmuck | 0:8f0d0ae0a077 | 1519 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1520 | Radio::Sleep( ); |
Wayne Roberts |
29:ad409c68c0a6 | 1521 | |
Wayne Roberts |
29:ad409c68c0a6 | 1522 | if (LoRaMacFlags.Bits.expecting_beacon) { |
Wayne Roberts |
29:ad409c68c0a6 | 1523 | float ourErrSecs = BeaconCtx.known_working_BeaconRxTimerError_us / 1000000.0; |
dudmuck | 0:8f0d0ae0a077 | 1524 | |
Wayne Roberts |
29:ad409c68c0a6 | 1525 | LoRaMacFlags.Bits.expecting_beacon = false; |
Wayne Roberts |
29:ad409c68c0a6 | 1526 | |
Wayne Roberts |
29:ad409c68c0a6 | 1527 | BeaconCtx.rx_setup_at += BEACON_INTERVAL_us + BeaconCtx.known_working_BeaconRxTimerError_us; |
Wayne Roberts |
29:ad409c68c0a6 | 1528 | BeaconCtx.rx_setup_at -= (PPM_BEACON_INTERVAL / 4); |
Wayne Roberts |
30:1c35c4f56e50 | 1529 | us_to_nSymbTimeout(BeaconCtx.SymbolTimeout_us + PPM_BEACON_INTERVAL); |
Wayne Roberts |
30:1c35c4f56e50 | 1530 | mac_printf("beacon timeout ourErr:%f SymbTo:%u(%uus)\r\n", ourErrSecs, BeaconCtx.nSymbsTimeout, BeaconCtx.SymbolTimeout_us); |
Wayne Roberts |
29:ad409c68c0a6 | 1531 | |
Wayne Roberts |
29:ad409c68c0a6 | 1532 | BeaconCtx._timeout_rx.attach_us(&OnRxBeaconSetup, BeaconCtx.rx_setup_at); |
Wayne Roberts |
29:ad409c68c0a6 | 1533 | BeaconCtx._timeout_guard.attach_us(&guard_callback, BeaconCtx.rx_setup_at - BEACON_GUARD_us); |
Wayne Roberts |
29:ad409c68c0a6 | 1534 | |
Wayne Roberts |
29:ad409c68c0a6 | 1535 | if (++BeaconCtx.num_missed > BEACONS_MISSED_LIMIT) { |
Wayne Roberts |
29:ad409c68c0a6 | 1536 | LoRaMacFlags.Bits.reJoin = 1; |
Wayne Roberts |
29:ad409c68c0a6 | 1537 | } else { |
Wayne Roberts |
29:ad409c68c0a6 | 1538 | MlmeIndication.MlmeIndication = MLME_BEACON; |
Wayne Roberts |
29:ad409c68c0a6 | 1539 | MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_BEACON_LOST; |
Wayne Roberts |
29:ad409c68c0a6 | 1540 | LoRaMacPrimitives->MacMlmeIndication( &MlmeIndication ); |
Wayne Roberts |
29:ad409c68c0a6 | 1541 | } |
Wayne Roberts |
29:ad409c68c0a6 | 1542 | |
Wayne Roberts |
29:ad409c68c0a6 | 1543 | BeaconCtx.sendAt = BeaconCtx.LastBeaconRx_us + ((BEACON_INTERVAL_us + BeaconCtx.known_working_BeaconRxTimerError_us) * BeaconCtx.num_missed); |
Wayne Roberts |
29:ad409c68c0a6 | 1544 | BeaconCtx.sendAt += BeaconCtx.tx_slot_offset * PING_SLOT_RESOLUTION_us; |
Wayne Roberts |
29:ad409c68c0a6 | 1545 | _tx_timeout.attach_us(&send_callback, BeaconCtx.sendAt); |
Wayne Roberts |
29:ad409c68c0a6 | 1546 | |
Wayne Roberts |
30:1c35c4f56e50 | 1547 | BeaconCtx.num_consecutive_ok = 0; |
dudmuck | 16:915815632c1f | 1548 | } else { |
dudmuck | 25:fed9d5b77183 | 1549 | if (LoRaMacFlags.Bits.MlmeReq && ( MlmeConfirm.MlmeRequest == MLME_JOIN )) { |
dudmuck | 25:fed9d5b77183 | 1550 | /* no join accept received: join retry */ |
Wayne Roberts |
29:ad409c68c0a6 | 1551 | _tx_timeout.attach_us(&join_send, _tx_timeout.read_us() + (JoinRequestTrials*20000) + randr(0, 70000)); |
dudmuck | 25:fed9d5b77183 | 1552 | } |
dudmuck | 0:8f0d0ae0a077 | 1553 | } |
dudmuck | 0:8f0d0ae0a077 | 1554 | |
Wayne Roberts |
29:ad409c68c0a6 | 1555 | if (LoRaMacFlags.Bits.NodeAckRequested) |
dudmuck | 0:8f0d0ae0a077 | 1556 | { |
dudmuck | 0:8f0d0ae0a077 | 1557 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT; |
dudmuck | 0:8f0d0ae0a077 | 1558 | } |
dudmuck | 0:8f0d0ae0a077 | 1559 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT; |
dudmuck | 0:8f0d0ae0a077 | 1560 | LoRaMacFlags.Bits.MacDone = 1; |
Wayne Roberts |
29:ad409c68c0a6 | 1561 | |
dudmuck | 16:915815632c1f | 1562 | application_callbacks(); |
dudmuck | 1:53c30224eda8 | 1563 | } // ..OnRadioRxTimeout(); |
dudmuck | 0:8f0d0ae0a077 | 1564 | |
dudmuck | 0:8f0d0ae0a077 | 1565 | static void OnAckTimeoutTimerEvent( void ) |
dudmuck | 0:8f0d0ae0a077 | 1566 | { |
dudmuck | 0:8f0d0ae0a077 | 1567 | } |
dudmuck | 0:8f0d0ae0a077 | 1568 | |
dudmuck | 0:8f0d0ae0a077 | 1569 | static bool ValueInRange( int8_t value, int8_t min, int8_t max ) |
dudmuck | 0:8f0d0ae0a077 | 1570 | { |
dudmuck | 0:8f0d0ae0a077 | 1571 | if( ( value >= min ) && ( value <= max ) ) |
dudmuck | 0:8f0d0ae0a077 | 1572 | { |
dudmuck | 0:8f0d0ae0a077 | 1573 | return true; |
dudmuck | 0:8f0d0ae0a077 | 1574 | } |
dudmuck | 0:8f0d0ae0a077 | 1575 | return false; |
dudmuck | 0:8f0d0ae0a077 | 1576 | } |
dudmuck | 0:8f0d0ae0a077 | 1577 | |
dudmuck | 0:8f0d0ae0a077 | 1578 | static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ) |
dudmuck | 0:8f0d0ae0a077 | 1579 | { |
dudmuck | 0:8f0d0ae0a077 | 1580 | LoRaMacStatus_t status = LORAMAC_STATUS_BUSY; |
dudmuck | 0:8f0d0ae0a077 | 1581 | // The maximum buffer length must take MAC commands to re-send into account. |
dudmuck | 0:8f0d0ae0a077 | 1582 | uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex; |
dudmuck | 0:8f0d0ae0a077 | 1583 | |
dudmuck | 0:8f0d0ae0a077 | 1584 | switch( cmd ) |
dudmuck | 0:8f0d0ae0a077 | 1585 | { |
dudmuck | 0:8f0d0ae0a077 | 1586 | case MOTE_MAC_LINK_CHECK_REQ: |
dudmuck | 0:8f0d0ae0a077 | 1587 | if( MacCommandsBufferIndex < bufLen ) |
dudmuck | 0:8f0d0ae0a077 | 1588 | { |
dudmuck | 0:8f0d0ae0a077 | 1589 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
dudmuck | 0:8f0d0ae0a077 | 1590 | // No payload for this command |
dudmuck | 0:8f0d0ae0a077 | 1591 | status = LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1592 | } |
dudmuck | 0:8f0d0ae0a077 | 1593 | break; |
dudmuck | 0:8f0d0ae0a077 | 1594 | case MOTE_MAC_RX_PARAM_SETUP_ANS: |
dudmuck | 0:8f0d0ae0a077 | 1595 | if( MacCommandsBufferIndex < ( bufLen - 1 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1596 | { |
dudmuck | 0:8f0d0ae0a077 | 1597 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
dudmuck | 0:8f0d0ae0a077 | 1598 | // Status: Datarate ACK, Channel ACK |
dudmuck | 0:8f0d0ae0a077 | 1599 | MacCommandsBuffer[MacCommandsBufferIndex++] = p1; |
dudmuck | 0:8f0d0ae0a077 | 1600 | status = LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1601 | } |
dudmuck | 0:8f0d0ae0a077 | 1602 | break; |
dudmuck | 0:8f0d0ae0a077 | 1603 | case MOTE_MAC_DEV_STATUS_ANS: |
dudmuck | 0:8f0d0ae0a077 | 1604 | if( MacCommandsBufferIndex < ( bufLen - 2 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1605 | { |
dudmuck | 0:8f0d0ae0a077 | 1606 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
dudmuck | 0:8f0d0ae0a077 | 1607 | // 1st byte Battery |
dudmuck | 0:8f0d0ae0a077 | 1608 | // 2nd byte Margin |
dudmuck | 0:8f0d0ae0a077 | 1609 | MacCommandsBuffer[MacCommandsBufferIndex++] = p1; |
dudmuck | 0:8f0d0ae0a077 | 1610 | MacCommandsBuffer[MacCommandsBufferIndex++] = p2; |
dudmuck | 0:8f0d0ae0a077 | 1611 | status = LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1612 | } |
dudmuck | 0:8f0d0ae0a077 | 1613 | break; |
dudmuck | 0:8f0d0ae0a077 | 1614 | case MOTE_MAC_RX_TIMING_SETUP_ANS: |
dudmuck | 0:8f0d0ae0a077 | 1615 | if( MacCommandsBufferIndex < bufLen ) |
dudmuck | 0:8f0d0ae0a077 | 1616 | { |
dudmuck | 0:8f0d0ae0a077 | 1617 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
dudmuck | 0:8f0d0ae0a077 | 1618 | // No payload for this answer |
dudmuck | 0:8f0d0ae0a077 | 1619 | status = LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1620 | } |
dudmuck | 0:8f0d0ae0a077 | 1621 | break; |
dudmuck | 0:8f0d0ae0a077 | 1622 | default: |
dudmuck | 0:8f0d0ae0a077 | 1623 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
dudmuck | 0:8f0d0ae0a077 | 1624 | } |
dudmuck | 0:8f0d0ae0a077 | 1625 | if( status == LORAMAC_STATUS_OK ) |
dudmuck | 0:8f0d0ae0a077 | 1626 | { |
dudmuck | 0:8f0d0ae0a077 | 1627 | MacCommandsInNextTx = true; |
dudmuck | 0:8f0d0ae0a077 | 1628 | } |
dudmuck | 0:8f0d0ae0a077 | 1629 | return status; |
dudmuck | 0:8f0d0ae0a077 | 1630 | } |
dudmuck | 0:8f0d0ae0a077 | 1631 | |
dudmuck | 0:8f0d0ae0a077 | 1632 | static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ) |
dudmuck | 0:8f0d0ae0a077 | 1633 | { |
dudmuck | 0:8f0d0ae0a077 | 1634 | uint8_t i = 0; |
dudmuck | 0:8f0d0ae0a077 | 1635 | uint8_t cmdCount = 0; |
dudmuck | 0:8f0d0ae0a077 | 1636 | |
dudmuck | 0:8f0d0ae0a077 | 1637 | if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) ) |
dudmuck | 0:8f0d0ae0a077 | 1638 | { |
dudmuck | 0:8f0d0ae0a077 | 1639 | return 0; |
dudmuck | 0:8f0d0ae0a077 | 1640 | } |
dudmuck | 0:8f0d0ae0a077 | 1641 | |
dudmuck | 0:8f0d0ae0a077 | 1642 | for( i = 0; i < length; i++ ) |
dudmuck | 0:8f0d0ae0a077 | 1643 | { |
dudmuck | 0:8f0d0ae0a077 | 1644 | switch( cmdBufIn[i] ) |
dudmuck | 0:8f0d0ae0a077 | 1645 | { |
dudmuck | 0:8f0d0ae0a077 | 1646 | // STICKY |
dudmuck | 0:8f0d0ae0a077 | 1647 | case MOTE_MAC_RX_PARAM_SETUP_ANS: |
dudmuck | 0:8f0d0ae0a077 | 1648 | { |
dudmuck | 0:8f0d0ae0a077 | 1649 | cmdBufOut[cmdCount++] = cmdBufIn[i++]; |
dudmuck | 0:8f0d0ae0a077 | 1650 | cmdBufOut[cmdCount++] = cmdBufIn[i]; |
dudmuck | 0:8f0d0ae0a077 | 1651 | break; |
dudmuck | 0:8f0d0ae0a077 | 1652 | } |
dudmuck | 0:8f0d0ae0a077 | 1653 | case MOTE_MAC_RX_TIMING_SETUP_ANS: |
dudmuck | 0:8f0d0ae0a077 | 1654 | { |
dudmuck | 0:8f0d0ae0a077 | 1655 | cmdBufOut[cmdCount++] = cmdBufIn[i]; |
dudmuck | 0:8f0d0ae0a077 | 1656 | break; |
dudmuck | 0:8f0d0ae0a077 | 1657 | } |
dudmuck | 0:8f0d0ae0a077 | 1658 | // NON-STICKY |
dudmuck | 0:8f0d0ae0a077 | 1659 | case MOTE_MAC_DEV_STATUS_ANS: |
dudmuck | 0:8f0d0ae0a077 | 1660 | { // 2 bytes payload |
dudmuck | 0:8f0d0ae0a077 | 1661 | i += 2; |
dudmuck | 0:8f0d0ae0a077 | 1662 | break; |
dudmuck | 0:8f0d0ae0a077 | 1663 | } |
dudmuck | 0:8f0d0ae0a077 | 1664 | case MOTE_MAC_LINK_CHECK_REQ: |
dudmuck | 0:8f0d0ae0a077 | 1665 | { // 0 byte payload |
dudmuck | 0:8f0d0ae0a077 | 1666 | break; |
dudmuck | 0:8f0d0ae0a077 | 1667 | } |
dudmuck | 0:8f0d0ae0a077 | 1668 | default: |
dudmuck | 0:8f0d0ae0a077 | 1669 | break; |
dudmuck | 0:8f0d0ae0a077 | 1670 | } |
dudmuck | 0:8f0d0ae0a077 | 1671 | } |
dudmuck | 0:8f0d0ae0a077 | 1672 | |
dudmuck | 0:8f0d0ae0a077 | 1673 | return cmdCount; |
dudmuck | 0:8f0d0ae0a077 | 1674 | } |
dudmuck | 0:8f0d0ae0a077 | 1675 | |
dudmuck | 0:8f0d0ae0a077 | 1676 | static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr ) |
dudmuck | 0:8f0d0ae0a077 | 1677 | { |
dudmuck | 0:8f0d0ae0a077 | 1678 | while( macIndex < commandsSize ) |
dudmuck | 0:8f0d0ae0a077 | 1679 | { |
dudmuck | 0:8f0d0ae0a077 | 1680 | // Decode Frame MAC commands |
dudmuck | 0:8f0d0ae0a077 | 1681 | switch( payload[macIndex++] ) |
dudmuck | 0:8f0d0ae0a077 | 1682 | { |
dudmuck | 0:8f0d0ae0a077 | 1683 | case SRV_MAC_LINK_CHECK_ANS: |
dudmuck | 0:8f0d0ae0a077 | 1684 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1685 | MlmeConfirm.DemodMargin = payload[macIndex++]; |
dudmuck | 0:8f0d0ae0a077 | 1686 | MlmeConfirm.NbGateways = payload[macIndex++]; |
dudmuck | 0:8f0d0ae0a077 | 1687 | break; |
dudmuck | 0:8f0d0ae0a077 | 1688 | case SRV_MAC_DEV_STATUS_REQ: |
dudmuck | 0:8f0d0ae0a077 | 1689 | { |
dudmuck | 0:8f0d0ae0a077 | 1690 | uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE; |
dudmuck | 0:8f0d0ae0a077 | 1691 | if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) ) |
dudmuck | 0:8f0d0ae0a077 | 1692 | { |
dudmuck | 0:8f0d0ae0a077 | 1693 | batteryLevel = LoRaMacCallbacks->GetBatteryLevel( ); |
dudmuck | 0:8f0d0ae0a077 | 1694 | } |
dudmuck | 0:8f0d0ae0a077 | 1695 | AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr ); |
dudmuck | 0:8f0d0ae0a077 | 1696 | break; |
dudmuck | 0:8f0d0ae0a077 | 1697 | } |
dudmuck | 0:8f0d0ae0a077 | 1698 | case SRV_MAC_RX_TIMING_SETUP_REQ: |
dudmuck | 0:8f0d0ae0a077 | 1699 | { |
dudmuck | 0:8f0d0ae0a077 | 1700 | uint8_t delay = payload[macIndex++] & 0x0F; |
dudmuck | 0:8f0d0ae0a077 | 1701 | |
dudmuck | 0:8f0d0ae0a077 | 1702 | if( delay == 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1703 | { |
dudmuck | 0:8f0d0ae0a077 | 1704 | delay++; |
dudmuck | 0:8f0d0ae0a077 | 1705 | } |
dudmuck | 0:8f0d0ae0a077 | 1706 | LoRaMacParams.ReceiveDelay_us = delay * 1e6; |
dudmuck | 0:8f0d0ae0a077 | 1707 | AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 ); |
dudmuck | 0:8f0d0ae0a077 | 1708 | } |
dudmuck | 0:8f0d0ae0a077 | 1709 | break; |
dudmuck | 0:8f0d0ae0a077 | 1710 | default: |
dudmuck | 0:8f0d0ae0a077 | 1711 | // Unknown command. ABORT MAC commands processing |
dudmuck | 0:8f0d0ae0a077 | 1712 | return; |
dudmuck | 0:8f0d0ae0a077 | 1713 | } |
dudmuck | 0:8f0d0ae0a077 | 1714 | } |
dudmuck | 0:8f0d0ae0a077 | 1715 | } |
dudmuck | 0:8f0d0ae0a077 | 1716 | |
dudmuck | 0:8f0d0ae0a077 | 1717 | LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) |
dudmuck | 0:8f0d0ae0a077 | 1718 | { |
dudmuck | 0:8f0d0ae0a077 | 1719 | LoRaMacFrameCtrl_t fCtrl; |
dudmuck | 0:8f0d0ae0a077 | 1720 | LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 1721 | |
dudmuck | 0:8f0d0ae0a077 | 1722 | fCtrl.Value = 0; |
dudmuck | 0:8f0d0ae0a077 | 1723 | fCtrl.Bits.FOptsLen = 0; |
dudmuck | 0:8f0d0ae0a077 | 1724 | fCtrl.Bits.FPending = 0; |
dudmuck | 0:8f0d0ae0a077 | 1725 | fCtrl.Bits.Ack = false; |
dudmuck | 0:8f0d0ae0a077 | 1726 | fCtrl.Bits.AdrAckReq = false; |
dudmuck | 0:8f0d0ae0a077 | 1727 | fCtrl.Bits.Adr = false; |
dudmuck | 0:8f0d0ae0a077 | 1728 | |
dudmuck | 0:8f0d0ae0a077 | 1729 | // Prepare the frame |
dudmuck | 0:8f0d0ae0a077 | 1730 | status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize ); |
dudmuck | 0:8f0d0ae0a077 | 1731 | |
dudmuck | 0:8f0d0ae0a077 | 1732 | // Validate status |
dudmuck | 0:8f0d0ae0a077 | 1733 | if( status != LORAMAC_STATUS_OK ) |
dudmuck | 0:8f0d0ae0a077 | 1734 | { |
dudmuck | 0:8f0d0ae0a077 | 1735 | return status; |
dudmuck | 0:8f0d0ae0a077 | 1736 | } |
dudmuck | 0:8f0d0ae0a077 | 1737 | |
dudmuck | 0:8f0d0ae0a077 | 1738 | // Reset confirm parameters |
dudmuck | 0:8f0d0ae0a077 | 1739 | McpsConfirm.AckReceived = false; |
dudmuck | 0:8f0d0ae0a077 | 1740 | McpsConfirm.UpLinkCounter = UpLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 1741 | |
dudmuck | 25:fed9d5b77183 | 1742 | ScheduleTx(); |
dudmuck | 25:fed9d5b77183 | 1743 | |
dudmuck | 25:fed9d5b77183 | 1744 | return LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1745 | } |
dudmuck | 0:8f0d0ae0a077 | 1746 | |
dudmuck | 0:8f0d0ae0a077 | 1747 | |
dudmuck | 0:8f0d0ae0a077 | 1748 | static void ResetMacParameters( void ) |
dudmuck | 0:8f0d0ae0a077 | 1749 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1750 | LoRaMacFlags.Bits.IsLoRaMacNetworkJoined = false; |
dudmuck | 0:8f0d0ae0a077 | 1751 | |
dudmuck | 0:8f0d0ae0a077 | 1752 | // Counters |
dudmuck | 0:8f0d0ae0a077 | 1753 | UpLinkCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 1754 | DownLinkCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 1755 | |
dudmuck | 0:8f0d0ae0a077 | 1756 | ChannelsNbRepCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 1757 | |
dudmuck | 0:8f0d0ae0a077 | 1758 | MacCommandsBufferIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 1759 | MacCommandsBufferToRepeatIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 1760 | |
dudmuck | 0:8f0d0ae0a077 | 1761 | IsRxWindowsEnabled = true; |
dudmuck | 0:8f0d0ae0a077 | 1762 | |
dudmuck | 0:8f0d0ae0a077 | 1763 | LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower; |
dudmuck | 0:8f0d0ae0a077 | 1764 | LoRaMacParams.ChannelsDatarate_fixed = LoRaMacParamsDefaults.ChannelsDatarate_fixed; |
dudmuck | 0:8f0d0ae0a077 | 1765 | |
dudmuck | 0:8f0d0ae0a077 | 1766 | LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset; |
dudmuck | 0:8f0d0ae0a077 | 1767 | |
Wayne Roberts |
29:ad409c68c0a6 | 1768 | LoRaMacFlags.Bits.NodeAckRequested = false; |
Wayne Roberts |
29:ad409c68c0a6 | 1769 | LoRaMacFlags.Bits.SrvAckRequested = false; |
dudmuck | 0:8f0d0ae0a077 | 1770 | MacCommandsInNextTx = false; |
dudmuck | 0:8f0d0ae0a077 | 1771 | |
dudmuck | 0:8f0d0ae0a077 | 1772 | // Reset Multicast downlink counters |
dudmuck | 0:8f0d0ae0a077 | 1773 | MulticastParams_t *cur = MulticastChannels; |
dudmuck | 0:8f0d0ae0a077 | 1774 | while( cur != NULL ) |
dudmuck | 0:8f0d0ae0a077 | 1775 | { |
dudmuck | 0:8f0d0ae0a077 | 1776 | cur->DownLinkCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 1777 | cur = cur->Next; |
dudmuck | 0:8f0d0ae0a077 | 1778 | } |
dudmuck | 0:8f0d0ae0a077 | 1779 | |
dudmuck | 0:8f0d0ae0a077 | 1780 | } |
dudmuck | 0:8f0d0ae0a077 | 1781 | |
dudmuck | 0:8f0d0ae0a077 | 1782 | LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) |
dudmuck | 0:8f0d0ae0a077 | 1783 | { |
dudmuck | 0:8f0d0ae0a077 | 1784 | uint16_t i; |
dudmuck | 0:8f0d0ae0a077 | 1785 | uint32_t mic = 0; |
dudmuck | 0:8f0d0ae0a077 | 1786 | const void* payload = fBuffer; |
dudmuck | 0:8f0d0ae0a077 | 1787 | uint8_t framePort = fPort; |
Wayne Roberts |
29:ad409c68c0a6 | 1788 | uint8_t LoRaMacTxPayloadLen = 0; |
Wayne Roberts |
29:ad409c68c0a6 | 1789 | |
Wayne Roberts |
29:ad409c68c0a6 | 1790 | LoRaMacFlags.Bits.NodeAckRequested = false; |
Wayne Roberts |
29:ad409c68c0a6 | 1791 | tx_buf_len = 0; |
dudmuck | 0:8f0d0ae0a077 | 1792 | |
dudmuck | 0:8f0d0ae0a077 | 1793 | if( fBuffer == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 1794 | { |
dudmuck | 0:8f0d0ae0a077 | 1795 | fBufferSize = 0; |
dudmuck | 0:8f0d0ae0a077 | 1796 | } |
dudmuck | 0:8f0d0ae0a077 | 1797 | |
dudmuck | 0:8f0d0ae0a077 | 1798 | LoRaMacTxPayloadLen = fBufferSize; |
dudmuck | 0:8f0d0ae0a077 | 1799 | |
Wayne Roberts |
29:ad409c68c0a6 | 1800 | Radio::radio.tx_buf[tx_buf_len++] = macHdr->Value; |
dudmuck | 0:8f0d0ae0a077 | 1801 | |
dudmuck | 0:8f0d0ae0a077 | 1802 | switch( macHdr->Bits.MType ) |
dudmuck | 0:8f0d0ae0a077 | 1803 | { |
dudmuck | 0:8f0d0ae0a077 | 1804 | case FRAME_TYPE_JOIN_REQ: |
Wayne Roberts |
29:ad409c68c0a6 | 1805 | memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacAppEui, 8 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1806 | tx_buf_len += 8; |
Wayne Roberts |
29:ad409c68c0a6 | 1807 | memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacDevEui, 8 ); |
Wayne Roberts |
29:ad409c68c0a6 | 1808 | tx_buf_len += 8; |
Wayne Roberts |
29:ad409c68c0a6 | 1809 | |
Wayne Roberts |
29:ad409c68c0a6 | 1810 | LoRaMacDevNonce = Radio::Random( ); |
Wayne Roberts |
29:ad409c68c0a6 | 1811 | |
Wayne Roberts |
29:ad409c68c0a6 | 1812 | Radio::radio.tx_buf[tx_buf_len++] = LoRaMacDevNonce & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1813 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1814 | |
Wayne Roberts |
29:ad409c68c0a6 | 1815 | LoRaMacJoinComputeMic( Radio::radio.tx_buf, tx_buf_len & 0xFF, LoRaMacAppKey, &mic ); |
Wayne Roberts |
29:ad409c68c0a6 | 1816 | |
Wayne Roberts |
29:ad409c68c0a6 | 1817 | Radio::radio.tx_buf[tx_buf_len++] = mic & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1818 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 8 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1819 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 16 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1820 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 24 ) & 0xFF; |
dudmuck | 0:8f0d0ae0a077 | 1821 | |
dudmuck | 0:8f0d0ae0a077 | 1822 | break; |
dudmuck | 0:8f0d0ae0a077 | 1823 | case FRAME_TYPE_DATA_CONFIRMED_UP: |
Wayne Roberts |
29:ad409c68c0a6 | 1824 | LoRaMacFlags.Bits.NodeAckRequested = true; |
dudmuck | 0:8f0d0ae0a077 | 1825 | //Intentional fallthrough |
dudmuck | 0:8f0d0ae0a077 | 1826 | case FRAME_TYPE_DATA_UNCONFIRMED_UP: |
Wayne Roberts |
29:ad409c68c0a6 | 1827 | if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) |
dudmuck | 0:8f0d0ae0a077 | 1828 | { |
dudmuck | 0:8f0d0ae0a077 | 1829 | return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet |
dudmuck | 0:8f0d0ae0a077 | 1830 | } |
dudmuck | 0:8f0d0ae0a077 | 1831 | |
dudmuck | 0:8f0d0ae0a077 | 1832 | fCtrl->Bits.AdrAckReq = 0; |
dudmuck | 0:8f0d0ae0a077 | 1833 | |
Wayne Roberts |
29:ad409c68c0a6 | 1834 | if( LoRaMacFlags.Bits.SrvAckRequested == true ) |
dudmuck | 0:8f0d0ae0a077 | 1835 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1836 | LoRaMacFlags.Bits.SrvAckRequested = false; |
dudmuck | 0:8f0d0ae0a077 | 1837 | fCtrl->Bits.Ack = 1; |
dudmuck | 0:8f0d0ae0a077 | 1838 | } |
dudmuck | 0:8f0d0ae0a077 | 1839 | |
Wayne Roberts |
29:ad409c68c0a6 | 1840 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1841 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 8 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1842 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 16 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1843 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 24 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1844 | |
Wayne Roberts |
29:ad409c68c0a6 | 1845 | Radio::radio.tx_buf[tx_buf_len++] = fCtrl->Value; |
Wayne Roberts |
29:ad409c68c0a6 | 1846 | |
Wayne Roberts |
29:ad409c68c0a6 | 1847 | Radio::radio.tx_buf[tx_buf_len++] = UpLinkCounter & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1848 | Radio::radio.tx_buf[tx_buf_len++] = ( UpLinkCounter >> 8 ) & 0xFF; |
dudmuck | 0:8f0d0ae0a077 | 1849 | |
dudmuck | 0:8f0d0ae0a077 | 1850 | // Copy the MAC commands which must be re-send into the MAC command buffer |
dudmuck | 0:8f0d0ae0a077 | 1851 | memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex ); |
dudmuck | 0:8f0d0ae0a077 | 1852 | MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex; |
dudmuck | 0:8f0d0ae0a077 | 1853 | |
dudmuck | 0:8f0d0ae0a077 | 1854 | if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1855 | { |
dudmuck | 0:8f0d0ae0a077 | 1856 | if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) ) |
dudmuck | 0:8f0d0ae0a077 | 1857 | { |
dudmuck | 0:8f0d0ae0a077 | 1858 | fCtrl->Bits.FOptsLen += MacCommandsBufferIndex; |
dudmuck | 0:8f0d0ae0a077 | 1859 | |
dudmuck | 0:8f0d0ae0a077 | 1860 | // Update FCtrl field with new value of OptionsLength |
Wayne Roberts |
29:ad409c68c0a6 | 1861 | Radio::radio.tx_buf[0x05] = fCtrl->Value; |
dudmuck | 0:8f0d0ae0a077 | 1862 | for( i = 0; i < MacCommandsBufferIndex; i++ ) |
dudmuck | 0:8f0d0ae0a077 | 1863 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1864 | Radio::radio.tx_buf[tx_buf_len++] = MacCommandsBuffer[i]; |
dudmuck | 0:8f0d0ae0a077 | 1865 | } |
dudmuck | 0:8f0d0ae0a077 | 1866 | } |
dudmuck | 0:8f0d0ae0a077 | 1867 | } |
dudmuck | 0:8f0d0ae0a077 | 1868 | else |
dudmuck | 0:8f0d0ae0a077 | 1869 | { |
dudmuck | 0:8f0d0ae0a077 | 1870 | if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) ) |
dudmuck | 0:8f0d0ae0a077 | 1871 | { |
dudmuck | 0:8f0d0ae0a077 | 1872 | LoRaMacTxPayloadLen = MacCommandsBufferIndex; |
dudmuck | 0:8f0d0ae0a077 | 1873 | payload = MacCommandsBuffer; |
dudmuck | 0:8f0d0ae0a077 | 1874 | framePort = 0; |
dudmuck | 0:8f0d0ae0a077 | 1875 | } |
dudmuck | 0:8f0d0ae0a077 | 1876 | } |
dudmuck | 0:8f0d0ae0a077 | 1877 | MacCommandsInNextTx = false; |
dudmuck | 0:8f0d0ae0a077 | 1878 | // Store MAC commands which must be re-send in case the device does not receive a downlink anymore |
dudmuck | 0:8f0d0ae0a077 | 1879 | MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat ); |
dudmuck | 0:8f0d0ae0a077 | 1880 | if( MacCommandsBufferToRepeatIndex > 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1881 | { |
dudmuck | 0:8f0d0ae0a077 | 1882 | MacCommandsInNextTx = true; |
dudmuck | 0:8f0d0ae0a077 | 1883 | } |
dudmuck | 0:8f0d0ae0a077 | 1884 | |
dudmuck | 0:8f0d0ae0a077 | 1885 | if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1886 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1887 | Radio::radio.tx_buf[tx_buf_len++] = framePort; |
dudmuck | 0:8f0d0ae0a077 | 1888 | |
dudmuck | 0:8f0d0ae0a077 | 1889 | if( framePort == 0 ) |
dudmuck | 0:8f0d0ae0a077 | 1890 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1891 | LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &Radio::radio.tx_buf[tx_buf_len] ); |
dudmuck | 0:8f0d0ae0a077 | 1892 | } |
dudmuck | 0:8f0d0ae0a077 | 1893 | else |
dudmuck | 0:8f0d0ae0a077 | 1894 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1895 | LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &Radio::radio.tx_buf[tx_buf_len] ); |
dudmuck | 0:8f0d0ae0a077 | 1896 | } |
dudmuck | 0:8f0d0ae0a077 | 1897 | } |
Wayne Roberts |
29:ad409c68c0a6 | 1898 | tx_buf_len = tx_buf_len + LoRaMacTxPayloadLen; |
Wayne Roberts |
29:ad409c68c0a6 | 1899 | |
Wayne Roberts |
29:ad409c68c0a6 | 1900 | LoRaMacComputeMic( Radio::radio.tx_buf, tx_buf_len, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic ); |
Wayne Roberts |
29:ad409c68c0a6 | 1901 | |
Wayne Roberts |
29:ad409c68c0a6 | 1902 | Radio::radio.tx_buf[tx_buf_len + 0] = mic & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1903 | Radio::radio.tx_buf[tx_buf_len + 1] = ( mic >> 8 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1904 | Radio::radio.tx_buf[tx_buf_len + 2] = ( mic >> 16 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1905 | Radio::radio.tx_buf[tx_buf_len + 3] = ( mic >> 24 ) & 0xFF; |
Wayne Roberts |
29:ad409c68c0a6 | 1906 | |
Wayne Roberts |
29:ad409c68c0a6 | 1907 | tx_buf_len += LORAMAC_MFR_LEN; |
dudmuck | 0:8f0d0ae0a077 | 1908 | |
dudmuck | 0:8f0d0ae0a077 | 1909 | break; |
dudmuck | 0:8f0d0ae0a077 | 1910 | case FRAME_TYPE_PROPRIETARY: |
dudmuck | 0:8f0d0ae0a077 | 1911 | if( ( fBuffer != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) |
dudmuck | 0:8f0d0ae0a077 | 1912 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1913 | memcpy1( Radio::radio.tx_buf + tx_buf_len, ( uint8_t* ) fBuffer, LoRaMacTxPayloadLen ); |
Wayne Roberts |
29:ad409c68c0a6 | 1914 | tx_buf_len = tx_buf_len + LoRaMacTxPayloadLen; |
dudmuck | 0:8f0d0ae0a077 | 1915 | } |
dudmuck | 0:8f0d0ae0a077 | 1916 | break; |
dudmuck | 0:8f0d0ae0a077 | 1917 | default: |
dudmuck | 0:8f0d0ae0a077 | 1918 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
dudmuck | 0:8f0d0ae0a077 | 1919 | } |
dudmuck | 0:8f0d0ae0a077 | 1920 | |
dudmuck | 0:8f0d0ae0a077 | 1921 | return LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1922 | } |
dudmuck | 0:8f0d0ae0a077 | 1923 | |
dudmuck | 0:8f0d0ae0a077 | 1924 | |
dudmuck | 0:8f0d0ae0a077 | 1925 | LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout ) |
dudmuck | 0:8f0d0ae0a077 | 1926 | { |
dudmuck | 0:8f0d0ae0a077 | 1927 | int8_t txPowerIndex = 0; |
dudmuck | 0:8f0d0ae0a077 | 1928 | int8_t txPower = 0; |
dudmuck | 0:8f0d0ae0a077 | 1929 | |
dudmuck | 0:8f0d0ae0a077 | 1930 | txPowerIndex = LoRaMacParams.ChannelsTxPower; |
dudmuck | 0:8f0d0ae0a077 | 1931 | txPower = TxPowers[txPowerIndex]; |
Wayne Roberts |
29:ad409c68c0a6 | 1932 | Radio::SetTxContinuousWave( Channels[Channel].Frequency, txPower, timeout ); |
dudmuck | 0:8f0d0ae0a077 | 1933 | |
dudmuck | 0:8f0d0ae0a077 | 1934 | return LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1935 | } |
dudmuck | 0:8f0d0ae0a077 | 1936 | |
dudmuck | 0:8f0d0ae0a077 | 1937 | LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power ) |
dudmuck | 0:8f0d0ae0a077 | 1938 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1939 | Radio::SetTxContinuousWave( frequency, power, timeout ); |
dudmuck | 0:8f0d0ae0a077 | 1940 | |
dudmuck | 0:8f0d0ae0a077 | 1941 | return LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 1942 | } |
dudmuck | 0:8f0d0ae0a077 | 1943 | |
dudmuck | 0:8f0d0ae0a077 | 1944 | void seconds() |
dudmuck | 0:8f0d0ae0a077 | 1945 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1946 | mac_printf("second\r\n"); |
Wayne Roberts |
29:ad409c68c0a6 | 1947 | } |
Wayne Roberts |
29:ad409c68c0a6 | 1948 | |
Wayne Roberts |
29:ad409c68c0a6 | 1949 | void on_dio0_top_half(us_timestamp_t dio0_at) |
Wayne Roberts |
29:ad409c68c0a6 | 1950 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1951 | mac_printf("dio0th\r\n"); |
dudmuck | 0:8f0d0ae0a077 | 1952 | } |
dudmuck | 0:8f0d0ae0a077 | 1953 | |
Wayne Roberts |
29:ad409c68c0a6 | 1954 | unsigned get_symbol_period_us(uint8_t sf) |
Wayne Roberts |
29:ad409c68c0a6 | 1955 | { |
Wayne Roberts |
29:ad409c68c0a6 | 1956 | float bwMHz = LORA_BANDWIDTH_KHZ / 1000.0; |
Wayne Roberts |
29:ad409c68c0a6 | 1957 | // return symbol period in microseconds |
Wayne Roberts |
29:ad409c68c0a6 | 1958 | return (1 << sf) / bwMHz; |
Wayne Roberts |
29:ad409c68c0a6 | 1959 | } |
Wayne Roberts |
29:ad409c68c0a6 | 1960 | |
Wayne Roberts |
29:ad409c68c0a6 | 1961 | const RadioEvents_t rev = { |
Wayne Roberts |
29:ad409c68c0a6 | 1962 | /* Dio0_top_half */ on_dio0_top_half, |
Wayne Roberts |
29:ad409c68c0a6 | 1963 | /* TxDone_topHalf */ NULL, |
Wayne Roberts |
29:ad409c68c0a6 | 1964 | /* TxDone_botHalf */ OnRadioTxDone_bh, |
Wayne Roberts |
29:ad409c68c0a6 | 1965 | /* TxTimeout */ OnRadioTxTimeout, |
Wayne Roberts |
29:ad409c68c0a6 | 1966 | /* RxDone */ OnRadioRxDone, |
Wayne Roberts |
29:ad409c68c0a6 | 1967 | /* RxTimeout */ OnRadioRxTimeout, |
Wayne Roberts |
29:ad409c68c0a6 | 1968 | /* RxError */ OnRadioRxError, |
Wayne Roberts |
29:ad409c68c0a6 | 1969 | /* FhssChangeChannel */NULL, |
Wayne Roberts |
29:ad409c68c0a6 | 1970 | /* CadDone */ NULL |
Wayne Roberts |
29:ad409c68c0a6 | 1971 | }; |
Wayne Roberts |
29:ad409c68c0a6 | 1972 | |
dudmuck | 0:8f0d0ae0a077 | 1973 | LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks ) |
dudmuck | 0:8f0d0ae0a077 | 1974 | { |
dudmuck | 0:8f0d0ae0a077 | 1975 | if( primitives == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 1976 | { |
dudmuck | 0:8f0d0ae0a077 | 1977 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 1978 | } |
dudmuck | 0:8f0d0ae0a077 | 1979 | |
dudmuck | 0:8f0d0ae0a077 | 1980 | if( ( primitives->MacMcpsConfirm == NULL ) || |
dudmuck | 0:8f0d0ae0a077 | 1981 | ( primitives->MacMcpsIndication == NULL ) || |
dudmuck | 0:8f0d0ae0a077 | 1982 | ( primitives->MacMlmeConfirm == NULL ) ) |
dudmuck | 0:8f0d0ae0a077 | 1983 | { |
dudmuck | 0:8f0d0ae0a077 | 1984 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 1985 | } |
dudmuck | 0:8f0d0ae0a077 | 1986 | |
dudmuck | 0:8f0d0ae0a077 | 1987 | LoRaMacPrimitives = primitives; |
dudmuck | 0:8f0d0ae0a077 | 1988 | LoRaMacCallbacks = callbacks; |
dudmuck | 0:8f0d0ae0a077 | 1989 | |
dudmuck | 0:8f0d0ae0a077 | 1990 | LoRaMacFlags.Value = 0; |
dudmuck | 0:8f0d0ae0a077 | 1991 | |
dudmuck | 0:8f0d0ae0a077 | 1992 | JoinRequestTrials = 0; |
dudmuck | 0:8f0d0ae0a077 | 1993 | MaxJoinRequestTrials = 255; |
dudmuck | 0:8f0d0ae0a077 | 1994 | |
Wayne Roberts |
29:ad409c68c0a6 | 1995 | BeaconCtx.symbol_period_us = get_symbol_period_us(Datarates[LORAMAC_DEFAULT_DATARATE]); |
dudmuck | 0:8f0d0ae0a077 | 1996 | |
dudmuck | 0:8f0d0ae0a077 | 1997 | // Reset to defaults |
dudmuck | 0:8f0d0ae0a077 | 1998 | LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; |
dudmuck | 0:8f0d0ae0a077 | 1999 | LoRaMacParamsDefaults.ChannelsDatarate_fixed = LORAMAC_DEFAULT_DATARATE; |
dudmuck | 0:8f0d0ae0a077 | 2000 | |
Wayne Roberts |
29:ad409c68c0a6 | 2001 | LoRaMacParamsDefaults.SystemMaxRxError_ms = 20; |
Wayne Roberts |
29:ad409c68c0a6 | 2002 | LoRaMacParamsDefaults.MinRxSymbols = (LoRaMacParamsDefaults.SystemMaxRxError_ms * 1000) / BeaconCtx.symbol_period_us; |
Wayne Roberts |
29:ad409c68c0a6 | 2003 | if (LoRaMacParamsDefaults.MinRxSymbols < MIN_SYMBOL_TIMEOUT) |
Wayne Roberts |
29:ad409c68c0a6 | 2004 | LoRaMacParamsDefaults.MinRxSymbols = MIN_SYMBOL_TIMEOUT; |
Wayne Roberts |
29:ad409c68c0a6 | 2005 | |
dudmuck | 0:8f0d0ae0a077 | 2006 | LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW; |
dudmuck | 0:8f0d0ae0a077 | 2007 | |
dudmuck | 0:8f0d0ae0a077 | 2008 | LoRaMacParamsDefaults.ReceiveDelay_us = RECEIVE_DELAY_us; |
dudmuck | 0:8f0d0ae0a077 | 2009 | LoRaMacParamsDefaults.JoinAcceptDelay_us = JOIN_ACCEPT_DELAY_us; |
dudmuck | 0:8f0d0ae0a077 | 2010 | |
dudmuck | 0:8f0d0ae0a077 | 2011 | LoRaMacParamsDefaults.ChannelsNbRep = 1; |
dudmuck | 0:8f0d0ae0a077 | 2012 | LoRaMacParamsDefaults.Rx1DrOffset = 0; |
dudmuck | 0:8f0d0ae0a077 | 2013 | |
dudmuck | 0:8f0d0ae0a077 | 2014 | for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS; i++ ) |
dudmuck | 0:8f0d0ae0a077 | 2015 | { |
dudmuck | 0:8f0d0ae0a077 | 2016 | Channels[i].Frequency = LORAMAC_FIRST_CHANNEL + (i * LORAMAC_STEPWIDTH_CHANNEL); |
dudmuck | 18:9ac71c0eb70d | 2017 | Channels[i].DrRange.Value = (LORAMAC_MAX_DATARATE << 4) | LORAMAC_MIN_DATARATE; |
dudmuck | 0:8f0d0ae0a077 | 2018 | Channels[i].Band = 0; |
dudmuck | 0:8f0d0ae0a077 | 2019 | } |
dudmuck | 0:8f0d0ae0a077 | 2020 | |
dudmuck | 0:8f0d0ae0a077 | 2021 | // Init parameters which are not set in function ResetMacParameters |
Wayne Roberts |
29:ad409c68c0a6 | 2022 | LoRaMacParams.SystemMaxRxError_ms = LoRaMacParamsDefaults.SystemMaxRxError_ms; |
dudmuck | 0:8f0d0ae0a077 | 2023 | LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols; |
dudmuck | 0:8f0d0ae0a077 | 2024 | LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow; |
dudmuck | 0:8f0d0ae0a077 | 2025 | LoRaMacParams.ReceiveDelay_us = LoRaMacParamsDefaults.ReceiveDelay_us; |
dudmuck | 0:8f0d0ae0a077 | 2026 | LoRaMacParams.JoinAcceptDelay_us = LoRaMacParamsDefaults.JoinAcceptDelay_us; |
dudmuck | 0:8f0d0ae0a077 | 2027 | LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep; |
dudmuck | 0:8f0d0ae0a077 | 2028 | |
dudmuck | 0:8f0d0ae0a077 | 2029 | ResetMacParameters( ); |
dudmuck | 0:8f0d0ae0a077 | 2030 | |
dudmuck | 0:8f0d0ae0a077 | 2031 | // Initialize Radio driver |
Wayne Roberts |
29:ad409c68c0a6 | 2032 | Radio::Init(&rev); |
Wayne Roberts |
29:ad409c68c0a6 | 2033 | // lpt started later. lpt will have smaller number. |
Wayne Roberts |
29:ad409c68c0a6 | 2034 | lpt_offset = _rx_timeout.read_us() - Radio::lpt.read_us(); |
Wayne Roberts |
29:ad409c68c0a6 | 2035 | mac_printf("lpt_offset:%d\r\n", lpt_offset); |
dudmuck | 0:8f0d0ae0a077 | 2036 | |
dudmuck | 0:8f0d0ae0a077 | 2037 | // Random seed initialization |
Wayne Roberts |
29:ad409c68c0a6 | 2038 | srand1( Radio::Random( ) ); |
dudmuck | 0:8f0d0ae0a077 | 2039 | |
dudmuck | 0:8f0d0ae0a077 | 2040 | PublicNetwork = true; |
Wayne Roberts |
29:ad409c68c0a6 | 2041 | Radio::SetPublicNetwork( PublicNetwork ); |
Wayne Roberts |
29:ad409c68c0a6 | 2042 | Radio::Sleep( ); |
Wayne Roberts |
29:ad409c68c0a6 | 2043 | |
Wayne Roberts |
29:ad409c68c0a6 | 2044 | RxWindowsParam = ComputeRxWindowParameters(LORAMAC_DEFAULT_DATARATE, LoRaMacParams.SystemMaxRxError_ms); |
dudmuck | 0:8f0d0ae0a077 | 2045 | |
dudmuck | 0:8f0d0ae0a077 | 2046 | return LORAMAC_STATUS_OK; |
Wayne Roberts |
29:ad409c68c0a6 | 2047 | } // ..LoRaMacInitialization() |
dudmuck | 0:8f0d0ae0a077 | 2048 | |
dudmuck | 0:8f0d0ae0a077 | 2049 | LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo ) |
dudmuck | 0:8f0d0ae0a077 | 2050 | { |
dudmuck | 0:8f0d0ae0a077 | 2051 | uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex; |
dudmuck | 0:8f0d0ae0a077 | 2052 | |
dudmuck | 0:8f0d0ae0a077 | 2053 | if( txInfo == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2054 | { |
dudmuck | 0:8f0d0ae0a077 | 2055 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2056 | } |
dudmuck | 0:8f0d0ae0a077 | 2057 | |
Wayne Roberts |
29:ad409c68c0a6 | 2058 | txInfo->CurrentPayloadSize = LORAMAC_PHY_MAXPAYLOAD; |
dudmuck | 0:8f0d0ae0a077 | 2059 | |
dudmuck | 0:8f0d0ae0a077 | 2060 | if( txInfo->CurrentPayloadSize >= fOptLen ) |
dudmuck | 0:8f0d0ae0a077 | 2061 | { |
dudmuck | 0:8f0d0ae0a077 | 2062 | txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen; |
dudmuck | 0:8f0d0ae0a077 | 2063 | } |
dudmuck | 0:8f0d0ae0a077 | 2064 | else |
dudmuck | 0:8f0d0ae0a077 | 2065 | { |
dudmuck | 0:8f0d0ae0a077 | 2066 | return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR; |
dudmuck | 0:8f0d0ae0a077 | 2067 | } |
dudmuck | 0:8f0d0ae0a077 | 2068 | |
dudmuck | 0:8f0d0ae0a077 | 2069 | return LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 2070 | } |
dudmuck | 0:8f0d0ae0a077 | 2071 | |
dudmuck | 0:8f0d0ae0a077 | 2072 | LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet ) |
dudmuck | 0:8f0d0ae0a077 | 2073 | { |
dudmuck | 0:8f0d0ae0a077 | 2074 | LoRaMacStatus_t status = LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 2075 | |
dudmuck | 0:8f0d0ae0a077 | 2076 | if( mibGet == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2077 | { |
dudmuck | 0:8f0d0ae0a077 | 2078 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2079 | } |
dudmuck | 0:8f0d0ae0a077 | 2080 | |
dudmuck | 0:8f0d0ae0a077 | 2081 | switch( mibGet->Type ) |
dudmuck | 0:8f0d0ae0a077 | 2082 | { |
dudmuck | 0:8f0d0ae0a077 | 2083 | case MIB_NETWORK_JOINED: |
dudmuck | 0:8f0d0ae0a077 | 2084 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2085 | mibGet->Param.IsNetworkJoined = LoRaMacFlags.Bits.IsLoRaMacNetworkJoined; |
dudmuck | 0:8f0d0ae0a077 | 2086 | break; |
dudmuck | 0:8f0d0ae0a077 | 2087 | } |
dudmuck | 0:8f0d0ae0a077 | 2088 | case MIB_NET_ID: |
dudmuck | 0:8f0d0ae0a077 | 2089 | { |
dudmuck | 0:8f0d0ae0a077 | 2090 | mibGet->Param.NetID = LoRaMacNetID; |
dudmuck | 0:8f0d0ae0a077 | 2091 | break; |
dudmuck | 0:8f0d0ae0a077 | 2092 | } |
dudmuck | 0:8f0d0ae0a077 | 2093 | case MIB_DEV_ADDR: |
dudmuck | 0:8f0d0ae0a077 | 2094 | { |
dudmuck | 0:8f0d0ae0a077 | 2095 | mibGet->Param.DevAddr = LoRaMacDevAddr; |
dudmuck | 0:8f0d0ae0a077 | 2096 | break; |
dudmuck | 0:8f0d0ae0a077 | 2097 | } |
dudmuck | 0:8f0d0ae0a077 | 2098 | case MIB_NWK_SKEY: |
dudmuck | 0:8f0d0ae0a077 | 2099 | { |
dudmuck | 0:8f0d0ae0a077 | 2100 | mibGet->Param.NwkSKey = LoRaMacNwkSKey; |
dudmuck | 0:8f0d0ae0a077 | 2101 | break; |
dudmuck | 0:8f0d0ae0a077 | 2102 | } |
dudmuck | 0:8f0d0ae0a077 | 2103 | case MIB_APP_SKEY: |
dudmuck | 0:8f0d0ae0a077 | 2104 | { |
dudmuck | 0:8f0d0ae0a077 | 2105 | mibGet->Param.AppSKey = LoRaMacAppSKey; |
dudmuck | 0:8f0d0ae0a077 | 2106 | break; |
dudmuck | 0:8f0d0ae0a077 | 2107 | } |
dudmuck | 0:8f0d0ae0a077 | 2108 | case MIB_PUBLIC_NETWORK: |
dudmuck | 0:8f0d0ae0a077 | 2109 | { |
dudmuck | 0:8f0d0ae0a077 | 2110 | mibGet->Param.EnablePublicNetwork = PublicNetwork; |
dudmuck | 0:8f0d0ae0a077 | 2111 | break; |
dudmuck | 0:8f0d0ae0a077 | 2112 | } |
dudmuck | 0:8f0d0ae0a077 | 2113 | case MIB_CHANNELS_NB_REP: |
dudmuck | 0:8f0d0ae0a077 | 2114 | { |
dudmuck | 0:8f0d0ae0a077 | 2115 | mibGet->Param.ChannelNbRep = LoRaMacParams.ChannelsNbRep; |
dudmuck | 0:8f0d0ae0a077 | 2116 | break; |
dudmuck | 0:8f0d0ae0a077 | 2117 | } |
dudmuck | 0:8f0d0ae0a077 | 2118 | case MIB_MAX_RX_WINDOW_DURATION: |
dudmuck | 0:8f0d0ae0a077 | 2119 | { |
dudmuck | 0:8f0d0ae0a077 | 2120 | mibGet->Param.MaxRxWindow = LoRaMacParams.MaxRxWindow; |
dudmuck | 0:8f0d0ae0a077 | 2121 | break; |
dudmuck | 0:8f0d0ae0a077 | 2122 | } |
dudmuck | 0:8f0d0ae0a077 | 2123 | case MIB_CHANNELS_DEFAULT_TX_POWER: |
dudmuck | 0:8f0d0ae0a077 | 2124 | { |
dudmuck | 0:8f0d0ae0a077 | 2125 | mibGet->Param.ChannelsDefaultTxPower = LoRaMacParamsDefaults.ChannelsTxPower; |
dudmuck | 0:8f0d0ae0a077 | 2126 | break; |
dudmuck | 0:8f0d0ae0a077 | 2127 | } |
dudmuck | 0:8f0d0ae0a077 | 2128 | case MIB_CHANNELS_TX_POWER: |
dudmuck | 0:8f0d0ae0a077 | 2129 | { |
dudmuck | 0:8f0d0ae0a077 | 2130 | mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower; |
dudmuck | 0:8f0d0ae0a077 | 2131 | break; |
dudmuck | 0:8f0d0ae0a077 | 2132 | } |
dudmuck | 0:8f0d0ae0a077 | 2133 | case MIB_UPLINK_COUNTER: |
dudmuck | 0:8f0d0ae0a077 | 2134 | { |
dudmuck | 0:8f0d0ae0a077 | 2135 | mibGet->Param.UpLinkCounter = UpLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 2136 | break; |
dudmuck | 0:8f0d0ae0a077 | 2137 | } |
dudmuck | 0:8f0d0ae0a077 | 2138 | case MIB_DOWNLINK_COUNTER: |
dudmuck | 0:8f0d0ae0a077 | 2139 | { |
dudmuck | 0:8f0d0ae0a077 | 2140 | mibGet->Param.DownLinkCounter = DownLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 2141 | break; |
dudmuck | 0:8f0d0ae0a077 | 2142 | } |
dudmuck | 0:8f0d0ae0a077 | 2143 | case MIB_MULTICAST_CHANNEL: |
dudmuck | 0:8f0d0ae0a077 | 2144 | { |
dudmuck | 0:8f0d0ae0a077 | 2145 | mibGet->Param.MulticastList = MulticastChannels; |
dudmuck | 0:8f0d0ae0a077 | 2146 | break; |
dudmuck | 0:8f0d0ae0a077 | 2147 | } |
dudmuck | 0:8f0d0ae0a077 | 2148 | case MIB_SYSTEM_MAX_RX_ERROR: |
dudmuck | 0:8f0d0ae0a077 | 2149 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2150 | mibGet->Param.SystemMaxRxError_ms = LoRaMacParams.SystemMaxRxError_ms; |
dudmuck | 0:8f0d0ae0a077 | 2151 | break; |
dudmuck | 0:8f0d0ae0a077 | 2152 | } |
dudmuck | 0:8f0d0ae0a077 | 2153 | case MIB_MIN_RX_SYMBOLS: |
dudmuck | 0:8f0d0ae0a077 | 2154 | { |
dudmuck | 0:8f0d0ae0a077 | 2155 | mibGet->Param.MinRxSymbols = LoRaMacParams.MinRxSymbols; |
dudmuck | 0:8f0d0ae0a077 | 2156 | break; |
dudmuck | 0:8f0d0ae0a077 | 2157 | } |
dudmuck | 0:8f0d0ae0a077 | 2158 | default: |
dudmuck | 0:8f0d0ae0a077 | 2159 | status = LORAMAC_STATUS_SERVICE_UNKNOWN; |
dudmuck | 0:8f0d0ae0a077 | 2160 | break; |
dudmuck | 0:8f0d0ae0a077 | 2161 | } |
dudmuck | 0:8f0d0ae0a077 | 2162 | |
dudmuck | 0:8f0d0ae0a077 | 2163 | return status; |
dudmuck | 0:8f0d0ae0a077 | 2164 | } |
dudmuck | 0:8f0d0ae0a077 | 2165 | |
dudmuck | 0:8f0d0ae0a077 | 2166 | LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet ) |
dudmuck | 0:8f0d0ae0a077 | 2167 | { |
dudmuck | 0:8f0d0ae0a077 | 2168 | LoRaMacStatus_t status = LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 2169 | |
dudmuck | 0:8f0d0ae0a077 | 2170 | if( mibSet == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2171 | { |
dudmuck | 0:8f0d0ae0a077 | 2172 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2173 | } |
dudmuck | 0:8f0d0ae0a077 | 2174 | |
dudmuck | 0:8f0d0ae0a077 | 2175 | switch( mibSet->Type ) |
dudmuck | 0:8f0d0ae0a077 | 2176 | { |
dudmuck | 0:8f0d0ae0a077 | 2177 | case MIB_NETWORK_JOINED: |
dudmuck | 0:8f0d0ae0a077 | 2178 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2179 | LoRaMacFlags.Bits.IsLoRaMacNetworkJoined = mibSet->Param.IsNetworkJoined; |
Wayne Roberts |
29:ad409c68c0a6 | 2180 | if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) { |
Wayne Roberts |
29:ad409c68c0a6 | 2181 | mac_printf("beaconDetach\r\n"); |
Wayne Roberts |
29:ad409c68c0a6 | 2182 | BeaconCtx._timeout_rx.detach(); |
Wayne Roberts |
29:ad409c68c0a6 | 2183 | BeaconCtx._timeout_guard.detach(); |
dudmuck | 16:915815632c1f | 2184 | BeaconCtx.state = BEACON_STATE_NONE; |
dudmuck | 16:915815632c1f | 2185 | } |
dudmuck | 0:8f0d0ae0a077 | 2186 | break; |
dudmuck | 0:8f0d0ae0a077 | 2187 | } |
dudmuck | 0:8f0d0ae0a077 | 2188 | case MIB_NET_ID: |
dudmuck | 0:8f0d0ae0a077 | 2189 | { |
dudmuck | 0:8f0d0ae0a077 | 2190 | LoRaMacNetID = mibSet->Param.NetID; |
dudmuck | 0:8f0d0ae0a077 | 2191 | break; |
dudmuck | 0:8f0d0ae0a077 | 2192 | } |
dudmuck | 0:8f0d0ae0a077 | 2193 | case MIB_DEV_ADDR: |
dudmuck | 0:8f0d0ae0a077 | 2194 | { |
dudmuck | 0:8f0d0ae0a077 | 2195 | LoRaMacDevAddr = mibSet->Param.DevAddr; |
dudmuck | 0:8f0d0ae0a077 | 2196 | break; |
dudmuck | 0:8f0d0ae0a077 | 2197 | } |
dudmuck | 0:8f0d0ae0a077 | 2198 | case MIB_NWK_SKEY: |
dudmuck | 0:8f0d0ae0a077 | 2199 | { |
dudmuck | 0:8f0d0ae0a077 | 2200 | if( mibSet->Param.NwkSKey != NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2201 | { |
dudmuck | 0:8f0d0ae0a077 | 2202 | memcpy1( LoRaMacNwkSKey, mibSet->Param.NwkSKey, |
dudmuck | 0:8f0d0ae0a077 | 2203 | sizeof( LoRaMacNwkSKey ) ); |
dudmuck | 0:8f0d0ae0a077 | 2204 | } |
dudmuck | 0:8f0d0ae0a077 | 2205 | else |
dudmuck | 0:8f0d0ae0a077 | 2206 | { |
dudmuck | 0:8f0d0ae0a077 | 2207 | status = LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2208 | } |
dudmuck | 0:8f0d0ae0a077 | 2209 | break; |
dudmuck | 0:8f0d0ae0a077 | 2210 | } |
dudmuck | 0:8f0d0ae0a077 | 2211 | case MIB_APP_SKEY: |
dudmuck | 0:8f0d0ae0a077 | 2212 | { |
dudmuck | 0:8f0d0ae0a077 | 2213 | if( mibSet->Param.AppSKey != NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2214 | { |
dudmuck | 0:8f0d0ae0a077 | 2215 | memcpy1( LoRaMacAppSKey, mibSet->Param.AppSKey, |
dudmuck | 0:8f0d0ae0a077 | 2216 | sizeof( LoRaMacAppSKey ) ); |
dudmuck | 0:8f0d0ae0a077 | 2217 | } |
dudmuck | 0:8f0d0ae0a077 | 2218 | else |
dudmuck | 0:8f0d0ae0a077 | 2219 | { |
dudmuck | 0:8f0d0ae0a077 | 2220 | status = LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2221 | } |
dudmuck | 0:8f0d0ae0a077 | 2222 | break; |
dudmuck | 0:8f0d0ae0a077 | 2223 | } |
dudmuck | 0:8f0d0ae0a077 | 2224 | case MIB_PUBLIC_NETWORK: |
dudmuck | 0:8f0d0ae0a077 | 2225 | { |
dudmuck | 0:8f0d0ae0a077 | 2226 | PublicNetwork = mibSet->Param.EnablePublicNetwork; |
Wayne Roberts |
29:ad409c68c0a6 | 2227 | Radio::SetPublicNetwork( PublicNetwork ); |
dudmuck | 0:8f0d0ae0a077 | 2228 | break; |
dudmuck | 0:8f0d0ae0a077 | 2229 | } |
dudmuck | 0:8f0d0ae0a077 | 2230 | case MIB_CHANNELS_NB_REP: |
dudmuck | 0:8f0d0ae0a077 | 2231 | { |
dudmuck | 0:8f0d0ae0a077 | 2232 | if( ( mibSet->Param.ChannelNbRep >= 1 ) && |
dudmuck | 0:8f0d0ae0a077 | 2233 | ( mibSet->Param.ChannelNbRep <= 15 ) ) |
dudmuck | 0:8f0d0ae0a077 | 2234 | { |
dudmuck | 0:8f0d0ae0a077 | 2235 | LoRaMacParams.ChannelsNbRep = mibSet->Param.ChannelNbRep; |
dudmuck | 0:8f0d0ae0a077 | 2236 | } |
dudmuck | 0:8f0d0ae0a077 | 2237 | else |
dudmuck | 0:8f0d0ae0a077 | 2238 | { |
dudmuck | 0:8f0d0ae0a077 | 2239 | status = LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2240 | } |
dudmuck | 0:8f0d0ae0a077 | 2241 | break; |
dudmuck | 0:8f0d0ae0a077 | 2242 | } |
dudmuck | 0:8f0d0ae0a077 | 2243 | case MIB_MAX_RX_WINDOW_DURATION: |
dudmuck | 0:8f0d0ae0a077 | 2244 | { |
dudmuck | 0:8f0d0ae0a077 | 2245 | LoRaMacParams.MaxRxWindow = mibSet->Param.MaxRxWindow; |
dudmuck | 0:8f0d0ae0a077 | 2246 | break; |
dudmuck | 0:8f0d0ae0a077 | 2247 | } |
dudmuck | 0:8f0d0ae0a077 | 2248 | case MIB_CHANNELS_DEFAULT_TX_POWER: |
dudmuck | 0:8f0d0ae0a077 | 2249 | { |
dudmuck | 0:8f0d0ae0a077 | 2250 | if( ValueInRange( mibSet->Param.ChannelsDefaultTxPower, |
dudmuck | 0:8f0d0ae0a077 | 2251 | LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) ) |
dudmuck | 0:8f0d0ae0a077 | 2252 | { |
dudmuck | 0:8f0d0ae0a077 | 2253 | LoRaMacParamsDefaults.ChannelsTxPower = mibSet->Param.ChannelsDefaultTxPower; |
dudmuck | 0:8f0d0ae0a077 | 2254 | } |
dudmuck | 0:8f0d0ae0a077 | 2255 | else |
dudmuck | 0:8f0d0ae0a077 | 2256 | { |
dudmuck | 0:8f0d0ae0a077 | 2257 | status = LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2258 | } |
dudmuck | 0:8f0d0ae0a077 | 2259 | break; |
dudmuck | 0:8f0d0ae0a077 | 2260 | } |
dudmuck | 0:8f0d0ae0a077 | 2261 | case MIB_CHANNELS_TX_POWER: |
dudmuck | 0:8f0d0ae0a077 | 2262 | { |
dudmuck | 0:8f0d0ae0a077 | 2263 | if( ValueInRange( mibSet->Param.ChannelsTxPower, |
dudmuck | 0:8f0d0ae0a077 | 2264 | LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) ) |
dudmuck | 0:8f0d0ae0a077 | 2265 | { |
dudmuck | 0:8f0d0ae0a077 | 2266 | LoRaMacParams.ChannelsTxPower = mibSet->Param.ChannelsTxPower; |
dudmuck | 0:8f0d0ae0a077 | 2267 | } |
dudmuck | 0:8f0d0ae0a077 | 2268 | else |
dudmuck | 0:8f0d0ae0a077 | 2269 | { |
dudmuck | 0:8f0d0ae0a077 | 2270 | status = LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2271 | } |
dudmuck | 0:8f0d0ae0a077 | 2272 | break; |
dudmuck | 0:8f0d0ae0a077 | 2273 | } |
dudmuck | 0:8f0d0ae0a077 | 2274 | case MIB_UPLINK_COUNTER: |
dudmuck | 0:8f0d0ae0a077 | 2275 | { |
dudmuck | 0:8f0d0ae0a077 | 2276 | UpLinkCounter = mibSet->Param.UpLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 2277 | break; |
dudmuck | 0:8f0d0ae0a077 | 2278 | } |
dudmuck | 0:8f0d0ae0a077 | 2279 | case MIB_DOWNLINK_COUNTER: |
dudmuck | 0:8f0d0ae0a077 | 2280 | { |
dudmuck | 0:8f0d0ae0a077 | 2281 | DownLinkCounter = mibSet->Param.DownLinkCounter; |
dudmuck | 0:8f0d0ae0a077 | 2282 | break; |
dudmuck | 0:8f0d0ae0a077 | 2283 | } |
dudmuck | 0:8f0d0ae0a077 | 2284 | case MIB_SYSTEM_MAX_RX_ERROR: |
dudmuck | 0:8f0d0ae0a077 | 2285 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2286 | LoRaMacParams.SystemMaxRxError_ms = LoRaMacParamsDefaults.SystemMaxRxError_ms = mibSet->Param.SystemMaxRxError_ms; |
dudmuck | 0:8f0d0ae0a077 | 2287 | break; |
dudmuck | 0:8f0d0ae0a077 | 2288 | } |
dudmuck | 0:8f0d0ae0a077 | 2289 | case MIB_MIN_RX_SYMBOLS: |
dudmuck | 0:8f0d0ae0a077 | 2290 | { |
dudmuck | 0:8f0d0ae0a077 | 2291 | LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols = mibSet->Param.MinRxSymbols; |
dudmuck | 0:8f0d0ae0a077 | 2292 | break; |
dudmuck | 0:8f0d0ae0a077 | 2293 | } |
dudmuck | 0:8f0d0ae0a077 | 2294 | default: |
dudmuck | 0:8f0d0ae0a077 | 2295 | status = LORAMAC_STATUS_SERVICE_UNKNOWN; |
dudmuck | 0:8f0d0ae0a077 | 2296 | break; |
dudmuck | 0:8f0d0ae0a077 | 2297 | } |
dudmuck | 0:8f0d0ae0a077 | 2298 | |
dudmuck | 0:8f0d0ae0a077 | 2299 | return status; |
dudmuck | 0:8f0d0ae0a077 | 2300 | } |
dudmuck | 0:8f0d0ae0a077 | 2301 | |
dudmuck | 0:8f0d0ae0a077 | 2302 | LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam ) |
dudmuck | 0:8f0d0ae0a077 | 2303 | { |
dudmuck | 0:8f0d0ae0a077 | 2304 | if( channelParam == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2305 | { |
dudmuck | 0:8f0d0ae0a077 | 2306 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2307 | } |
dudmuck | 0:8f0d0ae0a077 | 2308 | |
dudmuck | 0:8f0d0ae0a077 | 2309 | // Reset downlink counter |
dudmuck | 0:8f0d0ae0a077 | 2310 | channelParam->DownLinkCounter = 0; |
dudmuck | 0:8f0d0ae0a077 | 2311 | |
dudmuck | 0:8f0d0ae0a077 | 2312 | if( MulticastChannels == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2313 | { |
dudmuck | 0:8f0d0ae0a077 | 2314 | // New node is the fist element |
dudmuck | 0:8f0d0ae0a077 | 2315 | MulticastChannels = channelParam; |
dudmuck | 0:8f0d0ae0a077 | 2316 | } |
dudmuck | 0:8f0d0ae0a077 | 2317 | else |
dudmuck | 0:8f0d0ae0a077 | 2318 | { |
dudmuck | 0:8f0d0ae0a077 | 2319 | MulticastParams_t *cur = MulticastChannels; |
dudmuck | 0:8f0d0ae0a077 | 2320 | |
dudmuck | 0:8f0d0ae0a077 | 2321 | // Search the last node in the list |
dudmuck | 0:8f0d0ae0a077 | 2322 | while( cur->Next != NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2323 | { |
dudmuck | 0:8f0d0ae0a077 | 2324 | cur = cur->Next; |
dudmuck | 0:8f0d0ae0a077 | 2325 | } |
dudmuck | 0:8f0d0ae0a077 | 2326 | // This function always finds the last node |
dudmuck | 0:8f0d0ae0a077 | 2327 | cur->Next = channelParam; |
dudmuck | 0:8f0d0ae0a077 | 2328 | } |
dudmuck | 0:8f0d0ae0a077 | 2329 | |
dudmuck | 0:8f0d0ae0a077 | 2330 | return LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 2331 | } |
dudmuck | 0:8f0d0ae0a077 | 2332 | |
dudmuck | 0:8f0d0ae0a077 | 2333 | LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam ) |
dudmuck | 0:8f0d0ae0a077 | 2334 | { |
dudmuck | 0:8f0d0ae0a077 | 2335 | if( channelParam == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2336 | { |
dudmuck | 0:8f0d0ae0a077 | 2337 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2338 | } |
dudmuck | 0:8f0d0ae0a077 | 2339 | |
dudmuck | 0:8f0d0ae0a077 | 2340 | if( MulticastChannels != NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2341 | { |
dudmuck | 0:8f0d0ae0a077 | 2342 | if( MulticastChannels == channelParam ) |
dudmuck | 0:8f0d0ae0a077 | 2343 | { |
dudmuck | 0:8f0d0ae0a077 | 2344 | // First element |
dudmuck | 0:8f0d0ae0a077 | 2345 | MulticastChannels = channelParam->Next; |
dudmuck | 0:8f0d0ae0a077 | 2346 | } |
dudmuck | 0:8f0d0ae0a077 | 2347 | else |
dudmuck | 0:8f0d0ae0a077 | 2348 | { |
dudmuck | 0:8f0d0ae0a077 | 2349 | MulticastParams_t *cur = MulticastChannels; |
dudmuck | 0:8f0d0ae0a077 | 2350 | |
dudmuck | 0:8f0d0ae0a077 | 2351 | // Search the node in the list |
dudmuck | 0:8f0d0ae0a077 | 2352 | while( cur->Next && cur->Next != channelParam ) |
dudmuck | 0:8f0d0ae0a077 | 2353 | { |
dudmuck | 0:8f0d0ae0a077 | 2354 | cur = cur->Next; |
dudmuck | 0:8f0d0ae0a077 | 2355 | } |
dudmuck | 0:8f0d0ae0a077 | 2356 | // If we found the node, remove it |
dudmuck | 0:8f0d0ae0a077 | 2357 | if( cur->Next ) |
dudmuck | 0:8f0d0ae0a077 | 2358 | { |
dudmuck | 0:8f0d0ae0a077 | 2359 | cur->Next = channelParam->Next; |
dudmuck | 0:8f0d0ae0a077 | 2360 | } |
dudmuck | 0:8f0d0ae0a077 | 2361 | } |
dudmuck | 0:8f0d0ae0a077 | 2362 | channelParam->Next = NULL; |
dudmuck | 0:8f0d0ae0a077 | 2363 | } |
dudmuck | 0:8f0d0ae0a077 | 2364 | |
dudmuck | 0:8f0d0ae0a077 | 2365 | return LORAMAC_STATUS_OK; |
dudmuck | 0:8f0d0ae0a077 | 2366 | } |
dudmuck | 0:8f0d0ae0a077 | 2367 | |
dudmuck | 0:8f0d0ae0a077 | 2368 | LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest ) |
dudmuck | 0:8f0d0ae0a077 | 2369 | { |
dudmuck | 0:8f0d0ae0a077 | 2370 | LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; |
dudmuck | 0:8f0d0ae0a077 | 2371 | LoRaMacHeader_t macHdr; |
dudmuck | 0:8f0d0ae0a077 | 2372 | |
dudmuck | 0:8f0d0ae0a077 | 2373 | if( mlmeRequest == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2374 | { |
dudmuck | 0:8f0d0ae0a077 | 2375 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2376 | } |
dudmuck | 0:8f0d0ae0a077 | 2377 | |
dudmuck | 0:8f0d0ae0a077 | 2378 | memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) ); |
dudmuck | 0:8f0d0ae0a077 | 2379 | |
dudmuck | 2:f2d9aa163652 | 2380 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_MLMEREQ; |
dudmuck | 0:8f0d0ae0a077 | 2381 | |
dudmuck | 0:8f0d0ae0a077 | 2382 | switch( mlmeRequest->Type ) |
dudmuck | 0:8f0d0ae0a077 | 2383 | { |
dudmuck | 0:8f0d0ae0a077 | 2384 | case MLME_JOIN: |
dudmuck | 0:8f0d0ae0a077 | 2385 | { |
dudmuck | 0:8f0d0ae0a077 | 2386 | if( ( mlmeRequest->Req.Join.DevEui == NULL ) || |
dudmuck | 0:8f0d0ae0a077 | 2387 | ( mlmeRequest->Req.Join.AppEui == NULL ) || |
dudmuck | 0:8f0d0ae0a077 | 2388 | ( mlmeRequest->Req.Join.AppKey == NULL ) || |
dudmuck | 0:8f0d0ae0a077 | 2389 | ( mlmeRequest->Req.Join.NbTrials == 0 ) ) |
dudmuck | 0:8f0d0ae0a077 | 2390 | { |
dudmuck | 0:8f0d0ae0a077 | 2391 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2392 | } |
dudmuck | 0:8f0d0ae0a077 | 2393 | |
dudmuck | 0:8f0d0ae0a077 | 2394 | // Enables at least the usage of all datarates. |
dudmuck | 0:8f0d0ae0a077 | 2395 | if( mlmeRequest->Req.Join.NbTrials < 48 ) |
dudmuck | 0:8f0d0ae0a077 | 2396 | { |
dudmuck | 0:8f0d0ae0a077 | 2397 | mlmeRequest->Req.Join.NbTrials = 48; |
dudmuck | 0:8f0d0ae0a077 | 2398 | } |
dudmuck | 0:8f0d0ae0a077 | 2399 | |
dudmuck | 0:8f0d0ae0a077 | 2400 | LoRaMacFlags.Bits.MlmeReq = 1; |
dudmuck | 0:8f0d0ae0a077 | 2401 | MlmeConfirm.MlmeRequest = mlmeRequest->Type; |
dudmuck | 0:8f0d0ae0a077 | 2402 | |
dudmuck | 0:8f0d0ae0a077 | 2403 | LoRaMacDevEui = mlmeRequest->Req.Join.DevEui; |
dudmuck | 0:8f0d0ae0a077 | 2404 | LoRaMacAppEui = mlmeRequest->Req.Join.AppEui; |
dudmuck | 0:8f0d0ae0a077 | 2405 | LoRaMacAppKey = mlmeRequest->Req.Join.AppKey; |
dudmuck | 0:8f0d0ae0a077 | 2406 | MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials; |
dudmuck | 0:8f0d0ae0a077 | 2407 | |
dudmuck | 0:8f0d0ae0a077 | 2408 | // Reset variable JoinRequestTrials |
dudmuck | 0:8f0d0ae0a077 | 2409 | JoinRequestTrials = 0; |
dudmuck | 0:8f0d0ae0a077 | 2410 | |
dudmuck | 0:8f0d0ae0a077 | 2411 | // Setup header information |
dudmuck | 0:8f0d0ae0a077 | 2412 | macHdr.Value = 0; |
dudmuck | 0:8f0d0ae0a077 | 2413 | macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; |
dudmuck | 0:8f0d0ae0a077 | 2414 | |
dudmuck | 0:8f0d0ae0a077 | 2415 | ResetMacParameters( ); |
Wayne Roberts |
29:ad409c68c0a6 | 2416 | LoRaMacFlags.Bits.expecting_beacon = false; |
dudmuck | 16:915815632c1f | 2417 | BeaconCtx.state = BEACON_STATE_NONE; |
dudmuck | 0:8f0d0ae0a077 | 2418 | |
dudmuck | 0:8f0d0ae0a077 | 2419 | Channel = 0; // start with first channel |
Wayne Roberts |
29:ad409c68c0a6 | 2420 | mac_printf("<ch0>"); |
Wayne Roberts |
29:ad409c68c0a6 | 2421 | mac_printf("mlme-join-send ch%u\r\n", Channel); |
dudmuck | 0:8f0d0ae0a077 | 2422 | status = Send( &macHdr, 0, NULL, 0 ); |
dudmuck | 0:8f0d0ae0a077 | 2423 | break; |
dudmuck | 0:8f0d0ae0a077 | 2424 | } |
dudmuck | 0:8f0d0ae0a077 | 2425 | case MLME_LINK_CHECK: |
dudmuck | 0:8f0d0ae0a077 | 2426 | { |
dudmuck | 0:8f0d0ae0a077 | 2427 | LoRaMacFlags.Bits.MlmeReq = 1; |
dudmuck | 0:8f0d0ae0a077 | 2428 | // LoRaMac will send this command piggy-pack |
dudmuck | 0:8f0d0ae0a077 | 2429 | MlmeConfirm.MlmeRequest = mlmeRequest->Type; |
dudmuck | 0:8f0d0ae0a077 | 2430 | |
dudmuck | 0:8f0d0ae0a077 | 2431 | status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 ); |
dudmuck | 0:8f0d0ae0a077 | 2432 | break; |
dudmuck | 0:8f0d0ae0a077 | 2433 | } |
dudmuck | 0:8f0d0ae0a077 | 2434 | case MLME_TXCW: |
dudmuck | 0:8f0d0ae0a077 | 2435 | { |
dudmuck | 0:8f0d0ae0a077 | 2436 | MlmeConfirm.MlmeRequest = mlmeRequest->Type; |
dudmuck | 0:8f0d0ae0a077 | 2437 | LoRaMacFlags.Bits.MlmeReq = 1; |
dudmuck | 0:8f0d0ae0a077 | 2438 | status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout ); |
dudmuck | 0:8f0d0ae0a077 | 2439 | break; |
dudmuck | 0:8f0d0ae0a077 | 2440 | } |
dudmuck | 0:8f0d0ae0a077 | 2441 | case MLME_TXCW_1: |
dudmuck | 0:8f0d0ae0a077 | 2442 | { |
dudmuck | 0:8f0d0ae0a077 | 2443 | MlmeConfirm.MlmeRequest = mlmeRequest->Type; |
dudmuck | 0:8f0d0ae0a077 | 2444 | LoRaMacFlags.Bits.MlmeReq = 1; |
dudmuck | 0:8f0d0ae0a077 | 2445 | status = SetTxContinuousWave1( mlmeRequest->Req.TxCw.Timeout, mlmeRequest->Req.TxCw.Frequency, mlmeRequest->Req.TxCw.Power ); |
dudmuck | 0:8f0d0ae0a077 | 2446 | break; |
dudmuck | 0:8f0d0ae0a077 | 2447 | } |
dudmuck | 0:8f0d0ae0a077 | 2448 | default: |
dudmuck | 0:8f0d0ae0a077 | 2449 | break; |
dudmuck | 0:8f0d0ae0a077 | 2450 | } |
dudmuck | 0:8f0d0ae0a077 | 2451 | |
dudmuck | 0:8f0d0ae0a077 | 2452 | if( status != LORAMAC_STATUS_OK ) |
dudmuck | 0:8f0d0ae0a077 | 2453 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2454 | LoRaMacFlags.Bits.NodeAckRequested = false; |
dudmuck | 0:8f0d0ae0a077 | 2455 | LoRaMacFlags.Bits.MlmeReq = 0; |
dudmuck | 0:8f0d0ae0a077 | 2456 | } |
dudmuck | 0:8f0d0ae0a077 | 2457 | |
dudmuck | 0:8f0d0ae0a077 | 2458 | return status; |
dudmuck | 0:8f0d0ae0a077 | 2459 | } |
dudmuck | 0:8f0d0ae0a077 | 2460 | |
dudmuck | 0:8f0d0ae0a077 | 2461 | LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest ) |
dudmuck | 0:8f0d0ae0a077 | 2462 | { |
dudmuck | 0:8f0d0ae0a077 | 2463 | LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; |
dudmuck | 0:8f0d0ae0a077 | 2464 | LoRaMacHeader_t macHdr; |
dudmuck | 0:8f0d0ae0a077 | 2465 | uint8_t fPort = 0; |
dudmuck | 0:8f0d0ae0a077 | 2466 | void *fBuffer; |
dudmuck | 0:8f0d0ae0a077 | 2467 | uint16_t fBufferSize; |
dudmuck | 0:8f0d0ae0a077 | 2468 | bool readyToSend = false; |
dudmuck | 0:8f0d0ae0a077 | 2469 | |
dudmuck | 0:8f0d0ae0a077 | 2470 | if( mcpsRequest == NULL ) |
dudmuck | 0:8f0d0ae0a077 | 2471 | { |
dudmuck | 0:8f0d0ae0a077 | 2472 | return LORAMAC_STATUS_PARAMETER_INVALID; |
dudmuck | 0:8f0d0ae0a077 | 2473 | } |
dudmuck | 0:8f0d0ae0a077 | 2474 | |
dudmuck | 0:8f0d0ae0a077 | 2475 | macHdr.Value = 0; |
dudmuck | 0:8f0d0ae0a077 | 2476 | memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) ); |
dudmuck | 2:f2d9aa163652 | 2477 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_MCPSREQ; |
dudmuck | 0:8f0d0ae0a077 | 2478 | |
dudmuck | 0:8f0d0ae0a077 | 2479 | switch( mcpsRequest->Type ) |
dudmuck | 0:8f0d0ae0a077 | 2480 | { |
dudmuck | 0:8f0d0ae0a077 | 2481 | case MCPS_UNCONFIRMED: |
dudmuck | 0:8f0d0ae0a077 | 2482 | { |
dudmuck | 0:8f0d0ae0a077 | 2483 | readyToSend = true; |
dudmuck | 0:8f0d0ae0a077 | 2484 | |
dudmuck | 0:8f0d0ae0a077 | 2485 | macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP; |
dudmuck | 0:8f0d0ae0a077 | 2486 | fPort = mcpsRequest->Req.Unconfirmed.fPort; |
dudmuck | 0:8f0d0ae0a077 | 2487 | fBuffer = mcpsRequest->Req.Unconfirmed.fBuffer; |
dudmuck | 0:8f0d0ae0a077 | 2488 | fBufferSize = mcpsRequest->Req.Unconfirmed.fBufferSize; |
dudmuck | 0:8f0d0ae0a077 | 2489 | break; |
dudmuck | 0:8f0d0ae0a077 | 2490 | } |
dudmuck | 0:8f0d0ae0a077 | 2491 | case MCPS_CONFIRMED: |
dudmuck | 0:8f0d0ae0a077 | 2492 | { |
dudmuck | 0:8f0d0ae0a077 | 2493 | readyToSend = true; |
dudmuck | 0:8f0d0ae0a077 | 2494 | |
dudmuck | 0:8f0d0ae0a077 | 2495 | macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP; |
dudmuck | 0:8f0d0ae0a077 | 2496 | fPort = mcpsRequest->Req.Confirmed.fPort; |
dudmuck | 0:8f0d0ae0a077 | 2497 | fBuffer = mcpsRequest->Req.Confirmed.fBuffer; |
dudmuck | 0:8f0d0ae0a077 | 2498 | fBufferSize = mcpsRequest->Req.Confirmed.fBufferSize; |
dudmuck | 0:8f0d0ae0a077 | 2499 | break; |
dudmuck | 0:8f0d0ae0a077 | 2500 | } |
dudmuck | 0:8f0d0ae0a077 | 2501 | case MCPS_PROPRIETARY: |
dudmuck | 0:8f0d0ae0a077 | 2502 | { |
dudmuck | 0:8f0d0ae0a077 | 2503 | readyToSend = true; |
dudmuck | 0:8f0d0ae0a077 | 2504 | |
dudmuck | 0:8f0d0ae0a077 | 2505 | macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY; |
dudmuck | 0:8f0d0ae0a077 | 2506 | fBuffer = mcpsRequest->Req.Proprietary.fBuffer; |
dudmuck | 0:8f0d0ae0a077 | 2507 | fBufferSize = mcpsRequest->Req.Proprietary.fBufferSize; |
dudmuck | 0:8f0d0ae0a077 | 2508 | break; |
dudmuck | 0:8f0d0ae0a077 | 2509 | } |
dudmuck | 0:8f0d0ae0a077 | 2510 | default: |
dudmuck | 0:8f0d0ae0a077 | 2511 | break; |
dudmuck | 0:8f0d0ae0a077 | 2512 | } |
dudmuck | 0:8f0d0ae0a077 | 2513 | |
Wayne Roberts |
29:ad409c68c0a6 | 2514 | if (readyToSend) |
dudmuck | 0:8f0d0ae0a077 | 2515 | { |
dudmuck | 0:8f0d0ae0a077 | 2516 | status = Send( &macHdr, fPort, fBuffer, fBufferSize ); |
Wayne Roberts |
29:ad409c68c0a6 | 2517 | if (status == LORAMAC_STATUS_OK) |
dudmuck | 0:8f0d0ae0a077 | 2518 | { |
dudmuck | 0:8f0d0ae0a077 | 2519 | McpsConfirm.McpsRequest = mcpsRequest->Type; |
dudmuck | 0:8f0d0ae0a077 | 2520 | LoRaMacFlags.Bits.McpsReq = 1; |
dudmuck | 0:8f0d0ae0a077 | 2521 | } |
dudmuck | 0:8f0d0ae0a077 | 2522 | else |
dudmuck | 0:8f0d0ae0a077 | 2523 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2524 | LoRaMacFlags.Bits.NodeAckRequested = false; |
dudmuck | 0:8f0d0ae0a077 | 2525 | } |
dudmuck | 0:8f0d0ae0a077 | 2526 | } |
dudmuck | 0:8f0d0ae0a077 | 2527 | |
dudmuck | 0:8f0d0ae0a077 | 2528 | return status; |
dudmuck | 0:8f0d0ae0a077 | 2529 | } |
dudmuck | 0:8f0d0ae0a077 | 2530 | |
dudmuck | 0:8f0d0ae0a077 | 2531 | void LoRaMacTestRxWindowsOn( bool enable ) |
dudmuck | 0:8f0d0ae0a077 | 2532 | { |
dudmuck | 0:8f0d0ae0a077 | 2533 | IsRxWindowsEnabled = enable; |
dudmuck | 0:8f0d0ae0a077 | 2534 | } |
dudmuck | 0:8f0d0ae0a077 | 2535 | |
dudmuck | 0:8f0d0ae0a077 | 2536 | void LoRaMacTestSetMic( uint16_t txPacketCounter ) |
dudmuck | 0:8f0d0ae0a077 | 2537 | { |
dudmuck | 0:8f0d0ae0a077 | 2538 | UpLinkCounter = txPacketCounter; |
dudmuck | 16:915815632c1f | 2539 | //IsUpLinkCounterFixed = true; |
dudmuck | 0:8f0d0ae0a077 | 2540 | } |
dudmuck | 0:8f0d0ae0a077 | 2541 | |
dudmuck | 0:8f0d0ae0a077 | 2542 | void LoRaMacTestSetChannel( uint8_t channel ) |
dudmuck | 0:8f0d0ae0a077 | 2543 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2544 | mac_printf("set-testch%u\r\n", channel); |
dudmuck | 0:8f0d0ae0a077 | 2545 | Channel = channel; |
dudmuck | 0:8f0d0ae0a077 | 2546 | } |
dudmuck | 0:8f0d0ae0a077 | 2547 | |
dudmuck | 0:8f0d0ae0a077 | 2548 | |
dudmuck | 0:8f0d0ae0a077 | 2549 | static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError ) |
dudmuck | 0:8f0d0ae0a077 | 2550 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2551 | RxConfigParams_t rxConfigParams = { 0, 0 }; |
dudmuck | 0:8f0d0ae0a077 | 2552 | double tSymbol = 0.0; |
dudmuck | 0:8f0d0ae0a077 | 2553 | |
dudmuck | 0:8f0d0ae0a077 | 2554 | rxConfigParams.Datarate = datarate; |
dudmuck | 0:8f0d0ae0a077 | 2555 | |
dudmuck | 0:8f0d0ae0a077 | 2556 | #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) |
dudmuck | 0:8f0d0ae0a077 | 2557 | if( datarate == DR_7 ) |
dudmuck | 0:8f0d0ae0a077 | 2558 | { // FSK |
dudmuck | 0:8f0d0ae0a077 | 2559 | tSymbol = ( 1.0 / ( double )Datarates[datarate] ) * 8.0; // 1 symbol equals 1 byte |
dudmuck | 0:8f0d0ae0a077 | 2560 | } |
dudmuck | 0:8f0d0ae0a077 | 2561 | else |
dudmuck | 0:8f0d0ae0a077 | 2562 | #endif |
dudmuck | 0:8f0d0ae0a077 | 2563 | { // LoRa |
Wayne Roberts |
29:ad409c68c0a6 | 2564 | tSymbol = ( ( double )( 1 << Datarates[datarate] ) / LORA_BANDWIDTH_KHZ ) * 1e3; |
dudmuck | 0:8f0d0ae0a077 | 2565 | } |
dudmuck | 0:8f0d0ae0a077 | 2566 | |
dudmuck | 0:8f0d0ae0a077 | 2567 | rxConfigParams.RxWindowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * LoRaMacParams.MinRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), LoRaMacParams.MinRxSymbols ); // Computed number of symbols |
Wayne Roberts |
29:ad409c68c0a6 | 2568 | mac_printf("RxWindowTimeout:%u\r\n", rxConfigParams.RxWindowTimeout); |
dudmuck | 0:8f0d0ae0a077 | 2569 | |
dudmuck | 0:8f0d0ae0a077 | 2570 | return rxConfigParams; |
dudmuck | 0:8f0d0ae0a077 | 2571 | } |
dudmuck | 0:8f0d0ae0a077 | 2572 | |
dudmuck | 20:42839629a5dc | 2573 | void LoRaMacBottomHalf() |
dudmuck | 20:42839629a5dc | 2574 | { |
Wayne Roberts |
29:ad409c68c0a6 | 2575 | if (LoRaMacFlags.Bits.join_send) { |
Wayne Roberts |
29:ad409c68c0a6 | 2576 | join_send_bh(); |
Wayne Roberts |
29:ad409c68c0a6 | 2577 | LoRaMacFlags.Bits.join_send = 0; |
dudmuck | 20:42839629a5dc | 2578 | } |
Wayne Roberts |
29:ad409c68c0a6 | 2579 | if (LoRaMacFlags.Bits.send) { |
Wayne Roberts |
29:ad409c68c0a6 | 2580 | send_bh(); |
Wayne Roberts |
29:ad409c68c0a6 | 2581 | LoRaMacFlags.Bits.send = 0; |
dudmuck | 20:42839629a5dc | 2582 | } |
Wayne Roberts |
29:ad409c68c0a6 | 2583 | |
Wayne Roberts |
29:ad409c68c0a6 | 2584 | if (LoRaMacFlags.Bits.reJoin) { |
Wayne Roberts |
29:ad409c68c0a6 | 2585 | MlmeReq_t mlmeReq; |
Wayne Roberts |
29:ad409c68c0a6 | 2586 | mlmeReq.Type = MLME_JOIN; |
Wayne Roberts |
29:ad409c68c0a6 | 2587 | |
Wayne Roberts |
29:ad409c68c0a6 | 2588 | mlmeReq.Req.Join.DevEui = LoRaMacDevEui; |
Wayne Roberts |
29:ad409c68c0a6 | 2589 | mlmeReq.Req.Join.AppEui = LoRaMacAppEui; |
Wayne Roberts |
29:ad409c68c0a6 | 2590 | mlmeReq.Req.Join.AppKey = LoRaMacAppKey; |
Wayne Roberts |
29:ad409c68c0a6 | 2591 | mlmeReq.Req.Join.NbTrials = 255; |
Wayne Roberts |
29:ad409c68c0a6 | 2592 | |
Wayne Roberts |
29:ad409c68c0a6 | 2593 | if (LoRaMacMlmeRequest(&mlmeReq) == LORAMAC_STATUS_OK) |
Wayne Roberts |
29:ad409c68c0a6 | 2594 | LoRaMacFlags.Bits.reJoin = 0; |
dudmuck | 20:42839629a5dc | 2595 | } |
Wayne Roberts |
29:ad409c68c0a6 | 2596 | |
Wayne Roberts |
29:ad409c68c0a6 | 2597 | Radio::service(); |
dudmuck | 20:42839629a5dc | 2598 | } |