LoRaWAN end device MAC layer for SX1272 and SX1276. Supports LoRaWAN-1.0 and LoRaWAN-1.1
Dependents: LoRaWAN-SanJose_Bootcamp LoRaWAN-grove-cayenne LoRaWAN-classC-demo LoRaWAN-grove-cayenne ... more
radio chip selection
Radio chip driver is not included, because two options are available.
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 NAmote72 or Murata discovery, then you must import only sx127x driver.
application project requirements
This library requires mbed TLS to be enabled.
The file mbed_app.json
must be present in the project using this library:
{ "macros": [ "MBEDTLS_CMAC_C" ] }
regional PHY selection
All end device configuration is done in Commissioning.h, define desired radio frequency band of operation in this header file.
Commissioning.h is located in the application using this library.
end device provisioning
End device is provisioned by editing Commissioning.h in the application which is using this library
To use LoRaWAN-1.0 OTA: make sure LORAWAN_ROOT_APPKEY
is undefined.
To use LoRaWAN-1.1 OTA, define LORAWAN_ROOT_APPKEY
.
To select OTA operation, define LORAWAN_JOIN_EUI
, then LORAWAN_DEVICE_EUI
must be defined, along with root key(s).
To select ABP operation, undefine LORAWAN_JOIN_EUI
: then define session keys
LoRaWAN 1.0 name | LoRaWAN 1.1 name | Comissioning.h defne | description | |
---|---|---|---|---|
OTA | DevEUI | DevEUI | LORAWAN_DEVICE_EUI | uniquely identifies end device |
OTA | AppEUI | JoinEUI | LORAWAN_JOIN_EUI | |
OTA | AppKey | NwkKey | LORAWAN_ROOT_NWKKEY | root key for network server |
OTA | (note 1) | AppKey | LORAWAN_ROOT_APPKEY | root key for application server |
ABP | NwkSKey | (note 3) | LORAWAN_FNwkSIntKey | network session key |
ABP | (note 2) | SNwkSIntKey | LORAWAN_SNwkSIntKey | mac layer network integrity key |
ABP | (note 2) | NwkSEncKey | LORAWAN_NwkSEncKey | network session encryption key |
ABP | (note 2) | FNwkSIntKey | LORAWAN_FNwkSIntKey | forwarding network session integrity key |
ABP | AppSKey | AppSKey | LORAWAN_APPSKEY | application session encryption key |
(note 1): LoRaWAN-1.0 OTA uses a single root key for both network server and application server.
In LoRaWAN-1.0 OTA: the single root AppKey is used to generate NwkSkey and AppSKey.
(note 2): In LoRaWAN-1.0 (both OTA and ABP) SNwkSIntKey, NwkSEncKey. FNwkSIntKey are of same value and are collectively known as NwkSKey.
(note 3): LoRaWAN-1.0 uses single network session key, LoRaWAN-1.1 uses 3 network session keys. Both use a unique application session key.
In LoRaWAN-1.1 OTA: the root NwkKey is used to generate SNwkSIntKey, NwkSEncKey, FNwkSIntKey
In LoRaWAN-1.1 OTA: the root AppKey is used to generate AppSKey
in ABP mode, the DevAddr, and session keys are fixed (never change), and frame counters never reset to zero.
ABP operation has no concept of: root keys, or DevEUI or JoinEUI/AppEUI.
in OTA mode, the DevAddr and session keys are assigned at join procedure, and frame counters reset at join.
eeprom
This library includes eeprom driver to support non-volatile storage required by LoRaWAN specification.
Currently eeprom is implemented for STM32L1 family and STM32L0 family.
Writing of values are wear-leveled to increase endurance; each write operation circulates across several memory locations. A read operation returns the highest value found. This simple method is used for sequence numbers which only increase.
value name | used in | |
---|---|---|
DevNonce | OTA | for Join request (note 1) |
RJcount1 | OTA | for ReJoin Type 1 request |
FCntUp | ABP | uplink frame counter |
NFCntDown | ABP | downlink frame counter |
AFCntDown | ABP | downlink frame counter |
AFCntDown is only used in LoRaWAN-1.1 when application payload is present in downlink and FPort > 0.
NFCntDown is used in LoRaWAN-1.1 when FPort is zero in downlink or application payload not present.
NFCntDown is the only downlink frame counter used in LoRaWAN-1.0
(note 1) OTA DevNonce is random number in LoRaWAN-1.0, therefore not stored in eeprom. DevNonce in LoRaWAN-1.1 is forever increasing (non-volatile) number upon each join request,.
RJcount0 is only stored in RAM because the value resets upon new session from JoinAccept, therefore not stored in eeprom.
Frame counters in OTA mode reset upon new session in join request, therefore are stored in RAM instead of eeprom for OTA.
radio driver support
When SX127x driver is used, both SX1272 and SX1276 are supported without defining at compile time. The chip is detected at start-up.
Supported radio platforms:
Alternately, when SX126x driver is imported, the SX126xDVK1xAS board is used.
low-speed clock oscillator selection
LoRaWAN uses 32768Hz crystal to permit low-power operation.
However, some mbed targets might revert to low-speed internal oscillator, which is not accurate enough for LoRaWAN operation.
An oscillator check is performed at initialization; program will not start if internal oscillator is used.
To force LSE watch crystal, add to mbed_app.json
{ "macros": [ "MBEDTLS_CMAC_C" ], "target_overrides": { "<your-target>": { "target.lse_available": true } } }
mac/LoRaMac1v1.cpp@0:6b3ac9c5a042, 2018-02-28 (annotated)
- Committer:
- Wayne Roberts
- Date:
- Wed Feb 28 10:48:11 2018 -0800
- Revision:
- 0:6b3ac9c5a042
- Child:
- 1:62f7347b9e17
initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Wayne Roberts |
0:6b3ac9c5a042 | 1 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2 | #include "LoRaMacPrivate.h" |
Wayne Roberts |
0:6b3ac9c5a042 | 3 | #include "LoRaMacCrypto.h" |
Wayne Roberts |
0:6b3ac9c5a042 | 4 | |
Wayne Roberts |
0:6b3ac9c5a042 | 5 | #define ADR_ACK_LIMIT 64 |
Wayne Roberts |
0:6b3ac9c5a042 | 6 | #define ADR_ACK_DELAY 32 |
Wayne Roberts |
0:6b3ac9c5a042 | 7 | #define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4) |
Wayne Roberts |
0:6b3ac9c5a042 | 8 | #define RECEIVE_DELAY1_us 1000000 |
Wayne Roberts |
0:6b3ac9c5a042 | 9 | #define RECEIVE_DELAY2_us 2000000 |
Wayne Roberts |
0:6b3ac9c5a042 | 10 | #define LORAMAC_MFR_LEN 4 |
Wayne Roberts |
0:6b3ac9c5a042 | 11 | |
Wayne Roberts |
0:6b3ac9c5a042 | 12 | /*! |
Wayne Roberts |
0:6b3ac9c5a042 | 13 | * LoRaMAC Battery level indicator |
Wayne Roberts |
0:6b3ac9c5a042 | 14 | */ |
Wayne Roberts |
0:6b3ac9c5a042 | 15 | typedef enum eLoRaMacBatteryLevel |
Wayne Roberts |
0:6b3ac9c5a042 | 16 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 17 | /*! |
Wayne Roberts |
0:6b3ac9c5a042 | 18 | * External power source |
Wayne Roberts |
0:6b3ac9c5a042 | 19 | */ |
Wayne Roberts |
0:6b3ac9c5a042 | 20 | BAT_LEVEL_EXT_SRC = 0x00, |
Wayne Roberts |
0:6b3ac9c5a042 | 21 | /*! |
Wayne Roberts |
0:6b3ac9c5a042 | 22 | * Battery level empty |
Wayne Roberts |
0:6b3ac9c5a042 | 23 | */ |
Wayne Roberts |
0:6b3ac9c5a042 | 24 | BAT_LEVEL_EMPTY = 0x01, |
Wayne Roberts |
0:6b3ac9c5a042 | 25 | /*! |
Wayne Roberts |
0:6b3ac9c5a042 | 26 | * Battery level full |
Wayne Roberts |
0:6b3ac9c5a042 | 27 | */ |
Wayne Roberts |
0:6b3ac9c5a042 | 28 | BAT_LEVEL_FULL = 0xFE, |
Wayne Roberts |
0:6b3ac9c5a042 | 29 | /*! |
Wayne Roberts |
0:6b3ac9c5a042 | 30 | * Battery level - no measurement available |
Wayne Roberts |
0:6b3ac9c5a042 | 31 | */ |
Wayne Roberts |
0:6b3ac9c5a042 | 32 | BAT_LEVEL_NO_MEASURE = 0xFF, |
Wayne Roberts |
0:6b3ac9c5a042 | 33 | }LoRaMacBatteryLevel_t; |
Wayne Roberts |
0:6b3ac9c5a042 | 34 | |
Wayne Roberts |
0:6b3ac9c5a042 | 35 | /*! |
Wayne Roberts |
0:6b3ac9c5a042 | 36 | * LoRaMac internal state |
Wayne Roberts |
0:6b3ac9c5a042 | 37 | */ |
Wayne Roberts |
0:6b3ac9c5a042 | 38 | flags_t flags; |
Wayne Roberts |
0:6b3ac9c5a042 | 39 | |
Wayne Roberts |
0:6b3ac9c5a042 | 40 | void (*function_pending)(void); // one-shot |
Wayne Roberts |
0:6b3ac9c5a042 | 41 | |
Wayne Roberts |
0:6b3ac9c5a042 | 42 | /*! |
Wayne Roberts |
0:6b3ac9c5a042 | 43 | * Current channel index |
Wayne Roberts |
0:6b3ac9c5a042 | 44 | */ |
Wayne Roberts |
0:6b3ac9c5a042 | 45 | uint8_t Channel; |
Wayne Roberts |
0:6b3ac9c5a042 | 46 | |
Wayne Roberts |
0:6b3ac9c5a042 | 47 | static MlmeIndication_t MlmeIndication; |
Wayne Roberts |
0:6b3ac9c5a042 | 48 | static MlmeConfirm_t MlmeConfirm; |
Wayne Roberts |
0:6b3ac9c5a042 | 49 | static McpsIndication_t McpsIndication; |
Wayne Roberts |
0:6b3ac9c5a042 | 50 | static McpsConfirm_t McpsConfirm; |
Wayne Roberts |
0:6b3ac9c5a042 | 51 | |
Wayne Roberts |
0:6b3ac9c5a042 | 52 | uint32_t LoRaMacDevAddr; |
Wayne Roberts |
0:6b3ac9c5a042 | 53 | uint32_t LoRaMacNetID; |
Wayne Roberts |
0:6b3ac9c5a042 | 54 | static skey_t keys; |
Wayne Roberts |
0:6b3ac9c5a042 | 55 | |
Wayne Roberts |
0:6b3ac9c5a042 | 56 | uint8_t MacCommandsBufferToRepeatIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 57 | uint8_t MacCommandsBufferIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 58 | uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH]; |
Wayne Roberts |
0:6b3ac9c5a042 | 59 | static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH]; |
Wayne Roberts |
0:6b3ac9c5a042 | 60 | |
Wayne Roberts |
0:6b3ac9c5a042 | 61 | LoRaMacParams_t LoRaMacParams; |
Wayne Roberts |
0:6b3ac9c5a042 | 62 | LoRaMacParams_t LoRaMacParamsDefaults; |
Wayne Roberts |
0:6b3ac9c5a042 | 63 | |
Wayne Roberts |
0:6b3ac9c5a042 | 64 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 65 | #define JOIN_ACCEPT_DELAY1_us 5000000 |
Wayne Roberts |
0:6b3ac9c5a042 | 66 | #define JOIN_ACCEPT_DELAY2_us 6000000 |
Wayne Roberts |
0:6b3ac9c5a042 | 67 | static const uint8_t *LoRaMacDevEui; |
Wayne Roberts |
0:6b3ac9c5a042 | 68 | static const uint8_t *LoRaMacJoinEui; |
Wayne Roberts |
0:6b3ac9c5a042 | 69 | static const uint8_t *RootNwkKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 70 | static const uint8_t *RootAppKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 71 | static uint8_t MaxJoinRequestTrials; |
Wayne Roberts |
0:6b3ac9c5a042 | 72 | static uint8_t JSEncKey[16]; // TODO move to keys |
Wayne Roberts |
0:6b3ac9c5a042 | 73 | static uint8_t JSIntKey[16]; // TODO move to keys |
Wayne Roberts |
0:6b3ac9c5a042 | 74 | static uint8_t JoinReqType; |
Wayne Roberts |
0:6b3ac9c5a042 | 75 | static uint16_t LoRaMacDevNonce; |
Wayne Roberts |
0:6b3ac9c5a042 | 76 | uint16_t RJcount0; |
Wayne Roberts |
0:6b3ac9c5a042 | 77 | |
Wayne Roberts |
0:6b3ac9c5a042 | 78 | static uint32_t FCntUp; |
Wayne Roberts |
0:6b3ac9c5a042 | 79 | static uint32_t NFCntDown; /**< set to next expected value */ |
Wayne Roberts |
0:6b3ac9c5a042 | 80 | static uint32_t AFCntDown; /**< set to next expected value */ |
Wayne Roberts |
0:6b3ac9c5a042 | 81 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 82 | |
Wayne Roberts |
0:6b3ac9c5a042 | 83 | static uint32_t AdrAckCounter; |
Wayne Roberts |
0:6b3ac9c5a042 | 84 | static uint8_t AckTimeoutRetries; |
Wayne Roberts |
0:6b3ac9c5a042 | 85 | static uint8_t AckTimeoutRetriesCounter; |
Wayne Roberts |
0:6b3ac9c5a042 | 86 | |
Wayne Roberts |
0:6b3ac9c5a042 | 87 | //static uint8_t ChannelsNbRepCounter; |
Wayne Roberts |
0:6b3ac9c5a042 | 88 | DeviceClass_t LoRaMacDeviceClass; |
Wayne Roberts |
0:6b3ac9c5a042 | 89 | uint8_t tx_buf_len; |
Wayne Roberts |
0:6b3ac9c5a042 | 90 | const LoRaMacHeader_t* uplinkMHDR = (LoRaMacHeader_t*)&Radio::radio.tx_buf[0]; |
Wayne Roberts |
0:6b3ac9c5a042 | 91 | |
Wayne Roberts |
0:6b3ac9c5a042 | 92 | static uint32_t RxWindow1Delay_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 93 | static uint32_t RxWindow2Delay_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 94 | |
Wayne Roberts |
0:6b3ac9c5a042 | 95 | LoRaMacHeader_t last_up_macHdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 96 | static uint8_t rxFRMPayload[244]; |
Wayne Roberts |
0:6b3ac9c5a042 | 97 | |
Wayne Roberts |
0:6b3ac9c5a042 | 98 | static const LoRaMacPrimitives_t *LoRaMacPrimitives; |
Wayne Roberts |
0:6b3ac9c5a042 | 99 | static const LoRaMacCallback_t *LoRaMacCallbacks; |
Wayne Roberts |
0:6b3ac9c5a042 | 100 | |
Wayne Roberts |
0:6b3ac9c5a042 | 101 | /*! |
Wayne Roberts |
0:6b3ac9c5a042 | 102 | * LoRaMAC frame counter. Each time a packet is received the counter is incremented. |
Wayne Roberts |
0:6b3ac9c5a042 | 103 | * Only the 16 LSB bits are received |
Wayne Roberts |
0:6b3ac9c5a042 | 104 | */ |
Wayne Roberts |
0:6b3ac9c5a042 | 105 | static uint16_t ConfFCntDown; |
Wayne Roberts |
0:6b3ac9c5a042 | 106 | static uint16_t ConfFCntUp; |
Wayne Roberts |
0:6b3ac9c5a042 | 107 | |
Wayne Roberts |
0:6b3ac9c5a042 | 108 | static void PrepareRxDoneAbort(LoRaMacEventInfoStatus_t); |
Wayne Roberts |
0:6b3ac9c5a042 | 109 | |
Wayne Roberts |
0:6b3ac9c5a042 | 110 | LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 111 | AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 112 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 113 | LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 114 | // The maximum buffer length must take MAC commands to re-send into account. |
Wayne Roberts |
0:6b3ac9c5a042 | 115 | uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 116 | |
Wayne Roberts |
0:6b3ac9c5a042 | 117 | MAC_PRINTF("AddMacCommand(%02x, %02x, %02x)\r\n", cmd, p1, p2); |
Wayne Roberts |
0:6b3ac9c5a042 | 118 | switch( cmd ) |
Wayne Roberts |
0:6b3ac9c5a042 | 119 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 120 | case MOTE_MAC_LINK_CHECK_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 121 | case MOTE_MAC_DEVICE_TIME_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 122 | if( MacCommandsBufferIndex < bufLen ) |
Wayne Roberts |
0:6b3ac9c5a042 | 123 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 124 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 125 | // No payload for this command |
Wayne Roberts |
0:6b3ac9c5a042 | 126 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 127 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 128 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 129 | case MOTE_MAC_LINK_ADR_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 130 | if( MacCommandsBufferIndex < ( bufLen - 1 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 131 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 132 | MAC_PRINTF("LINK_ADR_ANS %02x ", p1); |
Wayne Roberts |
0:6b3ac9c5a042 | 133 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 134 | // Margin |
Wayne Roberts |
0:6b3ac9c5a042 | 135 | MacCommandsBuffer[MacCommandsBufferIndex++] = p1; |
Wayne Roberts |
0:6b3ac9c5a042 | 136 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 137 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 138 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 139 | case MOTE_MAC_DUTY_CYCLE_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 140 | if( MacCommandsBufferIndex < bufLen ) |
Wayne Roberts |
0:6b3ac9c5a042 | 141 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 142 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 143 | // No payload for this answer |
Wayne Roberts |
0:6b3ac9c5a042 | 144 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 145 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 146 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 147 | case MOTE_MAC_RX_PARAM_SETUP_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 148 | if( MacCommandsBufferIndex < ( bufLen - 1 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 149 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 150 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 151 | // Status: Datarate ACK, Channel ACK |
Wayne Roberts |
0:6b3ac9c5a042 | 152 | MacCommandsBuffer[MacCommandsBufferIndex++] = p1; |
Wayne Roberts |
0:6b3ac9c5a042 | 153 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 154 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 155 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 156 | case MOTE_MAC_DEV_STATUS_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 157 | if( MacCommandsBufferIndex < ( bufLen - 2 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 158 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 159 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 160 | // 1st byte Battery |
Wayne Roberts |
0:6b3ac9c5a042 | 161 | // 2nd byte Margin |
Wayne Roberts |
0:6b3ac9c5a042 | 162 | MacCommandsBuffer[MacCommandsBufferIndex++] = p1; |
Wayne Roberts |
0:6b3ac9c5a042 | 163 | MacCommandsBuffer[MacCommandsBufferIndex++] = p2; |
Wayne Roberts |
0:6b3ac9c5a042 | 164 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 165 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 166 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 167 | case MOTE_MAC_NEW_CHANNEL_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 168 | if( MacCommandsBufferIndex < ( bufLen - 1 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 169 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 170 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 171 | // Status: Datarate range OK, Channel frequency OK |
Wayne Roberts |
0:6b3ac9c5a042 | 172 | MacCommandsBuffer[MacCommandsBufferIndex++] = p1; |
Wayne Roberts |
0:6b3ac9c5a042 | 173 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 174 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 175 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 176 | case MOTE_MAC_RX_TIMING_SETUP_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 177 | if( MacCommandsBufferIndex < bufLen ) |
Wayne Roberts |
0:6b3ac9c5a042 | 178 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 179 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 180 | // No payload for this answer |
Wayne Roberts |
0:6b3ac9c5a042 | 181 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 182 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 183 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 184 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 185 | case MOTE_MAC_REKEY_IND: |
Wayne Roberts |
0:6b3ac9c5a042 | 186 | if( MacCommandsBufferIndex < bufLen-1 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 187 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 188 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 189 | // minor version: |
Wayne Roberts |
0:6b3ac9c5a042 | 190 | if (RootAppKey == NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 191 | MacCommandsBuffer[MacCommandsBufferIndex++] = 0; // lorawan1v0 |
Wayne Roberts |
0:6b3ac9c5a042 | 192 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 193 | MacCommandsBuffer[MacCommandsBufferIndex++] = 1; // lorawan1v1 |
Wayne Roberts |
0:6b3ac9c5a042 | 194 | |
Wayne Roberts |
0:6b3ac9c5a042 | 195 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 196 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 197 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 198 | case MOTE_MAC_REJOIN_PARAM_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 199 | if( MacCommandsBufferIndex < bufLen-1 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 200 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 201 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 202 | MacCommandsBuffer[MacCommandsBufferIndex++] = p1; |
Wayne Roberts |
0:6b3ac9c5a042 | 203 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 204 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 205 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 206 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 207 | case MOTE_MAC_RESET_IND: |
Wayne Roberts |
0:6b3ac9c5a042 | 208 | if( MacCommandsBufferIndex < bufLen-1 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 209 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 210 | MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; |
Wayne Roberts |
0:6b3ac9c5a042 | 211 | // minor version: |
Wayne Roberts |
0:6b3ac9c5a042 | 212 | MacCommandsBuffer[MacCommandsBufferIndex++] = p1; |
Wayne Roberts |
0:6b3ac9c5a042 | 213 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 214 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 215 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 216 | #endif /* !LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 217 | default: |
Wayne Roberts |
0:6b3ac9c5a042 | 218 | MAC_PRINTF("unknown-addCmd %02x\r\n", cmd); |
Wayne Roberts |
0:6b3ac9c5a042 | 219 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 220 | } // ..switch( cmd ) |
Wayne Roberts |
0:6b3ac9c5a042 | 221 | |
Wayne Roberts |
0:6b3ac9c5a042 | 222 | if( status == LORAMAC_STATUS_OK ) |
Wayne Roberts |
0:6b3ac9c5a042 | 223 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 224 | flags.MacCommandsInNextTx = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 225 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 226 | return status; |
Wayne Roberts |
0:6b3ac9c5a042 | 227 | } // ..AddMacCommand() |
Wayne Roberts |
0:6b3ac9c5a042 | 228 | |
Wayne Roberts |
0:6b3ac9c5a042 | 229 | static int8_t |
Wayne Roberts |
0:6b3ac9c5a042 | 230 | LimitTxPower( int8_t txPower ) |
Wayne Roberts |
0:6b3ac9c5a042 | 231 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 232 | int8_t resultTxPower = txPower; |
Wayne Roberts |
0:6b3ac9c5a042 | 233 | #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 234 | if( ( LoRaMacParams.ChannelsDatarate == DR_4 ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 235 | ( ( LoRaMacParams.ChannelsDatarate >= DR_8 ) && ( LoRaMacParams.ChannelsDatarate <= DR_13 ) ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 236 | {// Limit tx power to max 26dBm |
Wayne Roberts |
0:6b3ac9c5a042 | 237 | resultTxPower = MAX( txPower, TX_POWER_26_DBM ); |
Wayne Roberts |
0:6b3ac9c5a042 | 238 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 239 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 240 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 241 | if( CountNbEnabled125kHzChannels( LoRaMacParams.ChannelsMask ) < 50 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 242 | {// Limit tx power to max 21dBm |
Wayne Roberts |
0:6b3ac9c5a042 | 243 | resultTxPower = MAX( txPower, TX_POWER_20_DBM ); |
Wayne Roberts |
0:6b3ac9c5a042 | 244 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 245 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 246 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 247 | return resultTxPower; |
Wayne Roberts |
0:6b3ac9c5a042 | 248 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 249 | |
Wayne Roberts |
0:6b3ac9c5a042 | 250 | LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout ) |
Wayne Roberts |
0:6b3ac9c5a042 | 251 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 252 | int8_t txPowerIndex = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 253 | int8_t txPower = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 254 | |
Wayne Roberts |
0:6b3ac9c5a042 | 255 | txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower ); |
Wayne Roberts |
0:6b3ac9c5a042 | 256 | txPower = TxPowers[txPowerIndex]; |
Wayne Roberts |
0:6b3ac9c5a042 | 257 | |
Wayne Roberts |
0:6b3ac9c5a042 | 258 | Radio::SetTxContinuousWave( Channels[Channel].FreqHz, txPower, timeout ); |
Wayne Roberts |
0:6b3ac9c5a042 | 259 | |
Wayne Roberts |
0:6b3ac9c5a042 | 260 | flags.uplink_in_progress = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 261 | |
Wayne Roberts |
0:6b3ac9c5a042 | 262 | return LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 263 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 264 | |
Wayne Roberts |
0:6b3ac9c5a042 | 265 | __attribute__((weak)) LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 266 | LoRaMacMlmeRequestClassB( const MlmeReq_t *mlmeRequest ) |
Wayne Roberts |
0:6b3ac9c5a042 | 267 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 268 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 269 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 270 | |
Wayne Roberts |
0:6b3ac9c5a042 | 271 | __attribute__((weak)) LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 272 | AddMacCommandClassB( uint8_t cmd, uint8_t p1, uint8_t p2 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 273 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 274 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 275 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 276 | |
Wayne Roberts |
0:6b3ac9c5a042 | 277 | __attribute__((weak)) void |
Wayne Roberts |
0:6b3ac9c5a042 | 278 | ResetMacParametersClassB() |
Wayne Roberts |
0:6b3ac9c5a042 | 279 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 280 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 281 | |
Wayne Roberts |
0:6b3ac9c5a042 | 282 | static void ResetMacParameters( void ) |
Wayne Roberts |
0:6b3ac9c5a042 | 283 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 284 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 285 | flags.IsLoRaMacNetworkJoined = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 286 | NFCntDown = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 287 | AFCntDown = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 288 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 289 | AdrAckCounter = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 290 | |
Wayne Roberts |
0:6b3ac9c5a042 | 291 | //ChannelsNbRepCounter = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 292 | |
Wayne Roberts |
0:6b3ac9c5a042 | 293 | AckTimeoutRetries = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 294 | AckTimeoutRetriesCounter = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 295 | //AckTimeoutRetry = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 296 | |
Wayne Roberts |
0:6b3ac9c5a042 | 297 | #ifdef DUTY_ENABLE |
Wayne Roberts |
0:6b3ac9c5a042 | 298 | DutyInit(); |
Wayne Roberts |
0:6b3ac9c5a042 | 299 | #endif /* DUTY_ENABLE */ |
Wayne Roberts |
0:6b3ac9c5a042 | 300 | |
Wayne Roberts |
0:6b3ac9c5a042 | 301 | MacCommandsBufferIndex = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 302 | MacCommandsBufferToRepeatIndex = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 303 | |
Wayne Roberts |
0:6b3ac9c5a042 | 304 | //IsRxWindowsEnabled = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 305 | |
Wayne Roberts |
0:6b3ac9c5a042 | 306 | LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower; |
Wayne Roberts |
0:6b3ac9c5a042 | 307 | LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 308 | |
Wayne Roberts |
0:6b3ac9c5a042 | 309 | LoRaMacParams.MaxRxWindow_us = LoRaMacParamsDefaults.MaxRxWindow_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 310 | LoRaMacParams.ReceiveDelay1_us = LoRaMacParamsDefaults.ReceiveDelay1_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 311 | LoRaMacParams.ReceiveDelay2_us = LoRaMacParamsDefaults.ReceiveDelay2_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 312 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 313 | LoRaMacParams.JoinAcceptDelay1_us = LoRaMacParamsDefaults.JoinAcceptDelay1_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 314 | LoRaMacParams.JoinAcceptDelay2_us = LoRaMacParamsDefaults.JoinAcceptDelay2_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 315 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 316 | |
Wayne Roberts |
0:6b3ac9c5a042 | 317 | LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset; |
Wayne Roberts |
0:6b3ac9c5a042 | 318 | LoRaMacParams.NbTrans = LoRaMacParamsDefaults.NbTrans; |
Wayne Roberts |
0:6b3ac9c5a042 | 319 | |
Wayne Roberts |
0:6b3ac9c5a042 | 320 | LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel; |
Wayne Roberts |
0:6b3ac9c5a042 | 321 | |
Wayne Roberts |
0:6b3ac9c5a042 | 322 | memcpy( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 323 | |
Wayne Roberts |
0:6b3ac9c5a042 | 324 | #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 325 | memcpy( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 326 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 327 | |
Wayne Roberts |
0:6b3ac9c5a042 | 328 | |
Wayne Roberts |
0:6b3ac9c5a042 | 329 | flags.SrvAckRequested = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 330 | flags.MacCommandsInNextTx = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 331 | |
Wayne Roberts |
0:6b3ac9c5a042 | 332 | // Initialize channel index. |
Wayne Roberts |
0:6b3ac9c5a042 | 333 | Channel = LORA_MAX_NB_CHANNELS; |
Wayne Roberts |
0:6b3ac9c5a042 | 334 | |
Wayne Roberts |
0:6b3ac9c5a042 | 335 | ResetMacParametersClassB(); |
Wayne Roberts |
0:6b3ac9c5a042 | 336 | |
Wayne Roberts |
0:6b3ac9c5a042 | 337 | } // ..ResetMacParameters() |
Wayne Roberts |
0:6b3ac9c5a042 | 338 | |
Wayne Roberts |
0:6b3ac9c5a042 | 339 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 340 | static int8_t AlternateDatarate( uint16_t nbTrials ) |
Wayne Roberts |
0:6b3ac9c5a042 | 341 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 342 | int8_t datarate = LORAMAC_TX_MIN_DATARATE; |
Wayne Roberts |
0:6b3ac9c5a042 | 343 | #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 344 | #if defined( USE_BAND_915 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 345 | // Re-enable 500 kHz default channels |
Wayne Roberts |
0:6b3ac9c5a042 | 346 | LoRaMacParams.ChannelsMask[4] = 0x00FF; |
Wayne Roberts |
0:6b3ac9c5a042 | 347 | #else // defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 348 | // Re-enable 500 kHz default channels |
Wayne Roberts |
0:6b3ac9c5a042 | 349 | ReenableChannels( LoRaMacParamsDefaults.ChannelsMask[4], LoRaMacParams.ChannelsMask ); |
Wayne Roberts |
0:6b3ac9c5a042 | 350 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 351 | |
Wayne Roberts |
0:6b3ac9c5a042 | 352 | if( ( nbTrials & 0x01 ) == 0x01 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 353 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 354 | datarate = DR_4; |
Wayne Roberts |
0:6b3ac9c5a042 | 355 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 356 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 357 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 358 | datarate = DR_0; |
Wayne Roberts |
0:6b3ac9c5a042 | 359 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 360 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 361 | if( ( nbTrials % 48 ) == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 362 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 363 | datarate = DR_0; |
Wayne Roberts |
0:6b3ac9c5a042 | 364 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 365 | else if( ( nbTrials % 32 ) == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 366 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 367 | datarate = DR_1; |
Wayne Roberts |
0:6b3ac9c5a042 | 368 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 369 | else if( ( nbTrials % 24 ) == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 370 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 371 | datarate = DR_2; |
Wayne Roberts |
0:6b3ac9c5a042 | 372 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 373 | else if( ( nbTrials % 16 ) == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 374 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 375 | datarate = DR_3; |
Wayne Roberts |
0:6b3ac9c5a042 | 376 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 377 | else if( ( nbTrials % 8 ) == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 378 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 379 | datarate = DR_4; |
Wayne Roberts |
0:6b3ac9c5a042 | 380 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 381 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 382 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 383 | datarate = DR_5; |
Wayne Roberts |
0:6b3ac9c5a042 | 384 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 385 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 386 | return datarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 387 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 388 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 389 | |
Wayne Roberts |
0:6b3ac9c5a042 | 390 | static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut ) |
Wayne Roberts |
0:6b3ac9c5a042 | 391 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 392 | bool adrAckReq = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 393 | int8_t datarate = LoRaMacParams.ChannelsDatarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 394 | |
Wayne Roberts |
0:6b3ac9c5a042 | 395 | if( adrEnabled == true ) |
Wayne Roberts |
0:6b3ac9c5a042 | 396 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 397 | if( datarate == LORAMAC_TX_MIN_DATARATE ) |
Wayne Roberts |
0:6b3ac9c5a042 | 398 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 399 | AdrAckCounter = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 400 | adrAckReq = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 401 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 402 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 403 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 404 | if( AdrAckCounter >= ADR_ACK_LIMIT ) |
Wayne Roberts |
0:6b3ac9c5a042 | 405 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 406 | adrAckReq = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 407 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 408 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 409 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 410 | adrAckReq = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 411 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 412 | if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 413 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 414 | if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 415 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 416 | if( LoRaMacParams.ChannelsTxPower == LORAMAC_MAX_TX_POWER ) |
Wayne Roberts |
0:6b3ac9c5a042 | 417 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 418 | region_adr_next_dr(&datarate, updateChannelMask); |
Wayne Roberts |
0:6b3ac9c5a042 | 419 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 420 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 421 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 422 | LoRaMacParams.ChannelsTxPower = LORAMAC_MAX_TX_POWER; |
Wayne Roberts |
0:6b3ac9c5a042 | 423 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 424 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 425 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 426 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 427 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 428 | |
Wayne Roberts |
0:6b3ac9c5a042 | 429 | *datarateOut = datarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 430 | |
Wayne Roberts |
0:6b3ac9c5a042 | 431 | return adrAckReq; |
Wayne Roberts |
0:6b3ac9c5a042 | 432 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 433 | |
Wayne Roberts |
0:6b3ac9c5a042 | 434 | static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen ) |
Wayne Roberts |
0:6b3ac9c5a042 | 435 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 436 | uint16_t maxN = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 437 | uint8_t payloadSize; |
Wayne Roberts |
0:6b3ac9c5a042 | 438 | |
Wayne Roberts |
0:6b3ac9c5a042 | 439 | // Get the maximum payload length |
Wayne Roberts |
0:6b3ac9c5a042 | 440 | maxN = MaxPayloadOfDatarate[datarate]; |
Wayne Roberts |
0:6b3ac9c5a042 | 441 | |
Wayne Roberts |
0:6b3ac9c5a042 | 442 | // Calculate the resulting payload size |
Wayne Roberts |
0:6b3ac9c5a042 | 443 | payloadSize = ( lenN + fOptsLen ); |
Wayne Roberts |
0:6b3ac9c5a042 | 444 | |
Wayne Roberts |
0:6b3ac9c5a042 | 445 | // Validation of the application payload size |
Wayne Roberts |
0:6b3ac9c5a042 | 446 | if( payloadSize <= maxN ) |
Wayne Roberts |
0:6b3ac9c5a042 | 447 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 448 | return true; |
Wayne Roberts |
0:6b3ac9c5a042 | 449 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 450 | return false; |
Wayne Roberts |
0:6b3ac9c5a042 | 451 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 452 | |
Wayne Roberts |
0:6b3ac9c5a042 | 453 | static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ) |
Wayne Roberts |
0:6b3ac9c5a042 | 454 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 455 | uint8_t i = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 456 | uint8_t cmdCount = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 457 | |
Wayne Roberts |
0:6b3ac9c5a042 | 458 | if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 459 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 460 | return 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 461 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 462 | |
Wayne Roberts |
0:6b3ac9c5a042 | 463 | for( i = 0; i < length; i++ ) |
Wayne Roberts |
0:6b3ac9c5a042 | 464 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 465 | switch( cmdBufIn[i] ) |
Wayne Roberts |
0:6b3ac9c5a042 | 466 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 467 | // STICKY |
Wayne Roberts |
0:6b3ac9c5a042 | 468 | case MOTE_MAC_RX_PARAM_SETUP_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 469 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 470 | cmdBufOut[cmdCount++] = cmdBufIn[i++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 471 | cmdBufOut[cmdCount++] = cmdBufIn[i]; |
Wayne Roberts |
0:6b3ac9c5a042 | 472 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 473 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 474 | case MOTE_MAC_RX_TIMING_SETUP_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 475 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 476 | cmdBufOut[cmdCount++] = cmdBufIn[i]; |
Wayne Roberts |
0:6b3ac9c5a042 | 477 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 478 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 479 | // NON-STICKY |
Wayne Roberts |
0:6b3ac9c5a042 | 480 | case MOTE_MAC_DEV_STATUS_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 481 | { // 2 bytes payload |
Wayne Roberts |
0:6b3ac9c5a042 | 482 | i += 2; |
Wayne Roberts |
0:6b3ac9c5a042 | 483 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 484 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 485 | case MOTE_MAC_LINK_ADR_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 486 | case MOTE_MAC_NEW_CHANNEL_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 487 | { // 1 byte payload |
Wayne Roberts |
0:6b3ac9c5a042 | 488 | i++; |
Wayne Roberts |
0:6b3ac9c5a042 | 489 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 490 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 491 | case MOTE_MAC_DUTY_CYCLE_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 492 | case MOTE_MAC_LINK_CHECK_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 493 | { // 0 byte payload |
Wayne Roberts |
0:6b3ac9c5a042 | 494 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 495 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 496 | default: |
Wayne Roberts |
0:6b3ac9c5a042 | 497 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 498 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 499 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 500 | |
Wayne Roberts |
0:6b3ac9c5a042 | 501 | return cmdCount; |
Wayne Roberts |
0:6b3ac9c5a042 | 502 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 503 | |
Wayne Roberts |
0:6b3ac9c5a042 | 504 | LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) |
Wayne Roberts |
0:6b3ac9c5a042 | 505 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 506 | uint32_t fcnt_up; |
Wayne Roberts |
0:6b3ac9c5a042 | 507 | uint16_t i; |
Wayne Roberts |
0:6b3ac9c5a042 | 508 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 509 | uint32_t mic = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 510 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 511 | const void* payload = fBuffer; |
Wayne Roberts |
0:6b3ac9c5a042 | 512 | uint8_t framePort = fPort; |
Wayne Roberts |
0:6b3ac9c5a042 | 513 | uint8_t LoRaMacTxPayloadLen = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 514 | |
Wayne Roberts |
0:6b3ac9c5a042 | 515 | tx_buf_len = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 516 | |
Wayne Roberts |
0:6b3ac9c5a042 | 517 | if( fBuffer == NULL ) |
Wayne Roberts |
0:6b3ac9c5a042 | 518 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 519 | fBufferSize = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 520 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 521 | |
Wayne Roberts |
0:6b3ac9c5a042 | 522 | LoRaMacTxPayloadLen = fBufferSize; |
Wayne Roberts |
0:6b3ac9c5a042 | 523 | |
Wayne Roberts |
0:6b3ac9c5a042 | 524 | Radio::radio.tx_buf[tx_buf_len++] = macHdr->Value; |
Wayne Roberts |
0:6b3ac9c5a042 | 525 | |
Wayne Roberts |
0:6b3ac9c5a042 | 526 | switch( macHdr->Bits.MType ) |
Wayne Roberts |
0:6b3ac9c5a042 | 527 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 528 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 529 | case FRAME_TYPE_JOIN_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 530 | if (LoRaMacJoinEui == NULL || LoRaMacDevEui == NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 531 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 532 | |
Wayne Roberts |
0:6b3ac9c5a042 | 533 | RxWindow1Delay_us = LoRaMacParams.JoinAcceptDelay1_us - RADIO_WAKEUP_TIME_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 534 | RxWindow2Delay_us = LoRaMacParams.JoinAcceptDelay2_us - RADIO_WAKEUP_TIME_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 535 | |
Wayne Roberts |
0:6b3ac9c5a042 | 536 | memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacJoinEui, 8 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 537 | tx_buf_len += 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 538 | memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacDevEui, 8 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 539 | tx_buf_len += 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 540 | |
Wayne Roberts |
0:6b3ac9c5a042 | 541 | if (RootAppKey == NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 542 | LoRaMacDevNonce = Radio::Random(); /* lorawan 1.0 */ |
Wayne Roberts |
0:6b3ac9c5a042 | 543 | else { |
Wayne Roberts |
0:6b3ac9c5a042 | 544 | LoRaMacDevNonce = eeprom_read(EEPROM_DEVNONCE); |
Wayne Roberts |
0:6b3ac9c5a042 | 545 | /* joinReq DevNonce value is never re-used in 1v1 */ |
Wayne Roberts |
0:6b3ac9c5a042 | 546 | if (eeprom_increment_value(EEPROM_DEVNONCE) < 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 547 | return LORAMAC_STATUS_EEPROM_FAIL; |
Wayne Roberts |
0:6b3ac9c5a042 | 548 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 549 | MAC_PRINTF("DevNonce:%u ", LoRaMacDevNonce); |
Wayne Roberts |
0:6b3ac9c5a042 | 550 | |
Wayne Roberts |
0:6b3ac9c5a042 | 551 | Radio::radio.tx_buf[tx_buf_len++] = LoRaMacDevNonce & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 552 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 553 | |
Wayne Roberts |
0:6b3ac9c5a042 | 554 | if (LoRaMacJoinComputeMic(false, Radio::radio.tx_buf, tx_buf_len & 0xFF, RootNwkKey, &mic) < 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 555 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 556 | |
Wayne Roberts |
0:6b3ac9c5a042 | 557 | Radio::radio.tx_buf[tx_buf_len++] = mic & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 558 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 559 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 16 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 560 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 24 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 561 | |
Wayne Roberts |
0:6b3ac9c5a042 | 562 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 563 | case FRAME_TYPE_REJOIN_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 564 | RxWindow1Delay_us = LoRaMacParams.JoinAcceptDelay1_us - RADIO_WAKEUP_TIME_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 565 | RxWindow2Delay_us = LoRaMacParams.JoinAcceptDelay2_us - RADIO_WAKEUP_TIME_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 566 | |
Wayne Roberts |
0:6b3ac9c5a042 | 567 | Radio::radio.tx_buf[tx_buf_len++] = JoinReqType; |
Wayne Roberts |
0:6b3ac9c5a042 | 568 | |
Wayne Roberts |
0:6b3ac9c5a042 | 569 | tx_buf_len = tx_buf_len; |
Wayne Roberts |
0:6b3ac9c5a042 | 570 | |
Wayne Roberts |
0:6b3ac9c5a042 | 571 | if (JoinReqType == 0 || JoinReqType == 2) { |
Wayne Roberts |
0:6b3ac9c5a042 | 572 | LoRaMacDevNonce = RJcount0++; |
Wayne Roberts |
0:6b3ac9c5a042 | 573 | /* NetID + DevEUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 574 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacNetID ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 575 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacNetID >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 576 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacNetID >> 16 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 577 | |
Wayne Roberts |
0:6b3ac9c5a042 | 578 | memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacDevEui, 8 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 579 | tx_buf_len += 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 580 | |
Wayne Roberts |
0:6b3ac9c5a042 | 581 | Radio::radio.tx_buf[tx_buf_len++] = LoRaMacDevNonce & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 582 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 583 | |
Wayne Roberts |
0:6b3ac9c5a042 | 584 | if (LoRaMacJoinComputeMic(false, Radio::radio.tx_buf, tx_buf_len & 0xFF, keys.SNwkSIntKey, &mic) < 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 585 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 586 | |
Wayne Roberts |
0:6b3ac9c5a042 | 587 | } else if (JoinReqType == 1) { |
Wayne Roberts |
0:6b3ac9c5a042 | 588 | /* JoinEUI + DevEUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 589 | LoRaMacDevNonce = eeprom_read(EEPROM_RJCOUNT1); |
Wayne Roberts |
0:6b3ac9c5a042 | 590 | if (eeprom_increment_value(EEPROM_RJCOUNT1) < 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 591 | return LORAMAC_STATUS_EEPROM_FAIL; |
Wayne Roberts |
0:6b3ac9c5a042 | 592 | |
Wayne Roberts |
0:6b3ac9c5a042 | 593 | memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacJoinEui, 8 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 594 | tx_buf_len += 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 595 | memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacDevEui, 8 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 596 | tx_buf_len += 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 597 | |
Wayne Roberts |
0:6b3ac9c5a042 | 598 | Radio::radio.tx_buf[tx_buf_len++] = LoRaMacDevNonce & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 599 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 600 | |
Wayne Roberts |
0:6b3ac9c5a042 | 601 | //print_buf(JSIntKey, 16, "JSIntKey"); |
Wayne Roberts |
0:6b3ac9c5a042 | 602 | if (LoRaMacJoinComputeMic(false, Radio::radio.tx_buf, tx_buf_len & 0xFF, JSIntKey, &mic) < 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 603 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 604 | |
Wayne Roberts |
0:6b3ac9c5a042 | 605 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 606 | |
Wayne Roberts |
0:6b3ac9c5a042 | 607 | Radio::radio.tx_buf[tx_buf_len++] = mic & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 608 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 609 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 16 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 610 | Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 24 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 611 | MAC_PRINTF("up-rejoin-frame len%u type%u\r\n", tx_buf_len, JoinReqType); |
Wayne Roberts |
0:6b3ac9c5a042 | 612 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 613 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 614 | case FRAME_TYPE_DATA_CONFIRMED_UP: |
Wayne Roberts |
0:6b3ac9c5a042 | 615 | //Intentional fallthrough |
Wayne Roberts |
0:6b3ac9c5a042 | 616 | case FRAME_TYPE_DATA_UNCONFIRMED_UP: |
Wayne Roberts |
0:6b3ac9c5a042 | 617 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 618 | if (!flags.IsLoRaMacNetworkJoined) |
Wayne Roberts |
0:6b3ac9c5a042 | 619 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 620 | return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet |
Wayne Roberts |
0:6b3ac9c5a042 | 621 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 622 | |
Wayne Roberts |
0:6b3ac9c5a042 | 623 | if (flags.OptNeg && flags.need_ReKeyConf) { |
Wayne Roberts |
0:6b3ac9c5a042 | 624 | /* lorawan1v1 need rekeying confirmation */ |
Wayne Roberts |
0:6b3ac9c5a042 | 625 | LoRaMacStatus_t s = AddMacCommand(MOTE_MAC_REKEY_IND, 0, 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 626 | if (s != LORAMAC_STATUS_OK) |
Wayne Roberts |
0:6b3ac9c5a042 | 627 | return s; |
Wayne Roberts |
0:6b3ac9c5a042 | 628 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 629 | fcnt_up = FCntUp; |
Wayne Roberts |
0:6b3ac9c5a042 | 630 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 631 | if (flags.need_ResetConf) { |
Wayne Roberts |
0:6b3ac9c5a042 | 632 | LoRaMacStatus_t s = AddMacCommand(MOTE_MAC_RESET_IND, flags.OptNeg, 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 633 | if (s != LORAMAC_STATUS_OK) |
Wayne Roberts |
0:6b3ac9c5a042 | 634 | return s; |
Wayne Roberts |
0:6b3ac9c5a042 | 635 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 636 | fcnt_up = eeprom_read(EEPROM_FCNTUP); |
Wayne Roberts |
0:6b3ac9c5a042 | 637 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 638 | |
Wayne Roberts |
0:6b3ac9c5a042 | 639 | fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate ); |
Wayne Roberts |
0:6b3ac9c5a042 | 640 | |
Wayne Roberts |
0:6b3ac9c5a042 | 641 | if( ValidatePayloadLength( LoRaMacTxPayloadLen, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 642 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 643 | MAC_PRINTF("LoRaMacTxPayloadLen%u, FOptsLen%u\r\n", LoRaMacTxPayloadLen, MacCommandsBufferIndex); |
Wayne Roberts |
0:6b3ac9c5a042 | 644 | return LORAMAC_STATUS_LENGTH_ERROR; |
Wayne Roberts |
0:6b3ac9c5a042 | 645 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 646 | |
Wayne Roberts |
0:6b3ac9c5a042 | 647 | RxWindow1Delay_us = LoRaMacParams.ReceiveDelay1_us - RADIO_WAKEUP_TIME_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 648 | RxWindow2Delay_us = LoRaMacParams.ReceiveDelay2_us - RADIO_WAKEUP_TIME_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 649 | |
Wayne Roberts |
0:6b3ac9c5a042 | 650 | if( flags.SrvAckRequested == true ) |
Wayne Roberts |
0:6b3ac9c5a042 | 651 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 652 | flags.SrvAckRequested = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 653 | fCtrl->Bits.Ack = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 654 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 655 | |
Wayne Roberts |
0:6b3ac9c5a042 | 656 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 657 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 658 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 16 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 659 | Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 24 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 660 | |
Wayne Roberts |
0:6b3ac9c5a042 | 661 | Radio::radio.tx_buf[tx_buf_len++] = fCtrl->Value; |
Wayne Roberts |
0:6b3ac9c5a042 | 662 | |
Wayne Roberts |
0:6b3ac9c5a042 | 663 | // FCntUp will be inserted in SendFrameOnChannel(), where MIC is inserted also |
Wayne Roberts |
0:6b3ac9c5a042 | 664 | tx_buf_len += 2; |
Wayne Roberts |
0:6b3ac9c5a042 | 665 | |
Wayne Roberts |
0:6b3ac9c5a042 | 666 | ConfFCntUp = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 667 | if (flags.OptNeg) { |
Wayne Roberts |
0:6b3ac9c5a042 | 668 | if (macHdr->Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP) { |
Wayne Roberts |
0:6b3ac9c5a042 | 669 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 670 | ConfFCntUp = FCntUp; |
Wayne Roberts |
0:6b3ac9c5a042 | 671 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 672 | ConfFCntUp = eeprom_read(EEPROM_FCNTUP); |
Wayne Roberts |
0:6b3ac9c5a042 | 673 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 674 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 675 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 676 | |
Wayne Roberts |
0:6b3ac9c5a042 | 677 | // Copy the MAC commands which must be re-send into the MAC command buffer |
Wayne Roberts |
0:6b3ac9c5a042 | 678 | memcpy( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex ); |
Wayne Roberts |
0:6b3ac9c5a042 | 679 | MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 680 | |
Wayne Roberts |
0:6b3ac9c5a042 | 681 | if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 682 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 683 | if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( flags.MacCommandsInNextTx == true ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 684 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 685 | MAC_PRINTF("uplink mac-cmds %u into FOpts at %u ", MacCommandsBufferIndex, tx_buf_len); |
Wayne Roberts |
0:6b3ac9c5a042 | 686 | fCtrl->Bits.FOptsLen += MacCommandsBufferIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 687 | // Update FCtrl field with new value of OptionsLength |
Wayne Roberts |
0:6b3ac9c5a042 | 688 | Radio::radio.tx_buf[0x05] = fCtrl->Value; |
Wayne Roberts |
0:6b3ac9c5a042 | 689 | |
Wayne Roberts |
0:6b3ac9c5a042 | 690 | /* lorawan1v1: encode FOpts using NWkSEncKey */ |
Wayne Roberts |
0:6b3ac9c5a042 | 691 | if (flags.OptNeg) { |
Wayne Roberts |
0:6b3ac9c5a042 | 692 | LoRaMacEncrypt(0, MacCommandsBuffer, MacCommandsBufferIndex, keys.NwkSEncKey, LoRaMacDevAddr, UP_LINK, fcnt_up, Radio::radio.tx_buf + tx_buf_len); |
Wayne Roberts |
0:6b3ac9c5a042 | 693 | tx_buf_len += MacCommandsBufferIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 694 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 695 | for( i = 0; i < MacCommandsBufferIndex; i++ ) |
Wayne Roberts |
0:6b3ac9c5a042 | 696 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 697 | Radio::radio.tx_buf[tx_buf_len++] = MacCommandsBuffer[i]; |
Wayne Roberts |
0:6b3ac9c5a042 | 698 | MAC_PRINTF("%02x ", MacCommandsBuffer[i]); |
Wayne Roberts |
0:6b3ac9c5a042 | 699 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 700 | MAC_PRINTF(" fCtrl->Value:%02x\r\n", Radio::radio.tx_buf[0x05]); |
Wayne Roberts |
0:6b3ac9c5a042 | 701 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 702 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 703 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 704 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 705 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 706 | if( ( MacCommandsBufferIndex > 0 ) && ( flags.MacCommandsInNextTx ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 707 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 708 | MAC_PRINTF("uplink mac-cmds %u port0 ", MacCommandsBufferIndex); |
Wayne Roberts |
0:6b3ac9c5a042 | 709 | for (i = 0; i < MacCommandsBufferIndex; i++) |
Wayne Roberts |
0:6b3ac9c5a042 | 710 | MAC_PRINTF("%02x ", MacCommandsBuffer[i]); |
Wayne Roberts |
0:6b3ac9c5a042 | 711 | MAC_PRINTF("\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 712 | LoRaMacTxPayloadLen = MacCommandsBufferIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 713 | payload = MacCommandsBuffer; |
Wayne Roberts |
0:6b3ac9c5a042 | 714 | framePort = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 715 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 716 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 717 | flags.MacCommandsInNextTx = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 718 | // Store MAC commands which must be re-send in case the device does not receive a downlink anymore |
Wayne Roberts |
0:6b3ac9c5a042 | 719 | MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat ); |
Wayne Roberts |
0:6b3ac9c5a042 | 720 | if( MacCommandsBufferToRepeatIndex > 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 721 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 722 | flags.MacCommandsInNextTx = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 723 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 724 | MacCommandsBufferIndex = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 725 | |
Wayne Roberts |
0:6b3ac9c5a042 | 726 | if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 727 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 728 | const uint8_t* keyPtr; |
Wayne Roberts |
0:6b3ac9c5a042 | 729 | Radio::radio.tx_buf[tx_buf_len++] = framePort; |
Wayne Roberts |
0:6b3ac9c5a042 | 730 | |
Wayne Roberts |
0:6b3ac9c5a042 | 731 | if( framePort == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 732 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 733 | DEBUG_CRYPT_BUF(keys.NwkSEncKey, 16, "NwkSEncKey", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 734 | keyPtr = keys.NwkSEncKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 735 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 736 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 737 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 738 | DEBUG_CRYPT_BUF(keys.AppSKey, 16, "AppSKey", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 739 | keyPtr = keys.AppSKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 740 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 741 | LoRaMacEncrypt(1, (uint8_t* ) payload, LoRaMacTxPayloadLen, keyPtr, LoRaMacDevAddr, UP_LINK, fcnt_up, Radio::radio.tx_buf + tx_buf_len); |
Wayne Roberts |
0:6b3ac9c5a042 | 742 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 743 | tx_buf_len = tx_buf_len + LoRaMacTxPayloadLen; |
Wayne Roberts |
0:6b3ac9c5a042 | 744 | /* mic cacluation in SendFrameOnChannel() */ |
Wayne Roberts |
0:6b3ac9c5a042 | 745 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 746 | case FRAME_TYPE_PROPRIETARY: |
Wayne Roberts |
0:6b3ac9c5a042 | 747 | if( ( fBuffer != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 748 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 749 | memcpy( Radio::radio.tx_buf + tx_buf_len, ( uint8_t* ) fBuffer, LoRaMacTxPayloadLen ); |
Wayne Roberts |
0:6b3ac9c5a042 | 750 | tx_buf_len = tx_buf_len + LoRaMacTxPayloadLen; |
Wayne Roberts |
0:6b3ac9c5a042 | 751 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 752 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 753 | default: |
Wayne Roberts |
0:6b3ac9c5a042 | 754 | return LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 755 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 756 | |
Wayne Roberts |
0:6b3ac9c5a042 | 757 | flags.uplink_mtype = macHdr->Bits.MType; |
Wayne Roberts |
0:6b3ac9c5a042 | 758 | flags.uplink_in_progress = LoRaMacParams.NbTrans; |
Wayne Roberts |
0:6b3ac9c5a042 | 759 | |
Wayne Roberts |
0:6b3ac9c5a042 | 760 | return LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 761 | } // ..PrepareFrame() |
Wayne Roberts |
0:6b3ac9c5a042 | 762 | |
Wayne Roberts |
0:6b3ac9c5a042 | 763 | LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) |
Wayne Roberts |
0:6b3ac9c5a042 | 764 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 765 | LoRaMacFrameCtrl_t fCtrl; |
Wayne Roberts |
0:6b3ac9c5a042 | 766 | LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 767 | |
Wayne Roberts |
0:6b3ac9c5a042 | 768 | fCtrl.Value = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 769 | fCtrl.Bits.FOptsLen = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 770 | if( LoRaMacDeviceClass == CLASS_B ) |
Wayne Roberts |
0:6b3ac9c5a042 | 771 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 772 | fCtrl.Bits.FPending = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 773 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 774 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 775 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 776 | fCtrl.Bits.FPending = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 777 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 778 | fCtrl.Bits.Ack = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 779 | fCtrl.Bits.AdrAckReq = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 780 | fCtrl.Bits.Adr = flags.AdrCtrlOn; |
Wayne Roberts |
0:6b3ac9c5a042 | 781 | |
Wayne Roberts |
0:6b3ac9c5a042 | 782 | // Prepare the frame |
Wayne Roberts |
0:6b3ac9c5a042 | 783 | status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize ); |
Wayne Roberts |
0:6b3ac9c5a042 | 784 | |
Wayne Roberts |
0:6b3ac9c5a042 | 785 | // Validate status |
Wayne Roberts |
0:6b3ac9c5a042 | 786 | if( status != LORAMAC_STATUS_OK ) |
Wayne Roberts |
0:6b3ac9c5a042 | 787 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 788 | return status; |
Wayne Roberts |
0:6b3ac9c5a042 | 789 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 790 | |
Wayne Roberts |
0:6b3ac9c5a042 | 791 | // Reset confirm parameters |
Wayne Roberts |
0:6b3ac9c5a042 | 792 | McpsConfirm.NbRetries = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 793 | McpsConfirm.AckReceived = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 794 | |
Wayne Roberts |
0:6b3ac9c5a042 | 795 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 796 | if (flags.rxing) |
Wayne Roberts |
0:6b3ac9c5a042 | 797 | function_pending = region_ScheduleTx; |
Wayne Roberts |
0:6b3ac9c5a042 | 798 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 799 | region_ScheduleTx( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 800 | |
Wayne Roberts |
0:6b3ac9c5a042 | 801 | return status; |
Wayne Roberts |
0:6b3ac9c5a042 | 802 | } // ..Send() |
Wayne Roberts |
0:6b3ac9c5a042 | 803 | |
Wayne Roberts |
0:6b3ac9c5a042 | 804 | static void ReSend() |
Wayne Roberts |
0:6b3ac9c5a042 | 805 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 806 | region_ScheduleTx(); |
Wayne Roberts |
0:6b3ac9c5a042 | 807 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 808 | |
Wayne Roberts |
0:6b3ac9c5a042 | 809 | LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 810 | LoRaMacMlmeRequest( const MlmeReq_t *mlmeRequest ) |
Wayne Roberts |
0:6b3ac9c5a042 | 811 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 812 | LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 813 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 814 | LoRaMacHeader_t macHdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 815 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 816 | |
Wayne Roberts |
0:6b3ac9c5a042 | 817 | if( mlmeRequest == NULL ) |
Wayne Roberts |
0:6b3ac9c5a042 | 818 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 819 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 820 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 821 | |
Wayne Roberts |
0:6b3ac9c5a042 | 822 | if (flags.uplink_in_progress > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 823 | MAC_PRINTF("LoRaMacMlmeRequest() BUSY\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 824 | return LORAMAC_STATUS_IN_PROGRESS; |
Wayne Roberts |
0:6b3ac9c5a042 | 825 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 826 | |
Wayne Roberts |
0:6b3ac9c5a042 | 827 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_MLMEREQ; |
Wayne Roberts |
0:6b3ac9c5a042 | 828 | MlmeIndication.MlmeIndication = mlmeRequest->Type; |
Wayne Roberts |
0:6b3ac9c5a042 | 829 | |
Wayne Roberts |
0:6b3ac9c5a042 | 830 | MAC_PRINTF("LoRaMacMlmeRequest() "); |
Wayne Roberts |
0:6b3ac9c5a042 | 831 | switch( mlmeRequest->Type ) |
Wayne Roberts |
0:6b3ac9c5a042 | 832 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 833 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 834 | case MLME_JOIN: |
Wayne Roberts |
0:6b3ac9c5a042 | 835 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 836 | if( ( mlmeRequest->Req.Join.DevEui == NULL ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 837 | ( mlmeRequest->Req.Join.JoinEui == NULL ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 838 | ( mlmeRequest->Req.Join.NwkKey == NULL ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 839 | ( mlmeRequest->Req.Join.NbTrials == 0 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 840 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 841 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 842 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 843 | |
Wayne Roberts |
0:6b3ac9c5a042 | 844 | LoRaMacDevEui = mlmeRequest->Req.Join.DevEui; |
Wayne Roberts |
0:6b3ac9c5a042 | 845 | LoRaMacJoinEui = mlmeRequest->Req.Join.JoinEui; |
Wayne Roberts |
0:6b3ac9c5a042 | 846 | RootNwkKey = mlmeRequest->Req.Join.NwkKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 847 | RootAppKey = mlmeRequest->Req.Join.AppKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 848 | MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials; |
Wayne Roberts |
0:6b3ac9c5a042 | 849 | |
Wayne Roberts |
0:6b3ac9c5a042 | 850 | /*if (RootAppKey != NULL) {*/ |
Wayne Roberts |
0:6b3ac9c5a042 | 851 | LoRaMacGenerateJoinKey(0x05, RootNwkKey, LoRaMacDevEui, JSEncKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 852 | //print_buf(JSEncKey, 16, "new-JSEncKey"); |
Wayne Roberts |
0:6b3ac9c5a042 | 853 | LoRaMacGenerateJoinKey(0x06, RootNwkKey, LoRaMacDevEui, JSIntKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 854 | //print_buf(JSIntKey, 16, "new-JSIntKey"); |
Wayne Roberts |
0:6b3ac9c5a042 | 855 | /*}*/ |
Wayne Roberts |
0:6b3ac9c5a042 | 856 | JoinReqType = 0xff; |
Wayne Roberts |
0:6b3ac9c5a042 | 857 | |
Wayne Roberts |
0:6b3ac9c5a042 | 858 | // Reset variable JoinRequestTrials |
Wayne Roberts |
0:6b3ac9c5a042 | 859 | MlmeIndication.JoinRequestTrials = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 860 | |
Wayne Roberts |
0:6b3ac9c5a042 | 861 | // Setup header information |
Wayne Roberts |
0:6b3ac9c5a042 | 862 | macHdr.Value = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 863 | macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; |
Wayne Roberts |
0:6b3ac9c5a042 | 864 | |
Wayne Roberts |
0:6b3ac9c5a042 | 865 | ResetMacParameters( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 866 | |
Wayne Roberts |
0:6b3ac9c5a042 | 867 | // Add a +1, since we start to count from 0 |
Wayne Roberts |
0:6b3ac9c5a042 | 868 | LoRaMacParams.ChannelsDatarate = AlternateDatarate( MlmeIndication.JoinRequestTrials + 1 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 869 | |
Wayne Roberts |
0:6b3ac9c5a042 | 870 | status = Send( &macHdr, 0, NULL, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 871 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 872 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 873 | case MLME_REJOIN_1: |
Wayne Roberts |
0:6b3ac9c5a042 | 874 | if ( mlmeRequest->Req.Join.JoinEui == NULL ) |
Wayne Roberts |
0:6b3ac9c5a042 | 875 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 876 | |
Wayne Roberts |
0:6b3ac9c5a042 | 877 | LoRaMacJoinEui = mlmeRequest->Req.Join.JoinEui; |
Wayne Roberts |
0:6b3ac9c5a042 | 878 | JoinReqType = 0x01; |
Wayne Roberts |
0:6b3ac9c5a042 | 879 | // fall-thru |
Wayne Roberts |
0:6b3ac9c5a042 | 880 | case MLME_REJOIN_0: |
Wayne Roberts |
0:6b3ac9c5a042 | 881 | case MLME_REJOIN_2: // Type2 can only be sent via mac-command |
Wayne Roberts |
0:6b3ac9c5a042 | 882 | if( ( mlmeRequest->Req.Join.DevEui == NULL ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 883 | ( mlmeRequest->Req.Join.NwkKey == NULL ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 884 | ( mlmeRequest->Req.Join.NbTrials == 0 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 885 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 886 | MAC_PRINTF(" (missing %p %p %d)\n", |
Wayne Roberts |
0:6b3ac9c5a042 | 887 | mlmeRequest->Req.Join.DevEui, |
Wayne Roberts |
0:6b3ac9c5a042 | 888 | mlmeRequest->Req.Join.NwkKey, |
Wayne Roberts |
0:6b3ac9c5a042 | 889 | mlmeRequest->Req.Join.NbTrials |
Wayne Roberts |
0:6b3ac9c5a042 | 890 | ); |
Wayne Roberts |
0:6b3ac9c5a042 | 891 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 892 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 893 | |
Wayne Roberts |
0:6b3ac9c5a042 | 894 | RootNwkKey = mlmeRequest->Req.Join.NwkKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 895 | LoRaMacDevEui = mlmeRequest->Req.Join.DevEui; |
Wayne Roberts |
0:6b3ac9c5a042 | 896 | LoRaMacGenerateJoinKey(0x05, RootNwkKey, LoRaMacDevEui, JSEncKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 897 | LoRaMacGenerateJoinKey(0x06, RootNwkKey, LoRaMacDevEui, JSIntKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 898 | |
Wayne Roberts |
0:6b3ac9c5a042 | 899 | RootAppKey = mlmeRequest->Req.Join.AppKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 900 | |
Wayne Roberts |
0:6b3ac9c5a042 | 901 | macHdr.Value = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 902 | macHdr.Bits.MType = FRAME_TYPE_REJOIN_REQ; |
Wayne Roberts |
0:6b3ac9c5a042 | 903 | |
Wayne Roberts |
0:6b3ac9c5a042 | 904 | if (mlmeRequest->Type == MLME_REJOIN_0) |
Wayne Roberts |
0:6b3ac9c5a042 | 905 | JoinReqType = 0x00; |
Wayne Roberts |
0:6b3ac9c5a042 | 906 | else if (mlmeRequest->Type == MLME_REJOIN_2) |
Wayne Roberts |
0:6b3ac9c5a042 | 907 | JoinReqType = 0x02; |
Wayne Roberts |
0:6b3ac9c5a042 | 908 | |
Wayne Roberts |
0:6b3ac9c5a042 | 909 | MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials; |
Wayne Roberts |
0:6b3ac9c5a042 | 910 | |
Wayne Roberts |
0:6b3ac9c5a042 | 911 | status = Send( &macHdr, 0, NULL, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 912 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 913 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 914 | case MLME_LINK_CHECK: |
Wayne Roberts |
0:6b3ac9c5a042 | 915 | status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 916 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 917 | case MLME_TIME_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 918 | status = AddMacCommand( MOTE_MAC_DEVICE_TIME_REQ, 0, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 919 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 920 | case MLME_TXCW: |
Wayne Roberts |
0:6b3ac9c5a042 | 921 | status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout ); |
Wayne Roberts |
0:6b3ac9c5a042 | 922 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 923 | case MLME_PING_SLOT_INFO: |
Wayne Roberts |
0:6b3ac9c5a042 | 924 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 925 | uint8_t value = mlmeRequest->Req.PingSlotInfo.Value; |
Wayne Roberts |
0:6b3ac9c5a042 | 926 | status = LoRaMacMlmeRequestClassB(mlmeRequest); |
Wayne Roberts |
0:6b3ac9c5a042 | 927 | if (status == LORAMAC_STATUS_OK) |
Wayne Roberts |
0:6b3ac9c5a042 | 928 | status = AddMacCommandClassB( MOTE_MAC_PING_SLOT_INFO_REQ, value, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 929 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 930 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 931 | case MLME_BEACON_ACQUISITION: |
Wayne Roberts |
0:6b3ac9c5a042 | 932 | case MLME_BEACON_TIMING: |
Wayne Roberts |
0:6b3ac9c5a042 | 933 | status = LoRaMacMlmeRequestClassB(mlmeRequest); |
Wayne Roberts |
0:6b3ac9c5a042 | 934 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 935 | default: |
Wayne Roberts |
0:6b3ac9c5a042 | 936 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 937 | } // ...switch( mlmeRequest->Type ) |
Wayne Roberts |
0:6b3ac9c5a042 | 938 | |
Wayne Roberts |
0:6b3ac9c5a042 | 939 | if( status != LORAMAC_STATUS_OK ) |
Wayne Roberts |
0:6b3ac9c5a042 | 940 | MlmeConfirm.MlmeRequest = MLME_NONE; |
Wayne Roberts |
0:6b3ac9c5a042 | 941 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 942 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 943 | MlmeConfirm.MlmeRequest = mlmeRequest->Type; |
Wayne Roberts |
0:6b3ac9c5a042 | 944 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 945 | |
Wayne Roberts |
0:6b3ac9c5a042 | 946 | return status; |
Wayne Roberts |
0:6b3ac9c5a042 | 947 | } // ..LoRaMacMlmeRequest() |
Wayne Roberts |
0:6b3ac9c5a042 | 948 | |
Wayne Roberts |
0:6b3ac9c5a042 | 949 | LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 950 | LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet ) |
Wayne Roberts |
0:6b3ac9c5a042 | 951 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 952 | LoRaMacStatus_t status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 953 | |
Wayne Roberts |
0:6b3ac9c5a042 | 954 | switch( mibGet->Type ) { |
Wayne Roberts |
0:6b3ac9c5a042 | 955 | case MIB_APP_SKEY: |
Wayne Roberts |
0:6b3ac9c5a042 | 956 | mibGet->Param.key = keys.AppSKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 957 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 958 | case MIB_FNwkSIntKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 959 | mibGet->Param.key = keys.FNwkSIntKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 960 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 961 | case MIB_SNwkSIntKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 962 | mibGet->Param.key = keys.SNwkSIntKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 963 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 964 | case MIB_NwkSEncKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 965 | mibGet->Param.key = keys.NwkSEncKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 966 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 967 | case MIB_NwkSKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 968 | /* lorawan 1.0 */ |
Wayne Roberts |
0:6b3ac9c5a042 | 969 | mibGet->Param.key = keys.FNwkSIntKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 970 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 971 | case MIB_RX2_CHANNEL: |
Wayne Roberts |
0:6b3ac9c5a042 | 972 | mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel; |
Wayne Roberts |
0:6b3ac9c5a042 | 973 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 974 | case MIB_DEVICE_CLASS: |
Wayne Roberts |
0:6b3ac9c5a042 | 975 | mibGet->Param.Class = LoRaMacDeviceClass; |
Wayne Roberts |
0:6b3ac9c5a042 | 976 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 977 | case MIB_ADR: |
Wayne Roberts |
0:6b3ac9c5a042 | 978 | mibGet->Param.AdrEnable = flags.AdrCtrlOn; |
Wayne Roberts |
0:6b3ac9c5a042 | 979 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 980 | case MIB_DEV_ADDR: |
Wayne Roberts |
0:6b3ac9c5a042 | 981 | mibGet->Param.DevAddr = LoRaMacDevAddr; |
Wayne Roberts |
0:6b3ac9c5a042 | 982 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 983 | case MIB_PUBLIC_NETWORK: |
Wayne Roberts |
0:6b3ac9c5a042 | 984 | mibGet->Param.EnablePublicNetwork = flags.PublicNetwork; |
Wayne Roberts |
0:6b3ac9c5a042 | 985 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 986 | case MIB_CHANNELS_MASK: |
Wayne Roberts |
0:6b3ac9c5a042 | 987 | mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask; |
Wayne Roberts |
0:6b3ac9c5a042 | 988 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 989 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 990 | case MIB_NETWORK_JOINED: |
Wayne Roberts |
0:6b3ac9c5a042 | 991 | mibGet->Param.IsNetworkJoined = flags.IsLoRaMacNetworkJoined; |
Wayne Roberts |
0:6b3ac9c5a042 | 992 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 993 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 994 | } // ..switch( mibGet->Type ) |
Wayne Roberts |
0:6b3ac9c5a042 | 995 | |
Wayne Roberts |
0:6b3ac9c5a042 | 996 | return status; |
Wayne Roberts |
0:6b3ac9c5a042 | 997 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 998 | |
Wayne Roberts |
0:6b3ac9c5a042 | 999 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1000 | LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 1001 | LoRaMacQueryTxPossible(uint8_t size, LoRaMacTxInfo_t* txInfo) |
Wayne Roberts |
0:6b3ac9c5a042 | 1002 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1003 | int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 1004 | uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 1005 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1006 | if( txInfo == NULL ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1007 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1008 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1009 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1010 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1011 | AdrNextDr( flags.AdrCtrlOn, false, &datarate ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1012 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1013 | txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1014 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1015 | if( txInfo->CurrentPayloadSize >= fOptLen ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1016 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1017 | txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen; |
Wayne Roberts |
0:6b3ac9c5a042 | 1018 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1019 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1020 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1021 | return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR; |
Wayne Roberts |
0:6b3ac9c5a042 | 1022 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1023 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1024 | if( ValidatePayloadLength( size, datarate, 0 ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1025 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1026 | return LORAMAC_STATUS_LENGTH_ERROR; |
Wayne Roberts |
0:6b3ac9c5a042 | 1027 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1028 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1029 | if( ValidatePayloadLength( size, datarate, fOptLen ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1030 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1031 | return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR; |
Wayne Roberts |
0:6b3ac9c5a042 | 1032 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1033 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1034 | return LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 1035 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1036 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1037 | LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 1038 | LoRaMacMcpsRequest( McpsReq_t *mcpsRequest ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1039 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1040 | LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; |
Wayne Roberts |
0:6b3ac9c5a042 | 1041 | LoRaMacHeader_t macHdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1042 | uint8_t fPort = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1043 | void *fBuffer; |
Wayne Roberts |
0:6b3ac9c5a042 | 1044 | uint16_t fBufferSize; |
Wayne Roberts |
0:6b3ac9c5a042 | 1045 | int8_t datarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 1046 | bool readyToSend = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 1047 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1048 | if( mcpsRequest == NULL ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1049 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1050 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1051 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1052 | if (flags.uplink_in_progress > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1053 | MAC_PRINTF("LoRaMacMcpsRequest() in_progress BUSY\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 1054 | return LORAMAC_STATUS_IN_PROGRESS; |
Wayne Roberts |
0:6b3ac9c5a042 | 1055 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1056 | if (ConfFCntUp > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1057 | // unacknowledged confirmed uplink pending, must resend previous uplink |
Wayne Roberts |
0:6b3ac9c5a042 | 1058 | MAC_PRINTF("LoRaMacMcpsRequest() ConfFCntUp%u\r\n", ConfFCntUp); |
Wayne Roberts |
0:6b3ac9c5a042 | 1059 | return LORAMAC_STATUS_BUSY_UPCONF; |
Wayne Roberts |
0:6b3ac9c5a042 | 1060 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1061 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1062 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1063 | if (!flags.IsLoRaMacNetworkJoined) |
Wayne Roberts |
0:6b3ac9c5a042 | 1064 | return LORAMAC_STATUS_NO_NETWORK_JOINED; |
Wayne Roberts |
0:6b3ac9c5a042 | 1065 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1066 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1067 | macHdr.Value = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1068 | memset ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1069 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_MCPSREQ; |
Wayne Roberts |
0:6b3ac9c5a042 | 1070 | McpsConfirm.McpsRequest = mcpsRequest->Type; |
Wayne Roberts |
0:6b3ac9c5a042 | 1071 | McpsIndication.attempt = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1072 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1073 | datarate = mcpsRequest->Req.Datarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 1074 | fBufferSize = mcpsRequest->Req.fBufferSize; |
Wayne Roberts |
0:6b3ac9c5a042 | 1075 | fBuffer = mcpsRequest->Req.fBuffer; |
Wayne Roberts |
0:6b3ac9c5a042 | 1076 | readyToSend = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 1077 | AckTimeoutRetries = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1078 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1079 | switch( mcpsRequest->Type ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1080 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1081 | case MCPS_UNCONFIRMED: |
Wayne Roberts |
0:6b3ac9c5a042 | 1082 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1083 | macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP; |
Wayne Roberts |
0:6b3ac9c5a042 | 1084 | fPort = mcpsRequest->Req.fPort; |
Wayne Roberts |
0:6b3ac9c5a042 | 1085 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1086 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1087 | case MCPS_CONFIRMED: |
Wayne Roberts |
0:6b3ac9c5a042 | 1088 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1089 | AckTimeoutRetriesCounter = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1090 | AckTimeoutRetries = mcpsRequest->Req.NbTrials; |
Wayne Roberts |
0:6b3ac9c5a042 | 1091 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1092 | macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP; |
Wayne Roberts |
0:6b3ac9c5a042 | 1093 | fPort = mcpsRequest->Req.fPort; |
Wayne Roberts |
0:6b3ac9c5a042 | 1094 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1095 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1096 | case MCPS_PROPRIETARY: |
Wayne Roberts |
0:6b3ac9c5a042 | 1097 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1098 | macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY; |
Wayne Roberts |
0:6b3ac9c5a042 | 1099 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1100 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1101 | default: |
Wayne Roberts |
0:6b3ac9c5a042 | 1102 | readyToSend = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 1103 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1104 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1105 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1106 | if( readyToSend == true ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1107 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1108 | if( flags.AdrCtrlOn == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1109 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1110 | if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1111 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1112 | LoRaMacParams.ChannelsDatarate = datarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 1113 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1114 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1115 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1116 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1117 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1118 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1119 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1120 | status = Send( &macHdr, fPort, fBuffer, fBufferSize ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1121 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1122 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1123 | return status; |
Wayne Roberts |
0:6b3ac9c5a042 | 1124 | } // ..LoRaMacMcpsRequest() |
Wayne Roberts |
0:6b3ac9c5a042 | 1125 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1126 | __attribute__((weak)) LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 1127 | SwitchClassB( DeviceClass_t deviceClass ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1128 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1129 | return LORAMAC_STATUS_DEVICE_OFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 1130 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1131 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1132 | void |
Wayne Roberts |
0:6b3ac9c5a042 | 1133 | RxWindowSetup( unsigned freq, int8_t datarate, unsigned bandwidth, uint16_t timeout) |
Wayne Roberts |
0:6b3ac9c5a042 | 1134 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1135 | uint8_t downlinkDatarate = Datarates[datarate]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1136 | RadioModems_t modem; |
Wayne Roberts |
0:6b3ac9c5a042 | 1137 | //RadioState_t rs = Radio::GetStatus(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1138 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1139 | MAC_PRINTF(" rxwin-dr%u-sf%u ", datarate, downlinkDatarate); |
Wayne Roberts |
0:6b3ac9c5a042 | 1140 | Radio::SetChannel( freq ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1141 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1142 | // Store downlink datarate |
Wayne Roberts |
0:6b3ac9c5a042 | 1143 | McpsIndication.RxDatarate = ( uint8_t ) datarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 1144 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1145 | #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868) || defined(USE_BAND_ARIB_8CH) |
Wayne Roberts |
0:6b3ac9c5a042 | 1146 | if( datarate == DR_7 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1147 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1148 | modem = MODEM_FSK; |
Wayne Roberts |
0:6b3ac9c5a042 | 1149 | Radio::SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, 0, false, 0, true, false); |
Wayne Roberts |
0:6b3ac9c5a042 | 1150 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1151 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1152 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1153 | modem = MODEM_LORA; |
Wayne Roberts |
0:6b3ac9c5a042 | 1154 | Radio::SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, true); |
Wayne Roberts |
0:6b3ac9c5a042 | 1155 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1156 | #elif defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1157 | modem = MODEM_LORA; |
Wayne Roberts |
0:6b3ac9c5a042 | 1158 | Radio::SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, true); |
Wayne Roberts |
0:6b3ac9c5a042 | 1159 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 1160 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1161 | Radio::SetRxMaxPayloadLength( modem, MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1162 | } //..RxWindowSetup() |
Wayne Roberts |
0:6b3ac9c5a042 | 1163 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1164 | static void RxWindow2Start( void ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1165 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1166 | /* TODO: join accept rx2 channel unique */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1167 | if (LoRaMacDeviceClass == CLASS_C) |
Wayne Roberts |
0:6b3ac9c5a042 | 1168 | Radio::Rx( 0 ); // Continuous mode |
Wayne Roberts |
0:6b3ac9c5a042 | 1169 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1170 | Radio::Rx( LoRaMacParams.MaxRxWindow_us ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1171 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1172 | McpsIndication.RxSlot = 2; |
Wayne Roberts |
0:6b3ac9c5a042 | 1173 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1174 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1175 | static void mlme_confirm(LoRaMacEventInfoStatus_t status) |
Wayne Roberts |
0:6b3ac9c5a042 | 1176 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1177 | MlmeConfirm.Status = status; |
Wayne Roberts |
0:6b3ac9c5a042 | 1178 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1179 | if (MlmeConfirm.MlmeRequest != MLME_NONE) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1180 | if (LoRaMacPrimitives->MacMlmeConfirm != NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 1181 | LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1182 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1183 | MlmeConfirm.MlmeRequest = MLME_NONE; |
Wayne Roberts |
0:6b3ac9c5a042 | 1184 | MlmeIndication.MlmeIndication = MLME_NONE; |
Wayne Roberts |
0:6b3ac9c5a042 | 1185 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1186 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1187 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1188 | static void mcps_confirm(LoRaMacEventInfoStatus_t status) |
Wayne Roberts |
0:6b3ac9c5a042 | 1189 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1190 | McpsConfirm.Status = status; |
Wayne Roberts |
0:6b3ac9c5a042 | 1191 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1192 | if (McpsConfirm.McpsRequest != MCPS_NONE) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1193 | if (LoRaMacPrimitives->MacMcpsConfirm) |
Wayne Roberts |
0:6b3ac9c5a042 | 1194 | LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1195 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1196 | McpsConfirm.McpsRequest = MCPS_NONE; |
Wayne Roberts |
0:6b3ac9c5a042 | 1197 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1198 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1199 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1200 | #if defined(LORAWAN_JOIN_EUI) |
Wayne Roberts |
0:6b3ac9c5a042 | 1201 | static struct { |
Wayne Roberts |
0:6b3ac9c5a042 | 1202 | bool forced; |
Wayne Roberts |
0:6b3ac9c5a042 | 1203 | uint8_t dr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1204 | uint8_t type; |
Wayne Roberts |
0:6b3ac9c5a042 | 1205 | uint8_t retries; |
Wayne Roberts |
0:6b3ac9c5a042 | 1206 | uint8_t Period; |
Wayne Roberts |
0:6b3ac9c5a042 | 1207 | LowPowerTimeout event; |
Wayne Roberts |
0:6b3ac9c5a042 | 1208 | struct { |
Wayne Roberts |
0:6b3ac9c5a042 | 1209 | uint8_t MaxTimeN; |
Wayne Roberts |
0:6b3ac9c5a042 | 1210 | uint8_t MaxCountN; |
Wayne Roberts |
0:6b3ac9c5a042 | 1211 | unsigned uplinks_since; |
Wayne Roberts |
0:6b3ac9c5a042 | 1212 | bool enabled; |
Wayne Roberts |
0:6b3ac9c5a042 | 1213 | } type0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1214 | } rejoin; |
Wayne Roberts |
0:6b3ac9c5a042 | 1215 | void _rejoin_retry(void); |
Wayne Roberts |
0:6b3ac9c5a042 | 1216 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1217 | void rejoin_retry() |
Wayne Roberts |
0:6b3ac9c5a042 | 1218 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1219 | LoRaMacStatus_t status; |
Wayne Roberts |
0:6b3ac9c5a042 | 1220 | LoRaMacHeader_t macHdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1221 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1222 | macHdr.Value = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1223 | macHdr.Bits.MType = FRAME_TYPE_REJOIN_REQ; |
Wayne Roberts |
0:6b3ac9c5a042 | 1224 | LoRaMacParams.ChannelsDatarate = rejoin.dr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1225 | JoinReqType = rejoin.type; |
Wayne Roberts |
0:6b3ac9c5a042 | 1226 | status = Send( &macHdr, 0, NULL, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1227 | if (status != LORAMAC_STATUS_OK) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1228 | MAC_PRINTF("rejoin-send-failed%d ", status); |
Wayne Roberts |
0:6b3ac9c5a042 | 1229 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1230 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1231 | MAC_PRINTF("Rejoin%u ", JoinReqType); |
Wayne Roberts |
0:6b3ac9c5a042 | 1232 | if (rejoin.forced) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1233 | if (--rejoin.retries > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1234 | us_timestamp_t period_us = (1 << rejoin.Period) + random_at_most(32000000); |
Wayne Roberts |
0:6b3ac9c5a042 | 1235 | rejoin.event.attach_us(_rejoin_retry, period_us); |
Wayne Roberts |
0:6b3ac9c5a042 | 1236 | MAC_PRINTF("try%u", rejoin.retries); |
Wayne Roberts |
0:6b3ac9c5a042 | 1237 | } else |
Wayne Roberts |
0:6b3ac9c5a042 | 1238 | rejoin.forced = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 1239 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1240 | MAC_PRINTF("\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 1241 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1242 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1243 | void _rejoin_retry() |
Wayne Roberts |
0:6b3ac9c5a042 | 1244 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1245 | if (flags.uplink_in_progress > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1246 | function_pending = rejoin_retry; |
Wayne Roberts |
0:6b3ac9c5a042 | 1247 | } else |
Wayne Roberts |
0:6b3ac9c5a042 | 1248 | rejoin_retry(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1249 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1250 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1251 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1252 | void |
Wayne Roberts |
0:6b3ac9c5a042 | 1253 | finish_uplink(LoRaMacEventInfoStatus_t status) |
Wayne Roberts |
0:6b3ac9c5a042 | 1254 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1255 | if (flags.uplink_in_progress > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1256 | flags.uplink_in_progress--; |
Wayne Roberts |
0:6b3ac9c5a042 | 1257 | if (flags.uplink_in_progress > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1258 | if (flags.rxing) |
Wayne Roberts |
0:6b3ac9c5a042 | 1259 | function_pending = region_ScheduleTx; |
Wayne Roberts |
0:6b3ac9c5a042 | 1260 | else { |
Wayne Roberts |
0:6b3ac9c5a042 | 1261 | region_ScheduleTx( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1262 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1263 | } else |
Wayne Roberts |
0:6b3ac9c5a042 | 1264 | region_session_start(status); |
Wayne Roberts |
0:6b3ac9c5a042 | 1265 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1266 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1267 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1268 | LoRaMacHeader_t macHdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1269 | macHdr.Value = Radio::radio.tx_buf[0]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1270 | if (macHdr.Bits.MType != FRAME_TYPE_REJOIN_REQ) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1271 | if (rejoin.type0.enabled && --rejoin.type0.uplinks_since == 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1272 | rejoin.type0.uplinks_since = 1 << (rejoin.type0.MaxCountN + 4); |
Wayne Roberts |
0:6b3ac9c5a042 | 1273 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1274 | rejoin.type = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1275 | rejoin_retry(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1276 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 1277 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1278 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1279 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1280 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1281 | if (function_pending != NULL) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1282 | function_pending(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1283 | function_pending = NULL; |
Wayne Roberts |
0:6b3ac9c5a042 | 1284 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1285 | } // ..finish_uplink() |
Wayne Roberts |
0:6b3ac9c5a042 | 1286 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1287 | LowPowerTimeout TxDelayedEvent; |
Wayne Roberts |
0:6b3ac9c5a042 | 1288 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1289 | void OnTxDelayedTimerEvent() |
Wayne Roberts |
0:6b3ac9c5a042 | 1290 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1291 | MAC_PRINTF("OnTxDelayedTimerEvent() "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1292 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1293 | LoRaMacHeader_t macHdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1294 | LoRaMacFrameCtrl_t fCtrl; |
Wayne Roberts |
0:6b3ac9c5a042 | 1295 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1296 | if (!flags.IsLoRaMacNetworkJoined) |
Wayne Roberts |
0:6b3ac9c5a042 | 1297 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1298 | // Add a +1, since we start to count from 0 |
Wayne Roberts |
0:6b3ac9c5a042 | 1299 | LoRaMacParams.ChannelsDatarate = AlternateDatarate( MlmeIndication.JoinRequestTrials + 1 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1300 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1301 | macHdr.Value = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1302 | macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; |
Wayne Roberts |
0:6b3ac9c5a042 | 1303 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1304 | fCtrl.Value = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1305 | fCtrl.Bits.Adr = flags.AdrCtrlOn; |
Wayne Roberts |
0:6b3ac9c5a042 | 1306 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1307 | /* In case of join request retransmissions, the stack must prepare |
Wayne Roberts |
0:6b3ac9c5a042 | 1308 | * the frame again, because the network server keeps track of the random |
Wayne Roberts |
0:6b3ac9c5a042 | 1309 | * LoRaMacDevNonce values to prevent reply attacks. */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1310 | PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1311 | /* TODO PrepareFrame() != LORAMAC_STATUS_OK */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1312 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1313 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1314 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1315 | if (flags.rxing) |
Wayne Roberts |
0:6b3ac9c5a042 | 1316 | function_pending = region_ScheduleTx; |
Wayne Roberts |
0:6b3ac9c5a042 | 1317 | else { |
Wayne Roberts |
0:6b3ac9c5a042 | 1318 | region_ScheduleTx( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1319 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1320 | } // ..OnTxDelayedTimerEvent() |
Wayne Roberts |
0:6b3ac9c5a042 | 1321 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1322 | static void RxWindow2Setup(void) |
Wayne Roberts |
0:6b3ac9c5a042 | 1323 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1324 | MAC_PRINTF("RxWindow2Setup %uhz dr%u", LoRaMacParams.Rx2Channel.FrequencyHz, LoRaMacParams.Rx2Channel.Datarate); |
Wayne Roberts |
0:6b3ac9c5a042 | 1325 | RxWindowSetup( |
Wayne Roberts |
0:6b3ac9c5a042 | 1326 | LoRaMacParams.Rx2Channel.FrequencyHz, |
Wayne Roberts |
0:6b3ac9c5a042 | 1327 | LoRaMacParams.Rx2Channel.Datarate, |
Wayne Roberts |
0:6b3ac9c5a042 | 1328 | region_GetRxBandwidth( LoRaMacParams.Rx2Channel.Datarate ), |
Wayne Roberts |
0:6b3ac9c5a042 | 1329 | region_GetRxSymbolTimeout( LoRaMacParams.Rx2Channel.Datarate ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1330 | ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1331 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1332 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1333 | static void |
Wayne Roberts |
0:6b3ac9c5a042 | 1334 | upConfRetry(LoRaMacEventInfoStatus_t i_s) |
Wayne Roberts |
0:6b3ac9c5a042 | 1335 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1336 | if (uplinkMHDR->Bits.MType != FRAME_TYPE_DATA_CONFIRMED_UP) |
Wayne Roberts |
0:6b3ac9c5a042 | 1337 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 1338 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1339 | MAC_PRINTF(" resend "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1340 | TxDelayedEvent.attach_us(ReSend, 100000 + random_at_most(400000)); |
Wayne Roberts |
0:6b3ac9c5a042 | 1341 | if (LoRaMacParams.ChannelsDatarate > LORAMAC_TX_MIN_DATARATE) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1342 | LoRaMacParams.ChannelsDatarate--; |
Wayne Roberts |
0:6b3ac9c5a042 | 1343 | MAC_PRINTF("dr%u ", LoRaMacParams.ChannelsDatarate); |
Wayne Roberts |
0:6b3ac9c5a042 | 1344 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 1345 | /* datarate decreased to bottom: increase tx power */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1346 | if (LoRaMacParams.ChannelsTxPower > LORAMAC_MAX_TX_POWER) |
Wayne Roberts |
0:6b3ac9c5a042 | 1347 | LoRaMacParams.ChannelsTxPower--; |
Wayne Roberts |
0:6b3ac9c5a042 | 1348 | MAC_PRINTF("txIdx%u ", LoRaMacParams.ChannelsTxPower); |
Wayne Roberts |
0:6b3ac9c5a042 | 1349 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1350 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1351 | McpsIndication.attempt++; |
Wayne Roberts |
0:6b3ac9c5a042 | 1352 | McpsIndication.Status = i_s; |
Wayne Roberts |
0:6b3ac9c5a042 | 1353 | if (LoRaMacPrimitives->MacMcpsIndication != NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 1354 | LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); // RxAbort |
Wayne Roberts |
0:6b3ac9c5a042 | 1355 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1356 | } // ..upConfRetry() |
Wayne Roberts |
0:6b3ac9c5a042 | 1357 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1358 | static void |
Wayne Roberts |
0:6b3ac9c5a042 | 1359 | PrepareRxDoneAbort(LoRaMacEventInfoStatus_t status) |
Wayne Roberts |
0:6b3ac9c5a042 | 1360 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1361 | MAC_PRINTF("rxAbort "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1362 | if( ( McpsIndication.RxSlot == 1 ) && ( LoRaMacDeviceClass == CLASS_C ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1363 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1364 | RxWindow2Setup(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1365 | RxWindow2Start(); // start continuous rx2 reception |
Wayne Roberts |
0:6b3ac9c5a042 | 1366 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1367 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1368 | if (McpsIndication.RxSlot == 2) |
Wayne Roberts |
0:6b3ac9c5a042 | 1369 | upConfRetry(status); // mic-fail or other malformed downlink |
Wayne Roberts |
0:6b3ac9c5a042 | 1370 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1371 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1372 | if (!flags.IsLoRaMacNetworkJoined && LoRaMacJoinEui != NULL && LoRaMacDevEui == NULL) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1373 | TxDelayedEvent.attach_us(OnTxDelayedTimerEvent, 1000000); |
Wayne Roberts |
0:6b3ac9c5a042 | 1374 | MAC_PRINTF("RxDoneAbort-join-tx-delay"); |
Wayne Roberts |
0:6b3ac9c5a042 | 1375 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1376 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1377 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1378 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1379 | McpsIndication.Status = status; |
Wayne Roberts |
0:6b3ac9c5a042 | 1380 | if (LoRaMacPrimitives->MacMcpsIndication != NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 1381 | LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); // RxAbort |
Wayne Roberts |
0:6b3ac9c5a042 | 1382 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1383 | mcps_confirm(status); // RXAbort |
Wayne Roberts |
0:6b3ac9c5a042 | 1384 | mlme_confirm(status); |
Wayne Roberts |
0:6b3ac9c5a042 | 1385 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1386 | finish_uplink(status); |
Wayne Roberts |
0:6b3ac9c5a042 | 1387 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1388 | MAC_PRINTF("\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 1389 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1390 | } // ..PrepareRxDoneAbort() |
Wayne Roberts |
0:6b3ac9c5a042 | 1391 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1392 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1393 | static LoRaMacStatus_t SwitchClass( DeviceClass_t deviceClass ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1394 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1395 | LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1396 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1397 | switch( LoRaMacDeviceClass ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1398 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1399 | case CLASS_A: |
Wayne Roberts |
0:6b3ac9c5a042 | 1400 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1401 | MAC_PRINTF("CLASS_A "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1402 | if (deviceClass == CLASS_B) |
Wayne Roberts |
0:6b3ac9c5a042 | 1403 | status = SwitchClassB(deviceClass); |
Wayne Roberts |
0:6b3ac9c5a042 | 1404 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1405 | if (deviceClass == CLASS_C) |
Wayne Roberts |
0:6b3ac9c5a042 | 1406 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1407 | MAC_PRINTF("->C "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1408 | LoRaMacDeviceClass = deviceClass; |
Wayne Roberts |
0:6b3ac9c5a042 | 1409 | RxWindow2Setup(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1410 | RxWindow2Start(); // continuous rx2 reception |
Wayne Roberts |
0:6b3ac9c5a042 | 1411 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1412 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 1413 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1414 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1415 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1416 | case CLASS_B: |
Wayne Roberts |
0:6b3ac9c5a042 | 1417 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1418 | MAC_PRINTF("CLASS_B "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1419 | if( deviceClass == CLASS_A ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1420 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1421 | MAC_PRINTF("->A "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1422 | LoRaMacDeviceClass = deviceClass; |
Wayne Roberts |
0:6b3ac9c5a042 | 1423 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 1424 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1425 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1426 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1427 | case CLASS_C: |
Wayne Roberts |
0:6b3ac9c5a042 | 1428 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1429 | MAC_PRINTF("CLASS_C "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1430 | if( deviceClass == CLASS_A ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1431 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1432 | MAC_PRINTF("->A "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1433 | LoRaMacDeviceClass = deviceClass; |
Wayne Roberts |
0:6b3ac9c5a042 | 1434 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1435 | // Set the radio into sleep to setup a defined state |
Wayne Roberts |
0:6b3ac9c5a042 | 1436 | Radio::Sleep( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1437 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1438 | status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 1439 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1440 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1441 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1442 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1443 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1444 | MAC_PRINTF("\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 1445 | return status; |
Wayne Roberts |
0:6b3ac9c5a042 | 1446 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1447 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1448 | LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 1449 | LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1450 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1451 | LoRaMacStatus_t status = LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 1452 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1453 | if (mibSet == NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 1454 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1455 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1456 | if (flags.uplink_in_progress > 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 1457 | return LORAMAC_STATUS_IN_PROGRESS; |
Wayne Roberts |
0:6b3ac9c5a042 | 1458 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1459 | switch (mibSet->Type) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1460 | case MIB_CHANNELS_MASK: |
Wayne Roberts |
0:6b3ac9c5a042 | 1461 | if( mibSet->Param.ChannelsMask ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1462 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1463 | #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1464 | bool chanMaskState = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 1465 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1466 | #if defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1467 | chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsMask ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1468 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 1469 | if( chanMaskState == true ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1470 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1471 | if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) && |
Wayne Roberts |
0:6b3ac9c5a042 | 1472 | ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1473 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1474 | status = LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1475 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1476 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1477 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1478 | memcpy( ( uint8_t* ) LoRaMacParams.ChannelsMask, |
Wayne Roberts |
0:6b3ac9c5a042 | 1479 | ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1480 | for ( uint8_t i = 0; i < sizeof( LoRaMacParams.ChannelsMask ) / 2; i++ ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1481 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1482 | // Disable channels which are no longer available |
Wayne Roberts |
0:6b3ac9c5a042 | 1483 | ChannelsMaskRemaining[i] &= LoRaMacParams.ChannelsMask[i]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1484 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1485 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1486 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1487 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1488 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1489 | status = LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1490 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1491 | #elif defined( USE_BAND_470 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1492 | memcpy( ( uint8_t* ) LoRaMacParams.ChannelsMask, |
Wayne Roberts |
0:6b3ac9c5a042 | 1493 | ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1494 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 1495 | memcpy( ( uint8_t* ) LoRaMacParams.ChannelsMask, |
Wayne Roberts |
0:6b3ac9c5a042 | 1496 | ( uint8_t* ) mibSet->Param.ChannelsMask, 2 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1497 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 1498 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1499 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1500 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1501 | status = LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1502 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1503 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1504 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1505 | /* values which cannot be set in OTA */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1506 | case MIB_NwkSKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 1507 | case MIB_SNwkSIntKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 1508 | case MIB_NwkSEncKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 1509 | case MIB_FNwkSIntKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 1510 | case MIB_APP_SKEY: |
Wayne Roberts |
0:6b3ac9c5a042 | 1511 | case MIB_DEV_ADDR: |
Wayne Roberts |
0:6b3ac9c5a042 | 1512 | case MIB_NETWORK_JOINED: |
Wayne Roberts |
0:6b3ac9c5a042 | 1513 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 1514 | case MIB_RX2_CHANNEL: |
Wayne Roberts |
0:6b3ac9c5a042 | 1515 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 1516 | case MIB_DEVICE_CLASS: |
Wayne Roberts |
0:6b3ac9c5a042 | 1517 | status = SwitchClass(mibSet->Param.Class); |
Wayne Roberts |
0:6b3ac9c5a042 | 1518 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1519 | case MIB_ADR: |
Wayne Roberts |
0:6b3ac9c5a042 | 1520 | flags.AdrCtrlOn = mibSet->Param.AdrEnable; |
Wayne Roberts |
0:6b3ac9c5a042 | 1521 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1522 | case MIB_PUBLIC_NETWORK: |
Wayne Roberts |
0:6b3ac9c5a042 | 1523 | flags.PublicNetwork = mibSet->Param.EnablePublicNetwork; |
Wayne Roberts |
0:6b3ac9c5a042 | 1524 | Radio::SetPublicNetwork( flags.PublicNetwork ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1525 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1526 | #ifndef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1527 | case MIB_SNwkSIntKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 1528 | flags.have_SNwkSIntKey = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1529 | memcpy( keys.SNwkSIntKey, mibSet->Param.key, sizeof(keys.SNwkSIntKey) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1530 | if (flags.have_NwkSEncKey) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1531 | flags.OptNeg = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1532 | flags.need_ResetConf = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1533 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1534 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1535 | case MIB_NwkSEncKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 1536 | flags.have_NwkSEncKey = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1537 | memcpy( keys.NwkSEncKey, mibSet->Param.key, sizeof(keys.NwkSEncKey) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1538 | if (flags.have_SNwkSIntKey) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1539 | flags.OptNeg = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1540 | flags.need_ResetConf = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1541 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1542 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1543 | case MIB_APP_SKEY: |
Wayne Roberts |
0:6b3ac9c5a042 | 1544 | memcpy( keys.AppSKey, mibSet->Param.key, sizeof( keys.AppSKey ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1545 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1546 | case MIB_FNwkSIntKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 1547 | memcpy( keys.FNwkSIntKey, mibSet->Param.key, sizeof( keys.FNwkSIntKey ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1548 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1549 | case MIB_NwkSKey: |
Wayne Roberts |
0:6b3ac9c5a042 | 1550 | /* lorawan 1.0 ABP */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1551 | memcpy( keys.FNwkSIntKey, mibSet->Param.key, sizeof( keys.FNwkSIntKey ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1552 | memcpy( keys.SNwkSIntKey, mibSet->Param.key, sizeof( keys.SNwkSIntKey) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1553 | memcpy( keys.NwkSEncKey, mibSet->Param.key, sizeof( keys.NwkSEncKey) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1554 | flags.OptNeg = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1555 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1556 | case MIB_DEV_ADDR: |
Wayne Roberts |
0:6b3ac9c5a042 | 1557 | LoRaMacDevAddr = mibSet->Param.DevAddr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1558 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1559 | #endif /* !LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1560 | } // ..switch( mibSet->Type ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1561 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1562 | return status; |
Wayne Roberts |
0:6b3ac9c5a042 | 1563 | } // ..LoRaMacMibSetRequestConfirm() |
Wayne Roberts |
0:6b3ac9c5a042 | 1564 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1565 | __attribute__((weak)) LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 1566 | LoRaMacClassBInitialization( void ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1567 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1568 | return LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 1569 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1570 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1571 | LowPowerTimeout RxWindowEvent1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1572 | LowPowerTimeout RxWindowEvent2; |
Wayne Roberts |
0:6b3ac9c5a042 | 1573 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1574 | static void RxWindow1Start( void ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1575 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1576 | if (LoRaMacDeviceClass == CLASS_C) |
Wayne Roberts |
0:6b3ac9c5a042 | 1577 | Radio::Rx( 0 ); // Continuous mode |
Wayne Roberts |
0:6b3ac9c5a042 | 1578 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1579 | Radio::Rx( LoRaMacParams.MaxRxWindow_us ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1580 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1581 | McpsIndication.RxSlot = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1582 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1583 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1584 | volatile us_timestamp_t tx_done_at; |
Wayne Roberts |
0:6b3ac9c5a042 | 1585 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1586 | static void OnRadioTxDone( us_timestamp_t at_us ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1587 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1588 | if ((RxWindow1Delay_us < 100000 || RxWindow1Delay_us > 10000000) || |
Wayne Roberts |
0:6b3ac9c5a042 | 1589 | (RxWindow2Delay_us < 100000 || RxWindow2Delay_us > 10000000)) |
Wayne Roberts |
0:6b3ac9c5a042 | 1590 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1591 | PrepareRxDoneAbort(LORAMAC_EVENT_INFO_BAD_RX_DELAY); |
Wayne Roberts |
0:6b3ac9c5a042 | 1592 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 1593 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1594 | // Setup timers |
Wayne Roberts |
0:6b3ac9c5a042 | 1595 | RxWindowEvent1.attach_us(RxWindow1Start, RxWindow1Delay_us); |
Wayne Roberts |
0:6b3ac9c5a042 | 1596 | if( LoRaMacDeviceClass != CLASS_C ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1597 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1598 | RxWindowEvent2.attach_us(RxWindow2Start, RxWindow2Delay_us); |
Wayne Roberts |
0:6b3ac9c5a042 | 1599 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1600 | McpsIndication.RxSlot = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1601 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1602 | tx_done_at = at_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 1603 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1604 | if( LoRaMacDeviceClass != CLASS_C ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1605 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1606 | region_rx1_setup(Channel); |
Wayne Roberts |
0:6b3ac9c5a042 | 1607 | Radio::Sleep( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1608 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1609 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1610 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1611 | RxWindow2Setup(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1612 | RxWindow2Start(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1613 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1614 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1615 | // Store last tx channel |
Wayne Roberts |
0:6b3ac9c5a042 | 1616 | //LastTxChannel = Channel; |
Wayne Roberts |
0:6b3ac9c5a042 | 1617 | #ifdef DUTY_ENABLE |
Wayne Roberts |
0:6b3ac9c5a042 | 1618 | DutyTxDone(at_us); |
Wayne Roberts |
0:6b3ac9c5a042 | 1619 | #endif /* DUTY_ENABLE */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1620 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1621 | } // ..OnRadioTxDone() |
Wayne Roberts |
0:6b3ac9c5a042 | 1622 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1623 | static void OnRadioTxTimeout( void ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1624 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1625 | if( LoRaMacDeviceClass != CLASS_C ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1626 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1627 | Radio::Sleep( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1628 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1629 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1630 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1631 | RxWindow2Setup(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1632 | RxWindow2Start(); |
Wayne Roberts |
0:6b3ac9c5a042 | 1633 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1634 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1635 | finish_uplink(LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT); |
Wayne Roberts |
0:6b3ac9c5a042 | 1636 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1637 | mcps_confirm(LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT); |
Wayne Roberts |
0:6b3ac9c5a042 | 1638 | mlme_confirm(LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT); |
Wayne Roberts |
0:6b3ac9c5a042 | 1639 | } // ..OnRadioTxTimeout() |
Wayne Roberts |
0:6b3ac9c5a042 | 1640 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1641 | __attribute__((weak)) bool |
Wayne Roberts |
0:6b3ac9c5a042 | 1642 | beacon_rx_done_payload(uint8_t* payload, uint16_t size) |
Wayne Roberts |
0:6b3ac9c5a042 | 1643 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1644 | return false; |
Wayne Roberts |
0:6b3ac9c5a042 | 1645 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1646 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1647 | static void |
Wayne Roberts |
0:6b3ac9c5a042 | 1648 | print_mtype(uint8_t mt) |
Wayne Roberts |
0:6b3ac9c5a042 | 1649 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1650 | #ifdef MAC_DEBUG |
Wayne Roberts |
0:6b3ac9c5a042 | 1651 | const char* cp; |
Wayne Roberts |
0:6b3ac9c5a042 | 1652 | switch (mt) { |
Wayne Roberts |
0:6b3ac9c5a042 | 1653 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1654 | case FRAME_TYPE_JOIN_REQ: cp = "JOIN_REQ "; break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1655 | case FRAME_TYPE_JOIN_ACCEPT: cp = "JOIN_ACC "; break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1656 | case FRAME_TYPE_REJOIN_REQ: cp = "REJOIN_REQ"; break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1657 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1658 | case FRAME_TYPE_DATA_UNCONFIRMED_UP: cp = "UNCONF_UP"; break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1659 | case FRAME_TYPE_DATA_UNCONFIRMED_DOWN: cp = "UNCONF_DN"; break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1660 | case FRAME_TYPE_DATA_CONFIRMED_UP: cp = "CONF_UP"; break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1661 | case FRAME_TYPE_DATA_CONFIRMED_DOWN: cp = "CONF_DN"; break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1662 | case FRAME_TYPE_PROPRIETARY: cp = "P"; break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1663 | default: return; |
Wayne Roberts |
0:6b3ac9c5a042 | 1664 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1665 | MAC_PRINTF("MTYPE_%s ", cp); |
Wayne Roberts |
0:6b3ac9c5a042 | 1666 | #endif /* MAC_DEBUG */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1667 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1668 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1669 | /* bool a: true=AFCntDown, false=NFCntDown */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1670 | uint32_t get_fcntdwn(bool a) |
Wayne Roberts |
0:6b3ac9c5a042 | 1671 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1672 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1673 | if (a) |
Wayne Roberts |
0:6b3ac9c5a042 | 1674 | return AFCntDown; |
Wayne Roberts |
0:6b3ac9c5a042 | 1675 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1676 | return NFCntDown; |
Wayne Roberts |
0:6b3ac9c5a042 | 1677 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 1678 | if (a) |
Wayne Roberts |
0:6b3ac9c5a042 | 1679 | return eeprom_read(EEPROM_AFCNTDWN); |
Wayne Roberts |
0:6b3ac9c5a042 | 1680 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1681 | return eeprom_read(EEPROM_NFCNTDWN); |
Wayne Roberts |
0:6b3ac9c5a042 | 1682 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 1683 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1684 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1685 | __attribute__((weak)) bool |
Wayne Roberts |
0:6b3ac9c5a042 | 1686 | ProcessMacCommandsClassB(uint8_t* payload, uint8_t* macIndex) |
Wayne Roberts |
0:6b3ac9c5a042 | 1687 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1688 | return false; /* false: not taken */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1689 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1690 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1691 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1692 | static bool ValidateDatarate( int8_t datarate, uint16_t* channelsMask ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1693 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1694 | if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1695 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1696 | return false; |
Wayne Roberts |
0:6b3ac9c5a042 | 1697 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1698 | for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1699 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1700 | for( uint8_t j = 0; j < 16; j++ ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1701 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1702 | if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1703 | {// Check datarate validity for enabled channels |
Wayne Roberts |
0:6b3ac9c5a042 | 1704 | if( ValueInRange( datarate, Channels[i + j].DrRange.Fields.Min, Channels[i + j].DrRange.Fields.Max ) == true ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1705 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1706 | // At least 1 channel has been found we can return OK. |
Wayne Roberts |
0:6b3ac9c5a042 | 1707 | return true; |
Wayne Roberts |
0:6b3ac9c5a042 | 1708 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1709 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1710 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1711 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1712 | return false; |
Wayne Roberts |
0:6b3ac9c5a042 | 1713 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1714 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1715 | static bool Rx2FreqInRange( uint32_t freq ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1716 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1717 | #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) || defined (USE_BAND_ARIB_8CH) |
Wayne Roberts |
0:6b3ac9c5a042 | 1718 | if( Radio::CheckRfFrequency( freq ) == true ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1719 | #elif defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1720 | if( ( Radio::CheckRfFrequency( freq ) == true ) && |
Wayne Roberts |
0:6b3ac9c5a042 | 1721 | ( freq >= LORAMAC_FIRST_RX1_CHANNEL ) && |
Wayne Roberts |
0:6b3ac9c5a042 | 1722 | ( freq <= LORAMAC_LAST_RX1_CHANNEL ) && |
Wayne Roberts |
0:6b3ac9c5a042 | 1723 | ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX1_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX1_CHANNEL ) == 0 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1724 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 1725 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1726 | return true; |
Wayne Roberts |
0:6b3ac9c5a042 | 1727 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1728 | return false; |
Wayne Roberts |
0:6b3ac9c5a042 | 1729 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1730 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1731 | __attribute__((weak)) void |
Wayne Roberts |
0:6b3ac9c5a042 | 1732 | deviceTimeClassB(uint32_t secs, uint32_t subsecs) |
Wayne Roberts |
0:6b3ac9c5a042 | 1733 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1734 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1735 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1736 | /* return -1 for unknown mac cmd */ |
Wayne Roberts |
0:6b3ac9c5a042 | 1737 | static int |
Wayne Roberts |
0:6b3ac9c5a042 | 1738 | ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr, us_timestamp_t us_rxDone_at ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1739 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1740 | uint8_t buf[2]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1741 | int ret = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1742 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1743 | MACC_PRINTF("ProcessMacCommands(, %u, %u,,) ", macIndex, commandsSize); |
Wayne Roberts |
0:6b3ac9c5a042 | 1744 | while( macIndex < commandsSize ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1745 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1746 | MACC_PRINTF("ProcessMacCommands %u(0x%02x): ", macIndex, payload[macIndex]); |
Wayne Roberts |
0:6b3ac9c5a042 | 1747 | // Decode Frame MAC commands |
Wayne Roberts |
0:6b3ac9c5a042 | 1748 | switch( payload[macIndex++] ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1749 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1750 | case SRV_MAC_LINK_CHECK_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 1751 | MACC_PRINTF("LINK_CHECK_ANS "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1752 | buf[0] = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1753 | buf[1] = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1754 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 1755 | MlmeConfirm.fields.link.DemodMargin = buf[0]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1756 | MlmeConfirm.fields.link.NbGateways = buf[1]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1757 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1758 | case SRV_MAC_LINK_ADR_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 1759 | MACC_PRINTF("LINK_ADR_REQ "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1760 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1761 | uint8_t i; |
Wayne Roberts |
0:6b3ac9c5a042 | 1762 | int8_t txPower = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1763 | uint8_t Redundancy = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1764 | adr_t adr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1765 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1766 | adr.status = 0x07; |
Wayne Roberts |
0:6b3ac9c5a042 | 1767 | // Initialize local copy of the channels mask array |
Wayne Roberts |
0:6b3ac9c5a042 | 1768 | for( i = 0; i < 6; i++ ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1769 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1770 | adr.channelsMask[i] = LoRaMacParams.ChannelsMask[i]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1771 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1772 | adr.datarate = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1773 | txPower = adr.datarate & 0x0F; |
Wayne Roberts |
0:6b3ac9c5a042 | 1774 | adr.datarate = ( adr.datarate >> 4 ) & 0x0F; |
Wayne Roberts |
0:6b3ac9c5a042 | 1775 | MACC_PRINTF("dr%u power%u ", adr.datarate, txPower); |
Wayne Roberts |
0:6b3ac9c5a042 | 1776 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1777 | if( ( flags.AdrCtrlOn == false ) && |
Wayne Roberts |
0:6b3ac9c5a042 | 1778 | ( ( LoRaMacParams.ChannelsDatarate != adr.datarate ) || ( LoRaMacParams.ChannelsTxPower != txPower ) ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1779 | { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower |
Wayne Roberts |
0:6b3ac9c5a042 | 1780 | MACC_PRINTF("AdrCtrlOn:%u dr%u != dr%u, %d != %d\r\n", flags.AdrCtrlOn, |
Wayne Roberts |
0:6b3ac9c5a042 | 1781 | LoRaMacParams.ChannelsDatarate, adr.datarate, |
Wayne Roberts |
0:6b3ac9c5a042 | 1782 | LoRaMacParams.ChannelsTxPower, txPower |
Wayne Roberts |
0:6b3ac9c5a042 | 1783 | ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1784 | // Answer the server with fail status |
Wayne Roberts |
0:6b3ac9c5a042 | 1785 | // Power ACK = 0 |
Wayne Roberts |
0:6b3ac9c5a042 | 1786 | // Data rate ACK = 0 |
Wayne Roberts |
0:6b3ac9c5a042 | 1787 | // Channel mask = 0 |
Wayne Roberts |
0:6b3ac9c5a042 | 1788 | AddMacCommand( MOTE_MAC_LINK_ADR_ANS, 0, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1789 | macIndex += 3; // Skip over the remaining bytes of the request |
Wayne Roberts |
0:6b3ac9c5a042 | 1790 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1791 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1792 | adr.chMask = ( uint16_t )payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1793 | adr.chMask |= ( uint16_t )payload[macIndex++] << 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 1794 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1795 | Redundancy = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1796 | adr.chMaskCntl = ( Redundancy >> 4 ) & 0x07; |
Wayne Roberts |
0:6b3ac9c5a042 | 1797 | LoRaMacParams.NbTrans = Redundancy & 0x0f; |
Wayne Roberts |
0:6b3ac9c5a042 | 1798 | if (LoRaMacParams.NbTrans == 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 1799 | LoRaMacParams.NbTrans = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 1800 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1801 | MACC_PRINTF("chMask:%04x chMaskCntl:%x nbTrans:%u ", adr.chMask, adr.chMaskCntl, LoRaMacParams.NbTrans); |
Wayne Roberts |
0:6b3ac9c5a042 | 1802 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1803 | region_adr_request(&adr); |
Wayne Roberts |
0:6b3ac9c5a042 | 1804 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1805 | if( ValidateDatarate( adr.datarate, adr.channelsMask ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1806 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1807 | MACC_PRINTF("badDr "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1808 | adr.status &= 0xFD; // Datarate KO |
Wayne Roberts |
0:6b3ac9c5a042 | 1809 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1810 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1811 | // |
Wayne Roberts |
0:6b3ac9c5a042 | 1812 | // Remark MaxTxPower = 0 and MinTxPower = 5 |
Wayne Roberts |
0:6b3ac9c5a042 | 1813 | // |
Wayne Roberts |
0:6b3ac9c5a042 | 1814 | if( ValueInRange( txPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1815 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1816 | MACC_PRINTF("badPower(max:%d given:%d min:%d) ", LORAMAC_MAX_TX_POWER, txPower, LORAMAC_MIN_TX_POWER); |
Wayne Roberts |
0:6b3ac9c5a042 | 1817 | adr.status &= 0xFB; // TxPower KO |
Wayne Roberts |
0:6b3ac9c5a042 | 1818 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1819 | MACC_PRINTF("status:%x (idx %u) ", adr.status, macIndex); |
Wayne Roberts |
0:6b3ac9c5a042 | 1820 | if( ( adr.status & 0x07 ) == 0x07 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1821 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1822 | LoRaMacParams.ChannelsDatarate = adr.datarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 1823 | LoRaMacParams.ChannelsTxPower = txPower; |
Wayne Roberts |
0:6b3ac9c5a042 | 1824 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1825 | memcpy( ( uint8_t* )LoRaMacParams.ChannelsMask, ( uint8_t* )adr.channelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1826 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1827 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1828 | AddMacCommand( MOTE_MAC_LINK_ADR_ANS, adr.status, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1829 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1830 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1831 | case SRV_MAC_RX_PARAM_SETUP_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 1832 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1833 | uint8_t status = 0x07; |
Wayne Roberts |
0:6b3ac9c5a042 | 1834 | int8_t datarate = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1835 | int8_t drOffset = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1836 | uint32_t freq = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1837 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1838 | drOffset = ( payload[macIndex] >> 4 ) & 0x07; |
Wayne Roberts |
0:6b3ac9c5a042 | 1839 | datarate = payload[macIndex] & 0x0F; |
Wayne Roberts |
0:6b3ac9c5a042 | 1840 | macIndex++; |
Wayne Roberts |
0:6b3ac9c5a042 | 1841 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1842 | freq = ( uint32_t )payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1843 | freq |= ( uint32_t )payload[macIndex++] << 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 1844 | freq |= ( uint32_t )payload[macIndex++] << 16; |
Wayne Roberts |
0:6b3ac9c5a042 | 1845 | freq *= 100; |
Wayne Roberts |
0:6b3ac9c5a042 | 1846 | MACC_PRINTF("RX_PARAM_SETUP_REQ %uhz drOffset:%u dr%u ", freq, drOffset, datarate); |
Wayne Roberts |
0:6b3ac9c5a042 | 1847 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1848 | if( Rx2FreqInRange( freq ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1849 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1850 | status &= 0xFE; // Channel frequency KO |
Wayne Roberts |
0:6b3ac9c5a042 | 1851 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1852 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1853 | if( ValueInRange( datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1854 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1855 | status &= 0xFD; // Datarate KO |
Wayne Roberts |
0:6b3ac9c5a042 | 1856 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1857 | #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1858 | if( ( ValueInRange( datarate, DR_5, DR_7 ) == true ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 1859 | ( datarate > DR_13 ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1860 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1861 | status &= 0xFD; // Datarate KO |
Wayne Roberts |
0:6b3ac9c5a042 | 1862 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1863 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 1864 | if( ValueInRange( drOffset, LORAMAC_MIN_RX1_DR_OFFSET, LORAMAC_MAX_RX1_DR_OFFSET ) == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1865 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1866 | status &= 0xFB; // Rx1DrOffset range KO |
Wayne Roberts |
0:6b3ac9c5a042 | 1867 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1868 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1869 | MACC_PRINTF("status:0x%02x ", status); |
Wayne Roberts |
0:6b3ac9c5a042 | 1870 | if( ( status & 0x07 ) == 0x07 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1871 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1872 | LoRaMacParams.Rx2Channel.Datarate = datarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 1873 | LoRaMacParams.Rx2Channel.FrequencyHz = freq; |
Wayne Roberts |
0:6b3ac9c5a042 | 1874 | LoRaMacParams.Rx1DrOffset = drOffset; |
Wayne Roberts |
0:6b3ac9c5a042 | 1875 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1876 | AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1877 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1878 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1879 | case SRV_MAC_DEV_STATUS_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 1880 | MACC_PRINTF("DEV_STATUS_REQ "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1881 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1882 | uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE; |
Wayne Roberts |
0:6b3ac9c5a042 | 1883 | if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1884 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1885 | batteryLevel = LoRaMacCallbacks->GetBatteryLevel( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1886 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1887 | AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1888 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1889 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1890 | case SRV_MAC_NEW_CHANNEL_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 1891 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1892 | uint8_t status = 0x03; |
Wayne Roberts |
0:6b3ac9c5a042 | 1893 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1894 | #if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1895 | status &= 0xFC; // Channel frequency and datarate KO |
Wayne Roberts |
0:6b3ac9c5a042 | 1896 | macIndex += 5; |
Wayne Roberts |
0:6b3ac9c5a042 | 1897 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 1898 | int8_t channelIndex = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1899 | ChannelParams_t chParam; |
Wayne Roberts |
0:6b3ac9c5a042 | 1900 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1901 | channelIndex = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1902 | chParam.FreqHz = ( uint32_t )payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1903 | chParam.FreqHz |= ( uint32_t )payload[macIndex++] << 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 1904 | chParam.FreqHz |= ( uint32_t )payload[macIndex++] << 16; |
Wayne Roberts |
0:6b3ac9c5a042 | 1905 | chParam.FreqHz *= 100; |
Wayne Roberts |
0:6b3ac9c5a042 | 1906 | chParam.DrRange.Value = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1907 | MACC_PRINTF("NEW_CHANNEL_REQ ch%u %uhz drRange:%02x ", channelIndex, chParam.Frequency, chParam.DrRange.Value); |
Wayne Roberts |
0:6b3ac9c5a042 | 1908 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1909 | if( chParam.FreqHz == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1910 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1911 | if( channelIndex < 3 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1912 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1913 | status &= 0xFC; |
Wayne Roberts |
0:6b3ac9c5a042 | 1914 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1915 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1916 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1917 | if( LoRaMacChannelRemove( channelIndex ) != LORAMAC_STATUS_OK ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1918 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1919 | status &= 0xFC; |
Wayne Roberts |
0:6b3ac9c5a042 | 1920 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1921 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1922 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1923 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 1924 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1925 | switch( LoRaMacChannelAdd( channelIndex, chParam ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1926 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1927 | case LORAMAC_STATUS_OK: |
Wayne Roberts |
0:6b3ac9c5a042 | 1928 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1929 | MACC_PRINTF("add-ok "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1930 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1931 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1932 | case LORAMAC_STATUS_FREQUENCY_INVALID: |
Wayne Roberts |
0:6b3ac9c5a042 | 1933 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1934 | MACC_PRINTF("add-bad-freq "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1935 | status &= 0xFE; |
Wayne Roberts |
0:6b3ac9c5a042 | 1936 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1937 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1938 | case LORAMAC_STATUS_DATARATE_INVALID: |
Wayne Roberts |
0:6b3ac9c5a042 | 1939 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1940 | MACC_PRINTF("add-bad-dr "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1941 | status &= 0xFD; |
Wayne Roberts |
0:6b3ac9c5a042 | 1942 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1943 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1944 | case LORAMAC_STATUS_FREQ_AND_DR_INVALID: |
Wayne Roberts |
0:6b3ac9c5a042 | 1945 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1946 | MACC_PRINTF("add-bad-both "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1947 | status &= 0xFC; |
Wayne Roberts |
0:6b3ac9c5a042 | 1948 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1949 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1950 | default: |
Wayne Roberts |
0:6b3ac9c5a042 | 1951 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1952 | MACC_PRINTF("add-bad-? "); |
Wayne Roberts |
0:6b3ac9c5a042 | 1953 | status &= 0xFC; |
Wayne Roberts |
0:6b3ac9c5a042 | 1954 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1955 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1956 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1957 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1958 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 1959 | MACC_PRINTF("status:%x ", status); |
Wayne Roberts |
0:6b3ac9c5a042 | 1960 | AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1961 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1962 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1963 | case SRV_MAC_RX_TIMING_SETUP_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 1964 | MACC_PRINTF("RX_TIMING_SETUP_REQ"); |
Wayne Roberts |
0:6b3ac9c5a042 | 1965 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1966 | uint8_t delay = payload[macIndex++] & 0x0F; |
Wayne Roberts |
0:6b3ac9c5a042 | 1967 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1968 | if( delay == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 1969 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1970 | delay++; |
Wayne Roberts |
0:6b3ac9c5a042 | 1971 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1972 | LoRaMacParams.ReceiveDelay1_us = delay * 1e6; |
Wayne Roberts |
0:6b3ac9c5a042 | 1973 | LoRaMacParams.ReceiveDelay2_us = LoRaMacParams.ReceiveDelay1_us + 1e6; |
Wayne Roberts |
0:6b3ac9c5a042 | 1974 | AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 1975 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1976 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1977 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 1978 | case SRV_MAC_REKEY_CONF: |
Wayne Roberts |
0:6b3ac9c5a042 | 1979 | macIndex++;//TODo server_version = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1980 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1981 | flags.need_ReKeyConf = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1982 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 1983 | case SRV_MAC_FORCE_REJOIN_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 1984 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 1985 | uint16_t cmd_payload = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 1986 | cmd_payload |= payload[macIndex++] << 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 1987 | rejoin.type = (cmd_payload >> 4) & 7; |
Wayne Roberts |
0:6b3ac9c5a042 | 1988 | if (rejoin.type == 2) |
Wayne Roberts |
0:6b3ac9c5a042 | 1989 | JoinReqType = 2; |
Wayne Roberts |
0:6b3ac9c5a042 | 1990 | else { |
Wayne Roberts |
0:6b3ac9c5a042 | 1991 | JoinReqType = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1992 | rejoin.type = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 1993 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 1994 | |
Wayne Roberts |
0:6b3ac9c5a042 | 1995 | rejoin.dr = cmd_payload & 0x0f; |
Wayne Roberts |
0:6b3ac9c5a042 | 1996 | LoRaMacParams.ChannelsDatarate = rejoin.dr; |
Wayne Roberts |
0:6b3ac9c5a042 | 1997 | rejoin.retries = 1 + ((cmd_payload >> 8) & 7); |
Wayne Roberts |
0:6b3ac9c5a042 | 1998 | MAC_PRINTF("FORCE_REJOIN 0x%04x dr%u type%u tries%u ", cmd_payload, LoRaMacParams.ChannelsDatarate, JoinReqType, rejoin.retries); |
Wayne Roberts |
0:6b3ac9c5a042 | 1999 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2000 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2001 | rejoin.Period = (cmd_payload >> 11) & 7; |
Wayne Roberts |
0:6b3ac9c5a042 | 2002 | /* first forced-rejoin attempt must be immediate */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2003 | rejoin.event.attach_us(_rejoin_retry, 50000); |
Wayne Roberts |
0:6b3ac9c5a042 | 2004 | rejoin.forced = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2005 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2006 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2007 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2008 | case SRV_MAC_REJOIN_PARAM_REQ: |
Wayne Roberts |
0:6b3ac9c5a042 | 2009 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2010 | uint8_t p = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2011 | rejoin.type0.MaxTimeN = p >> 4; |
Wayne Roberts |
0:6b3ac9c5a042 | 2012 | rejoin.type0.MaxCountN = p & 0xf; |
Wayne Roberts |
0:6b3ac9c5a042 | 2013 | rejoin.type0.enabled = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2014 | MACC_PRINTF("REJOIN_PARAM MaxTimeN%u MaxCountN%u ", rejoin.type0.MaxTimeN, rejoin.type0.MaxCountN); |
Wayne Roberts |
0:6b3ac9c5a042 | 2015 | rejoin.type0.uplinks_since = 1 << (rejoin.type0.MaxCountN + 4); |
Wayne Roberts |
0:6b3ac9c5a042 | 2016 | AddMacCommand(MOTE_MAC_REJOIN_PARAM_ANS, 0, 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2017 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2018 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2019 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 2020 | case SRV_MAC_RESET_CONF: |
Wayne Roberts |
0:6b3ac9c5a042 | 2021 | macIndex++; //TODO server_version = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2022 | flags.need_ResetConf = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2023 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2024 | #endif /* !LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2025 | case SRV_MAC_DEVICE_TIME_ANS: |
Wayne Roberts |
0:6b3ac9c5a042 | 2026 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2027 | uint32_t subusecs, secs; |
Wayne Roberts |
0:6b3ac9c5a042 | 2028 | us_timestamp_t us_since_tx_done; |
Wayne Roberts |
0:6b3ac9c5a042 | 2029 | secs = payload[macIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2030 | secs += payload[macIndex++] << 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 2031 | secs += payload[macIndex++] << 16; |
Wayne Roberts |
0:6b3ac9c5a042 | 2032 | secs += payload[macIndex++] << 24; |
Wayne Roberts |
0:6b3ac9c5a042 | 2033 | subusecs = payload[macIndex++] * 3906.5; |
Wayne Roberts |
0:6b3ac9c5a042 | 2034 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2035 | //MAC_PRINTF("secs:%u, subusecs:%u\r\n", secs, subusecs); |
Wayne Roberts |
0:6b3ac9c5a042 | 2036 | deviceTimeClassB(secs, subusecs); |
Wayne Roberts |
0:6b3ac9c5a042 | 2037 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2038 | us_since_tx_done = Radio::lpt.read_us() - tx_done_at; |
Wayne Roberts |
0:6b3ac9c5a042 | 2039 | MlmeConfirm.fields.time.uSeconds += us_since_tx_done; |
Wayne Roberts |
0:6b3ac9c5a042 | 2040 | while (us_since_tx_done >= 1000000) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2041 | MlmeConfirm.fields.time.Seconds++; |
Wayne Roberts |
0:6b3ac9c5a042 | 2042 | us_since_tx_done -= 1000000; |
Wayne Roberts |
0:6b3ac9c5a042 | 2043 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2044 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2045 | MlmeConfirm.fields.time.Seconds = secs; |
Wayne Roberts |
0:6b3ac9c5a042 | 2046 | MlmeConfirm.fields.time.uSeconds = subusecs; |
Wayne Roberts |
0:6b3ac9c5a042 | 2047 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2048 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2049 | default: |
Wayne Roberts |
0:6b3ac9c5a042 | 2050 | --macIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 2051 | if (ProcessMacCommandsClassB(payload, &macIndex)) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2052 | /* mac command was taken */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2053 | //MACC_PRINTF("B-cont\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2054 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2055 | #ifdef DUTY_ENABLE |
Wayne Roberts |
0:6b3ac9c5a042 | 2056 | else if (ProcessMacCommandsDuty(payload, &macIndex)) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2057 | /* mac command was taken */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2058 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2059 | #endif /* DUTY_ENABLE */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2060 | else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2061 | ret = -1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2062 | MAC_PRINTF("[31munknown mac:0x%02x at %u[0m\r\n", payload[macIndex-1], macIndex-1); |
Wayne Roberts |
0:6b3ac9c5a042 | 2063 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2064 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2065 | } // ..switch(payload[macIndex++]) |
Wayne Roberts |
0:6b3ac9c5a042 | 2066 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2067 | MACC_PRINTF("\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2068 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2069 | } // ..while( macIndex < commandsSize ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2070 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2071 | return ret; |
Wayne Roberts |
0:6b3ac9c5a042 | 2072 | } // ..ProcessMacCommands() |
Wayne Roberts |
0:6b3ac9c5a042 | 2073 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2074 | #define MAX_FCNT_GAP 0x4000 |
Wayne Roberts |
0:6b3ac9c5a042 | 2075 | /* return: true == send downlink ack */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2076 | static int |
Wayne Roberts |
0:6b3ac9c5a042 | 2077 | rx_downlink(uint8_t pktHeaderLen, uint8_t* rx_payload, uint16_t rx_size, int8_t snr, us_timestamp_t us_rxDone_at) |
Wayne Roberts |
0:6b3ac9c5a042 | 2078 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2079 | LoRaMacHeader_t macHdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 2080 | LoRaMacFrameCtrl_t fCtrl; |
Wayne Roberts |
0:6b3ac9c5a042 | 2081 | uint32_t myFCntDwn32, rxFCnt32; |
Wayne Roberts |
0:6b3ac9c5a042 | 2082 | uint8_t rxFPort; |
Wayne Roberts |
0:6b3ac9c5a042 | 2083 | uint16_t rxFCnt16; |
Wayne Roberts |
0:6b3ac9c5a042 | 2084 | uint32_t address; |
Wayne Roberts |
0:6b3ac9c5a042 | 2085 | uint32_t mic, micRx; |
Wayne Roberts |
0:6b3ac9c5a042 | 2086 | uint8_t appPayloadStartIndex = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2087 | bool skipIndication = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2088 | uint8_t frameLen = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2089 | bool is_AFCntDown; |
Wayne Roberts |
0:6b3ac9c5a042 | 2090 | block_t block; |
Wayne Roberts |
0:6b3ac9c5a042 | 2091 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2092 | macHdr.Value = rx_payload[0]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2093 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2094 | address = rx_payload[pktHeaderLen++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2095 | address |= ( (uint32_t)rx_payload[pktHeaderLen++] << 8 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2096 | address |= ( (uint32_t)rx_payload[pktHeaderLen++] << 16 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2097 | address |= ( (uint32_t)rx_payload[pktHeaderLen++] << 24 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2098 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2099 | fCtrl.Value = rx_payload[pktHeaderLen++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2100 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2101 | rxFCnt16 = ( uint16_t )rx_payload[pktHeaderLen++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2102 | rxFCnt16 |= ( uint16_t )rx_payload[pktHeaderLen++] << 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 2103 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2104 | is_AFCntDown = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2105 | if (( ( rx_size - 4 ) - (8 + fCtrl.Bits.FOptsLen) ) > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2106 | appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen; |
Wayne Roberts |
0:6b3ac9c5a042 | 2107 | rxFPort = rx_payload[appPayloadStartIndex++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2108 | if (flags.OptNeg && rxFPort > 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 2109 | is_AFCntDown = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2110 | } /* else no payload/fport present */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2111 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2112 | myFCntDwn32 = get_fcntdwn(is_AFCntDown); |
Wayne Roberts |
0:6b3ac9c5a042 | 2113 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2114 | McpsIndication.expectedFCntDown = myFCntDwn32; |
Wayne Roberts |
0:6b3ac9c5a042 | 2115 | McpsIndication.receivedFCntDown = rxFCnt16; |
Wayne Roberts |
0:6b3ac9c5a042 | 2116 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2117 | rxFCnt32 = (myFCntDwn32 & 0xffff0000) | rxFCnt16; |
Wayne Roberts |
0:6b3ac9c5a042 | 2118 | DEBUG_MIC_DOWN(" rxFCnt32:%" PRIu32" ", rxFCnt32); |
Wayne Roberts |
0:6b3ac9c5a042 | 2119 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2120 | micRx = ( uint32_t )rx_payload[rx_size - LORAMAC_MFR_LEN]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2121 | micRx |= ( ( uint32_t )rx_payload[rx_size - LORAMAC_MFR_LEN + 1] << 8 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2122 | micRx |= ( ( uint32_t )rx_payload[rx_size - LORAMAC_MFR_LEN + 2] << 16 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2123 | micRx |= ( ( uint32_t )rx_payload[rx_size - LORAMAC_MFR_LEN + 3] << 24 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2124 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2125 | block.b.header = 0x49; |
Wayne Roberts |
0:6b3ac9c5a042 | 2126 | if (flags.OptNeg) |
Wayne Roberts |
0:6b3ac9c5a042 | 2127 | block.b.confFCnt = ConfFCntUp; |
Wayne Roberts |
0:6b3ac9c5a042 | 2128 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2129 | block.b.confFCnt = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2130 | block.b.dr = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2131 | block.b.ch = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2132 | block.b.dir = DOWN_LINK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2133 | block.b.DevAddr = address; |
Wayne Roberts |
0:6b3ac9c5a042 | 2134 | block.b.FCnt = rxFCnt32; |
Wayne Roberts |
0:6b3ac9c5a042 | 2135 | block.b.zero8 = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2136 | block.b.lenMsg = rx_size - LORAMAC_MFR_LEN; |
Wayne Roberts |
0:6b3ac9c5a042 | 2137 | mic = LoRaMacComputeMic(&block, rx_payload, keys.SNwkSIntKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 2138 | if (micRx != mic) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2139 | bool ignore_rx = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2140 | MAC_PRINTF("\e[31mmicFail"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2141 | if (flags.OptNeg) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2142 | block.b.confFCnt = ConfFCntUp - 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2143 | mic = LoRaMacComputeMic(&block, rx_payload, keys.SNwkSIntKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 2144 | if (micRx == mic) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2145 | ignore_rx = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2146 | if (McpsIndication.RxSlot == 2) |
Wayne Roberts |
0:6b3ac9c5a042 | 2147 | upConfRetry(LORAMAC_EVENT_INFO_STATUS_MIC_FAIL); |
Wayne Roberts |
0:6b3ac9c5a042 | 2148 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2149 | block.b.confFCnt = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2150 | mic = LoRaMacComputeMic(&block, rx_payload, keys.SNwkSIntKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 2151 | if (micRx == mic) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2152 | ignore_rx = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2153 | if (McpsIndication.RxSlot == 2) |
Wayne Roberts |
0:6b3ac9c5a042 | 2154 | upConfRetry(LORAMAC_EVENT_INFO_STATUS_MIC_FAIL); |
Wayne Roberts |
0:6b3ac9c5a042 | 2155 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2156 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2157 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2158 | if (ignore_rx) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2159 | MAC_PRINTF("\e[0m\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2160 | PrepareRxDoneAbort(LORAMAC_EVENT_INFO_STATUS_MIC_FAIL); |
Wayne Roberts |
0:6b3ac9c5a042 | 2161 | return -1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2162 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2163 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; |
Wayne Roberts |
0:6b3ac9c5a042 | 2164 | if (LoRaMacPrimitives->MacMcpsIndication != NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 2165 | LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2166 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2167 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2168 | /* downlink with good MIC means previous confirmed uplink was receied */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2169 | ConfFCntUp = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2170 | if (McpsIndication.RxSlot == 1) // no need for RX2 with good mic on rx1 |
Wayne Roberts |
0:6b3ac9c5a042 | 2171 | RxWindowEvent2.detach(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2172 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2173 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2174 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2175 | //McpsIndication.Multicast = 0;//multicast; |
Wayne Roberts |
0:6b3ac9c5a042 | 2176 | McpsIndication.FramePending = fCtrl.Bits.FPending; |
Wayne Roberts |
0:6b3ac9c5a042 | 2177 | McpsIndication.Buffer = NULL; |
Wayne Roberts |
0:6b3ac9c5a042 | 2178 | McpsIndication.BufferSize = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2179 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2180 | AdrAckCounter = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2181 | MacCommandsBufferToRepeatIndex = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2182 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2183 | if (macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN) |
Wayne Roberts |
0:6b3ac9c5a042 | 2184 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2185 | flags.SrvAckRequested = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2186 | McpsIndication.McpsIndication = MCPS_CONFIRMED; |
Wayne Roberts |
0:6b3ac9c5a042 | 2187 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2188 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2189 | if (flags.IsLoRaMacNetworkJoined) |
Wayne Roberts |
0:6b3ac9c5a042 | 2190 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2191 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2192 | if (flags.OptNeg) |
Wayne Roberts |
0:6b3ac9c5a042 | 2193 | ConfFCntDown = rxFCnt16; |
Wayne Roberts |
0:6b3ac9c5a042 | 2194 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2195 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2196 | { // FRAME_TYPE_DATA_UNCONFIRMED_DOWN: |
Wayne Roberts |
0:6b3ac9c5a042 | 2197 | ConfFCntDown = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2198 | flags.SrvAckRequested = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2199 | McpsIndication.McpsIndication = MCPS_UNCONFIRMED; |
Wayne Roberts |
0:6b3ac9c5a042 | 2200 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2201 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2202 | if (fCtrl.Bits.FOptsLen > 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 2203 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2204 | // Decode Options field MAC commands |
Wayne Roberts |
0:6b3ac9c5a042 | 2205 | if (flags.OptNeg) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2206 | uint32_t FCnt32; |
Wayne Roberts |
0:6b3ac9c5a042 | 2207 | bool fromStored; |
Wayne Roberts |
0:6b3ac9c5a042 | 2208 | uint8_t macDecrypt[16]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2209 | DEBUG_CRYPT_BUF(keys.NwkSEncKey, 16, "NwkSEncKey", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2210 | if (appPayloadStartIndex > 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2211 | /* rx header has AFCntDown: not for use with FOpts */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2212 | FCnt32 = get_fcntdwn(false); |
Wayne Roberts |
0:6b3ac9c5a042 | 2213 | fromStored = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2214 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2215 | /* NFCntDown received in rx header */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2216 | FCnt32 = (get_fcntdwn(false) & 0xffff0000) | rxFCnt16; |
Wayne Roberts |
0:6b3ac9c5a042 | 2217 | fromStored = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2218 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2219 | DEBUG_CRYPT("FCnt32:%" PRIu32" ", FCnt32); |
Wayne Roberts |
0:6b3ac9c5a042 | 2220 | DEBUG_CRYPT_BUF(rx_payload+8, fCtrl.Bits.FOptsLen, "FOpts-rx", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2221 | LoRaMacEncrypt(0, rx_payload+8, fCtrl.Bits.FOptsLen, keys.NwkSEncKey, LoRaMacDevAddr, DOWN_LINK, FCnt32, macDecrypt); |
Wayne Roberts |
0:6b3ac9c5a042 | 2222 | DEBUG_CRYPT_BUF(macDecrypt, fCtrl.Bits.FOptsLen, "FOpts-decrypt", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2223 | if (ProcessMacCommands(macDecrypt, 0, fCtrl.Bits.FOptsLen, snr, us_rxDone_at) < 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2224 | if (fromStored) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2225 | MAC_PRINTF("fromStored-"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2226 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2227 | MAC_PRINTF("FCnt32:%lu ", FCnt32); |
Wayne Roberts |
0:6b3ac9c5a042 | 2228 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2229 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2230 | MAC_PRINTF("ProcessMacCommands-FOpts "); |
Wayne Roberts |
0:6b3ac9c5a042 | 2231 | ProcessMacCommands( rx_payload, 8, fCtrl.Bits.FOptsLen + 8, snr, us_rxDone_at ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2232 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2233 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2234 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2235 | if (appPayloadStartIndex > 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 2236 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2237 | frameLen = ( rx_size - 4 ) - appPayloadStartIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 2238 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2239 | McpsIndication.Port = rxFPort; |
Wayne Roberts |
0:6b3ac9c5a042 | 2240 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2241 | if (rxFPort == 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 2242 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2243 | if( ( fCtrl.Bits.FOptsLen == 0 ) /*&& ( multicast == 0 )*/ ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2244 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2245 | uint8_t macDecrypt[16]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2246 | LoRaMacPayloadDecrypt(rx_payload + appPayloadStartIndex, |
Wayne Roberts |
0:6b3ac9c5a042 | 2247 | frameLen, |
Wayne Roberts |
0:6b3ac9c5a042 | 2248 | keys.NwkSEncKey, |
Wayne Roberts |
0:6b3ac9c5a042 | 2249 | address, |
Wayne Roberts |
0:6b3ac9c5a042 | 2250 | DOWN_LINK, |
Wayne Roberts |
0:6b3ac9c5a042 | 2251 | rxFCnt32, |
Wayne Roberts |
0:6b3ac9c5a042 | 2252 | macDecrypt |
Wayne Roberts |
0:6b3ac9c5a042 | 2253 | ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2254 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2255 | // Decode frame payload MAC commands |
Wayne Roberts |
0:6b3ac9c5a042 | 2256 | MAC_PRINTF("ProcessMacCommands-payload "); |
Wayne Roberts |
0:6b3ac9c5a042 | 2257 | if (ProcessMacCommands( macDecrypt, 0, frameLen, snr, us_rxDone_at ) < 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2258 | MAC_PRINTF(" rxFCnt32:%" PRIu32 " ", rxFCnt32); |
Wayne Roberts |
0:6b3ac9c5a042 | 2259 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2260 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2261 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2262 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2263 | skipIndication = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2264 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2265 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2266 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2267 | { /* rxFPort > 0 */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2268 | MAC_PRINTF("rxFCnt32:%" PRIu32" %08" PRIx32" ", rxFCnt32, address); |
Wayne Roberts |
0:6b3ac9c5a042 | 2269 | MAC_PRINTF("FCntDown%" PRIu32 " ", rxFCnt32); |
Wayne Roberts |
0:6b3ac9c5a042 | 2270 | DEBUG_CRYPT(" addr%" PRIx32" len%u\r\n", address, frameLen); |
Wayne Roberts |
0:6b3ac9c5a042 | 2271 | DEBUG_CRYPT_BUF(rx_payload + appPayloadStartIndex, frameLen, "rxEncd", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2272 | DEBUG_CRYPT_BUF(keys.AppSKey, 16, "AppSKey", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2273 | LoRaMacPayloadDecrypt(rx_payload + appPayloadStartIndex, |
Wayne Roberts |
0:6b3ac9c5a042 | 2274 | frameLen, |
Wayne Roberts |
0:6b3ac9c5a042 | 2275 | keys.AppSKey, |
Wayne Roberts |
0:6b3ac9c5a042 | 2276 | address, |
Wayne Roberts |
0:6b3ac9c5a042 | 2277 | DOWN_LINK, |
Wayne Roberts |
0:6b3ac9c5a042 | 2278 | rxFCnt32, |
Wayne Roberts |
0:6b3ac9c5a042 | 2279 | rxFRMPayload |
Wayne Roberts |
0:6b3ac9c5a042 | 2280 | ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2281 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2282 | if( skipIndication == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2283 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2284 | McpsIndication.Buffer = rxFRMPayload; |
Wayne Roberts |
0:6b3ac9c5a042 | 2285 | McpsIndication.BufferSize = frameLen; |
Wayne Roberts |
0:6b3ac9c5a042 | 2286 | McpsIndication.RxData = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2287 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2288 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2289 | } // ..if have payload |
Wayne Roberts |
0:6b3ac9c5a042 | 2290 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2291 | if( skipIndication == false ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2292 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2293 | // Check if the frame is an acknowledgement |
Wayne Roberts |
0:6b3ac9c5a042 | 2294 | if( fCtrl.Bits.Ack == 1 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2295 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2296 | McpsConfirm.AckReceived = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2297 | McpsIndication.AckReceived = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2298 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2299 | // Stop the AckTimeout timer as no more retransmissions |
Wayne Roberts |
0:6b3ac9c5a042 | 2300 | // are needed. |
Wayne Roberts |
0:6b3ac9c5a042 | 2301 | //TimerStop( &AckTimeoutTimer ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2302 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2303 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2304 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2305 | McpsConfirm.AckReceived = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2306 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2307 | if( AckTimeoutRetriesCounter > AckTimeoutRetries ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2308 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2309 | // Stop the AckTimeout timer as no more retransmissions |
Wayne Roberts |
0:6b3ac9c5a042 | 2310 | // are needed. |
Wayne Roberts |
0:6b3ac9c5a042 | 2311 | //TimerStop( &AckTimeoutTimer ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2312 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2313 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2314 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2315 | if (LoRaMacPrimitives->MacMcpsIndication != NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 2316 | LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); // RxDone |
Wayne Roberts |
0:6b3ac9c5a042 | 2317 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2318 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2319 | /* set FCntDwn to next expected value */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2320 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2321 | if (last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2322 | if (fCtrl.Bits.Ack) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2323 | FCntUp++; |
Wayne Roberts |
0:6b3ac9c5a042 | 2324 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2325 | MAC_PRINTF("\e[31mrx-!ack\e[0m\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2326 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2327 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2328 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2329 | if (is_AFCntDown) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2330 | AFCntDown = rxFCnt32 + 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2331 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2332 | NFCntDown = rxFCnt32 + 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2333 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2334 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 2335 | if (fCtrl.Bits.Ack && last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP) |
Wayne Roberts |
0:6b3ac9c5a042 | 2336 | eeprom_increment_value(EEPROM_FCNTUP); /* TODO handle ee-failure return */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2337 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2338 | if (is_AFCntDown) |
Wayne Roberts |
0:6b3ac9c5a042 | 2339 | eeprom_write_word(EEPROM_AFCNTDWN, rxFCnt32 + 1); |
Wayne Roberts |
0:6b3ac9c5a042 | 2340 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2341 | eeprom_write_word(EEPROM_NFCNTDWN, rxFCnt32 + 1); |
Wayne Roberts |
0:6b3ac9c5a042 | 2342 | #endif /* !LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2343 | /*vt.SetCursorPos( ROW_END, 1 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2344 | vt.printf("ZZZ ");*/ |
Wayne Roberts |
0:6b3ac9c5a042 | 2345 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2346 | return 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2347 | } // ...rx_downlink() |
Wayne Roberts |
0:6b3ac9c5a042 | 2348 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2349 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2350 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2351 | typedef union { |
Wayne Roberts |
0:6b3ac9c5a042 | 2352 | struct { |
Wayne Roberts |
0:6b3ac9c5a042 | 2353 | uint8_t mhdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 2354 | unsigned int joinNonce : 24; |
Wayne Roberts |
0:6b3ac9c5a042 | 2355 | unsigned int Home_NetID : 24; |
Wayne Roberts |
0:6b3ac9c5a042 | 2356 | uint32_t DevAddr; |
Wayne Roberts |
0:6b3ac9c5a042 | 2357 | struct { |
Wayne Roberts |
0:6b3ac9c5a042 | 2358 | uint8_t RX2dr : 4; // 0,1,2,3 |
Wayne Roberts |
0:6b3ac9c5a042 | 2359 | uint8_t RX1DRoffset : 3; // 4,5,6 |
Wayne Roberts |
0:6b3ac9c5a042 | 2360 | uint8_t OptNeg : 1; // 7 |
Wayne Roberts |
0:6b3ac9c5a042 | 2361 | } DLSettings; |
Wayne Roberts |
0:6b3ac9c5a042 | 2362 | uint8_t RxDelay; |
Wayne Roberts |
0:6b3ac9c5a042 | 2363 | } __attribute__((packed)) fields; |
Wayne Roberts |
0:6b3ac9c5a042 | 2364 | uint8_t octets[13]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2365 | } joinAccept_t; |
Wayne Roberts |
0:6b3ac9c5a042 | 2366 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2367 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2368 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2369 | #define JOIN_ACCEPT_MAX_SIZE 34 |
Wayne Roberts |
0:6b3ac9c5a042 | 2370 | static void |
Wayne Roberts |
0:6b3ac9c5a042 | 2371 | OnRadioRxDone(uint8_t *rx_payload, uint16_t rx_size, int16_t rssi, int8_t snr, us_timestamp_t us_rxDone_at) |
Wayne Roberts |
0:6b3ac9c5a042 | 2372 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2373 | LoRaMacEventInfoStatus_t status = LORAMAC_EVENT_INFO_STATUS_UNKNOWN_MTYPE; |
Wayne Roberts |
0:6b3ac9c5a042 | 2374 | LoRaMacHeader_t macHdr; |
Wayne Roberts |
0:6b3ac9c5a042 | 2375 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2376 | uint8_t _jaDecrypted[JOIN_ACCEPT_MAX_SIZE]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2377 | uint32_t mic, micRx; |
Wayne Roberts |
0:6b3ac9c5a042 | 2378 | const uint8_t* key; |
Wayne Roberts |
0:6b3ac9c5a042 | 2379 | const joinAccept_t* ja; |
Wayne Roberts |
0:6b3ac9c5a042 | 2380 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2381 | uint8_t pktHeaderLen = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2382 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2383 | McpsConfirm.AckReceived = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2384 | McpsIndication.Rssi = rssi; |
Wayne Roberts |
0:6b3ac9c5a042 | 2385 | McpsIndication.Snr = snr; |
Wayne Roberts |
0:6b3ac9c5a042 | 2386 | McpsIndication.Port = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2387 | //McpsIndication.Multicast = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2388 | McpsIndication.FramePending = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2389 | McpsIndication.Buffer = NULL; |
Wayne Roberts |
0:6b3ac9c5a042 | 2390 | McpsIndication.BufferSize = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2391 | McpsIndication.RxData = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2392 | McpsIndication.AckReceived = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2393 | McpsIndication.McpsIndication = MCPS_UNCONFIRMED; |
Wayne Roberts |
0:6b3ac9c5a042 | 2394 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2395 | if (MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_SENDING) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2396 | /* when regular downlink is sent in response to rejoin request */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2397 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2398 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2399 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2400 | if( LoRaMacDeviceClass != CLASS_C ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2401 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2402 | Radio::Sleep( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2403 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2404 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2405 | MAC_PRINTF("OnRadioRxDone(%u) RxSlot%d ", rx_size, McpsIndication.RxSlot); |
Wayne Roberts |
0:6b3ac9c5a042 | 2406 | if (beacon_rx_done_payload(rx_payload, rx_size)) |
Wayne Roberts |
0:6b3ac9c5a042 | 2407 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 2408 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2409 | macHdr.Value = rx_payload[pktHeaderLen++]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2410 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2411 | MAC_PRINTF(" rx-"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2412 | print_mtype(macHdr.Bits.MType); |
Wayne Roberts |
0:6b3ac9c5a042 | 2413 | switch (macHdr.Bits.MType) |
Wayne Roberts |
0:6b3ac9c5a042 | 2414 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2415 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2416 | case FRAME_TYPE_JOIN_ACCEPT: |
Wayne Roberts |
0:6b3ac9c5a042 | 2417 | /* always permitting join accept because it might be due to rejoin */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2418 | if (rx_size >= JOIN_ACCEPT_MAX_SIZE) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2419 | printf("joinAccept overSize %u\r\n", rx_size); |
Wayne Roberts |
0:6b3ac9c5a042 | 2420 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 2421 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2422 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2423 | DEBUG_CRYPT_BUF(rx_payload, rx_size, "rxBuf", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2424 | MAC_PRINTF("JoinReqType:%02x ", JoinReqType); |
Wayne Roberts |
0:6b3ac9c5a042 | 2425 | if (JoinReqType == 0xff) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2426 | DEBUG_CRYPT_BUF(RootNwkKey, 16, "NwkKey", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2427 | key = RootNwkKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 2428 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2429 | key = JSEncKey; |
Wayne Roberts |
0:6b3ac9c5a042 | 2430 | DEBUG_CRYPT_BUF(JSEncKey, 16, "JSEncKey", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2431 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2432 | LoRaMacJoinDecrypt( rx_payload + 1, rx_size - 1, key, &_jaDecrypted[1]); |
Wayne Roberts |
0:6b3ac9c5a042 | 2433 | DEBUG_CRYPT_BUF(_jaDecrypted, rx_size, "macbuf", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2434 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2435 | _jaDecrypted[0] = macHdr.Value; |
Wayne Roberts |
0:6b3ac9c5a042 | 2436 | ja = (joinAccept_t*)_jaDecrypted; |
Wayne Roberts |
0:6b3ac9c5a042 | 2437 | flags.OptNeg = ja->fields.DLSettings.OptNeg; |
Wayne Roberts |
0:6b3ac9c5a042 | 2438 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2439 | if (flags.OptNeg) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2440 | uint8_t micBuf[40]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2441 | uint8_t* ptr = micBuf; |
Wayne Roberts |
0:6b3ac9c5a042 | 2442 | if (RootAppKey == NULL) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2443 | MAC_PRINTF("OptNeg-without-AppKey "); |
Wayne Roberts |
0:6b3ac9c5a042 | 2444 | PrepareRxDoneAbort(LORAMAC_EVENT_INFO_STATUS_NO_APPKEY); |
Wayne Roberts |
0:6b3ac9c5a042 | 2445 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 2446 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2447 | *ptr++ = JoinReqType; |
Wayne Roberts |
0:6b3ac9c5a042 | 2448 | memcpyr(ptr, LoRaMacJoinEui, 8); |
Wayne Roberts |
0:6b3ac9c5a042 | 2449 | ptr += 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 2450 | *ptr++ = LoRaMacDevNonce & 0xff; |
Wayne Roberts |
0:6b3ac9c5a042 | 2451 | *ptr++ = LoRaMacDevNonce >> 8; |
Wayne Roberts |
0:6b3ac9c5a042 | 2452 | memcpy(ptr, _jaDecrypted, rx_size - LORAMAC_MFR_LEN); |
Wayne Roberts |
0:6b3ac9c5a042 | 2453 | ptr += rx_size - LORAMAC_MFR_LEN; |
Wayne Roberts |
0:6b3ac9c5a042 | 2454 | DEBUG_MIC_BUF_DOWN(JSIntKey, 16, "JSIntKey", ROW_MIC); |
Wayne Roberts |
0:6b3ac9c5a042 | 2455 | DEBUG_MIC_BUF_DOWN(micBuf, ptr - micBuf, "jaMic-in", ROW_MIC+1); |
Wayne Roberts |
0:6b3ac9c5a042 | 2456 | if (LoRaMacJoinComputeMic(false, micBuf, ptr - micBuf, JSIntKey, &mic ) < 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2457 | MAC_PRINTF("cryptFail\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2458 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 2459 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2460 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2461 | if (LoRaMacJoinComputeMic(false, _jaDecrypted, rx_size - LORAMAC_MFR_LEN, RootNwkKey, &mic ) < 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2462 | MAC_PRINTF("cryptFail\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2463 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 2464 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2465 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2466 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2467 | micRx = ( uint32_t )_jaDecrypted[rx_size - LORAMAC_MFR_LEN]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2468 | micRx |= ( ( uint32_t )_jaDecrypted[rx_size - LORAMAC_MFR_LEN + 1] << 8 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2469 | micRx |= ( ( uint32_t )_jaDecrypted[rx_size - LORAMAC_MFR_LEN + 2] << 16 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2470 | micRx |= ( ( uint32_t )_jaDecrypted[rx_size - LORAMAC_MFR_LEN + 3] << 24 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2471 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2472 | MAC_PRINTF("JOIN_ACCEPT %u,OptNeg%" PRIu32" ", rx_size, flags.OptNeg); |
Wayne Roberts |
0:6b3ac9c5a042 | 2473 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2474 | if (micRx == mic) |
Wayne Roberts |
0:6b3ac9c5a042 | 2475 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2476 | if (McpsIndication.RxSlot == 1) // no need for RX2 with good mic on rx1 |
Wayne Roberts |
0:6b3ac9c5a042 | 2477 | RxWindowEvent2.detach(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2478 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2479 | #ifdef LORAWAN_ROOT_APPKEY |
Wayne Roberts |
0:6b3ac9c5a042 | 2480 | if (flags.OptNeg) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2481 | MlmeConfirm.fields.join.myJoinNonce = eeprom_read(EEPROM_JOINNONCE); |
Wayne Roberts |
0:6b3ac9c5a042 | 2482 | MlmeConfirm.fields.join.rxJoinNonce = ja->fields.joinNonce; |
Wayne Roberts |
0:6b3ac9c5a042 | 2483 | if (MlmeConfirm.fields.join.rxJoinNonce <= MlmeConfirm.fields.join.myJoinNonce) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2484 | /* replay attack */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2485 | PrepareRxDoneAbort(LORAMAC_EVENT_INFO_STATUS_JOINNONCE); |
Wayne Roberts |
0:6b3ac9c5a042 | 2486 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 2487 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2488 | flags.need_ReKeyConf = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2489 | LoRaMacJoinComputeSKeys_1v1( RootNwkKey, RootAppKey, _jaDecrypted+1, LoRaMacJoinEui, LoRaMacDevNonce, &keys); |
Wayne Roberts |
0:6b3ac9c5a042 | 2490 | eeprom_write_word(EEPROM_JOINNONCE, MlmeConfirm.fields.join.rxJoinNonce); |
Wayne Roberts |
0:6b3ac9c5a042 | 2491 | } else |
Wayne Roberts |
0:6b3ac9c5a042 | 2492 | #endif /* LORAWAN_ROOT_APPKEY */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2493 | LoRaMacJoinComputeSKeys_1v0( RootNwkKey, _jaDecrypted+1, LoRaMacDevNonce, &keys); |
Wayne Roberts |
0:6b3ac9c5a042 | 2494 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2495 | DEBUG_CRYPT_BUF(keys.AppSKey , 16, "create-AppSKey", 0); |
Wayne Roberts |
0:6b3ac9c5a042 | 2496 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2497 | LoRaMacNetID = ja->fields.Home_NetID; |
Wayne Roberts |
0:6b3ac9c5a042 | 2498 | LoRaMacDevAddr = ja->fields.DevAddr; |
Wayne Roberts |
0:6b3ac9c5a042 | 2499 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2500 | // DLSettings |
Wayne Roberts |
0:6b3ac9c5a042 | 2501 | LoRaMacParams.Rx1DrOffset = ja->fields.DLSettings.RX1DRoffset; |
Wayne Roberts |
0:6b3ac9c5a042 | 2502 | LoRaMacParams.Rx2Channel.Datarate = ja->fields.DLSettings.RX2dr; |
Wayne Roberts |
0:6b3ac9c5a042 | 2503 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2504 | // RxDelay |
Wayne Roberts |
0:6b3ac9c5a042 | 2505 | LoRaMacParams.ReceiveDelay1_us = (ja->fields.RxDelay & 0x0f) * 1000000; |
Wayne Roberts |
0:6b3ac9c5a042 | 2506 | if( LoRaMacParams.ReceiveDelay1_us == 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2507 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2508 | LoRaMacParams.ReceiveDelay1_us = 1000000; |
Wayne Roberts |
0:6b3ac9c5a042 | 2509 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2510 | LoRaMacParams.ReceiveDelay2_us = LoRaMacParams.ReceiveDelay1_us + 1000000; |
Wayne Roberts |
0:6b3ac9c5a042 | 2511 | MAC_PRINTF("rx1droffset:%u, rx2dr%u rxDelays:%" PRIu32" %" PRIu32", devaddr:%08" PRIx32" ", |
Wayne Roberts |
0:6b3ac9c5a042 | 2512 | LoRaMacParams.Rx1DrOffset, |
Wayne Roberts |
0:6b3ac9c5a042 | 2513 | LoRaMacParams.Rx2Channel.Datarate, |
Wayne Roberts |
0:6b3ac9c5a042 | 2514 | LoRaMacParams.ReceiveDelay1_us, |
Wayne Roberts |
0:6b3ac9c5a042 | 2515 | LoRaMacParams.ReceiveDelay2_us, |
Wayne Roberts |
0:6b3ac9c5a042 | 2516 | LoRaMacDevAddr |
Wayne Roberts |
0:6b3ac9c5a042 | 2517 | ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2518 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2519 | #if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) // TODO |
Wayne Roberts |
0:6b3ac9c5a042 | 2520 | //CFList |
Wayne Roberts |
0:6b3ac9c5a042 | 2521 | if( ( rx_size - 1 ) > 16 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2522 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2523 | ChannelParams_t param; |
Wayne Roberts |
0:6b3ac9c5a042 | 2524 | param.DrRange.Value = ( LORAMAC_TX_MAX_DATARATE << 4 ) | LORAMAC_TX_MIN_DATARATE; |
Wayne Roberts |
0:6b3ac9c5a042 | 2525 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2526 | for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2527 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2528 | param.FreqHz = ( ( uint32_t )_jaDecrypted[13 + j] | ( ( uint32_t )_jaDecrypted[14 + j] << 8 ) | ( ( uint32_t )_jaDecrypted[15 + j] << 16 ) ) * 100; |
Wayne Roberts |
0:6b3ac9c5a042 | 2529 | if( param.FreqHz != 0 ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2530 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2531 | LoRaMacChannelAdd( i, param ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2532 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2533 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2534 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2535 | LoRaMacChannelRemove( i ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2536 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2537 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2538 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2539 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 2540 | status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2541 | flags.IsLoRaMacNetworkJoined = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2542 | LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 2543 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2544 | MAC_PRINTF("JoinReqType%x\r\n", JoinReqType); |
Wayne Roberts |
0:6b3ac9c5a042 | 2545 | FCntUp = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2546 | NFCntDown = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2547 | AFCntDown = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2548 | ConfFCntDown = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2549 | RJcount0 = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2550 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2551 | rejoin.event.detach(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2552 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2553 | // must always notify application layer |
Wayne Roberts |
0:6b3ac9c5a042 | 2554 | MlmeConfirm.MlmeRequest = MLME_JOIN; |
Wayne Roberts |
0:6b3ac9c5a042 | 2555 | region_session_start(LORAMAC_EVENT_INFO_STATUS_OK); |
Wayne Roberts |
0:6b3ac9c5a042 | 2556 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2557 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2558 | { /* join-accept mic fail */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2559 | status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL; |
Wayne Roberts |
0:6b3ac9c5a042 | 2560 | MAC_PRINTF("ja-mic-fail rx:%" PRIx32 " calc:%" PRIx32" size:%d\r\n", micRx, mic, rx_size); |
Wayne Roberts |
0:6b3ac9c5a042 | 2561 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2562 | if (MlmeIndication.MlmeIndication != MLME_NONE) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2563 | MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; |
Wayne Roberts |
0:6b3ac9c5a042 | 2564 | if (LoRaMacPrimitives->MacMlmeIndication != NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 2565 | LoRaMacPrimitives->MacMlmeIndication(&MlmeIndication); |
Wayne Roberts |
0:6b3ac9c5a042 | 2566 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2567 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2568 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2569 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2570 | case FRAME_TYPE_DATA_CONFIRMED_DOWN: |
Wayne Roberts |
0:6b3ac9c5a042 | 2571 | case FRAME_TYPE_DATA_UNCONFIRMED_DOWN: |
Wayne Roberts |
0:6b3ac9c5a042 | 2572 | if (rx_downlink(pktHeaderLen, rx_payload, rx_size, snr, us_rxDone_at) == 0) |
Wayne Roberts |
0:6b3ac9c5a042 | 2573 | status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2574 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2575 | case FRAME_TYPE_PROPRIETARY: |
Wayne Roberts |
0:6b3ac9c5a042 | 2576 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2577 | McpsIndication.McpsIndication = MCPS_PROPRIETARY; |
Wayne Roberts |
0:6b3ac9c5a042 | 2578 | McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2579 | McpsIndication.Buffer = Radio::radio.rx_buf; |
Wayne Roberts |
0:6b3ac9c5a042 | 2580 | McpsIndication.BufferSize = rx_size - pktHeaderLen; |
Wayne Roberts |
0:6b3ac9c5a042 | 2581 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2582 | if (LoRaMacPrimitives->MacMcpsIndication != NULL) |
Wayne Roberts |
0:6b3ac9c5a042 | 2583 | LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); // RxDone |
Wayne Roberts |
0:6b3ac9c5a042 | 2584 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2585 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2586 | default: |
Wayne Roberts |
0:6b3ac9c5a042 | 2587 | MAC_PRINTF("unknown frame type:%02x\r\n", macHdr.Value); |
Wayne Roberts |
0:6b3ac9c5a042 | 2588 | PrepareRxDoneAbort(LORAMAC_EVENT_INFO_STATUS_UNKNOWN_MTYPE); |
Wayne Roberts |
0:6b3ac9c5a042 | 2589 | break; |
Wayne Roberts |
0:6b3ac9c5a042 | 2590 | } // ..switch( macHdr.Bits.MType ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2591 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2592 | if (LoRaMacDeviceClass == CLASS_C) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2593 | if (McpsIndication.RxSlot == 1) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2594 | RxWindow2Setup(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2595 | RxWindow2Start(); // immiediately to continuous rx2 reception |
Wayne Roberts |
0:6b3ac9c5a042 | 2596 | McpsIndication.RxSlot = 2; |
Wayne Roberts |
0:6b3ac9c5a042 | 2597 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2598 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2599 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2600 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2601 | finish_uplink(status); |
Wayne Roberts |
0:6b3ac9c5a042 | 2602 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2603 | mcps_confirm(status); // RxDone |
Wayne Roberts |
0:6b3ac9c5a042 | 2604 | mlme_confirm(status); |
Wayne Roberts |
0:6b3ac9c5a042 | 2605 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2606 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2607 | MAC_PRINTF("\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2608 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2609 | flags.rxing = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2610 | } // ..OnRadioRxDone() |
Wayne Roberts |
0:6b3ac9c5a042 | 2611 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2612 | __attribute__((weak)) bool |
Wayne Roberts |
0:6b3ac9c5a042 | 2613 | beacon_rx_timeout() |
Wayne Roberts |
0:6b3ac9c5a042 | 2614 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2615 | return false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2616 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2617 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2618 | void OnRadioRxTimeout( void ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2619 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2620 | MAC_PRINTF("OnRadioRxTimeout()%d ", McpsIndication.RxSlot); |
Wayne Roberts |
0:6b3ac9c5a042 | 2621 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2622 | MAC_PRINTF(",%u ", flags.IsLoRaMacNetworkJoined); |
Wayne Roberts |
0:6b3ac9c5a042 | 2623 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2624 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2625 | /*vt.SetCursorPos( ROW_END+1, 1 ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2626 | vt.printf("TTT ");*/ |
Wayne Roberts |
0:6b3ac9c5a042 | 2627 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2628 | if (beacon_rx_timeout()) |
Wayne Roberts |
0:6b3ac9c5a042 | 2629 | return; |
Wayne Roberts |
0:6b3ac9c5a042 | 2630 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2631 | if (McpsIndication.RxSlot == 1) |
Wayne Roberts |
0:6b3ac9c5a042 | 2632 | RxWindow2Setup(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2633 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2634 | if (LoRaMacDeviceClass == CLASS_C) |
Wayne Roberts |
0:6b3ac9c5a042 | 2635 | RxWindow2Start(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2636 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2637 | Radio::Sleep( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2638 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2639 | if (McpsIndication.RxSlot == 2) |
Wayne Roberts |
0:6b3ac9c5a042 | 2640 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2641 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2642 | if (flags.IsLoRaMacNetworkJoined) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2643 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2644 | if (uplinkMHDR->Bits.MType == FRAME_TYPE_DATA_UNCONFIRMED_UP) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2645 | /* sent once, stoping now */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2646 | mcps_confirm(LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT); |
Wayne Roberts |
0:6b3ac9c5a042 | 2647 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2648 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2649 | mlme_confirm(LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT); |
Wayne Roberts |
0:6b3ac9c5a042 | 2650 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2651 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2652 | if (++MlmeIndication.JoinRequestTrials < MaxJoinRequestTrials) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2653 | TxDelayedEvent.attach_us(OnTxDelayedTimerEvent, 1000000); |
Wayne Roberts |
0:6b3ac9c5a042 | 2654 | MAC_PRINTF("RxTImeout-join-tx-delay\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2655 | MAC_PRINTF("join-try%u of%u ", MlmeIndication.JoinRequestTrials, MaxJoinRequestTrials); |
Wayne Roberts |
0:6b3ac9c5a042 | 2656 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2657 | if (MlmeIndication.MlmeIndication != MLME_NONE) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2658 | MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT; |
Wayne Roberts |
0:6b3ac9c5a042 | 2659 | if (LoRaMacPrimitives->MacMlmeIndication) |
Wayne Roberts |
0:6b3ac9c5a042 | 2660 | LoRaMacPrimitives->MacMlmeIndication(&MlmeIndication); |
Wayne Roberts |
0:6b3ac9c5a042 | 2661 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2662 | } else { |
Wayne Roberts |
0:6b3ac9c5a042 | 2663 | mlme_confirm(LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL); |
Wayne Roberts |
0:6b3ac9c5a042 | 2664 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2665 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2666 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2667 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2668 | finish_uplink(LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT); |
Wayne Roberts |
0:6b3ac9c5a042 | 2669 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2670 | upConfRetry(LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT); |
Wayne Roberts |
0:6b3ac9c5a042 | 2671 | } // ..if (McpsIndication.RxSlot == 2) |
Wayne Roberts |
0:6b3ac9c5a042 | 2672 | MAC_PRINTF("\r\n"); |
Wayne Roberts |
0:6b3ac9c5a042 | 2673 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2674 | flags.rxing = false; |
Wayne Roberts |
0:6b3ac9c5a042 | 2675 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2676 | } // ..OnRadioRxTimeout() |
Wayne Roberts |
0:6b3ac9c5a042 | 2677 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2678 | __attribute__((weak)) void |
Wayne Roberts |
0:6b3ac9c5a042 | 2679 | on_dio0_top_half(us_timestamp_t dio0_at) |
Wayne Roberts |
0:6b3ac9c5a042 | 2680 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2681 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2682 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2683 | static void OnRadioRxError( void ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2684 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2685 | if( LoRaMacDeviceClass != CLASS_C ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2686 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2687 | Radio::Sleep( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2688 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2689 | else |
Wayne Roberts |
0:6b3ac9c5a042 | 2690 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2691 | RxWindow2Setup(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2692 | RxWindow2Start(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2693 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2694 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2695 | if (McpsIndication.RxSlot == 2) |
Wayne Roberts |
0:6b3ac9c5a042 | 2696 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2697 | flags.uplink_in_progress = 0; // TODO check |
Wayne Roberts |
0:6b3ac9c5a042 | 2698 | mlme_confirm(LORAMAC_EVENT_INFO_STATUS_RX2_ERROR); |
Wayne Roberts |
0:6b3ac9c5a042 | 2699 | mcps_confirm(LORAMAC_EVENT_INFO_STATUS_RX2_ERROR); |
Wayne Roberts |
0:6b3ac9c5a042 | 2700 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2701 | } // ..OnRadioRxError |
Wayne Roberts |
0:6b3ac9c5a042 | 2702 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2703 | const RadioEvents_t RadioEvents = { |
Wayne Roberts |
0:6b3ac9c5a042 | 2704 | /* Dio0_top_half */ on_dio0_top_half, |
Wayne Roberts |
0:6b3ac9c5a042 | 2705 | /* TxDone */ OnRadioTxDone, |
Wayne Roberts |
0:6b3ac9c5a042 | 2706 | /* TxTimeout */ OnRadioTxTimeout, |
Wayne Roberts |
0:6b3ac9c5a042 | 2707 | /* RxDone */ OnRadioRxDone, |
Wayne Roberts |
0:6b3ac9c5a042 | 2708 | /* RxTimeout */ OnRadioRxTimeout, |
Wayne Roberts |
0:6b3ac9c5a042 | 2709 | /* RxError */ OnRadioRxError, |
Wayne Roberts |
0:6b3ac9c5a042 | 2710 | /* FhssChangeChannel */ NULL, |
Wayne Roberts |
0:6b3ac9c5a042 | 2711 | /* CadDone */ NULL |
Wayne Roberts |
0:6b3ac9c5a042 | 2712 | }; |
Wayne Roberts |
0:6b3ac9c5a042 | 2713 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2714 | LoRaMacStatus_t |
Wayne Roberts |
0:6b3ac9c5a042 | 2715 | LoRaMacInitialization( const LoRaMacPrimitives_t *primitives, const LoRaMacCallback_t *callbacks ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2716 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2717 | if( primitives == NULL ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2718 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2719 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 2720 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2721 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2722 | if( ( primitives->MacMcpsConfirm == NULL ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 2723 | ( primitives->MacMcpsIndication == NULL ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 2724 | ( primitives->MacMlmeConfirm == NULL ) || |
Wayne Roberts |
0:6b3ac9c5a042 | 2725 | ( primitives->MacMlmeIndication == NULL ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2726 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2727 | return LORAMAC_STATUS_PARAMETER_INVALID; |
Wayne Roberts |
0:6b3ac9c5a042 | 2728 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2729 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2730 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2731 | LoRaMacPrimitives = primitives; |
Wayne Roberts |
0:6b3ac9c5a042 | 2732 | LoRaMacCallbacks = callbacks; |
Wayne Roberts |
0:6b3ac9c5a042 | 2733 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2734 | LoRaMacDeviceClass = CLASS_A; |
Wayne Roberts |
0:6b3ac9c5a042 | 2735 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2736 | #ifdef DUTY_ENABLE |
Wayne Roberts |
0:6b3ac9c5a042 | 2737 | DutyInit(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2738 | #endif /* DUTY_ENABLE */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2739 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2740 | // Reset to defaults |
Wayne Roberts |
0:6b3ac9c5a042 | 2741 | LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; |
Wayne Roberts |
0:6b3ac9c5a042 | 2742 | LoRaMacParamsDefaults.ChannelsDatarate = LORAMAC_DEFAULT_DATARATE; |
Wayne Roberts |
0:6b3ac9c5a042 | 2743 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2744 | LoRaMacParamsDefaults.MaxRxWindow_us = MAX_RX_WINDOW_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 2745 | LoRaMacParamsDefaults.ReceiveDelay1_us = RECEIVE_DELAY1_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 2746 | LoRaMacParamsDefaults.ReceiveDelay2_us = RECEIVE_DELAY2_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 2747 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2748 | LoRaMacParamsDefaults.JoinAcceptDelay1_us = JOIN_ACCEPT_DELAY1_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 2749 | LoRaMacParamsDefaults.JoinAcceptDelay2_us = JOIN_ACCEPT_DELAY2_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 2750 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2751 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2752 | LoRaMacParamsDefaults.NbTrans = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2753 | LoRaMacParamsDefaults.Rx1DrOffset = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2754 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2755 | LoRaMacParamsDefaults.Rx2Channel = ( Rx2ChannelParams_t )RX_WND_2_CHANNEL; |
Wayne Roberts |
0:6b3ac9c5a042 | 2756 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2757 | region_mac_init(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2758 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2759 | ResetMacParameters( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2760 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2761 | // Initialize Radio driver |
Wayne Roberts |
0:6b3ac9c5a042 | 2762 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2763 | LoRaMacClassBInitialization(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2764 | Radio::Init( &RadioEvents ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2765 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2766 | // Random seed initialization |
Wayne Roberts |
0:6b3ac9c5a042 | 2767 | srand(Radio::Random()); |
Wayne Roberts |
0:6b3ac9c5a042 | 2768 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2769 | flags.PublicNetwork = true; |
Wayne Roberts |
0:6b3ac9c5a042 | 2770 | Radio::SetPublicNetwork( flags.PublicNetwork ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2771 | Radio::Sleep( ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2772 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2773 | McpsIndication.RxSlot = -1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2774 | function_pending = NULL; |
Wayne Roberts |
0:6b3ac9c5a042 | 2775 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2776 | McpsConfirm.McpsRequest = MCPS_NONE; |
Wayne Roberts |
0:6b3ac9c5a042 | 2777 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2778 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2779 | MaxJoinRequestTrials = 1; |
Wayne Roberts |
0:6b3ac9c5a042 | 2780 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 2781 | flags.have_SNwkSIntKey = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2782 | flags.have_NwkSEncKey = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2783 | flags.OptNeg = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2784 | #endif /* !LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2785 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2786 | LoRaMacCryptoInit(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2787 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2788 | MlmeIndication.MlmeIndication = MLME_NONE; |
Wayne Roberts |
0:6b3ac9c5a042 | 2789 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2790 | return LORAMAC_STATUS_OK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2791 | } // ..LoRaMacInitialization() |
Wayne Roberts |
0:6b3ac9c5a042 | 2792 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2793 | void SendFrameOnChannel( uint8_t ch_num ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2794 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2795 | int8_t txPowerIndex = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2796 | int8_t txPower = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2797 | uint8_t tx_len = tx_buf_len; |
Wayne Roberts |
0:6b3ac9c5a042 | 2798 | uint32_t mic; |
Wayne Roberts |
0:6b3ac9c5a042 | 2799 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2800 | /* TODO: if beacon guard, defer until pingslot 0 */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2801 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2802 | last_up_macHdr.Value = Radio::radio.tx_buf[0]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2803 | if (last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_UNCONFIRMED_UP || |
Wayne Roberts |
0:6b3ac9c5a042 | 2804 | last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP) |
Wayne Roberts |
0:6b3ac9c5a042 | 2805 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2806 | block_t block; |
Wayne Roberts |
0:6b3ac9c5a042 | 2807 | uint32_t fcnt_up; |
Wayne Roberts |
0:6b3ac9c5a042 | 2808 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2809 | fcnt_up = FCntUp; |
Wayne Roberts |
0:6b3ac9c5a042 | 2810 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 2811 | fcnt_up = eeprom_read(EEPROM_FCNTUP); |
Wayne Roberts |
0:6b3ac9c5a042 | 2812 | #endif /* LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2813 | Radio::radio.tx_buf[6] = fcnt_up & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 2814 | Radio::radio.tx_buf[7] = ( fcnt_up >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 2815 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2816 | block.b.header = 0x49; |
Wayne Roberts |
0:6b3ac9c5a042 | 2817 | block.b.confFCnt = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2818 | block.b.dr = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2819 | block.b.ch = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2820 | block.b.dir = UP_LINK; |
Wayne Roberts |
0:6b3ac9c5a042 | 2821 | block.b.DevAddr = LoRaMacDevAddr; |
Wayne Roberts |
0:6b3ac9c5a042 | 2822 | block.b.FCnt = fcnt_up; |
Wayne Roberts |
0:6b3ac9c5a042 | 2823 | block.b.zero8 = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2824 | block.b.lenMsg = tx_len; |
Wayne Roberts |
0:6b3ac9c5a042 | 2825 | if (flags.OptNeg) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2826 | uint16_t cmacF, cmacS; |
Wayne Roberts |
0:6b3ac9c5a042 | 2827 | cmacF = LoRaMacComputeMic(&block, Radio::radio.tx_buf, keys.FNwkSIntKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 2828 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2829 | block.b.confFCnt = ConfFCntDown; |
Wayne Roberts |
0:6b3ac9c5a042 | 2830 | block.b.dr = LoRaMacParams.ChannelsDatarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 2831 | block.b.ch = ch_num; |
Wayne Roberts |
0:6b3ac9c5a042 | 2832 | cmacS = LoRaMacComputeMic(&block, Radio::radio.tx_buf, keys.SNwkSIntKey) & 0xffff; |
Wayne Roberts |
0:6b3ac9c5a042 | 2833 | mic = cmacS | (cmacF << 16); |
Wayne Roberts |
0:6b3ac9c5a042 | 2834 | ConfFCntDown = 0; /* single use */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2835 | } else |
Wayne Roberts |
0:6b3ac9c5a042 | 2836 | mic = LoRaMacComputeMic(&block, Radio::radio.tx_buf, keys.FNwkSIntKey); |
Wayne Roberts |
0:6b3ac9c5a042 | 2837 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2838 | Radio::radio.tx_buf[tx_buf_len + 0] = mic & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 2839 | Radio::radio.tx_buf[tx_buf_len + 1] = ( mic >> 8 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 2840 | Radio::radio.tx_buf[tx_buf_len + 2] = ( mic >> 16 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 2841 | Radio::radio.tx_buf[tx_buf_len + 3] = ( mic >> 24 ) & 0xFF; |
Wayne Roberts |
0:6b3ac9c5a042 | 2842 | tx_len += LORAMAC_MFR_LEN; |
Wayne Roberts |
0:6b3ac9c5a042 | 2843 | MAC_PRINTF("FCntUp%u ", fcnt_up); |
Wayne Roberts |
0:6b3ac9c5a042 | 2844 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2845 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2846 | McpsConfirm.UpLinkCounter = FCntUp; |
Wayne Roberts |
0:6b3ac9c5a042 | 2847 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 2848 | McpsConfirm.UpLinkCounter = eeprom_read(EEPROM_FCNTUP); |
Wayne Roberts |
0:6b3ac9c5a042 | 2849 | #endif /* !LORAWAN_JOIN_EUI */ |
Wayne Roberts |
0:6b3ac9c5a042 | 2850 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2851 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2852 | txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2853 | txPower = TxPowers[txPowerIndex]; |
Wayne Roberts |
0:6b3ac9c5a042 | 2854 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2855 | if (MlmeConfirm.MlmeRequest != MLME_NONE) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2856 | MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_SENDING; |
Wayne Roberts |
0:6b3ac9c5a042 | 2857 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2858 | if (McpsConfirm.McpsRequest != MCPS_NONE) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2859 | McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_SENDING; |
Wayne Roberts |
0:6b3ac9c5a042 | 2860 | McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate; |
Wayne Roberts |
0:6b3ac9c5a042 | 2861 | McpsConfirm.TxPower = txPowerIndex; |
Wayne Roberts |
0:6b3ac9c5a042 | 2862 | McpsConfirm.UpLinkFreqHz = Channels[ch_num].FreqHz; |
Wayne Roberts |
0:6b3ac9c5a042 | 2863 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2864 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2865 | Radio::SetChannel(Channels[ch_num].FreqHz); |
Wayne Roberts |
0:6b3ac9c5a042 | 2866 | if (MlmeIndication.MlmeIndication != MLME_NONE) |
Wayne Roberts |
0:6b3ac9c5a042 | 2867 | MlmeIndication.freqHz = Channels[ch_num].FreqHz; |
Wayne Roberts |
0:6b3ac9c5a042 | 2868 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2869 | region_tx_setup(txPower, tx_len); |
Wayne Roberts |
0:6b3ac9c5a042 | 2870 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2871 | // Store the time on air |
Wayne Roberts |
0:6b3ac9c5a042 | 2872 | //McpsConfirm.TxTimeOnAir = TxTimeOnAir_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 2873 | //MlmeConfirm.TxTimeOnAir = TxTimeOnAir_us; |
Wayne Roberts |
0:6b3ac9c5a042 | 2874 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2875 | // Send now |
Wayne Roberts |
0:6b3ac9c5a042 | 2876 | Radio::Send(tx_len); |
Wayne Roberts |
0:6b3ac9c5a042 | 2877 | MAC_PRINTF(" sfoc %u, %" PRIu32"hz\r\n", tx_len, Channels[ch_num].FreqHz); |
Wayne Roberts |
0:6b3ac9c5a042 | 2878 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2879 | if (last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_UNCONFIRMED_UP) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2880 | #ifdef LORAWAN_JOIN_EUI |
Wayne Roberts |
0:6b3ac9c5a042 | 2881 | FCntUp++; |
Wayne Roberts |
0:6b3ac9c5a042 | 2882 | #else |
Wayne Roberts |
0:6b3ac9c5a042 | 2883 | if (eeprom_increment_value(EEPROM_FCNTUP) < 0) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2884 | mcps_confirm(LORAMAC_EVENT_INFO_STATUS_INCR_FAIL); // SendFrame fail |
Wayne Roberts |
0:6b3ac9c5a042 | 2885 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2886 | #endif |
Wayne Roberts |
0:6b3ac9c5a042 | 2887 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2888 | } // ..SendFrameOnChannel() |
Wayne Roberts |
0:6b3ac9c5a042 | 2889 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2890 | uint8_t CountBits( uint16_t mask, uint8_t nbBits ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2891 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2892 | uint8_t nbActiveBits = 0; |
Wayne Roberts |
0:6b3ac9c5a042 | 2893 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2894 | for( uint8_t j = 0; j < nbBits; j++ ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2895 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2896 | if( ( mask & ( 1 << j ) ) == ( 1 << j ) ) |
Wayne Roberts |
0:6b3ac9c5a042 | 2897 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2898 | nbActiveBits++; |
Wayne Roberts |
0:6b3ac9c5a042 | 2899 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2900 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2901 | return nbActiveBits; |
Wayne Roberts |
0:6b3ac9c5a042 | 2902 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2903 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2904 | void LoRaMacPrintStatus() |
Wayne Roberts |
0:6b3ac9c5a042 | 2905 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2906 | MAC_PRINTF("uplink_in_progress:%u, ConfFCntUp%u\r\n", flags.uplink_in_progress, ConfFCntUp); |
Wayne Roberts |
0:6b3ac9c5a042 | 2907 | MAC_PRINTF("function_pending:%p\r\n", function_pending); |
Wayne Roberts |
0:6b3ac9c5a042 | 2908 | MAC_PRINTF("rx delays:%u, %u, %u, %u\r\n", |
Wayne Roberts |
0:6b3ac9c5a042 | 2909 | RxWindow1Delay_us, |
Wayne Roberts |
0:6b3ac9c5a042 | 2910 | LoRaMacParams.ReceiveDelay1_us, |
Wayne Roberts |
0:6b3ac9c5a042 | 2911 | RxWindow2Delay_us, |
Wayne Roberts |
0:6b3ac9c5a042 | 2912 | LoRaMacParams.ReceiveDelay2_us |
Wayne Roberts |
0:6b3ac9c5a042 | 2913 | ); |
Wayne Roberts |
0:6b3ac9c5a042 | 2914 | if (flags.uplink_in_progress) { |
Wayne Roberts |
0:6b3ac9c5a042 | 2915 | MAC_PRINTF("since txDone:%u\r\n", Radio::lpt.read_us() - tx_done_at); |
Wayne Roberts |
0:6b3ac9c5a042 | 2916 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2917 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2918 | Radio::PrintStatus(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2919 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2920 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2921 | us_timestamp_t LoRaMacReadTimer() |
Wayne Roberts |
0:6b3ac9c5a042 | 2922 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2923 | return Radio::lpt.read_us(); |
Wayne Roberts |
0:6b3ac9c5a042 | 2924 | } |
Wayne Roberts |
0:6b3ac9c5a042 | 2925 | |
Wayne Roberts |
0:6b3ac9c5a042 | 2926 | int8_t |
Wayne Roberts |
0:6b3ac9c5a042 | 2927 | LoRaMacGetRxSlot() |
Wayne Roberts |
0:6b3ac9c5a042 | 2928 | { |
Wayne Roberts |
0:6b3ac9c5a042 | 2929 | return McpsIndication.RxSlot; |
Wayne Roberts |
0:6b3ac9c5a042 | 2930 | } |