Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 /* 00002 00003 Description: MBED LoRaWAN example application 00004 00005 License: Revised BSD License, see LICENSE.TXT file include in the project 00006 00007 Maintainer: Espotel 00008 */ 00009 00010 #include "mbed.h" 00011 00012 #include <string.h> 00013 #include <math.h> 00014 //#include "board.h" 00015 00016 #include "LoRaMac.h" 00017 #include "utilities.h" 00018 00019 #define USE_BAND_868 00020 /*! 00021 * When set to 1 the application uses the Over-the-Air activation procedure 00022 * When set to 0 the application uses the Personalization activation procedure 00023 */ 00024 #define OVER_THE_AIR_ACTIVATION 1 00025 00026 /*! 00027 * Indicates if the end-device is to be connected to a private or public network 00028 */ 00029 #define LORAWAN_PUBLIC_NETWORK true 00030 00031 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00032 00033 /*! 00034 * Join requests trials duty cycle. 00035 */ 00036 #define OVER_THE_AIR_ACTIVATION_DUTYCYCLE 10000000 // 10 [s] value in us 00037 00038 /*! 00039 * Mote device IEEE EUI 00040 * 00041 * \remark must be written as a little endian value (reverse order of normal reading) 00042 * 00043 * \remark In this application the value is automatically generated by calling 00044 * BoardGetUniqueId function 00045 */ 00046 #define LORAWAN_DEVICE_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } 00047 00048 /*! 00049 * Application IEEE EUI 00050 * 00051 * \remark must be written as a little endian value (reverse order of normal reading) 00052 */ 00053 //#define LORAWAN_APPLICATION_EUI { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 } 00054 #define LORAWAN_APPLICATION_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } 00055 00056 /*! 00057 * AES encryption/decryption cipher application key 00058 */ 00059 00060 #define LORAWAN_APPLICATION_KEY { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } 00061 //#define LORAWAN_APPLICATION_KEY { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } 00062 00063 #else 00064 00065 /*! 00066 * Current network ID 00067 */ 00068 #define LORAWAN_NETWORK_ID ( uint32_t )0 00069 00070 /*! 00071 * Device address on the network 00072 * 00073 * \remark must be written as a big endian value (normal reading order) 00074 * 00075 * \remark In this application the value is automatically generated using 00076 * a pseudo random generator seeded with a value derived from 00077 * BoardUniqueId value 00078 */ 00079 #define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x00000000 00080 00081 /*! 00082 * AES encryption/decryption cipher network session key 00083 */ 00084 #define LORAWAN_NWKSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } 00085 00086 /*! 00087 * AES encryption/decryption cipher application session key 00088 */ 00089 #define LORAWAN_APPSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } 00090 00091 #endif 00092 00093 /*! 00094 * Defines the application data transmission duty cycle. 5s, value in [us]. 00095 */ 00096 #define APP_TX_DUTYCYCLE 5000000 00097 /*! 00098 * Defines a random delay for application data transmission duty cycle. 1s, 00099 * value in [us]. 00100 */ 00101 #define APP_TX_DUTYCYCLE_RND 1000000 00102 00103 /*! 00104 * LoRaWAN confirmed messages 00105 */ 00106 #define LORAWAN_CONFIRMED_MSG_ON true 00107 00108 /*! 00109 * LoRaWAN Adaptative Data Rate 00110 * 00111 * \remark Please note that when ADR is enabled the end-device should be static 00112 */ 00113 #define LORAWAN_ADR_ON 1 00114 00115 /*! 00116 * LoRaWAN ETSI duty cycle control enable/disable 00117 * 00118 * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes 00119 */ 00120 #define LORAWAN_DUTYCYCLE_ON true 00121 #define LORAWAN_DUTYCYCLE_OFF false 00122 00123 /*! 00124 * LoRaWAN application port 00125 */ 00126 #define LORAWAN_APP_PORT 2 00127 00128 /*! 00129 * User application data buffer size 00130 */ 00131 #define LORAWAN_APP_DATA_SIZE 16 00132 00133 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00134 00135 static uint8_t DevEui[] = LORAWAN_DEVICE_EUI; 00136 static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI; 00137 static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY; 00138 00139 #else 00140 00141 static uint8_t NwkSKey[] = LORAWAN_NWKSKEY; 00142 static uint8_t AppSKey[] = LORAWAN_APPSKEY; 00143 00144 /*! 00145 * Device address 00146 */ 00147 static uint32_t DevAddr; 00148 00149 #endif 00150 00151 /*! 00152 * Indicates if the MAC layer has already joined a network. 00153 */ 00154 static bool IsNetworkJoined = false; 00155 00156 /*! 00157 * Application port 00158 */ 00159 static uint8_t AppPort = LORAWAN_APP_PORT; 00160 00161 /*! 00162 * User application data size 00163 */ 00164 static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE; 00165 00166 /*! 00167 * User application data buffer size 00168 */ 00169 #define LORAWAN_APP_DATA_MAX_SIZE 64 00170 00171 /*! 00172 * User application data 00173 */ 00174 static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; 00175 00176 00177 /*! 00178 * Indicates if the node is sending confirmed or unconfirmed messages 00179 */ 00180 static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; 00181 00182 /*! 00183 * Defines the application data transmission duty cycle 00184 */ 00185 static uint32_t TxDutyCycleTime; 00186 00187 00188 static void OnTxNextPacketTimerEvent( void ); 00189 static Timeout TxNextPacketTimer;//(OnTxNextPacketTimerEvent, osTimerOnce); 00190 00191 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00192 00193 static void OnJoinReqTimerEvent( void ); 00194 /*! 00195 * Defines the join request timer 00196 */ 00197 static Timeout JoinReqTimer;//(OnJoinReqTimerEvent, osTimerOnce); 00198 00199 #endif 00200 00201 /*! 00202 * Indicates if a new packet can be sent 00203 */ 00204 static bool TxNextPacket = true; 00205 static bool ScheduleNextTx = false; 00206 static bool DownlinkStatusUpdate = false; 00207 00208 static bool AppLedStateOn = false; 00209 00210 static LoRaMacCallbacks_t LoRaMacCallbacks; 00211 /* 00212 static TimerEvent_t Led1Timer; 00213 volatile bool Led1StateChanged = false; 00214 static TimerEvent_t Led2Timer; 00215 volatile bool Led2StateChanged = false; 00216 static TimerEvent_t Led4Timer; 00217 volatile bool Led4StateChanged = false; 00218 00219 volatile bool Led3StateChanged = false; 00220 */ 00221 static bool ComplianceTestOn = false; 00222 static uint8_t ComplianceTestState = 0; 00223 static uint16_t ComplianceTestDownLinkCounter = 0; 00224 static bool ComplianceTestLinkCheck = false; 00225 static uint8_t ComplianceTestDemodMargin = 0; 00226 static uint8_t ComplianceTestNbGateways = 0; 00227 00228 /*! 00229 * Prepares the frame buffer to be sent 00230 */ 00231 static void PrepareTxFrame( uint8_t port ) 00232 { 00233 switch( port ) 00234 { 00235 case 2: 00236 { 00237 uint16_t pressure = 0; 00238 int16_t altitudeBar = 0; 00239 int16_t temperature = 0; 00240 int32_t latitude, longitude = 0; 00241 uint16_t altitudeGps = 0xFFFF; 00242 uint8_t batteryLevel = 0; 00243 00244 //pressure = ( uint16_t )( MPL3115ReadPressure( ) / 10 ); // in hPa / 10 00245 //temperature = ( int16_t )( MPL3115ReadTemperature( ) * 100 ); // in °C * 100 00246 //altitudeBar = ( int16_t )( MPL3115ReadAltitude( ) * 10 ); // in m * 10 00247 //batteryLevel = BoardGetBatteryLevel( ); // 1 (very low) to 254 (fully charged) 00248 //GpsGetLatestGpsPositionBinary( &latitude, &longitude ); 00249 //altitudeGps = GpsGetLatestGpsAltitude( ); // in m 00250 00251 AppData[0] = AppLedStateOn; 00252 AppData[1] = ( pressure >> 8 ) & 0xFF; 00253 AppData[2] = pressure & 0xFF; 00254 AppData[3] = ( temperature >> 8 ) & 0xFF; 00255 AppData[4] = temperature & 0xFF; 00256 AppData[5] = ( altitudeBar >> 8 ) & 0xFF; 00257 AppData[6] = altitudeBar & 0xFF; 00258 AppData[7] = batteryLevel; 00259 AppData[8] = ( latitude >> 16 ) & 0xFF; 00260 AppData[9] = ( latitude >> 8 ) & 0xFF; 00261 AppData[10] = latitude & 0xFF; 00262 AppData[11] = ( longitude >> 16 ) & 0xFF; 00263 AppData[12] = ( longitude >> 8 ) & 0xFF; 00264 AppData[13] = longitude & 0xFF; 00265 AppData[14] = ( altitudeGps >> 8 ) & 0xFF; 00266 AppData[15] = altitudeGps & 0xFF; 00267 } 00268 break; 00269 case 224: 00270 if( ComplianceTestLinkCheck == true ) 00271 { 00272 printf("ComplianceTestLinkCheck\r\n"); 00273 ComplianceTestLinkCheck = false; 00274 AppDataSize = 3; 00275 AppData[0] = 5; 00276 AppData[1] = ComplianceTestDemodMargin; 00277 AppData[2] = ComplianceTestNbGateways; 00278 ComplianceTestState = 1; 00279 } 00280 else 00281 { 00282 switch( ComplianceTestState ) 00283 { 00284 case 4: 00285 printf("Sending downlink COUNTER!!!!\r\n"); 00286 ComplianceTestState = 1; 00287 break; 00288 case 1: 00289 AppDataSize = 2; 00290 AppData[0] = ComplianceTestDownLinkCounter >> 8; 00291 AppData[1] = ComplianceTestDownLinkCounter; 00292 break; 00293 } 00294 } 00295 default: 00296 break; 00297 } 00298 } 00299 00300 static void ProcessRxFrame( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info ) 00301 { 00302 switch( info->RxPort ) // Check Rx port number 00303 { 00304 case 1: // The application LED can be controlled on port 1 or 2 00305 case 2: 00306 if( info->RxBufferSize == 1 ) 00307 { 00308 AppLedStateOn = info->RxBuffer[0] & 0x01; 00309 //Led3StateChanged = true; 00310 } 00311 break; 00312 case 224: 00313 if( ComplianceTestOn == false ) 00314 { 00315 // Check compliance test enable command (i) 00316 if( ( info->RxBufferSize == 4 ) && 00317 ( info->RxBuffer[0] == 0x01 ) && 00318 ( info->RxBuffer[1] == 0x01 ) && 00319 ( info->RxBuffer[2] == 0x01 ) && 00320 ( info->RxBuffer[3] == 0x01 ) ) 00321 { 00322 IsTxConfirmed = false; 00323 AppPort = 224; 00324 AppDataSize = 2; 00325 ComplianceTestDownLinkCounter = 0; 00326 ComplianceTestLinkCheck = false; 00327 ComplianceTestDemodMargin = 0; 00328 ComplianceTestNbGateways = 0; 00329 ComplianceTestOn = true; 00330 ComplianceTestState = 1; 00331 00332 LoRaMacSetAdrOn( true ); 00333 LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_OFF ); 00334 } 00335 } 00336 else 00337 { 00338 ComplianceTestState = info->RxBuffer[0]; 00339 switch( ComplianceTestState ) 00340 { 00341 case 0: // Check compliance test disable command (ii) 00342 IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; 00343 AppPort = LORAWAN_APP_PORT; 00344 AppDataSize = LORAWAN_APP_DATA_SIZE; 00345 ComplianceTestDownLinkCounter = 0; 00346 ComplianceTestOn = false; 00347 00348 LoRaMacSetAdrOn( LORAWAN_ADR_ON ); 00349 LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON ); 00350 break; 00351 case 1: // (iii, iv) 00352 AppDataSize = 2; 00353 break; 00354 case 2: // Enable confirmed messages (v) 00355 IsTxConfirmed = true; 00356 ComplianceTestState = 1; 00357 break; 00358 case 3: // Disable confirmed messages (vi) 00359 IsTxConfirmed = false; 00360 ComplianceTestState = 1; 00361 break; 00362 case 4: // (vii) 00363 AppDataSize = info->RxBufferSize; 00364 printf("VII <------------------- rozmiar %i \r\n", AppDataSize); 00365 AppData[0] = 4; 00366 for( uint8_t i = 1; i < AppDataSize; i++ ) 00367 { 00368 00369 printf("VII <-------------------dodaje \r\n"); 00370 AppData[i] = info->RxBuffer[i] + 1; 00371 } 00372 break; 00373 case 5: // (viii) 00374 LoRaMacLinkCheckReq( ); 00375 break; 00376 default: 00377 break; 00378 } 00379 } 00380 break; 00381 default: 00382 break; 00383 } 00384 #warning needed extension to check counter scopes 00385 } 00386 00387 static bool SendFrame( void ) 00388 { 00389 uint8_t sendFrameStatus = 0; 00390 00391 if( IsTxConfirmed == false ) 00392 { 00393 sendFrameStatus = LoRaMacSendFrame( AppPort, AppData, AppDataSize ); 00394 } 00395 else 00396 { 00397 sendFrameStatus = LoRaMacSendConfirmedFrame( AppPort, AppData, AppDataSize, 8 ); 00398 } 00399 00400 switch( sendFrameStatus ) 00401 { 00402 case 5: // NO_FREE_CHANNEL 00403 // Try again later 00404 return true; 00405 default: 00406 return false; 00407 } 00408 } 00409 00410 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00411 00412 /*! 00413 * \brief Function executed on JoinReq Timeout event 00414 */ 00415 static void OnJoinReqTimerEvent( void ) 00416 { 00417 JoinReqTimer.detach(); 00418 TxNextPacket = true; 00419 } 00420 00421 #endif 00422 00423 /*! 00424 * \brief Function executed on TxNextPacket Timeout event 00425 */ 00426 static void OnTxNextPacketTimerEvent( void ) 00427 { 00428 //TimerStop( &TxNextPacketTimer ); 00429 //TxNextPacketTimer.stop(); 00430 TxNextPacketTimer.detach(); 00431 TxNextPacket = true; 00432 } 00433 00434 /*! 00435 * \brief Function executed on Led 1 Timeout event 00436 */ 00437 /*static void OnLed1TimerEvent( void ) 00438 { 00439 TimerStop( &Led1Timer ); 00440 Led1StateChanged = true; 00441 }*/ 00442 00443 /*! 00444 * \brief Function executed on Led 2 Timeout event 00445 */ 00446 /*static void OnLed2TimerEvent( void ) 00447 { 00448 TimerStop( &Led2Timer ); 00449 Led2StateChanged = true; 00450 }*/ 00451 00452 /*! 00453 * \brief Function executed on Led 4 Timeout event 00454 */ 00455 /*void OnLed4TimerEvent( void ) 00456 { 00457 TimerStop( &Led4Timer ); 00458 Led4StateChanged = true; 00459 }*/ 00460 00461 /*! 00462 * \brief Function to be executed on MAC layer event 00463 */ 00464 static void OnMacEvent( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info ) 00465 { 00466 if( flags->Bits.JoinAccept == 1 ) 00467 { 00468 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00469 JoinReqTimer.detach(); 00470 #endif 00471 IsNetworkJoined = true; 00472 } 00473 else 00474 { 00475 if( flags->Bits.Tx == 1 ) 00476 { 00477 } 00478 00479 if( flags->Bits.Rx == 1 ) 00480 { 00481 if( ComplianceTestOn == true ) 00482 { 00483 ComplianceTestDownLinkCounter++; 00484 if( flags->Bits.LinkCheck == 1 ) 00485 { 00486 ComplianceTestLinkCheck = true; 00487 ComplianceTestDemodMargin = info->DemodMargin; 00488 ComplianceTestNbGateways = info->NbGateways; 00489 } 00490 } 00491 if( flags->Bits.RxData == true ) 00492 { 00493 ProcessRxFrame( flags, info ); 00494 } 00495 00496 DownlinkStatusUpdate = true; 00497 //TimerStart( &Led2Timer ); 00498 } 00499 } 00500 // Schedule a new transmission 00501 ScheduleNextTx = true; 00502 } 00503 00504 /** 00505 * Main application entry point. 00506 */ 00507 00508 int main( void ) 00509 { 00510 DigitalOut myled1(LED1); 00511 DigitalOut myled2(LED2); 00512 00513 myled1 = 1; 00514 myled2 = 1; 00515 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00516 uint8_t sendFrameStatus = 0; 00517 #endif 00518 bool trySendingFrameAgain = false; 00519 00520 #warning HW and RADIO CHIP must be configured!!!! 00521 //BoardInitMcu( ); 00522 //BoardInitPeriph( ); 00523 //hal_init(); 00524 //radio_init(); 00525 00526 LoRaMacCallbacks.MacEvent = OnMacEvent; 00527 //LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel; 00528 LoRaMacInit( &LoRaMacCallbacks ); 00529 00530 IsNetworkJoined = false; 00531 00532 #if( OVER_THE_AIR_ACTIVATION == 0 ) 00533 // Random seed initialization 00534 #warning seed initialization must be implemented 00535 srand1( 1 ); 00536 // Choose a random device address based on Board unique ID 00537 // NwkAddr rand [0, 33554431] 00538 DevAddr = randr( 0, 0x01FFFFFF ); 00539 00540 LoRaMacInitNwkIds( LORAWAN_NETWORK_ID, DevAddr, NwkSKey, AppSKey ); 00541 IsNetworkJoined = true; 00542 #else 00543 // Initialize LoRaMac device unique ID 00544 //BoardGetUniqueId( DevEui ); 00545 #endif 00546 00547 TxNextPacket = true; 00548 00549 //TimerInit( &Led1Timer, OnLed1TimerEvent ); 00550 //TimerSetValue( &Led1Timer, 25000 ); 00551 00552 //TimerInit( &Led2Timer, OnLed2TimerEvent ); 00553 //TimerSetValue( &Led2Timer, 25000 ); 00554 00555 //TimerInit( &Led4Timer, OnLed4TimerEvent ); 00556 //TimerSetValue( &Led4Timer, 25000 ); 00557 00558 LoRaMacSetAdrOn( LORAWAN_ADR_ON ); 00559 #warning dutycycleON OFFFFFFFFFFFFF!!!!!!!!!!!!!!!!!!!!!!! 00560 // LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON ); 00561 LoRaMacTestSetDutyCycleOn( 0 ); 00562 LoRaMacSetPublicNetwork( LORAWAN_PUBLIC_NETWORK ); 00563 00564 LoRaMacSetRx2Channel( ( Rx2ChannelParams_t ){ 869525000, DR_3 } ); 00565 while( 1 ) 00566 { 00567 while( IsNetworkJoined == false ) 00568 { 00569 #if( OVER_THE_AIR_ACTIVATION != 0 ) 00570 if( TxNextPacket == true ) 00571 { 00572 printf("Trial to join network... txnextpacket %i \r\n", TxNextPacket); 00573 TxNextPacket = false; 00574 00575 sendFrameStatus = LoRaMacJoinReq( DevEui, AppEui, AppKey ); 00576 printf("status = %i\r\n", sendFrameStatus); 00577 switch( sendFrameStatus ) 00578 { 00579 case 1: // BUSY 00580 printf("busy...\r\n"); 00581 break; 00582 case 0: // OK 00583 case 2: // NO_NETWORK_JOINED 00584 case 3: // LENGTH_PORT_ERROR 00585 case 4: // MAC_CMD_ERROR 00586 case 6: // DEVICE_OFF 00587 default: 00588 // Relaunch timer for next trial 00589 JoinReqTimer.attach_us(OnJoinReqTimerEvent, OVER_THE_AIR_ACTIVATION_DUTYCYCLE); 00590 break; 00591 } 00592 } 00593 //TimerLowPowerHandler( ); 00594 #endif 00595 } 00596 00597 /* 00598 if( Led1StateChanged == true ) 00599 { 00600 Led1StateChanged = false; 00601 // Switch LED 1 OFF 00602 GpioWrite( &Led1, 1 ); 00603 } 00604 if( Led2StateChanged == true ) 00605 { 00606 Led2StateChanged = false; 00607 // Switch LED 2 OFF 00608 GpioWrite( &Led2, 1 ); 00609 } 00610 if( Led3StateChanged == true ) 00611 { 00612 Led3StateChanged = false; 00613 GpioWrite( &Led3, ( ( AppLedStateOn & 0x01 ) != 0 ) ? 0 : 1 ); 00614 } 00615 if( Led4StateChanged == true ) 00616 { 00617 Led4StateChanged = false; 00618 // Switch LED 4 OFF 00619 GpioWrite( &Led4, 1 ); 00620 }*/ 00621 if( DownlinkStatusUpdate == true ) 00622 { 00623 DownlinkStatusUpdate = false; 00624 // Switch LED 2 ON for each received downlink 00625 //GpioWrite( &Led2, 0 ); 00626 } 00627 00628 if( ScheduleNextTx == true ) 00629 { 00630 printf("Sending data..."); 00631 ScheduleNextTx = false; 00632 00633 if( ComplianceTestOn == true ) 00634 { 00635 TxNextPacket = true; 00636 } 00637 else 00638 { 00639 // Schedule next packet transmission 00640 TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); 00641 TxNextPacketTimer.attach_us(OnTxNextPacketTimerEvent, TxDutyCycleTime); 00642 } 00643 } 00644 00645 if( trySendingFrameAgain == true ) 00646 { 00647 trySendingFrameAgain = SendFrame( ); 00648 } 00649 if( TxNextPacket == true ) 00650 { 00651 TxNextPacket = false; 00652 00653 PrepareTxFrame( AppPort ); 00654 00655 // Switch LED 1 ON 00656 //GpioWrite( &Led1, 0 ); 00657 //TimerStart( &Led1Timer ); 00658 00659 trySendingFrameAgain = SendFrame( ); 00660 } 00661 00662 //TimerLowPowerHandler( ); 00663 } 00664 }
Generated on Wed Jul 13 2022 23:48:00 by
