April_12th_San_Jose_LoRa_Bootcamp
Fork of LoRaWAN-grove-cayenne by
sensorDemoVT100.cpp
00001 /* 00002 / _____) _ | | 00003 ( (____ _____ ____ _| |_ _____ ____| |__ 00004 \____ \| ___ | (_ _) ___ |/ ___) _ \ 00005 _____) ) ____| | | || |_| ____( (___| | | | 00006 (______/|_____)_|_|_| \__)_____)\____)_| |_| 00007 (C)2018 Semtech 00008 00009 Description: LoRaMac classB device implementation 00010 00011 License: Revised BSD License, see LICENSE.TXT file include in the project 00012 00013 */ 00014 00015 #include "LoRaMac1v1.h" 00016 #include "SerialDisplay.h" 00017 #include "LoRaMacString.h" 00018 #ifdef ENABLE_VT100 00019 00020 /*! 00021 * Defines the application data transmission duty cycle. 5s, value in [ms]. 00022 */ 00023 #define APP_TX_DUTYCYCLE_us 8000000 00024 00025 /*! 00026 * Defines a random delay for application data transmission duty cycle. 1s, 00027 * value in [ms]. 00028 */ 00029 #define APP_TX_DUTYCYCLE_RND_us 2000000 00030 00031 /*! 00032 * Default datarate 00033 */ 00034 00035 #if defined( USE_BAND_ARIB_8CH ) 00036 #define LORAWAN_DEFAULT_DATARATE DR_3 00037 #else 00038 #define LORAWAN_DEFAULT_DATARATE DR_0 00039 #endif 00040 00041 /*! 00042 * LoRaWAN confirmed messages 00043 */ 00044 #define LORAWAN_CONFIRMED_MSG_ON false 00045 00046 /*! 00047 * LoRaWAN Adaptive Data Rate 00048 * 00049 * \remark Please note that when ADR is enabled the end-device should be static 00050 */ 00051 #define LORAWAN_ADR_ON 1 00052 00053 #if defined( USE_BAND_868 ) 00054 00055 /*! 00056 * LoRaWAN ETSI duty cycle control enable/disable 00057 * 00058 * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes 00059 */ 00060 #define LORAWAN_DUTYCYCLE_ON false 00061 00062 #define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP 1 00063 00064 #if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) 00065 00066 #define LC4 { 867100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 00067 #define LC5 { 867300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 00068 #define LC6 { 867500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 00069 #define LC7 { 867700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 00070 #define LC8 { 867900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 00071 #define LC9 { 868800000, { ( ( DR_7 << 4 ) | DR_7 ) }, 2 } 00072 #define LC10 { 868300000, { ( ( DR_6 << 4 ) | DR_6 ) }, 1 } 00073 00074 #endif 00075 00076 #endif 00077 00078 /*! 00079 * LoRaWAN application port 00080 */ 00081 #define LORAWAN_APP_PORT 2 00082 00083 /*! 00084 * User application data buffer size 00085 */ 00086 #define LORAWAN_APP_DATA_SIZE 3 00087 00088 00089 #ifdef LORAWAN_JOIN_EUI 00090 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI; 00091 static const uint8_t JoinEui[] = LORAWAN_JOIN_EUI; 00092 static const uint8_t NwkKey[] = LORAWAN_ROOT_NWKKEY; 00093 #ifdef LORAWAN_ROOT_APPKEY 00094 static const uint8_t AppKey[] = LORAWAN_ROOT_APPKEY; 00095 #endif 00096 #else 00097 static const uint8_t FNwkSIntKey[] = LORAWAN_FNwkSIntKey; 00098 static const uint8_t AppSKey[] = LORAWAN_APPSKEY; 00099 static const uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS; 00100 #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey) 00101 static const uint8_t SNwkSIntKey[] = LORAWAN_SNwkSIntKey; 00102 static const uint8_t NwkSEncKey[] = LORAWAN_NwkSEncKey; 00103 #endif 00104 #endif 00105 00106 /*! 00107 * Application port 00108 */ 00109 static uint8_t AppPort = LORAWAN_APP_PORT; 00110 00111 /*! 00112 * User application data size 00113 */ 00114 static uint8_t gAppDataSize = LORAWAN_APP_DATA_SIZE; 00115 00116 /*! 00117 * User application data buffer size 00118 */ 00119 #define LORAWAN_APP_DATA_MAX_SIZE 64 00120 00121 /*! 00122 * User application data 00123 */ 00124 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; 00125 00126 /*! 00127 * Indicates if the node is sending confirmed or unconfirmed messages 00128 */ 00129 static uint8_t gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; 00130 00131 /*! 00132 * Timer to handle the application data transmission duty cycle 00133 * 00134 */ 00135 LowPowerTimeout tx_timeout; 00136 00137 /*! 00138 * Indicates if a new packet can be sent 00139 */ 00140 static volatile struct { 00141 uint8_t gmi : 1; 00142 uint8_t gmc : 1; 00143 } flags; 00144 00145 /*! 00146 * Device states 00147 */ 00148 volatile enum eDevicState 00149 { 00150 /* 0 */ DEVICE_STATE_INIT = 0, 00151 /* 1 */ DEVICE_STATE_SEND, 00152 /* 2 */ DEVICE_STATE_TRIGGER, 00153 /* 3 */ DEVICE_STATE_SLEEP, 00154 #ifdef LORAWAN_JOIN_EUI 00155 /* 4 */ DEVICE_STATE_JOIN, 00156 /* 5 */ DEVICE_STATE_JOIN_OK 00157 #endif /* LORAWAN_JOIN_EUI */ 00158 } DeviceState, WakeUpState; 00159 00160 #if defined(TARGET_MOTE_L152RC) && !defined(TARGET_FF_ARDUINO) 00161 #define TARGET_FF_ARDUINO 00162 #endif 00163 00164 #if defined(TARGET_FF_ARDUINO) 00165 InterruptIn d8(D8); 00166 DigitalOut extLed(D15); 00167 #endif /* TARGET_FF_ARDUINO */ 00168 00169 #if defined(TARGET_FF_MORPHO) && !defined(TARGET_DISCO_L072CZ_LRWAN1) 00170 #define JUMPER_ENABLE 00171 #endif /* */ 00172 00173 #ifdef JUMPER_ENABLE 00174 #define TX_INTERVAL_US 15000000 00175 DigitalOut jumper_out(PC_10); 00176 InterruptIn jumper_in(PC_12); 00177 #endif /* JUMPER_ENABLE */ 00178 00179 uint8_t c_ch; 00180 us_timestamp_t buttonStartAt; 00181 #ifdef TARGET_DISCO_L072CZ_LRWAN1 00182 PwmOut pwm(PA_0); 00183 #elif defined(TARGET_FF_ARDUINO) 00184 PwmOut pwm(PB_11); 00185 #endif /* TARGET_DISCO_L072CZ_LRWAN1 */ 00186 volatile int cayenne_ack_ch; 00187 00188 /*! 00189 * LoRaWAN compliance tests support data 00190 */ 00191 struct ComplianceTest_s 00192 { 00193 bool Running; 00194 uint8_t State; 00195 bool IsTxConfirmed; 00196 uint8_t AppPort; 00197 uint8_t AppDataSize; 00198 uint8_t *AppDataBuffer; 00199 uint16_t DownLinkCounter; 00200 bool LinkCheck; 00201 uint8_t DemodMargin; 00202 uint8_t NbGateways; 00203 }ComplianceTest; 00204 00205 McpsIndication_t gmi; 00206 00207 McpsConfirm_t gmc; 00208 00209 #ifdef JUMPER_ENABLE 00210 void autoUplink() 00211 { 00212 if (jumper_in.read() == 1) { 00213 tx_timeout.attach_us(autoUplink, TX_INTERVAL_US); 00214 } 00215 00216 c_ch = 0xff; 00217 DeviceState = DEVICE_STATE_SEND; 00218 } 00219 00220 void jumper_callback() 00221 { 00222 tx_timeout.attach_us(autoUplink, TX_INTERVAL_US); 00223 } 00224 #endif /* JUMPER_ENABLE */ 00225 00226 static void 00227 clearIndications() 00228 { 00229 vt.SetCursorPos(ROW_MCPS_CONF, 1); 00230 vt.printf("\e[K"); 00231 vt.SetCursorPos(ROW_MCPS_IND, 1); 00232 vt.printf("\e[K"); 00233 vt.SetCursorPos(ROW_MLME_IND, 1); 00234 vt.printf("\e[K"); 00235 vt.SetCursorPos(ROW_MLME_CONF, 1); 00236 vt.printf("\e[K"); 00237 00238 vt.SetCursorPos(ROW_MIC+3, 1); 00239 vt.printf("\e[K"); 00240 } 00241 00242 #define LPP_DIGITAL_INPUT 0 // 1 byte 00243 #define LPP_DIGITAL_OUTPUT 1 // 1 byte 00244 #define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed 00245 #define LPP_ANALOG_OUTPUT 3 // 2 bytes, 0.01 signed 00246 #define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned 00247 #define LPP_PRESENCE 102 // 1 byte, 1 00248 #define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed 00249 #define LPP_RELATIVE_HUMIDITY 104 // 1 byte, 0.5% unsigned 00250 #define LPP_ACCELEROMETER 113 // 2 bytes per axis, 0.001G 00251 #define LPP_BAROMETRIC_PRESSURE 115 // 2 bytes 0.1 hPa Unsigned 00252 #define LPP_GYROMETER 134 // 2 bytes per axis, 0.01 °/s 00253 #define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01m 00254 00255 00256 // Data ID + Data Type + Data Size 00257 #define LPP_DIGITAL_INPUT_SIZE 3 00258 #define LPP_DIGITAL_OUTPUT_SIZE 3 00259 #define LPP_ANALOG_INPUT_SIZE 4 00260 #define LPP_ANALOG_OUTPUT_SIZE 4 00261 #define LPP_LUMINOSITY_SIZE 4 00262 #define LPP_PRESENCE_SIZE 3 00263 #define LPP_TEMPERATURE_SIZE 4 00264 #define LPP_RELATIVE_HUMIDITY_SIZE 3 00265 #define LPP_ACCELEROMETER_SIZE 8 00266 #define LPP_BAROMETRIC_PRESSURE_SIZE 4 00267 #define LPP_GYROMETER_SIZE 8 00268 #define LPP_GPS_SIZE 11 00269 00270 #define CAYENNE_CH_DOUT 2 00271 #define CAYENNE_CH_AOUT 3 00272 #define CAYENNE_CH_TEMP 0 00273 #define CAYENNE_CH_POT 1 00274 #define CAYENNE_CH_DIN 4 00275 00276 AnalogIn a1(A1); 00277 AnalogIn a3(A3); 00278 00279 const unsigned R0 = 100000; 00280 const unsigned B = 4275; 00281 volatile bool dout_downlink; 00282 00283 /*! 00284 * \brief Prepares the payload of the frame 00285 */ 00286 static void PrepareTxFrame( uint8_t port ) 00287 { 00288 uint16_t u16, rot; 00289 float t, f, R; 00290 static uint8_t seq; 00291 00292 if (c_ch != 0xff) { 00293 gAppDataSize = 0; 00294 AppData[gAppDataSize++] = c_ch; 00295 switch (c_ch) { 00296 case CAYENNE_CH_TEMP: 00297 AppData[gAppDataSize++] = LPP_TEMPERATURE; 00298 u16 = a3.read_u16() >> 4; 00299 R = 4096.0 / u16 - 1.0; 00300 R = R0 * R; 00301 t = 1.0/(log(R/R0)/B+1/298.15)-273.15; 00302 u16 = t * 10; // 0.1C per bit 00303 AppData[gAppDataSize++] = u16 >> 8; 00304 AppData[gAppDataSize++] = u16; 00305 break; 00306 case CAYENNE_CH_POT: 00307 AppData[gAppDataSize++] = LPP_ANALOG_INPUT; 00308 u16 = a1.read_u16(); // pot (rotary angle) 00309 f = u16 / 198.6; // scale 65535/3.3 to 0.01v per bit 00310 rot = (uint16_t) f; 00311 AppData[gAppDataSize++] = rot >> 8; 00312 AppData[gAppDataSize++] = rot; 00313 break; 00314 case CAYENNE_CH_DOUT: 00315 AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT; 00316 AppData[gAppDataSize++] = extLed.read(); 00317 break; 00318 case CAYENNE_CH_AOUT: 00319 AppData[gAppDataSize++] = LPP_ANALOG_OUTPUT; 00320 u16 = pwm.read() * 100; 00321 AppData[gAppDataSize++] = u16 >> 8; 00322 AppData[gAppDataSize++] = u16; 00323 break; 00324 } 00325 return; 00326 } else if (cayenne_ack_ch != -1) { 00327 switch (cayenne_ack_ch) { 00328 case CAYENNE_CH_DOUT: 00329 AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT; 00330 AppData[gAppDataSize++] = extLed.read(); 00331 break; 00332 case CAYENNE_CH_AOUT: 00333 AppData[gAppDataSize++] = LPP_ANALOG_OUTPUT; 00334 u16 = pwm.read() * 100; 00335 AppData[gAppDataSize++] = u16 >> 8; 00336 AppData[gAppDataSize++] = u16; 00337 break; 00338 } 00339 cayenne_ack_ch = -1; 00340 } 00341 00342 while (d8.read() == 1) { 00343 us_timestamp_t duration = LoRaMacReadTimer() - buttonStartAt; 00344 if (duration > 1000000) { 00345 gAppDataSize = 0; 00346 AppData[gAppDataSize++] = CAYENNE_CH_DOUT; 00347 AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT; 00348 AppData[gAppDataSize++] = extLed.read(); 00349 return; 00350 } 00351 } 00352 00353 switch( port ) { 00354 case LORAWAN_APP_PORT: 00355 gAppDataSize = 0; 00356 AppData[gAppDataSize++] = CAYENNE_CH_TEMP; 00357 AppData[gAppDataSize++] = LPP_TEMPERATURE; 00358 u16 = a3.read_u16() >> 4; 00359 R = 4096.0 / u16 - 1.0; 00360 R = R0 * R; 00361 t = 1.0/(log(R/R0)/B+1/298.15)-273.15; 00362 u16 = t * 10; // 0.1C per bit 00363 AppData[gAppDataSize++] = u16 >> 8; 00364 AppData[gAppDataSize++] = u16; 00365 AppData[gAppDataSize++] = CAYENNE_CH_POT; 00366 AppData[gAppDataSize++] = LPP_ANALOG_INPUT; 00367 u16 = a1.read_u16(); // pot (rotary angle) 00368 f = u16 / 198.6; // scale 65535/3.3 to 0.01v per bit 00369 rot = (uint16_t) f; 00370 AppData[gAppDataSize++] = rot >> 8; 00371 AppData[gAppDataSize++] = rot; 00372 00373 /* limited packet size: either ack downlink, or send sequence number */ 00374 if (dout_downlink) { 00375 AppData[gAppDataSize++] = CAYENNE_CH_DOUT; 00376 AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT; 00377 AppData[gAppDataSize++] = extLed.read(); 00378 dout_downlink = false; 00379 } else { 00380 AppData[gAppDataSize++] = CAYENNE_CH_DIN; 00381 AppData[gAppDataSize++] = LPP_DIGITAL_INPUT; 00382 AppData[gAppDataSize++] = seq++; 00383 } 00384 break; 00385 case 224: 00386 if( ComplianceTest.LinkCheck == true ) { 00387 ComplianceTest.LinkCheck = false; 00388 gAppDataSize = 3; 00389 AppData[0] = 5; 00390 AppData[1] = ComplianceTest.DemodMargin; 00391 AppData[2] = ComplianceTest.NbGateways; 00392 ComplianceTest.State = 1; 00393 } else { 00394 switch( ComplianceTest.State ) { 00395 case 4: 00396 ComplianceTest.State = 1; 00397 break; 00398 case 1: 00399 gAppDataSize = 2; 00400 AppData[0] = ComplianceTest.DownLinkCounter >> 8; 00401 AppData[1] = ComplianceTest.DownLinkCounter; 00402 break; 00403 } 00404 } 00405 break; 00406 default: 00407 break; 00408 } 00409 } 00410 00411 00412 /*! 00413 * \brief Prepares the payload of the frame 00414 * 00415 * \retval [0: frame could be send, 1: error] 00416 */ 00417 static LoRaMacStatus_t SendFrame(bool IsTxConfirmed, uint8_t AppDataSize) 00418 { 00419 LoRaMacStatus_t status; 00420 char str[64]; 00421 McpsReq_t mcpsReq; 00422 LoRaMacTxInfo_t txInfo; 00423 00424 if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK ) 00425 { 00426 // Send empty frame in order to flush MAC commands 00427 mcpsReq.Type = MCPS_UNCONFIRMED; 00428 mcpsReq.Req.fBuffer = NULL; 00429 mcpsReq.Req.fBufferSize = 0; 00430 mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE; 00431 } 00432 else 00433 { 00434 SerialDisplayUpdateFrameType(IsTxConfirmed); 00435 if( IsTxConfirmed == false ) 00436 { 00437 mcpsReq.Type = MCPS_UNCONFIRMED; 00438 mcpsReq.Req.fPort = AppPort; 00439 mcpsReq.Req.fBuffer = AppData; 00440 mcpsReq.Req.fBufferSize = AppDataSize; 00441 mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE; 00442 } 00443 else 00444 { 00445 mcpsReq.Type = MCPS_CONFIRMED; 00446 mcpsReq.Req.fPort = AppPort; 00447 mcpsReq.Req.fBuffer = AppData; 00448 mcpsReq.Req.fBufferSize = AppDataSize; 00449 mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE; 00450 } 00451 } 00452 00453 clearIndications(); 00454 status = LoRaMacMcpsRequest( &mcpsReq ); 00455 if (status == LORAMAC_STATUS_OK) { 00456 SerialDisplayUplink(mcpsReq.Req.fPort, AppData, mcpsReq.Req.fBufferSize); 00457 vt.SetCursorPos( ROW_END, 1 ); 00458 vt.printf("sendFrame() OK %u\e[K", AppDataSize); 00459 } else { 00460 LoRaMacStatus_to_string(status, str); 00461 vt.SetCursorPos( ROW_END, 1 ); 00462 vt.printf("sendFrame() %s rx%d\e[K", str, LoRaMacGetRxSlot()); 00463 } 00464 00465 return status; 00466 } // ..SendFrame() 00467 00468 /*! 00469 * \brief MCPS-Confirm event function 00470 * 00471 * \param [IN] mcpsConfirm - Pointer to the confirm structure, 00472 * containing confirm attributes. 00473 */ 00474 static void McpsConfirm( const McpsConfirm_t *mcpsConfirm ) 00475 { 00476 char str[64]; 00477 00478 vt.SetCursorPos( ROW_MCPS_CONF, 1); 00479 vt.printf("McpsConfirm up:%uhz ", mcpsConfirm->UpLinkFreqHz); 00480 LoRaMacEventInfoStatus_to_string(mcpsConfirm->Status, str); 00481 if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) 00482 vt.printf("%s \e[K", str); 00483 else 00484 vt.printf("\e[31m%s\e[0m \e[K", str); 00485 00486 if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) 00487 { 00488 switch( mcpsConfirm->McpsRequest ) 00489 { 00490 case MCPS_UNCONFIRMED: 00491 { 00492 // Check Datarate 00493 // Check TxPower 00494 break; 00495 } 00496 case MCPS_CONFIRMED: 00497 { 00498 // Check Datarate 00499 // Check TxPower 00500 // Check AckReceived 00501 // Check NbTrials 00502 //LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived; 00503 break; 00504 } 00505 case MCPS_PROPRIETARY: 00506 { 00507 break; 00508 } 00509 default: 00510 break; 00511 } 00512 } else { 00513 /* fail */ 00514 } 00515 memcpy(&gmc, mcpsConfirm, sizeof(McpsConfirm_t)); 00516 flags.gmc = true; 00517 00518 DeviceState = DEVICE_STATE_TRIGGER; 00519 } // ..McpsConfirm() 00520 00521 00522 /*! 00523 * \brief MCPS-Indication event function 00524 * 00525 * \param [IN] mcpsIndication - Pointer to the indication structure, 00526 * containing indication attributes. 00527 */ 00528 static void McpsIndication( const McpsIndication_t *mcpsIndication ) 00529 { 00530 char str[64]; 00531 00532 memcpy(&gmi, mcpsIndication, sizeof(McpsIndication_t)); 00533 flags.gmi = true; 00534 00535 vt.SetCursorPos(ROW_MCPS_CONF, 1); 00536 vt.printf("\e[K"); // clear stale mcpsconf if retrying 00537 00538 vt.SetCursorPos( ROW_MCPS_IND, 0); 00539 vt.printf("McpsIndication rx%d ADR_ACK_CNT:%u ", mcpsIndication->RxSlot, mcpsIndication->ADR_ACK_CNT); 00540 if (mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK) 00541 { 00542 LoRaMacEventInfoStatus_to_string(mcpsIndication->Status, str); 00543 vt.printf("\e[31m%s\e[0m\e[K", str); 00544 return; 00545 } 00546 vt.printf("OK\e[K"); 00547 00548 switch( mcpsIndication->McpsIndication ) 00549 { 00550 case MCPS_UNCONFIRMED: 00551 { 00552 break; 00553 } 00554 case MCPS_CONFIRMED: 00555 { 00556 /* ack sent by mac layer */ 00557 break; 00558 } 00559 case MCPS_PROPRIETARY: 00560 { 00561 break; 00562 } 00563 case MCPS_MULTICAST: 00564 { 00565 break; 00566 } 00567 default: 00568 break; 00569 } 00570 00571 // Check Multicast 00572 // Check Port 00573 // Check Datarate 00574 // Check FramePending 00575 // Check Buffer 00576 // Check BufferSize 00577 // Check Rssi 00578 // Check Snr 00579 // Check RxSlot 00580 00581 00582 if( ComplianceTest.Running == true ) 00583 { 00584 ComplianceTest.DownLinkCounter++; 00585 } 00586 00587 if( mcpsIndication->RxData == true ) 00588 { 00589 unsigned n; 00590 for (n = 0; n < mcpsIndication->BufferSize; n += 4) { 00591 uint16_t val = mcpsIndication->Buffer[n+1] << 8; 00592 val += mcpsIndication->Buffer[n+2]; 00593 cayenne_ack_ch = mcpsIndication->Buffer[n]; 00594 switch (mcpsIndication->Buffer[n]) { 00595 case CAYENNE_CH_DOUT: 00596 extLed.write(val); 00597 dout_downlink = true; 00598 break; 00599 case CAYENNE_CH_AOUT: 00600 pwm.write(val / 100.0); 00601 break; 00602 default: 00603 break; 00604 } 00605 } 00606 00607 switch( mcpsIndication->Port ) 00608 { 00609 case 1: // The application LED can be controlled on port 1 or 2 00610 case 2: 00611 break; 00612 case 224: 00613 if( ComplianceTest.Running == false ) 00614 { 00615 // Check compliance test enable command (i) 00616 if( ( mcpsIndication->BufferSize == 4 ) && 00617 ( mcpsIndication->Buffer[0] == 0x01 ) && 00618 ( mcpsIndication->Buffer[1] == 0x01 ) && 00619 ( mcpsIndication->Buffer[2] == 0x01 ) && 00620 ( mcpsIndication->Buffer[3] == 0x01 ) ) 00621 { 00622 gIsTxConfirmed = false; 00623 AppPort = 224; 00624 gAppDataSize = 2; 00625 ComplianceTest.DownLinkCounter = 0; 00626 ComplianceTest.LinkCheck = false; 00627 ComplianceTest.DemodMargin = 0; 00628 ComplianceTest.NbGateways = 0; 00629 ComplianceTest.Running = true; 00630 ComplianceTest.State = 1; 00631 00632 MibRequestConfirm_t mibReq; 00633 mibReq.Type = MIB_ADR; 00634 mibReq.Param.AdrEnable = true; 00635 LoRaMacMibSetRequestConfirm( &mibReq ); 00636 00637 #if defined( USE_BAND_868 ) 00638 DutyCycleOn = false; 00639 #endif 00640 } 00641 } 00642 else 00643 { 00644 ComplianceTest.State = mcpsIndication->Buffer[0]; 00645 switch( ComplianceTest.State ) 00646 { 00647 case 0: // Check compliance test disable command (ii) 00648 gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; 00649 AppPort = LORAWAN_APP_PORT; 00650 gAppDataSize = LORAWAN_APP_DATA_SIZE; 00651 ComplianceTest.DownLinkCounter = 0; 00652 ComplianceTest.Running = false; 00653 00654 MibRequestConfirm_t mibReq; 00655 mibReq.Type = MIB_ADR; 00656 mibReq.Param.AdrEnable = LORAWAN_ADR_ON; 00657 LoRaMacMibSetRequestConfirm( &mibReq ); 00658 #if defined( USE_BAND_868 ) 00659 DutyCycleOn = LORAWAN_DUTYCYCLE_ON; 00660 #endif 00661 break; 00662 case 1: // (iii, iv) 00663 gAppDataSize = 2; 00664 break; 00665 case 2: // Enable confirmed messages (v) 00666 gIsTxConfirmed = true; 00667 ComplianceTest.State = 1; 00668 break; 00669 case 3: // Disable confirmed messages (vi) 00670 gIsTxConfirmed = false; 00671 ComplianceTest.State = 1; 00672 break; 00673 case 4: // (vii) 00674 gAppDataSize = mcpsIndication->BufferSize; 00675 00676 AppData[0] = 4; 00677 for( uint8_t i = 1; i < gAppDataSize; i++ ) 00678 { 00679 AppData[i] = mcpsIndication->Buffer[i] + 1; 00680 } 00681 break; 00682 case 5: // (viii) 00683 { 00684 MlmeReq_t mlmeReq; 00685 mlmeReq.Type = MLME_LINK_CHECK; 00686 LoRaMacMlmeRequest( &mlmeReq ); 00687 } 00688 break; 00689 case 6: // (ix) 00690 { 00691 #ifdef LORAWAN_JOIN_EUI 00692 MlmeReq_t mlmeReq = {}; 00693 00694 // Disable TestMode and revert back to normal operation 00695 gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; 00696 AppPort = LORAWAN_APP_PORT; 00697 gAppDataSize = LORAWAN_APP_DATA_SIZE; 00698 ComplianceTest.DownLinkCounter = 0; 00699 ComplianceTest.Running = false; 00700 00701 MibRequestConfirm_t mibReq; 00702 mibReq.Type = MIB_ADR; 00703 mibReq.Param.AdrEnable = LORAWAN_ADR_ON; 00704 LoRaMacMibSetRequestConfirm( &mibReq ); 00705 #if defined( USE_BAND_868 ) 00706 DutyCycleOn = LORAWAN_DUTYCYCLE_ON; 00707 #endif 00708 00709 mlmeReq.Type = MLME_JOIN; 00710 00711 mlmeReq.Req.Join.DevEui = DevEui; 00712 mlmeReq.Req.Join.JoinEui = JoinEui; 00713 mlmeReq.Req.Join.NwkKey = NwkKey; 00714 #ifdef LORAWAN_ROOT_APPKEY 00715 mlmeReq.Req.Join.AppKey = AppKey; 00716 #endif /* LORAWAN_ROOT_APPKEY */ 00717 00718 LoRaMacMlmeRequest( &mlmeReq ); 00719 #endif /* LORAWAN_JOIN_EUI */ 00720 DeviceState = DEVICE_STATE_SLEEP; 00721 } 00722 break; 00723 case 7: // Switch end device Class 00724 { 00725 MlmeReq_t mlmeReq; 00726 00727 mlmeReq.Type = MLME_SWITCH_CLASS; 00728 00729 // CLASS_A = 0, CLASS_B = 1, CLASS_C = 2 00730 mlmeReq.Req.SwitchClass.Class = ( DeviceClass_t )mcpsIndication->Buffer[1]; 00731 00732 LoRaMacMlmeRequest( &mlmeReq ); 00733 00734 PrepareTxFrame( AppPort ); 00735 /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize); 00736 } 00737 break; 00738 case 8: // Send PingSlotInfoReq 00739 { 00740 MlmeReq_t mlmeReq; 00741 00742 mlmeReq.Type = MLME_PING_SLOT_INFO; 00743 00744 mlmeReq.Req.PingSlotInfo.Value = mcpsIndication->Buffer[1]; 00745 00746 LoRaMacMlmeRequest( &mlmeReq ); 00747 PrepareTxFrame( AppPort ); 00748 /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize); 00749 } 00750 break; 00751 case 9: // Send BeaconTimingReq 00752 { 00753 MlmeReq_t mlmeReq; 00754 00755 mlmeReq.Type = MLME_BEACON_TIMING; 00756 00757 LoRaMacMlmeRequest( &mlmeReq ); 00758 PrepareTxFrame( AppPort ); 00759 /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize); 00760 } 00761 break; 00762 default: 00763 break; 00764 } 00765 } 00766 break; 00767 default: 00768 break; 00769 } 00770 00771 } 00772 00773 } // ..McpsIndication() 00774 00775 #ifdef LORAWAN_JOIN_EUI 00776 void 00777 join(uint8_t tries) 00778 { 00779 char str[64]; 00780 LoRaMacStatus_t status; 00781 MlmeReq_t mlmeReq = { }; 00782 00783 mlmeReq.Type = MLME_JOIN; 00784 00785 clearIndications(); 00786 #ifdef LORAWAN_ROOT_APPKEY 00787 mlmeReq.Req.Join.AppKey = AppKey; 00788 #endif 00789 mlmeReq.Req.Join.DevEui = DevEui; 00790 mlmeReq.Req.Join.JoinEui = JoinEui; 00791 mlmeReq.Req.Join.NwkKey = NwkKey; 00792 mlmeReq.Req.Join.NbTrials = tries; 00793 status = LoRaMacMlmeRequest( &mlmeReq ); 00794 if (status != LORAMAC_STATUS_OK) { 00795 LoRaMacStatus_to_string(status, str); 00796 } else 00797 extLed = 1; 00798 } 00799 #endif /* LORAWAN_JOIN_EUI */ 00800 00801 /*! 00802 * \brief MLME-Confirm event function 00803 * 00804 * \param [IN] mlmeConfirm - Pointer to the confirm structure, 00805 * containing confirm attributes. 00806 */ 00807 static void MlmeConfirm( const MlmeConfirm_t *mlmeConfirm ) 00808 { 00809 char str[64]; 00810 static uint8_t failCnt = 0; 00811 00812 vt.SetCursorPos(ROW_MLME_CONF, 1); 00813 Mlme_to_string(mlmeConfirm->MlmeRequest, str); 00814 vt.printf("MlmeConfirm %s ", str); 00815 LoRaMacEventInfoStatus_to_string(mlmeConfirm->Status, str); 00816 if (mlmeConfirm->Status != LORAMAC_EVENT_INFO_STATUS_OK) 00817 vt.printf("\e[31m%s \e[0m \e[K", str); 00818 else 00819 vt.printf("%s \e[K", str); 00820 00821 #if defined(LORAWAN_ROOT_APPKEY) && defined(LORAWAN_JOIN_EUI) 00822 /* 1v1 joinNonce is incrementing non-volatile value */ 00823 if (mlmeConfirm->MlmeRequest == MLME_JOIN) { 00824 vt.printf(" rxJoinNonce:%u vs %u", 00825 mlmeConfirm->fields.join.rxJoinNonce, 00826 mlmeConfirm->fields.join.myJoinNonce 00827 ); 00828 } 00829 #endif /* LORAWAN_ROOT_APPKEY */ 00830 00831 if (mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) 00832 { 00833 failCnt = 0; 00834 switch (mlmeConfirm->MlmeRequest) 00835 { 00836 #ifdef LORAWAN_JOIN_EUI 00837 case MLME_JOIN: 00838 { 00839 // Status is OK, node has joined the network 00840 /* collect any mac cmds from server until expected channel mask */ 00841 extLed = 0; 00842 DeviceState = DEVICE_STATE_JOIN_OK; 00843 break; 00844 } 00845 #endif /* LORAWAN_JOIN_EUI*/ 00846 case MLME_LINK_CHECK: 00847 { 00848 // Check DemodMargin 00849 // Check NbGateways 00850 if( ComplianceTest.Running == true ) 00851 { 00852 ComplianceTest.LinkCheck = true; 00853 ComplianceTest.DemodMargin = mlmeConfirm->fields.link.DemodMargin; 00854 ComplianceTest.NbGateways = mlmeConfirm->fields.link.NbGateways; 00855 } 00856 break; 00857 } 00858 case MLME_TIME_REQ: 00859 break; 00860 default: 00861 /* TODO: handle unknown MLME request */ 00862 DeviceState = DEVICE_STATE_SLEEP; 00863 break; 00864 } 00865 } 00866 else // not ok... 00867 { 00868 failCnt++; 00869 00870 #ifdef LORAWAN_JOIN_EUI 00871 if (failCnt > 5) { 00872 join(1); 00873 return; 00874 } 00875 #endif 00876 00877 switch( mlmeConfirm->MlmeRequest ) 00878 { 00879 #ifdef LORAWAN_JOIN_EUI 00880 case MLME_JOIN: 00881 { 00882 // Join failed, restart join procedure 00883 break; 00884 } 00885 #endif /* LORAWAN_JOIN_EUI */ 00886 case MLME_LINK_CHECK: 00887 DeviceState = DEVICE_STATE_SLEEP; 00888 break; 00889 #ifdef LORAWAN_JOIN_EUI 00890 case MLME_REJOIN_0: 00891 break; 00892 case MLME_REJOIN_2: 00893 break; 00894 case MLME_TIME_REQ: 00895 break; 00896 #endif /* LORAWAN_JOIN_EUI */ 00897 default: 00898 DeviceState = DEVICE_STATE_SLEEP; 00899 break; 00900 } 00901 } 00902 } // ..MlmeConfirm 00903 00904 static void MlmeIndication( const MlmeIndication_t *MlmeIndication ) 00905 { 00906 char str[48]; 00907 MibRequestConfirm_t mibReq; 00908 00909 vt.SetCursorPos(ROW_MLME_IND, 1); 00910 Mlme_to_string(MlmeIndication->MlmeIndication, str); 00911 vt.printf("MlmeIndication %s %08x ", str, RCC->CSR); 00912 LoRaMacEventInfoStatus_to_string(MlmeIndication->Status, str); 00913 if (MlmeIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK) 00914 vt.printf("\e[31m%s \e[0m \e[K", str); 00915 else 00916 vt.printf("%s \e[K", str); 00917 00918 switch( MlmeIndication->MlmeIndication ) 00919 { 00920 case MLME_SWITCH_CLASS: 00921 { 00922 /* mac gave up on beacon */ 00923 mibReq.Type = MIB_DEVICE_CLASS; 00924 mibReq.Param.Class = CLASS_A; 00925 LoRaMacMibSetRequestConfirm( &mibReq ); 00926 00927 // Switch to class A again 00928 DeviceState = DEVICE_STATE_SLEEP; // class-B manual switch 00929 break; 00930 } 00931 case MLME_BEACON: 00932 { 00933 LoRaMacEventInfoStatus_to_string(MlmeIndication->Status, str); 00934 break; 00935 00936 } 00937 #ifdef LORAWAN_JOIN_EUI 00938 case MLME_JOIN: 00939 vt.printf("%uhz try%u", MlmeIndication->freqHz, MlmeIndication->JoinRequestTrials); 00940 break; 00941 #endif /* !LORAWAN_JOIN_EUI */ 00942 default: 00943 break; 00944 } 00945 00946 } // ..MlmeIndication() 00947 00948 uint8_t periodicity; 00949 00950 void SerialDisplayRefresh( void ) 00951 { 00952 #ifdef LORAWAN_JOIN_EUI 00953 MibRequestConfirm_t mibReq; 00954 #endif 00955 00956 SerialDisplayInit( ); 00957 #ifdef LORAWAN_JOIN_EUI 00958 SerialDisplayUpdateActivationMode(true); 00959 SerialDisplayUpdateEui( ROW_DEVEUI, DevEui); 00960 SerialDisplayUpdateEui( ROW_JOINEUI, JoinEui); 00961 SerialDisplayUpdateKey( ROW_NWKKEY, NwkKey); 00962 00963 #ifdef LORAWAN_ROOT_APPKEY 00964 SerialDisplayUpdateKey(ROW_APPKEY, AppKey); 00965 #endif 00966 00967 mibReq.Type = MIB_NETWORK_JOINED; 00968 LoRaMacMibGetRequestConfirm( &mibReq ); 00969 SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined ); 00970 #else 00971 //SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID ); 00972 SerialDisplayUpdateDevAddr( DevAddr ); 00973 SerialDisplayUpdateKey( ROW_FNwkSIntKey, FNwkSIntKey); 00974 SerialDisplayUpdateKey( ROW_AppSKey, AppSKey ); 00975 #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey) 00976 SerialDisplayUpdateKey(ROW_NwkSEncKey, NwkSEncKey); 00977 SerialDisplayUpdateKey(ROW_SNwkSIntKey, SNwkSIntKey); 00978 #endif /* 1v1 ABP */ 00979 00980 vt.SetCursorPos( ROW_END, 1 ); 00981 vt.printf("FCntUp:%08x", eeprom_read(EEPROM_FCNTUP)); 00982 vt.printf(" AFCntDown:%08x", get_fcntdwn(true)); 00983 vt.printf(" NFCntDown:%08x", get_fcntdwn(false)); 00984 #endif 00985 00986 00987 SerialDisplayUpdateAdr( LORAWAN_ADR_ON ); 00988 #if defined( USE_BAND_868 ) 00989 SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON ); 00990 #else 00991 SerialDisplayUpdateDutyCycle( false ); 00992 #endif 00993 SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK ); 00994 00995 //SerialDisplayUpdateLedState( 3, AppLedStateOn ); 00996 } 00997 00998 void SerialRxProcess( void ) 00999 { 01000 LoRaMacStatus_t status; 01001 MlmeReq_t mlmeReq; 01002 #ifndef LORAWAN_JOIN_EUI 01003 static uint8_t icnt = 0; 01004 #endif 01005 01006 if( SerialDisplayReadable( ) == true ) { 01007 char ch = SerialDisplayGetChar(); 01008 #ifndef LORAWAN_JOIN_EUI 01009 if (ch == 'I') { 01010 if (++icnt == 3) { 01011 vt.SetCursorPos( ROW_END, 1 ); 01012 vt.printf("reset-fcnts\e[K"); 01013 eeprom_clear(EEPROM_AFCNTDWN); 01014 eeprom_clear(EEPROM_NFCNTDWN); 01015 eeprom_clear(EEPROM_FCNTUP); 01016 } 01017 } else 01018 icnt = 0; 01019 #endif /* !LORAWAN_JOIN_EUI */ 01020 01021 if ( ch >= '0' && ch <= '9') { 01022 c_ch = ch - '0'; 01023 DeviceState = DEVICE_STATE_SEND; 01024 return; 01025 } 01026 switch( ch ) { 01027 case 'R': 01028 case 'r': 01029 // Refresh Serial screen 01030 SerialDisplayRefresh( ); 01031 break; 01032 case 'L': 01033 clearIndications(); 01034 mlmeReq.Type = MLME_LINK_CHECK; 01035 status = LoRaMacMlmeRequest( &mlmeReq ); 01036 if (status == LORAMAC_STATUS_OK) 01037 SendFrame(0, false); 01038 break; 01039 #ifdef LORAWAN_JOIN_EUI 01040 case 'j': 01041 DeviceState = DEVICE_STATE_JOIN; 01042 break; 01043 #endif 01044 default: 01045 break; 01046 } 01047 } 01048 } 01049 01050 static void d8isr() 01051 { 01052 c_ch = 0xff; 01053 DeviceState = DEVICE_STATE_SEND; 01054 buttonStartAt = LoRaMacReadTimer(); 01055 } 01056 01057 static const LoRaMacPrimitives_t LoRaMacPrimitives = { 01058 McpsConfirm, 01059 McpsIndication, 01060 MlmeConfirm, 01061 MlmeIndication 01062 }; 01063 01064 static const LoRaMacCallback_t LoRaMacCallbacks = { 01065 BoardGetBatteryLevel, 01066 NULL 01067 }; 01068 01069 /** 01070 * Main application entry point. 01071 */ 01072 int main() 01073 { 01074 LoRaMacStatus_t status; 01075 MibRequestConfirm_t mibReq; 01076 01077 DeviceState = DEVICE_STATE_INIT; 01078 01079 if (sleep_manager_can_deep_sleep()) 01080 sleep_manager_lock_deep_sleep(); // prevent deep sleep 01081 01082 #ifdef JUMPER_ENABLE 01083 jumper_out = 1; 01084 jumper_in.mode(PullDown); 01085 jumper_in.rise(jumper_callback); 01086 // Q: does InterruptIn.rise() call immediately if already high? 01087 if (jumper_in.read()) 01088 jumper_callback(); // A: probably not 01089 #endif /* JUMPER_ENABLE */ 01090 01091 while( 1 ) 01092 { 01093 SerialRxProcess( ); 01094 01095 if (flags.gmi) { 01096 flags.gmi = false; 01097 SerialDisplayMcpsIndication(&gmi); 01098 } 01099 01100 if (flags.gmc) { 01101 flags.gmc = false; 01102 SerialDisplayMcpsConfirm(&gmc); 01103 } 01104 01105 switch( DeviceState ) 01106 { 01107 case DEVICE_STATE_INIT: 01108 { 01109 status = LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks ); 01110 if (LORAMAC_STATUS_OK != status) { 01111 char str[48]; 01112 LoRaMacStatus_to_string(status, str); 01113 vt.SetCursorPos(1, 1); 01114 vt.printf("MacInit: %s\e[K", str); 01115 for (;;) asm("nop"); 01116 } 01117 01118 pwm.period(1.0 / 60); 01119 cayenne_ack_ch = -1; 01120 c_ch = 0xff; 01121 d8.mode(PullDown); 01122 d8.rise(d8isr); 01123 01124 mibReq.Type = MIB_ADR; 01125 mibReq.Param.AdrEnable = LORAWAN_ADR_ON; 01126 LoRaMacMibSetRequestConfirm( &mibReq ); 01127 01128 mibReq.Type = MIB_PUBLIC_NETWORK; 01129 mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK; 01130 LoRaMacMibSetRequestConfirm( &mibReq ); 01131 01132 #if defined( USE_BAND_868 ) 01133 DutyCycleOn = LORAWAN_DUTYCYCLE_ON ; 01134 #if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) 01135 LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 ); 01136 LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 ); 01137 LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 ); 01138 LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 ); 01139 LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 ); 01140 LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 ); 01141 LoRaMacChannelAdd( 9, ( ChannelParams_t )LC10 ); 01142 01143 mibReq.Type = MIB_RX2_CHANNEL; 01144 mibReq.Param.Rx2Channel = ( Rx2ChannelParams_t ){ 869525000, DR_3 }; 01145 LoRaMacMibSetRequestConfirm( &mibReq ); 01146 #endif 01147 01148 #endif 01149 01150 SerialDisplayRefresh(); 01151 #ifdef LORAWAN_JOIN_EUI 01152 01153 #ifndef SENETCO /* for senet, use network provided DevEUI */ 01154 // Initialize LoRaMac device unique ID 01155 //HardwareIDtoDevEUI(DevEui); Comment to assign your Own DevEUI, Uncomment to assign based on device serail number 01156 #ifdef LORAWAN_ROOT_APPKEY 01157 // inverted DevEui provisioned as v1.1 on server (non-inv = lorawan1v0) 01158 for (int i = 0; i < 8; i++) 01159 DevEui[i] ^= 0xff; 01160 #endif /* LORAWAN_ROOT_APPKEY */ 01161 #endif /* !SENETCO */ 01162 SerialDisplayUpdateEui( 5, DevEui ); 01163 DeviceState = DEVICE_STATE_JOIN; 01164 #else /* ABP... */ 01165 01166 mibReq.Type = MIB_DEV_ADDR; 01167 mibReq.Param.DevAddr = DevAddr; 01168 LoRaMacMibSetRequestConfirm( &mibReq ); 01169 SerialDisplayUpdateDevAddr(DevAddr); 01170 01171 mibReq.Type = MIB_APP_SKEY; 01172 mibReq.Param.key = AppSKey; 01173 LoRaMacMibSetRequestConfirm( &mibReq ); 01174 SerialDisplayUpdateKey(ROW_AppSKey, AppSKey); 01175 01176 #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey) 01177 /* lorawan 1v1 ABP */ 01178 mibReq.Type = MIB_NwkSEncKey; 01179 mibReq.Param.key = NwkSEncKey; 01180 LoRaMacMibSetRequestConfirm( &mibReq ); 01181 SerialDisplayUpdateKey(ROW_NwkSEncKey, NwkSEncKey); 01182 01183 mibReq.Type = MIB_SNwkSIntKey; 01184 mibReq.Param.key = SNwkSIntKey; 01185 LoRaMacMibSetRequestConfirm( &mibReq ); 01186 SerialDisplayUpdateKey(ROW_SNwkSIntKey, SNwkSIntKey); 01187 01188 mibReq.Type = MIB_FNwkSIntKey; 01189 mibReq.Param.key = FNwkSIntKey; 01190 LoRaMacMibSetRequestConfirm( &mibReq ); 01191 SerialDisplayUpdateKey(ROW_FNwkSIntKey, mibReq.Param.key); 01192 #else 01193 /* lorawan 1v0 ABP */ 01194 mibReq.Type = MIB_NwkSKey; 01195 mibReq.Param.key = FNwkSIntKey; 01196 LoRaMacMibSetRequestConfirm( &mibReq ); 01197 SerialDisplayUpdateKey(ROW_FNwkSIntKey, mibReq.Param.key); 01198 #endif 01199 01200 DeviceState = DEVICE_STATE_TRIGGER; 01201 #endif /* !LORAWAN_JOIN_EUI */ 01202 break; 01203 } 01204 #ifdef LORAWAN_JOIN_EUI 01205 case DEVICE_STATE_JOIN: 01206 { 01207 join(8); 01208 DeviceState = DEVICE_STATE_SLEEP; 01209 break; 01210 } 01211 case DEVICE_STATE_JOIN_OK: 01212 MibRequestConfirm_t mibReq; 01213 mibReq.Type = MIB_NETWORK_JOINED; 01214 LoRaMacMibGetRequestConfirm( &mibReq ); 01215 SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined ); 01216 mibReq.Type = MIB_DEV_ADDR; 01217 LoRaMacMibGetRequestConfirm( &mibReq ); 01218 SerialDisplayUpdateDevAddr(mibReq.Param.DevAddr); 01219 mibReq.Type = MIB_FNwkSIntKey; 01220 LoRaMacMibGetRequestConfirm( &mibReq ); 01221 SerialDisplayUpdateKey( ROW_FNwkSIntKey, mibReq.Param.key ); 01222 mibReq.Type = MIB_APP_SKEY; 01223 LoRaMacMibGetRequestConfirm( &mibReq ); 01224 SerialDisplayUpdateKey( ROW_AppSKey, mibReq.Param.key ); 01225 01226 #ifdef LORAWAN_ROOT_APPKEY 01227 mibReq.Type = MIB_SNwkSIntKey; 01228 LoRaMacMibGetRequestConfirm( &mibReq ); 01229 SerialDisplayUpdateKey(ROW_SNwkSIntKey, mibReq.Param.key); 01230 mibReq.Type = MIB_NwkSEncKey; 01231 LoRaMacMibGetRequestConfirm( &mibReq ); 01232 SerialDisplayUpdateKey(ROW_NwkSEncKey, mibReq.Param.key); 01233 #endif /* LORAWAN_ROOT_APPKEY */ 01234 DeviceState = DEVICE_STATE_TRIGGER; 01235 break; 01236 #endif /* LORAWAN_JOIN_EUI */ 01237 case DEVICE_STATE_SEND: 01238 SerialDisplayUpdateUplinkAcked( false ); 01239 SerialDisplayUpdateDonwlinkRxData( false ); 01240 PrepareTxFrame( AppPort ); 01241 status = SendFrame(gIsTxConfirmed, gAppDataSize); 01242 if (status == LORAMAC_STATUS_OK) { 01243 /* McpsConfirm or McpsIndication callback will continue */ 01244 DeviceState = DEVICE_STATE_SLEEP; 01245 } else 01246 DeviceState = DEVICE_STATE_TRIGGER; 01247 break; 01248 case DEVICE_STATE_SLEEP: 01249 { 01250 // Wake up through events 01251 sleep_manager_sleep_auto(); 01252 break; 01253 } 01254 case DEVICE_STATE_TRIGGER: 01255 /* wait button ISR */ 01256 sleep_manager_sleep_auto(); 01257 break; 01258 default: 01259 DeviceState = DEVICE_STATE_INIT; 01260 break; 01261 } // ..switch( DeviceState ) 01262 01263 LoRaMacUserContext(); 01264 } // ..while( 1 ) 01265 } 01266 #endif /* ENABLE_VT100 */
Generated on Sat Jul 16 2022 03:38:23 by
![doxygen](doxygen.png)