@@ -284,9 +284,12 @@ fn main() -> ! {
284
284
let mut usb_suspended = false ;
285
285
let mut last_usb_suspended = usb_suspended;
286
286
let mut sleep_reason: Option < SleepReason > = None ;
287
+ let mut last_sleep_reason: Option < SleepReason > ;
287
288
let mut last_host_sleep = sleep. is_low ( ) . unwrap ( ) ;
288
289
289
290
loop {
291
+ last_sleep_reason = sleep_reason;
292
+
290
293
if dip1_present {
291
294
state. debug_mode = dip1. is_high ( ) . unwrap ( ) ;
292
295
}
@@ -298,11 +301,13 @@ fn main() -> ! {
298
301
// Or if it currently sleeping. Don't change if not sleeping
299
302
// because then sleep is controlled by timing or by API.
300
303
if host_sleep_changed || host_sleeping {
301
- sleep_reason = if host_sleeping {
302
- Some ( SleepReason :: SleepPin )
303
- } else {
304
- None
305
- } ;
304
+ sleep_reason = assign_sleep_reason (
305
+ last_sleep_reason,
306
+ sleep_reason,
307
+ host_sleeping,
308
+ host_sleep_changed,
309
+ SleepReason :: SleepPin ,
310
+ ) ;
306
311
}
307
312
last_host_sleep = host_sleeping;
308
313
}
@@ -316,17 +321,25 @@ fn main() -> ! {
316
321
// initialized for the first time. But we don't want to show the
317
322
// sleep animation during startup.
318
323
if usb_initialized && ( usb_suspended_changed || usb_suspended) {
319
- sleep_reason = if usb_suspended {
320
- Some ( SleepReason :: UsbSuspend )
321
- } else {
322
- None
323
- } ;
324
+ sleep_reason = assign_sleep_reason (
325
+ last_sleep_reason,
326
+ sleep_reason,
327
+ usb_suspended,
328
+ usb_suspended_changed,
329
+ SleepReason :: UsbSuspend ,
330
+ ) ;
324
331
}
325
332
last_usb_suspended = usb_suspended;
326
333
327
334
// Go to sleep after the timer has run out
328
335
if timer. get_counter ( ) . ticks ( ) > sleep_timer + SLEEP_TIMEOUT && !state. debug_mode {
329
- sleep_reason = Some ( SleepReason :: Timeout ) ;
336
+ sleep_reason = assign_sleep_reason (
337
+ last_sleep_reason,
338
+ sleep_reason,
339
+ true ,
340
+ true ,
341
+ SleepReason :: Timeout ,
342
+ ) ;
330
343
}
331
344
// Constantly resetting timer during sleep is same as reset it once on waking up.
332
345
// This means the timer ends up counting the time spent awake.
@@ -401,11 +414,13 @@ fn main() -> ! {
401
414
}
402
415
( Some ( command) , _) => {
403
416
if let Command :: Sleep ( go_sleeping) = command {
404
- sleep_reason = if go_sleeping {
405
- Some ( SleepReason :: Command )
406
- } else {
407
- None
408
- } ;
417
+ sleep_reason = assign_sleep_reason (
418
+ last_sleep_reason,
419
+ sleep_reason,
420
+ go_sleeping,
421
+ true ,
422
+ SleepReason :: Command ,
423
+ ) ;
409
424
} else {
410
425
// If already sleeping, wake up.
411
426
// This means every command will wake the device up.
@@ -542,6 +557,23 @@ fn show_startup_animation(state: &LedmatrixState) -> bool {
542
557
STARTUP_ANIMATION && !debug_mode ( state)
543
558
}
544
559
560
+ fn assign_sleep_reason (
561
+ previous : Option < SleepReason > ,
562
+ current : Option < SleepReason > ,
563
+ need_sleep : bool ,
564
+ // Whether the signal has actually changed in between firing
565
+ signal_changed : bool ,
566
+ new : SleepReason ,
567
+ ) -> Option < SleepReason > {
568
+ if !need_sleep {
569
+ None
570
+ } else if current. is_some ( ) && ( Some ( new) == previous || !signal_changed) {
571
+ current
572
+ } else {
573
+ Some ( new)
574
+ }
575
+ }
576
+
545
577
// Will do nothing if already in the right state
546
578
fn handle_sleep (
547
579
sleep_reason : Option < SleepReason > ,
@@ -551,6 +583,7 @@ fn handle_sleep(
551
583
led_enable : & mut gpio:: Pin < Gpio29 , gpio:: Output < gpio:: PushPull > > ,
552
584
) {
553
585
match ( state. sleeping . clone ( ) , sleep_reason) {
586
+ // Awake and staying awake
554
587
( SleepState :: Awake , None ) => ( ) ,
555
588
( SleepState :: Awake , Some ( sleep_reason) ) => {
556
589
state. sleeping = SleepState :: Sleeping ( ( state. grid . clone ( ) , state. brightness ) ) ;
@@ -567,26 +600,34 @@ fn handle_sleep(
567
600
}
568
601
}
569
602
570
- // Turn LED controller off to save power
571
603
if debug_mode ( state) {
572
604
state. grid = display_sleep_reason ( sleep_reason) ;
573
605
fill_grid_pixels ( state, matrix) ;
574
606
} else {
607
+ // Turn LED controller off to save power
575
608
led_enable. set_low ( ) . unwrap ( ) ;
576
609
}
577
610
578
611
// TODO: Set up SLEEP# pin as interrupt and wfi
579
612
//cortex_m::asm::wfi();
580
613
}
581
- ( SleepState :: Sleeping ( _) , Some ( _) ) => ( ) ,
614
+ // Already sleeping and new sleep reason => just keep sleeping
615
+ ( SleepState :: Sleeping ( _) , Some ( sleep_reason) ) => {
616
+ // If debug mode is enabled, then make sure the latest sleep reason is displayed
617
+ if debug_mode ( state) {
618
+ state. grid = display_sleep_reason ( sleep_reason) ;
619
+ fill_grid_pixels ( state, matrix) ;
620
+ }
621
+ }
622
+ // Sleeping and need to wake up
582
623
( SleepState :: Sleeping ( ( old_grid, old_brightness) ) , None ) => {
583
624
// Restore back grid before sleeping
584
625
state. sleeping = SleepState :: Awake ;
585
626
state. grid = old_grid;
586
627
fill_grid_pixels ( state, matrix) ;
587
628
588
629
// Power LED controller back on
589
- if debug_mode ( state) {
630
+ if ! debug_mode ( state) {
590
631
led_enable. set_high ( ) . unwrap ( ) ;
591
632
}
592
633
0 commit comments