@@ -42,6 +42,9 @@ const MAX_CURRENT: usize = 500;
42
42
/// Maximum brightness out of 255
43
43
/// On HW Rev 1 from BizLink set to 94 to have just below 500mA current draw.
44
44
/// 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" ) ) ]
45
48
const MAX_BRIGHTNESS : u8 = 255 ;
46
49
47
50
// TODO: Doesn't work yet, unless I panic right at the beginning of main
@@ -215,6 +218,18 @@ fn main() -> ! {
215
218
& clocks. peripheral_clock ,
216
219
) ;
217
220
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
+
218
233
let mut state = LedmatrixState {
219
234
grid : percentage ( 0 ) ,
220
235
col_buffer : Grid :: default ( ) ,
@@ -226,6 +241,14 @@ fn main() -> ! {
226
241
pwm_freq : PwmFreqArg :: P29k ,
227
242
debug_mode : false ,
228
243
} ;
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
+ } ;
229
252
230
253
let mut matrix = LedMatrix :: configure ( i2c) ;
231
254
matrix
@@ -246,9 +269,6 @@ fn main() -> ! {
246
269
let mut sleep_timer = timer. get_counter ( ) . ticks ( ) ;
247
270
248
271
let mut startup_percentage = Some ( 0 ) ;
249
- if !STARTUP_ANIMATION || state. debug_mode {
250
- state. grid = percentage ( 100 ) ;
251
- }
252
272
253
273
// Detect whether the sleep pin is connected
254
274
// Early revisions of the hardware didn't have it wired up, if that is the
@@ -263,25 +283,16 @@ fn main() -> ! {
263
283
sleep_present = true ;
264
284
}
265
285
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
-
278
286
let mut usb_initialized = false ;
279
287
let mut usb_suspended = false ;
280
288
let mut last_usb_suspended = usb_suspended;
281
289
let mut sleep_reason: Option < SleepReason > = None ;
290
+ let mut last_sleep_reason: Option < SleepReason > ;
282
291
let mut last_host_sleep = sleep. is_low ( ) . unwrap ( ) ;
283
292
284
293
loop {
294
+ last_sleep_reason = sleep_reason;
295
+
285
296
if dip1_present {
286
297
state. debug_mode = dip1. is_high ( ) . unwrap ( ) ;
287
298
}
@@ -293,11 +304,13 @@ fn main() -> ! {
293
304
// Or if it currently sleeping. Don't change if not sleeping
294
305
// because then sleep is controlled by timing or by API.
295
306
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
+ ) ;
301
314
}
302
315
last_host_sleep = host_sleeping;
303
316
}
@@ -311,17 +324,25 @@ fn main() -> ! {
311
324
// initialized for the first time. But we don't want to show the
312
325
// sleep animation during startup.
313
326
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
+ ) ;
319
334
}
320
335
last_usb_suspended = usb_suspended;
321
336
322
337
// Go to sleep after the timer has run out
323
338
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
+ ) ;
325
346
}
326
347
// Constantly resetting timer during sleep is same as reset it once on waking up.
327
348
// This means the timer ends up counting the time spent awake.
@@ -342,7 +363,7 @@ fn main() -> ! {
342
363
if matches ! ( state. sleeping, SleepState :: Awake ) && render_again {
343
364
// On startup slowly turn the screen on - it's a pretty effect :)
344
365
match startup_percentage {
345
- Some ( p) if p <= 100 && ( STARTUP_ANIMATION || state. debug_mode ) => {
366
+ Some ( p) if p <= 100 && show_startup_animation ( & state) => {
346
367
state. grid = percentage ( p) ;
347
368
startup_percentage = Some ( p + 5 ) ;
348
369
}
@@ -396,11 +417,13 @@ fn main() -> ! {
396
417
}
397
418
( Some ( command) , _) => {
398
419
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
+ ) ;
404
427
} else {
405
428
// If already sleeping, wake up.
406
429
// This means every command will wake the device up.
@@ -520,14 +543,40 @@ fn get_random_byte(rosc: &RingOscillator<Enabled>) -> u8 {
520
543
byte
521
544
}
522
545
523
- fn dyn_sleep_mode ( state : & mut LedmatrixState ) -> SleepMode {
546
+ fn dyn_sleep_mode ( state : & LedmatrixState ) -> SleepMode {
524
547
if state. debug_mode {
525
548
SleepMode :: Debug
526
549
} else {
527
550
SLEEP_MODE
528
551
}
529
552
}
530
553
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
+
531
580
// Will do nothing if already in the right state
532
581
fn handle_sleep (
533
582
sleep_reason : Option < SleepReason > ,
@@ -537,6 +586,7 @@ fn handle_sleep(
537
586
led_enable : & mut gpio:: Pin < Gpio29 , gpio:: Output < gpio:: PushPull > > ,
538
587
) {
539
588
match ( state. sleeping . clone ( ) , sleep_reason) {
589
+ // Awake and staying awake
540
590
( SleepState :: Awake , None ) => ( ) ,
541
591
( SleepState :: Awake , Some ( sleep_reason) ) => {
542
592
state. sleeping = SleepState :: Sleeping ( ( state. grid . clone ( ) , state. brightness ) ) ;
@@ -553,26 +603,34 @@ fn handle_sleep(
553
603
}
554
604
}
555
605
556
- // Turn LED controller off to save power
557
- if dyn_sleep_mode ( state) == SleepMode :: Debug {
606
+ if debug_mode ( state) {
558
607
state. grid = display_sleep_reason ( sleep_reason) ;
559
608
fill_grid_pixels ( state, matrix) ;
560
609
} else {
610
+ // Turn LED controller off to save power
561
611
led_enable. set_low ( ) . unwrap ( ) ;
562
612
}
563
613
564
614
// TODO: Set up SLEEP# pin as interrupt and wfi
565
615
//cortex_m::asm::wfi();
566
616
}
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
568
626
( SleepState :: Sleeping ( ( old_grid, old_brightness) ) , None ) => {
569
627
// Restore back grid before sleeping
570
628
state. sleeping = SleepState :: Awake ;
571
629
state. grid = old_grid;
572
630
fill_grid_pixels ( state, matrix) ;
573
631
574
632
// Power LED controller back on
575
- if dyn_sleep_mode ( state) != SleepMode :: Debug {
633
+ if ! debug_mode ( state) {
576
634
led_enable. set_high ( ) . unwrap ( ) ;
577
635
}
578
636
0 commit comments