@@ -42,6 +42,9 @@ const MAX_CURRENT: usize = 500;
4242/// Maximum brightness out of 255
4343/// On HW Rev 1 from BizLink set to 94 to have just below 500mA current draw.
4444/// BizLink HW Rev 2 has a larger current limiting resistor
45+ #[ cfg( feature = "10k" ) ]
46+ const MAX_BRIGHTNESS : u8 = 94 ;
47+ #[ cfg( not( feature = "10k" ) ) ]
4548const MAX_BRIGHTNESS : u8 = 255 ;
4649
4750// TODO: Doesn't work yet, unless I panic right at the beginning of main
@@ -215,6 +218,18 @@ fn main() -> ! {
215218 & clocks. peripheral_clock ,
216219 ) ;
217220
221+ // Detect whether the dip1 pin is connected
222+ // We switched from bootsel button to DIP-switch with general purpose DIP1 pin in DVT2
223+ let mut dip1_present = false ;
224+ let dip1 = pins. dip1 . into_pull_up_input ( ) ;
225+ if dip1. is_low ( ) . unwrap ( ) {
226+ dip1_present = true ;
227+ }
228+ let dip1 = dip1. into_pull_down_input ( ) ;
229+ if dip1. is_high ( ) . unwrap ( ) {
230+ dip1_present = true ;
231+ }
232+
218233 let mut state = LedmatrixState {
219234 grid : percentage ( 0 ) ,
220235 col_buffer : Grid :: default ( ) ,
@@ -226,6 +241,14 @@ fn main() -> ! {
226241 pwm_freq : PwmFreqArg :: P29k ,
227242 debug_mode : false ,
228243 } ;
244+ if dip1_present {
245+ state. debug_mode = dip1. is_high ( ) . unwrap ( ) ;
246+ }
247+ if !show_startup_animation ( & state) {
248+ // If no startup animation, render another pattern
249+ // Lighting up every second column is a good pattern to test for noise.
250+ state. grid = every_nth_col ( 2 ) ;
251+ } ;
229252
230253 let mut matrix = LedMatrix :: configure ( i2c) ;
231254 matrix
@@ -246,9 +269,6 @@ fn main() -> ! {
246269 let mut sleep_timer = timer. get_counter ( ) . ticks ( ) ;
247270
248271 let mut startup_percentage = Some ( 0 ) ;
249- if !STARTUP_ANIMATION || state. debug_mode {
250- state. grid = percentage ( 100 ) ;
251- }
252272
253273 // Detect whether the sleep pin is connected
254274 // Early revisions of the hardware didn't have it wired up, if that is the
@@ -263,25 +283,16 @@ fn main() -> ! {
263283 sleep_present = true ;
264284 }
265285
266- // Detect whether the dip1 pin is connected
267- // We switched from bootsel button to DIP-switch with general purpose DIP1 pin in DVT2
268- let mut dip1_present = false ;
269- let dip1 = pins. dip1 . into_pull_up_input ( ) ;
270- if dip1. is_low ( ) . unwrap ( ) {
271- dip1_present = true ;
272- }
273- let dip1 = dip1. into_pull_down_input ( ) ;
274- if sleep. is_high ( ) . unwrap ( ) {
275- dip1_present = true ;
276- }
277-
278286 let mut usb_initialized = false ;
279287 let mut usb_suspended = false ;
280288 let mut last_usb_suspended = usb_suspended;
281289 let mut sleep_reason: Option < SleepReason > = None ;
290+ let mut last_sleep_reason: Option < SleepReason > ;
282291 let mut last_host_sleep = sleep. is_low ( ) . unwrap ( ) ;
283292
284293 loop {
294+ last_sleep_reason = sleep_reason;
295+
285296 if dip1_present {
286297 state. debug_mode = dip1. is_high ( ) . unwrap ( ) ;
287298 }
@@ -293,11 +304,13 @@ fn main() -> ! {
293304 // Or if it currently sleeping. Don't change if not sleeping
294305 // because then sleep is controlled by timing or by API.
295306 if host_sleep_changed || host_sleeping {
296- sleep_reason = if host_sleeping {
297- Some ( SleepReason :: SleepPin )
298- } else {
299- None
300- } ;
307+ sleep_reason = assign_sleep_reason (
308+ last_sleep_reason,
309+ sleep_reason,
310+ host_sleeping,
311+ host_sleep_changed,
312+ SleepReason :: SleepPin ,
313+ ) ;
301314 }
302315 last_host_sleep = host_sleeping;
303316 }
@@ -311,17 +324,25 @@ fn main() -> ! {
311324 // initialized for the first time. But we don't want to show the
312325 // sleep animation during startup.
313326 if usb_initialized && ( usb_suspended_changed || usb_suspended) {
314- sleep_reason = if usb_suspended {
315- Some ( SleepReason :: UsbSuspend )
316- } else {
317- None
318- } ;
327+ sleep_reason = assign_sleep_reason (
328+ last_sleep_reason,
329+ sleep_reason,
330+ usb_suspended,
331+ usb_suspended_changed,
332+ SleepReason :: UsbSuspend ,
333+ ) ;
319334 }
320335 last_usb_suspended = usb_suspended;
321336
322337 // Go to sleep after the timer has run out
323338 if timer. get_counter ( ) . ticks ( ) > sleep_timer + SLEEP_TIMEOUT && !state. debug_mode {
324- sleep_reason = Some ( SleepReason :: Timeout ) ;
339+ sleep_reason = assign_sleep_reason (
340+ last_sleep_reason,
341+ sleep_reason,
342+ true ,
343+ true ,
344+ SleepReason :: Timeout ,
345+ ) ;
325346 }
326347 // Constantly resetting timer during sleep is same as reset it once on waking up.
327348 // This means the timer ends up counting the time spent awake.
@@ -342,7 +363,7 @@ fn main() -> ! {
342363 if matches ! ( state. sleeping, SleepState :: Awake ) && render_again {
343364 // On startup slowly turn the screen on - it's a pretty effect :)
344365 match startup_percentage {
345- Some ( p) if p <= 100 && ( STARTUP_ANIMATION || state. debug_mode ) => {
366+ Some ( p) if p <= 100 && show_startup_animation ( & state) => {
346367 state. grid = percentage ( p) ;
347368 startup_percentage = Some ( p + 5 ) ;
348369 }
@@ -396,11 +417,13 @@ fn main() -> ! {
396417 }
397418 ( Some ( command) , _) => {
398419 if let Command :: Sleep ( go_sleeping) = command {
399- sleep_reason = if go_sleeping {
400- Some ( SleepReason :: Command )
401- } else {
402- None
403- } ;
420+ sleep_reason = assign_sleep_reason (
421+ last_sleep_reason,
422+ sleep_reason,
423+ go_sleeping,
424+ true ,
425+ SleepReason :: Command ,
426+ ) ;
404427 } else {
405428 // If already sleeping, wake up.
406429 // This means every command will wake the device up.
@@ -520,14 +543,40 @@ fn get_random_byte(rosc: &RingOscillator<Enabled>) -> u8 {
520543 byte
521544}
522545
523- fn dyn_sleep_mode ( state : & mut LedmatrixState ) -> SleepMode {
546+ fn dyn_sleep_mode ( state : & LedmatrixState ) -> SleepMode {
524547 if state. debug_mode {
525548 SleepMode :: Debug
526549 } else {
527550 SLEEP_MODE
528551 }
529552}
530553
554+ fn debug_mode ( state : & LedmatrixState ) -> bool {
555+ dyn_sleep_mode ( state) == SleepMode :: Debug
556+ }
557+
558+ fn show_startup_animation ( state : & LedmatrixState ) -> bool {
559+ // Show startup animation
560+ STARTUP_ANIMATION && !debug_mode ( state)
561+ }
562+
563+ fn assign_sleep_reason (
564+ previous : Option < SleepReason > ,
565+ current : Option < SleepReason > ,
566+ need_sleep : bool ,
567+ // Whether the signal has actually changed in between firing
568+ signal_changed : bool ,
569+ new : SleepReason ,
570+ ) -> Option < SleepReason > {
571+ if !need_sleep {
572+ None
573+ } else if current. is_some ( ) && ( Some ( new) == previous || !signal_changed) {
574+ current
575+ } else {
576+ Some ( new)
577+ }
578+ }
579+
531580// Will do nothing if already in the right state
532581fn handle_sleep (
533582 sleep_reason : Option < SleepReason > ,
@@ -537,6 +586,7 @@ fn handle_sleep(
537586 led_enable : & mut gpio:: Pin < Gpio29 , gpio:: Output < gpio:: PushPull > > ,
538587) {
539588 match ( state. sleeping . clone ( ) , sleep_reason) {
589+ // Awake and staying awake
540590 ( SleepState :: Awake , None ) => ( ) ,
541591 ( SleepState :: Awake , Some ( sleep_reason) ) => {
542592 state. sleeping = SleepState :: Sleeping ( ( state. grid . clone ( ) , state. brightness ) ) ;
@@ -553,26 +603,34 @@ fn handle_sleep(
553603 }
554604 }
555605
556- // Turn LED controller off to save power
557- if dyn_sleep_mode ( state) == SleepMode :: Debug {
606+ if debug_mode ( state) {
558607 state. grid = display_sleep_reason ( sleep_reason) ;
559608 fill_grid_pixels ( state, matrix) ;
560609 } else {
610+ // Turn LED controller off to save power
561611 led_enable. set_low ( ) . unwrap ( ) ;
562612 }
563613
564614 // TODO: Set up SLEEP# pin as interrupt and wfi
565615 //cortex_m::asm::wfi();
566616 }
567- ( SleepState :: Sleeping ( _) , Some ( _) ) => ( ) ,
617+ // Already sleeping and new sleep reason => just keep sleeping
618+ ( SleepState :: Sleeping ( _) , Some ( sleep_reason) ) => {
619+ // If debug mode is enabled, then make sure the latest sleep reason is displayed
620+ if debug_mode ( state) {
621+ state. grid = display_sleep_reason ( sleep_reason) ;
622+ fill_grid_pixels ( state, matrix) ;
623+ }
624+ }
625+ // Sleeping and need to wake up
568626 ( SleepState :: Sleeping ( ( old_grid, old_brightness) ) , None ) => {
569627 // Restore back grid before sleeping
570628 state. sleeping = SleepState :: Awake ;
571629 state. grid = old_grid;
572630 fill_grid_pixels ( state, matrix) ;
573631
574632 // Power LED controller back on
575- if dyn_sleep_mode ( state) != SleepMode :: Debug {
633+ if ! debug_mode ( state) {
576634 led_enable. set_high ( ) . unwrap ( ) ;
577635 }
578636
0 commit comments