wayne roberts / lorawan1v1

Dependencies:   sx12xx_hal

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

Committer:
Wayne Roberts
Date:
Thu Mar 29 14:40:59 2018 -0700
Revision:
5:4e9d41359897
Parent:
4:e4bfe9183f94
Child:
7:4b6f960dcca2
report stalled timer failure codes

Who changed what in which revision?

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