1 /*!
2 * \file main.c
3 *
4 * \brief FUOTA interop tests - test 01
5 *
6 * \copyright Revised BSD License, see section \ref LICENSE.
7 *
8 * \code
9 * ______ _
10 * / _____) _ | |
11 * ( (____ _____ ____ _| |_ _____ ____| |__
12 * \____ \| ___ | (_ _) ___ |/ ___) _ \
13 * _____) ) ____| | | || |_| ____( (___| | | |
14 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15 * (C)2013-2018 Semtech
16 *
17 * \endcode
18 *
19 * \author Miguel Luis ( Semtech )
20 */
21
22 /*! \file fuota-test-01/NAMote72/main.c */
23
24 #include <stdio.h>
25 #include "../firmwareVersion.h"
26 #include "../../common/githubVersion.h"
27 #include "utilities.h"
28 #include "board-config.h"
29 #include "board.h"
30 #include "gpio.h"
31 #include "uart.h"
32 #include "RegionCommon.h"
33 #include "gps.h"
34 #include "mpl3115.h"
35
36 #include "cli.h"
37 #include "Commissioning.h"
38 #include "LmHandler.h"
39 #include "LmhpCompliance.h"
40 #include "LmhpClockSync.h"
41 #include "LmhpRemoteMcastSetup.h"
42 #include "LmhpFragmentation.h"
43 #include "LmHandlerMsgDisplay.h"
44
45 #ifndef ACTIVE_REGION
46
47 #warning "No active region defined, LORAMAC_REGION_EU868 will be used as default."
48
49 #define ACTIVE_REGION LORAMAC_REGION_EU868
50
51 #endif
52
53 /*!
54 * LoRaWAN default end-device class
55 */
56 #define LORAWAN_DEFAULT_CLASS CLASS_A
57
58 /*!
59 * Defines the application data transmission duty cycle. 40s, value in [ms].
60 */
61 #define APP_TX_DUTYCYCLE 40000
62
63 /*!
64 * Defines a random delay for application data transmission duty cycle. 5s,
65 * value in [ms].
66 */
67 #define APP_TX_DUTYCYCLE_RND 5000
68
69 /*!
70 * LoRaWAN Adaptive Data Rate
71 *
72 * \remark Please note that when ADR is enabled the end-device should be static
73 */
74 #define LORAWAN_ADR_STATE LORAMAC_HANDLER_ADR_ON
75
76 /*!
77 * Default datarate
78 *
79 * \remark Please note that LORAWAN_DEFAULT_DATARATE is used only when ADR is disabled
80 */
81 #define LORAWAN_DEFAULT_DATARATE DR_3
82
83 /*!
84 * LoRaWAN confirmed messages
85 */
86 #define LORAWAN_DEFAULT_CONFIRMED_MSG_STATE LORAMAC_HANDLER_UNCONFIRMED_MSG
87
88 /*!
89 * User application data buffer size
90 */
91 #define LORAWAN_APP_DATA_BUFFER_MAX_SIZE 242
92
93 /*!
94 * LoRaWAN ETSI duty cycle control enable/disable
95 *
96 * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes
97 */
98 #define LORAWAN_DUTYCYCLE_ON true
99
100 /*!
101 *
102 */
103 typedef enum
104 {
105 LORAMAC_HANDLER_TX_ON_TIMER,
106 LORAMAC_HANDLER_TX_ON_EVENT,
107 }LmHandlerTxEvents_t;
108
109 /*!
110 * User application data
111 */
112 static uint8_t AppDataBuffer[LORAWAN_APP_DATA_BUFFER_MAX_SIZE];
113
114 /*!
115 * Timer to handle the application data transmission duty cycle
116 */
117 static TimerEvent_t TxTimer;
118
119 /*!
120 * Timer to handle the state of LED1
121 */
122 static TimerEvent_t Led1Timer;
123
124 /*!
125 * Timer to handle the state of LED2
126 */
127 static TimerEvent_t Led2Timer;
128
129 /*!
130 * Timer to handle the state of LED beacon indicator
131 */
132 static TimerEvent_t LedBeaconTimer;
133
134 static void OnMacProcessNotify( void );
135 static void OnNvmDataChange( LmHandlerNvmContextStates_t state, uint16_t size );
136 static void OnNetworkParametersChange( CommissioningParams_t* params );
137 static void OnMacMcpsRequest( LoRaMacStatus_t status, McpsReq_t *mcpsReq, TimerTime_t nextTxIn );
138 static void OnMacMlmeRequest( LoRaMacStatus_t status, MlmeReq_t *mlmeReq, TimerTime_t nextTxIn );
139 static void OnJoinRequest( LmHandlerJoinParams_t* params );
140 static void OnTxData( LmHandlerTxParams_t* params );
141 static void OnRxData( LmHandlerAppData_t* appData, LmHandlerRxParams_t* params );
142 static void OnClassChange( DeviceClass_t deviceClass );
143 static void OnBeaconStatusChange( LoRaMacHandlerBeaconParams_t* params );
144 #if( LMH_SYS_TIME_UPDATE_NEW_API == 1 )
145 static void OnSysTimeUpdate( bool isSynchronized, int32_t timeCorrection );
146 #else
147 static void OnSysTimeUpdate( void );
148 #endif
149 #if( FRAG_DECODER_FILE_HANDLING_NEW_API == 1 )
150 static int8_t FragDecoderWrite( uint32_t addr, uint8_t *data, uint32_t size );
151 static int8_t FragDecoderRead( uint32_t addr, uint8_t *data, uint32_t size );
152 #endif
153 static void OnFragProgress( uint16_t fragCounter, uint16_t fragNb, uint8_t fragSize, uint16_t fragNbLost );
154 #if( FRAG_DECODER_FILE_HANDLING_NEW_API == 1 )
155 static void OnFragDone( int32_t status, uint32_t size );
156 #else
157 static void OnFragDone( int32_t status, uint8_t *file, uint32_t size );
158 #endif
159 static void StartTxProcess( LmHandlerTxEvents_t txEvent );
160 static void UplinkProcess( void );
161
162 static void OnTxPeriodicityChanged( uint32_t periodicity );
163 static void OnTxFrameCtrlChanged( LmHandlerMsgTypes_t isTxConfirmed );
164 static void OnPingSlotPeriodicityChanged( uint8_t pingSlotPeriodicity );
165
166 /*!
167 * Function executed on TxTimer event
168 */
169 static void OnTxTimerEvent( void* context );
170
171 /*!
172 * Function executed on Led 1 Timeout event
173 */
174 static void OnLed1TimerEvent( void* context );
175
176 /*!
177 * Function executed on Led 2 Timeout event
178 */
179 static void OnLed2TimerEvent( void* context );
180
181 /*!
182 * \brief Function executed on Beacon timer Timeout event
183 */
184 static void OnLedBeaconTimerEvent( void* context );
185
186 static LmHandlerCallbacks_t LmHandlerCallbacks =
187 {
188 .GetBatteryLevel = BoardGetBatteryLevel,
189 .GetTemperature = MPL3115ReadTemperature,
190 .GetRandomSeed = BoardGetRandomSeed,
191 .OnMacProcess = OnMacProcessNotify,
192 .OnNvmDataChange = OnNvmDataChange,
193 .OnNetworkParametersChange = OnNetworkParametersChange,
194 .OnMacMcpsRequest = OnMacMcpsRequest,
195 .OnMacMlmeRequest = OnMacMlmeRequest,
196 .OnJoinRequest = OnJoinRequest,
197 .OnTxData = OnTxData,
198 .OnRxData = OnRxData,
199 .OnClassChange= OnClassChange,
200 .OnBeaconStatusChange = OnBeaconStatusChange,
201 .OnSysTimeUpdate = OnSysTimeUpdate,
202 };
203
204 static LmHandlerParams_t LmHandlerParams =
205 {
206 .Region = ACTIVE_REGION,
207 .AdrEnable = LORAWAN_ADR_STATE,
208 .IsTxConfirmed = LORAWAN_DEFAULT_CONFIRMED_MSG_STATE,
209 .TxDatarate = LORAWAN_DEFAULT_DATARATE,
210 .PublicNetworkEnable = LORAWAN_PUBLIC_NETWORK,
211 .DutyCycleEnabled = LORAWAN_DUTYCYCLE_ON,
212 .DataBufferMaxSize = LORAWAN_APP_DATA_BUFFER_MAX_SIZE,
213 .DataBuffer = AppDataBuffer,
214 .PingSlotPeriodicity = REGION_COMMON_DEFAULT_PING_SLOT_PERIODICITY,
215 };
216
217 static LmhpComplianceParams_t LmhpComplianceParams =
218 {
219 .FwVersion.Value = FIRMWARE_VERSION,
220 .OnTxPeriodicityChanged = OnTxPeriodicityChanged,
221 .OnTxFrameCtrlChanged = OnTxFrameCtrlChanged,
222 .OnPingSlotPeriodicityChanged = OnPingSlotPeriodicityChanged,
223 };
224
225 /*!
226 * Defines the maximum size for the buffer receiving the fragmentation result.
227 *
228 * \remark By default FragDecoder.h defines:
229 * \ref FRAG_MAX_NB 21
230 * \ref FRAG_MAX_SIZE 50
231 *
232 * FileSize = FRAG_MAX_NB * FRAG_MAX_SIZE
233 *
234 * If bigger file size is to be received or is fragmented differently
235 * one must update those parameters.
236 */
237 #define UNFRAGMENTED_DATA_SIZE ( 21 * 50 )
238
239 /*
240 * Un-fragmented data storage.
241 */
242 static uint8_t UnfragmentedData[UNFRAGMENTED_DATA_SIZE];
243
244 static LmhpFragmentationParams_t FragmentationParams =
245 {
246 #if( FRAG_DECODER_FILE_HANDLING_NEW_API == 1 )
247 .DecoderCallbacks =
248 {
249 .FragDecoderWrite = FragDecoderWrite,
250 .FragDecoderRead = FragDecoderRead,
251 },
252 #else
253 .Buffer = UnfragmentedData,
254 .BufferSize = UNFRAGMENTED_DATA_SIZE,
255 #endif
256 .OnProgress = OnFragProgress,
257 .OnDone = OnFragDone
258 };
259
260 /*!
261 * Indicates if LoRaMacProcess call is pending.
262 *
263 * \warning If variable is equal to 0 then the MCU can be set in low power mode
264 */
265 static volatile uint8_t IsMacProcessPending = 0;
266
267 static volatile uint8_t IsTxFramePending = 0;
268
269 static volatile uint32_t TxPeriodicity = 0;
270
271 /*
272 * Indicates if the system time has been synchronized
273 */
274 static volatile bool IsClockSynched = false;
275
276 /*
277 * MC Session Started
278 */
279 static volatile bool IsMcSessionStarted = false;
280
281 /*
282 * Indicates if the file transfer is done
283 */
284 static volatile bool IsFileTransferDone = false;
285
286 /*
287 * Received file computed CRC32
288 */
289 static volatile uint32_t FileRxCrc = 0;
290
291 /*!
292 * LED GPIO pins objects
293 */
294 extern Gpio_t Led1; // Tx
295 extern Gpio_t Led2; // Rx
296 extern Gpio_t Led3; // App
297
298 /*!
299 * UART object used for command line interface handling
300 */
301 extern Uart_t Uart2;
302
303 /*!
304 * Main application entry point.
305 */
main(void)306 int main( void )
307 {
308 BoardInitMcu( );
309 BoardInitPeriph( );
310
311 TimerInit( &Led1Timer, OnLed1TimerEvent );
312 TimerSetValue( &Led1Timer, 25 );
313
314 TimerInit( &Led2Timer, OnLed2TimerEvent );
315 TimerSetValue( &Led2Timer, 100 );
316
317 TimerInit( &LedBeaconTimer, OnLedBeaconTimerEvent );
318 TimerSetValue( &LedBeaconTimer, 5000 );
319
320 // Initialize transmission periodicity variable
321 TxPeriodicity = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
322
323 const Version_t appVersion = { .Value = FIRMWARE_VERSION };
324 const Version_t gitHubVersion = { .Value = GITHUB_VERSION };
325 DisplayAppInfo( "fuota-test-01",
326 &appVersion,
327 &gitHubVersion );
328
329 if ( LmHandlerInit( &LmHandlerCallbacks, &LmHandlerParams ) != LORAMAC_HANDLER_SUCCESS )
330 {
331 printf( "LoRaMac wasn't properly initialized\n" );
332 // Fatal error, endless loop.
333 while ( 1 )
334 {
335 }
336 }
337
338 // Set system maximum tolerated rx error in milliseconds
339 LmHandlerSetSystemMaxRxError( 20 );
340
341 // The LoRa-Alliance Compliance protocol package should always be
342 // initialized and activated.
343 LmHandlerPackageRegister( PACKAGE_ID_COMPLIANCE, &LmhpComplianceParams );
344 LmHandlerPackageRegister( PACKAGE_ID_CLOCK_SYNC, NULL );
345 LmHandlerPackageRegister( PACKAGE_ID_REMOTE_MCAST_SETUP, NULL );
346 LmHandlerPackageRegister( PACKAGE_ID_FRAGMENTATION, &FragmentationParams );
347
348 IsClockSynched = false;
349 IsFileTransferDone = false;
350
351 LmHandlerJoin( );
352
353 StartTxProcess( LORAMAC_HANDLER_TX_ON_TIMER );
354
355 while( 1 )
356 {
357 // Process characters sent over the command line interface
358 CliProcess( &Uart2 );
359
360 // Processes the LoRaMac events
361 LmHandlerProcess( );
362
363 // Process application uplinks management
364 UplinkProcess( );
365
366 CRITICAL_SECTION_BEGIN( );
367 if( IsMacProcessPending == 1 )
368 {
369 // Clear flag and prevent MCU to go into low power modes.
370 IsMacProcessPending = 0;
371 }
372 else
373 {
374 // The MCU wakes up through events
375 BoardLowPowerHandler( );
376 }
377 CRITICAL_SECTION_END( );
378 }
379 }
380
OnMacProcessNotify(void)381 static void OnMacProcessNotify( void )
382 {
383 IsMacProcessPending = 1;
384 }
385
OnNvmDataChange(LmHandlerNvmContextStates_t state,uint16_t size)386 static void OnNvmDataChange( LmHandlerNvmContextStates_t state, uint16_t size )
387 {
388 DisplayNvmDataChange( state, size );
389 }
390
OnNetworkParametersChange(CommissioningParams_t * params)391 static void OnNetworkParametersChange( CommissioningParams_t* params )
392 {
393 DisplayNetworkParametersUpdate( params );
394 }
395
OnMacMcpsRequest(LoRaMacStatus_t status,McpsReq_t * mcpsReq,TimerTime_t nextTxIn)396 static void OnMacMcpsRequest( LoRaMacStatus_t status, McpsReq_t *mcpsReq, TimerTime_t nextTxIn )
397 {
398 DisplayMacMcpsRequestUpdate( status, mcpsReq, nextTxIn );
399 }
400
OnMacMlmeRequest(LoRaMacStatus_t status,MlmeReq_t * mlmeReq,TimerTime_t nextTxIn)401 static void OnMacMlmeRequest( LoRaMacStatus_t status, MlmeReq_t *mlmeReq, TimerTime_t nextTxIn )
402 {
403 DisplayMacMlmeRequestUpdate( status, mlmeReq, nextTxIn );
404 }
405
OnJoinRequest(LmHandlerJoinParams_t * params)406 static void OnJoinRequest( LmHandlerJoinParams_t* params )
407 {
408 DisplayJoinRequestUpdate( params );
409 if( params->Status == LORAMAC_HANDLER_ERROR )
410 {
411 LmHandlerJoin( );
412 }
413 else
414 {
415 LmHandlerRequestClass( LORAWAN_DEFAULT_CLASS );
416 }
417 }
418
OnTxData(LmHandlerTxParams_t * params)419 static void OnTxData( LmHandlerTxParams_t* params )
420 {
421 DisplayTxUpdate( params );
422 }
423
OnRxData(LmHandlerAppData_t * appData,LmHandlerRxParams_t * params)424 static void OnRxData( LmHandlerAppData_t* appData, LmHandlerRxParams_t* params )
425 {
426 DisplayRxUpdate( appData, params );
427 }
428
OnClassChange(DeviceClass_t deviceClass)429 static void OnClassChange( DeviceClass_t deviceClass )
430 {
431 DisplayClassUpdate( deviceClass );
432
433 switch( deviceClass )
434 {
435 default:
436 case CLASS_A:
437 {
438 IsMcSessionStarted = false;
439 break;
440 }
441 case CLASS_B:
442 {
443 // Inform the server as soon as possible that the end-device has switched to ClassB
444 LmHandlerAppData_t appData =
445 {
446 .Buffer = NULL,
447 .BufferSize = 0,
448 .Port = 0,
449 };
450 LmHandlerSend( &appData, LORAMAC_HANDLER_UNCONFIRMED_MSG );
451 IsMcSessionStarted = true;
452 break;
453 }
454 case CLASS_C:
455 {
456 IsMcSessionStarted = true;
457 // Switch LED 2 ON
458 GpioWrite( &Led2, 0 );
459 break;
460 }
461 }
462 }
463
OnBeaconStatusChange(LoRaMacHandlerBeaconParams_t * params)464 static void OnBeaconStatusChange( LoRaMacHandlerBeaconParams_t* params )
465 {
466 switch( params->State )
467 {
468 case LORAMAC_HANDLER_BEACON_RX:
469 {
470 TimerStart( &LedBeaconTimer );
471 break;
472 }
473 case LORAMAC_HANDLER_BEACON_LOST:
474 case LORAMAC_HANDLER_BEACON_NRX:
475 {
476 TimerStop( &LedBeaconTimer );
477 break;
478 }
479 default:
480 {
481 break;
482 }
483 }
484
485 DisplayBeaconUpdate( params );
486 }
487
488 #if( LMH_SYS_TIME_UPDATE_NEW_API == 1 )
OnSysTimeUpdate(bool isSynchronized,int32_t timeCorrection)489 static void OnSysTimeUpdate( bool isSynchronized, int32_t timeCorrection )
490 {
491 IsClockSynched = isSynchronized;
492 }
493 #else
OnSysTimeUpdate(void)494 static void OnSysTimeUpdate( void )
495 {
496 IsClockSynched = true;
497 }
498 #endif
499
500 #if( FRAG_DECODER_FILE_HANDLING_NEW_API == 1 )
FragDecoderWrite(uint32_t addr,uint8_t * data,uint32_t size)501 static int8_t FragDecoderWrite( uint32_t addr, uint8_t *data, uint32_t size )
502 {
503 if( size >= UNFRAGMENTED_DATA_SIZE )
504 {
505 return -1; // Fail
506 }
507 for(uint32_t i = 0; i < size; i++ )
508 {
509 UnfragmentedData[addr + i] = data[i];
510 }
511 return 0; // Success
512 }
513
FragDecoderRead(uint32_t addr,uint8_t * data,uint32_t size)514 static int8_t FragDecoderRead( uint32_t addr, uint8_t *data, uint32_t size )
515 {
516 if( size >= UNFRAGMENTED_DATA_SIZE )
517 {
518 return -1; // Fail
519 }
520 for(uint32_t i = 0; i < size; i++ )
521 {
522 data[i] = UnfragmentedData[addr + i];
523 }
524 return 0; // Success
525 }
526 #endif
527
OnFragProgress(uint16_t fragCounter,uint16_t fragNb,uint8_t fragSize,uint16_t fragNbLost)528 static void OnFragProgress( uint16_t fragCounter, uint16_t fragNb, uint8_t fragSize, uint16_t fragNbLost )
529 {
530 // Switch LED 2 OFF for each received downlink
531 GpioWrite( &Led2, 1 );
532 TimerStart( &Led2Timer );
533
534 printf( "\n###### =========== FRAG_DECODER ============ ######\n" );
535 printf( "###### PROGRESS ######\n");
536 printf( "###### ===================================== ######\n");
537 printf( "RECEIVED : %5d / %5d Fragments\n", fragCounter, fragNb );
538 printf( " %5d / %5d Bytes\n", fragCounter * fragSize, fragNb * fragSize );
539 printf( "LOST : %7d Fragments\n\n", fragNbLost );
540 }
541
542 #if( FRAG_DECODER_FILE_HANDLING_NEW_API == 1 )
OnFragDone(int32_t status,uint32_t size)543 static void OnFragDone( int32_t status, uint32_t size )
544 {
545 FileRxCrc = Crc32( UnfragmentedData, size );
546 IsFileTransferDone = true;
547 // Switch LED 2 OFF
548 GpioWrite( &Led2, 1 );
549
550 printf( "\n###### =========== FRAG_DECODER ============ ######\n" );
551 printf( "###### FINISHED ######\n");
552 printf( "###### ===================================== ######\n");
553 printf( "STATUS : %ld\n", status );
554 printf( "CRC : %08lX\n\n", FileRxCrc );
555 }
556 #else
OnFragDone(int32_t status,uint8_t * file,uint32_t size)557 static void OnFragDone( int32_t status, uint8_t *file, uint32_t size )
558 {
559 FileRxCrc = Crc32( file, size );
560 IsFileTransferDone = true;
561 // Switch LED 2 OFF
562 GpioWrite( &Led2, 1 );
563
564 printf( "\n###### =========== FRAG_DECODER ============ ######\n" );
565 printf( "###### FINISHED ######\n");
566 printf( "###### ===================================== ######\n");
567 printf( "STATUS : %ld\n", status );
568 printf( "CRC : %08lX\n\n", FileRxCrc );
569 }
570 #endif
571
StartTxProcess(LmHandlerTxEvents_t txEvent)572 static void StartTxProcess( LmHandlerTxEvents_t txEvent )
573 {
574 switch( txEvent )
575 {
576 default:
577 // Intentional fall through
578 case LORAMAC_HANDLER_TX_ON_TIMER:
579 {
580 // Schedule 1st packet transmission
581 TimerInit( &TxTimer, OnTxTimerEvent );
582 TimerSetValue( &TxTimer, TxPeriodicity );
583 OnTxTimerEvent( NULL );
584 }
585 break;
586 case LORAMAC_HANDLER_TX_ON_EVENT:
587 {
588 }
589 break;
590 }
591 }
592
UplinkProcess(void)593 static void UplinkProcess( void )
594 {
595 LmHandlerErrorStatus_t status = LORAMAC_HANDLER_ERROR;
596
597 if( LmHandlerIsBusy( ) == true )
598 {
599 return;
600 }
601
602 uint8_t isPending = 0;
603 CRITICAL_SECTION_BEGIN( );
604 isPending = IsTxFramePending;
605 IsTxFramePending = 0;
606 CRITICAL_SECTION_END( );
607 if( isPending == 1 )
608 {
609 if( IsMcSessionStarted == false )
610 {
611 if( IsFileTransferDone == false )
612 {
613 if( IsClockSynched == false )
614 {
615 status = LmhpClockSyncAppTimeReq( );
616 }
617 else
618 {
619 AppDataBuffer[0] = randr( 0, 255 );
620 // Send random packet
621 LmHandlerAppData_t appData =
622 {
623 .Buffer = AppDataBuffer,
624 .BufferSize = 1,
625 .Port = 1,
626 };
627 status = LmHandlerSend( &appData, LmHandlerParams.IsTxConfirmed );
628 }
629 }
630 else
631 {
632 AppDataBuffer[0] = 0x05; // FragDataBlockAuthReq
633 AppDataBuffer[1] = FileRxCrc & 0x000000FF;
634 AppDataBuffer[2] = ( FileRxCrc >> 8 ) & 0x000000FF;
635 AppDataBuffer[3] = ( FileRxCrc >> 16 ) & 0x000000FF;
636 AppDataBuffer[4] = ( FileRxCrc >> 24 ) & 0x000000FF;
637
638 // Send FragAuthReq
639 LmHandlerAppData_t appData =
640 {
641 .Buffer = AppDataBuffer,
642 .BufferSize = 5,
643 .Port = 201,
644 };
645 status = LmHandlerSend( &appData, LmHandlerParams.IsTxConfirmed );
646 }
647 if( status == LORAMAC_HANDLER_SUCCESS )
648 {
649 // Switch LED 1 ON
650 GpioWrite( &Led1, 0 );
651 TimerStart( &Led1Timer );
652 }
653 }
654 }
655 }
656
OnTxPeriodicityChanged(uint32_t periodicity)657 static void OnTxPeriodicityChanged( uint32_t periodicity )
658 {
659 TxPeriodicity = periodicity;
660
661 if( TxPeriodicity == 0 )
662 { // Revert to application default periodicity
663 TxPeriodicity = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
664 }
665
666 // Update timer periodicity
667 TimerStop( &TxTimer );
668 TimerSetValue( &TxTimer, TxPeriodicity );
669 TimerStart( &TxTimer );
670 }
671
OnTxFrameCtrlChanged(LmHandlerMsgTypes_t isTxConfirmed)672 static void OnTxFrameCtrlChanged( LmHandlerMsgTypes_t isTxConfirmed )
673 {
674 LmHandlerParams.IsTxConfirmed = isTxConfirmed;
675 }
676
OnPingSlotPeriodicityChanged(uint8_t pingSlotPeriodicity)677 static void OnPingSlotPeriodicityChanged( uint8_t pingSlotPeriodicity )
678 {
679 LmHandlerParams.PingSlotPeriodicity = pingSlotPeriodicity;
680 }
681
682 /*!
683 * Function executed on TxTimer event
684 */
OnTxTimerEvent(void * context)685 static void OnTxTimerEvent( void* context )
686 {
687 TimerStop( &TxTimer );
688
689 IsTxFramePending = 1;
690
691 // Schedule next transmission
692 TimerSetValue( &TxTimer, TxPeriodicity );
693 TimerStart( &TxTimer );
694 }
695
696 /*!
697 * Function executed on Led 1 Timeout event
698 */
OnLed1TimerEvent(void * context)699 static void OnLed1TimerEvent( void* context )
700 {
701 TimerStop( &Led1Timer );
702 // Switch LED 1 OFF
703 GpioWrite( &Led1, 1 );
704 }
705
706 /*!
707 * Function executed on Led 2 Timeout event
708 */
OnLed2TimerEvent(void * context)709 static void OnLed2TimerEvent( void* context )
710 {
711 TimerStop( &Led2Timer );
712 // Switch LED 2 ON
713 GpioWrite( &Led2, 0 );
714 }
715
716 /*!
717 * \brief Function executed on Beacon timer Timeout event
718 */
OnLedBeaconTimerEvent(void * context)719 static void OnLedBeaconTimerEvent( void* context )
720 {
721 GpioWrite( &Led2, 0 );
722 TimerStart( &Led2Timer );
723
724 TimerStart( &LedBeaconTimer );
725 }
726