wayne roberts / lorawan1v1

Dependencies:   sx12xx_hal

Dependents:   LoRaWAN-SanJose_Bootcamp LoRaWAN-grove-cayenne LoRaWAN-classC-demo LoRaWAN-grove-cayenne ... more

Committer:
Wayne Roberts
Date:
Fri May 04 11:00:06 2018 -0700
Revision:
7:4b6f960dcca2
Parent:
5:4e9d41359897
Child:
8:5a5ea7cc946f
Add class-C support, and LBT

Who changed what in which revision?

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