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