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