@@ -33,6 +33,10 @@ const SLEEP_MODE: SleepMode = SleepMode::Fading;
33
33
34
34
const STARTUP_ANIMATION : bool = true ;
35
35
36
+ /// Go to sleep after 60s awake
37
+ const SLEEP_TIMEOUT : u64 = 60_000_000 ;
38
+
39
+ /// List maximum current as 500mA in the USB descriptor
36
40
const MAX_CURRENT : usize = 500 ;
37
41
38
42
/// Maximum brightness out of 255
@@ -232,8 +236,9 @@ fn main() -> ! {
232
236
fill_grid_pixels ( & state, & mut matrix) ;
233
237
234
238
let timer = Timer :: new ( pac. TIMER , & mut pac. RESETS ) ;
235
- let mut prev_timer = timer. get_counter ( ) . ticks ( ) ;
239
+ let mut animation_timer = timer. get_counter ( ) . ticks ( ) ;
236
240
let mut game_timer = timer. get_counter ( ) . ticks ( ) ;
241
+ let mut sleep_timer = timer. get_counter ( ) . ticks ( ) ;
237
242
238
243
let mut startup_percentage = Some ( 0 ) ;
239
244
if !STARTUP_ANIMATION {
@@ -254,27 +259,58 @@ fn main() -> ! {
254
259
}
255
260
256
261
let mut usb_initialized = false ;
257
- let mut usb_suspended = true ;
262
+ let mut usb_suspended = false ;
263
+ let mut last_usb_suspended = usb_suspended;
264
+ let mut sleeping = false ;
265
+ let mut last_host_sleep = sleep. is_low ( ) . unwrap ( ) ;
258
266
259
267
loop {
260
268
if sleep_present {
261
269
// Go to sleep if the host is sleeping
262
- // Or if USB is suspended. Only if it was previously initialized,
263
- // since the OS puts the device into suspend before it's fully
264
- // initialized for the first time. But we don't want to show the
265
- // sleep animation during startup.
266
- let host_sleeping = sleep. is_low ( ) . unwrap ( ) || ( usb_suspended && usb_initialized) ;
267
- handle_sleep (
268
- host_sleeping,
269
- & mut state,
270
- & mut matrix,
271
- & mut delay,
272
- & mut led_enable,
273
- ) ;
270
+ let host_sleeping = sleep. is_low ( ) . unwrap ( ) ;
271
+ let host_sleep_changed = host_sleeping != last_host_sleep;
272
+ // Change sleep state either if SLEEP# has changed
273
+ // Or if it currently sleeping. Don't change if not sleeping
274
+ // because then sleep is controlled by timing or by API.
275
+ if host_sleep_changed || host_sleeping {
276
+ sleeping = host_sleeping;
277
+ }
278
+ last_host_sleep = host_sleeping;
274
279
}
275
280
281
+ // Change sleep state either if SLEEP# has changed
282
+ // Or if it currently sleeping. Don't change if not sleeping
283
+ // because then sleep is controlled by timing or by API.
284
+ let usb_suspended_changed = usb_suspended != last_usb_suspended;
285
+ // Only if USB was previously initialized,
286
+ // since the OS puts the device into suspend before it's fully
287
+ // initialized for the first time. But we don't want to show the
288
+ // sleep animation during startup.
289
+ if usb_initialized && ( usb_suspended_changed || usb_suspended) {
290
+ sleeping = usb_suspended;
291
+ }
292
+ last_usb_suspended = usb_suspended;
293
+
294
+ // Go to sleep after the timer has run out
295
+ if timer. get_counter ( ) . ticks ( ) > sleep_timer + SLEEP_TIMEOUT {
296
+ sleeping = true ;
297
+ }
298
+ // Constantly resetting timer during sleep is same as reset it once on waking up.
299
+ // This means the timer ends up counting the time spent awake.
300
+ if sleeping {
301
+ sleep_timer = timer. get_counter ( ) . ticks ( ) ;
302
+ }
303
+
304
+ handle_sleep (
305
+ sleeping,
306
+ & mut state,
307
+ & mut matrix,
308
+ & mut delay,
309
+ & mut led_enable,
310
+ ) ;
311
+
276
312
// Handle period display updates. Don't do it too often
277
- let render_again = timer. get_counter ( ) . ticks ( ) > prev_timer + state. animation_period ;
313
+ let render_again = timer. get_counter ( ) . ticks ( ) > animation_timer + state. animation_period ;
278
314
if matches ! ( state. sleeping, SleepState :: Awake ) && render_again {
279
315
// On startup slowly turn the screen on - it's a pretty effect :)
280
316
match startup_percentage {
@@ -291,7 +327,7 @@ fn main() -> ! {
291
327
state. grid . 0 [ x] . rotate_right ( 1 ) ;
292
328
}
293
329
}
294
- prev_timer = timer. get_counter ( ) . ticks ( ) ;
330
+ animation_timer = timer. get_counter ( ) . ticks ( ) ;
295
331
}
296
332
297
333
// Check for new data
@@ -325,28 +361,43 @@ fn main() -> ! {
325
361
Ok ( count) => {
326
362
let random = get_random_byte ( & rosc) ;
327
363
match ( parse_command ( count, & buf) , & state. sleeping ) {
328
- ( Some ( Command :: Sleep ( go_sleeping) ) , _) => {
364
+ // Handle bootloader command without any delay
365
+ // No need, it'll reset the device anyways
366
+ ( Some ( c @ Command :: BootloaderReset ) , _) => {
367
+ handle_command ( & c, & mut state, & mut matrix, random) ;
368
+ }
369
+ ( Some ( command) , _) => {
370
+ if let Command :: Sleep ( go_sleeping) = command {
371
+ sleeping = go_sleeping;
372
+ } else {
373
+ // If already sleeping, wake up.
374
+ // This means every command will wake the device up.
375
+ // Much more convenient than having to send the wakeup commmand.
376
+ sleeping = false ;
377
+ }
378
+ // Make sure sleep animation only goes up to newly set brightness,
379
+ // if setting the brightness causes wakeup
380
+ if let SleepState :: Sleeping ( ( ref grid, _) ) = state. sleeping {
381
+ if let Command :: SetBrightness ( new_brightness) = command {
382
+ state. sleeping =
383
+ SleepState :: Sleeping ( ( grid. clone ( ) , new_brightness) ) ;
384
+ }
385
+ }
329
386
handle_sleep (
330
- go_sleeping ,
387
+ sleeping ,
331
388
& mut state,
332
389
& mut matrix,
333
390
& mut delay,
334
391
& mut led_enable,
335
392
) ;
336
- }
337
- ( Some ( c @ Command :: BootloaderReset ) , _)
338
- | ( Some ( c @ Command :: IsSleeping ) , _) => {
339
- if let Some ( response) =
340
- handle_command ( & c, & mut state, & mut matrix, random)
341
- {
342
- let _ = serial. write ( & response) ;
343
- } ;
344
- }
345
- ( Some ( command) , SleepState :: Awake ) => {
393
+
346
394
// If there's a very early command, cancel the startup animation
347
395
startup_percentage = None ;
348
396
349
- // While sleeping no command is handled, except waking up
397
+ // Reset sleep timer when interacting with the device
398
+ // Very easy way to keep the device from going to sleep
399
+ sleep_timer = timer. get_counter ( ) . ticks ( ) ;
400
+
350
401
if let Some ( response) =
351
402
handle_command ( & command, & mut state, & mut matrix, random)
352
403
{
@@ -361,9 +412,11 @@ fn main() -> ! {
361
412
buf[ 0 ] , buf[ 1 ] , buf[ 2 ] , buf[ 3 ]
362
413
)
363
414
. unwrap ( ) ;
415
+ // let _ = serial.write(text.as_bytes());
416
+
364
417
fill_grid_pixels ( & state, & mut matrix) ;
365
418
}
366
- _ => { }
419
+ ( None , _ ) => { }
367
420
}
368
421
}
369
422
}
@@ -435,6 +488,7 @@ fn get_random_byte(rosc: &RingOscillator<Enabled>) -> u8 {
435
488
byte
436
489
}
437
490
491
+ // Will do nothing if already in the right state
438
492
fn handle_sleep (
439
493
go_sleeping : bool ,
440
494
state : & mut LedmatrixState ,
0 commit comments