wayne roberts / lorawan1v1

Dependencies:   sx12xx_hal

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

Committer:
Wayne Roberts
Date:
Mon Mar 19 14:39:06 2018 -0700
Revision:
4:e4bfe9183f94
Parent:
3:eb174e10afbb
Child:
5:4e9d41359897
move mutex locks from ISR to user context

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