@@ -284,9 +284,12 @@ fn main() -> ! {
284284 let mut usb_suspended = false ;
285285 let mut last_usb_suspended = usb_suspended;
286286 let mut sleep_reason: Option < SleepReason > = None ;
287+ let mut last_sleep_reason: Option < SleepReason > ;
287288 let mut last_host_sleep = sleep. is_low ( ) . unwrap ( ) ;
288289
289290 loop {
291+ last_sleep_reason = sleep_reason;
292+
290293 if dip1_present {
291294 state. debug_mode = dip1. is_high ( ) . unwrap ( ) ;
292295 }
@@ -298,11 +301,13 @@ fn main() -> ! {
298301 // Or if it currently sleeping. Don't change if not sleeping
299302 // because then sleep is controlled by timing or by API.
300303 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+ ) ;
306311 }
307312 last_host_sleep = host_sleeping;
308313 }
@@ -316,17 +321,25 @@ fn main() -> ! {
316321 // initialized for the first time. But we don't want to show the
317322 // sleep animation during startup.
318323 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+ ) ;
324331 }
325332 last_usb_suspended = usb_suspended;
326333
327334 // Go to sleep after the timer has run out
328335 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+ ) ;
330343 }
331344 // Constantly resetting timer during sleep is same as reset it once on waking up.
332345 // This means the timer ends up counting the time spent awake.
@@ -401,11 +414,13 @@ fn main() -> ! {
401414 }
402415 ( Some ( command) , _) => {
403416 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+ ) ;
409424 } else {
410425 // If already sleeping, wake up.
411426 // This means every command will wake the device up.
@@ -542,6 +557,23 @@ fn show_startup_animation(state: &LedmatrixState) -> bool {
542557 STARTUP_ANIMATION && !debug_mode ( state)
543558}
544559
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+
545577// Will do nothing if already in the right state
546578fn handle_sleep (
547579 sleep_reason : Option < SleepReason > ,
@@ -551,6 +583,7 @@ fn handle_sleep(
551583 led_enable : & mut gpio:: Pin < Gpio29 , gpio:: Output < gpio:: PushPull > > ,
552584) {
553585 match ( state. sleeping . clone ( ) , sleep_reason) {
586+ // Awake and staying awake
554587 ( SleepState :: Awake , None ) => ( ) ,
555588 ( SleepState :: Awake , Some ( sleep_reason) ) => {
556589 state. sleeping = SleepState :: Sleeping ( ( state. grid . clone ( ) , state. brightness ) ) ;
@@ -567,26 +600,34 @@ fn handle_sleep(
567600 }
568601 }
569602
570- // Turn LED controller off to save power
571603 if debug_mode ( state) {
572604 state. grid = display_sleep_reason ( sleep_reason) ;
573605 fill_grid_pixels ( state, matrix) ;
574606 } else {
607+ // Turn LED controller off to save power
575608 led_enable. set_low ( ) . unwrap ( ) ;
576609 }
577610
578611 // TODO: Set up SLEEP# pin as interrupt and wfi
579612 //cortex_m::asm::wfi();
580613 }
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
582623 ( SleepState :: Sleeping ( ( old_grid, old_brightness) ) , None ) => {
583624 // Restore back grid before sleeping
584625 state. sleeping = SleepState :: Awake ;
585626 state. grid = old_grid;
586627 fill_grid_pixels ( state, matrix) ;
587628
588629 // Power LED controller back on
589- if debug_mode ( state) {
630+ if ! debug_mode ( state) {
590631 led_enable. set_high ( ) . unwrap ( ) ;
591632 }
592633
0 commit comments