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