53
53
#include "supervisor/port.h"
54
54
#include "supervisor/serial.h"
55
55
#include "supervisor/shared/autoreload.h"
56
- #include "supervisor/shared/rgb_led_status.h"
57
56
#include "supervisor/shared/safe_mode.h"
58
57
#include "supervisor/shared/stack.h"
59
58
#include "supervisor/shared/status_leds.h"
@@ -114,7 +113,6 @@ static void reset_devices(void) {
114
113
}
115
114
116
115
STATIC void start_mp (supervisor_allocation * heap ) {
117
- reset_status_led ();
118
116
autoreload_stop ();
119
117
supervisor_workflow_reset ();
120
118
@@ -251,7 +249,6 @@ STATIC void cleanup_after_vm(supervisor_allocation* heap) {
251
249
#endif
252
250
reset_port ();
253
251
reset_board ();
254
- reset_status_led ();
255
252
}
256
253
257
254
STATIC void print_code_py_status_message (safe_mode_t safe_mode ) {
@@ -284,8 +281,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
284
281
bool found_main = false;
285
282
286
283
if (safe_mode == NO_SAFE_MODE ) {
287
- new_status_color (MAIN_RUNNING );
288
-
289
284
static const char * const supported_filenames [] = STRING_LIST (
290
285
"code.txt" , "code.py" , "main.py" , "main.txt" );
291
286
#if CIRCUITPY_FULL_BUILD
@@ -311,6 +306,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
311
306
serial_write_compressed (translate ("WARNING: Your code filename has two extensions\n" ));
312
307
}
313
308
}
309
+ #else
310
+ (void ) found_main ;
314
311
#endif
315
312
316
313
cleanup_after_vm (heap );
@@ -327,42 +324,64 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
327
324
}
328
325
329
326
// Program has finished running.
330
-
331
327
bool printed_press_any_key = false;
332
328
#if CIRCUITPY_DISPLAYIO
333
- bool refreshed_epaper_display = false ;
329
+ size_t time_to_epaper_refresh = 1 ;
334
330
#endif
335
331
336
- rgb_status_animation_t animation ;
337
- prep_rgb_status_animation (& result , found_main , safe_mode , & animation );
332
+ // Setup LED blinks.
333
+ #if CIRCUITPY_STATUS_LED
334
+ uint32_t color ;
335
+ uint8_t blink_count ;
336
+ #if CIRCUITPY_ALARM
337
+ if (result .return_code & PYEXEC_DEEP_SLEEP ) {
338
+ color = BLACK ;
339
+ blink_count = 0 ;
340
+ } else
341
+ #endif
342
+ if (result .return_code != PYEXEC_EXCEPTION ) {
343
+ if (safe_mode == NO_SAFE_MODE ) {
344
+ color = ALL_DONE ;
345
+ blink_count = ALL_DONE_BLINKS ;
346
+ } else {
347
+ color = SAFE_MODE ;
348
+ blink_count = SAFE_MODE_BLINKS ;
349
+ }
350
+ } else {
351
+ color = EXCEPTION ;
352
+ blink_count = EXCEPTION_BLINKS ;
353
+ }
354
+ size_t pattern_start = supervisor_ticks_ms32 ();
355
+ size_t single_blink_time = (OFF_ON_RATIO + 1 ) * BLINK_TIME_MS ;
356
+ size_t blink_time = single_blink_time * blink_count ;
357
+ size_t total_time = blink_time + LED_SLEEP_TIME_MS ;
358
+ if (blink_count > 0 ) {
359
+ status_led_init ();
360
+ }
361
+ #endif
362
+
363
+ #if CIRCUITPY_ALARM
338
364
bool fake_sleeping = false;
365
+ #endif
366
+ bool skip_repl = false;
339
367
while (true) {
340
368
RUN_BACKGROUND_TASKS ;
341
369
342
370
// If a reload was requested by the supervisor or autoreload, return
343
371
if (reload_requested ) {
344
- #if CIRCUITPY_ALARM
345
- if (fake_sleeping ) {
346
- board_init ();
347
- }
348
- #endif
349
372
reload_requested = false;
350
- return true;
373
+ skip_repl = true;
374
+ break ;
351
375
}
352
376
353
377
// If interrupted by keyboard, return
354
378
if (serial_connected () && serial_bytes_available ()) {
355
- #if CIRCUITPY_ALARM
356
- if (fake_sleeping ) {
357
- board_init ();
358
- }
359
- #endif
360
379
// Skip REPL if reload was requested.
361
- bool ctrl_d = serial_read () == CHAR_CTRL_D ;
362
- if (ctrl_d ) {
380
+ skip_repl = serial_read () == CHAR_CTRL_D ;
381
+ if (skip_repl ) {
363
382
supervisor_set_run_reason (RUN_REASON_REPL_RELOAD );
364
383
}
365
- return ctrl_d ;
384
+ break ;
366
385
}
367
386
368
387
// Check for a deep sleep alarm and restart the VM. This can happen if
@@ -371,9 +390,9 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
371
390
#if CIRCUITPY_ALARM
372
391
if (fake_sleeping && common_hal_alarm_woken_from_sleep ()) {
373
392
serial_write_compressed (translate ("Woken up by alarm.\n" ));
374
- board_init ();
375
393
supervisor_set_run_reason (RUN_REASON_STARTUP );
376
- return true;
394
+ skip_repl = true;
395
+ break ;
377
396
}
378
397
#endif
379
398
@@ -393,25 +412,21 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
393
412
printed_press_any_key = false;
394
413
}
395
414
396
- // Refresh the ePaper display if we have one. That way it'll show an error message.
397
- #if CIRCUITPY_DISPLAYIO
398
- // Don't refresh the display if we're about to deep sleep.
399
- #if CIRCUITPY_ALARM
400
- refreshed_epaper_display = refreshed_epaper_display || result .return_code & PYEXEC_DEEP_SLEEP ;
401
- #endif
402
- if (!refreshed_epaper_display ) {
403
- refreshed_epaper_display = maybe_refresh_epaperdisplay ();
404
- }
405
- #endif
406
-
407
415
// Sleep until our next interrupt.
408
416
#if CIRCUITPY_ALARM
409
417
if (result .return_code & PYEXEC_DEEP_SLEEP ) {
410
418
// Make sure we have been awake long enough for USB to connect (enumeration delay).
411
419
int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks (NULL );
412
- // Until it's safe to decide whether we're real/fake sleeping, just run the RGB
413
- if (connecting_delay_ticks < 0 && !fake_sleeping ) {
414
- fake_sleeping = true;
420
+ // Until it's safe to decide whether we're real/fake sleeping
421
+ if (fake_sleeping ) {
422
+ // This waits until a pretend deep sleep alarm occurs. They are set
423
+ // during common_hal_alarm_set_deep_sleep_alarms. On some platforms
424
+ // it may also return due to another interrupt, that's why we check
425
+ // for deep sleep alarms above. If it wasn't a deep sleep alarm,
426
+ // then we'll idle here again.
427
+ common_hal_alarm_pretending_deep_sleep ();
428
+ } else if (connecting_delay_ticks < 0 ) {
429
+ // Entering deep sleep (may be fake or real.)
415
430
new_status_color (BLACK );
416
431
board_deinit ();
417
432
if (!supervisor_workflow_active ()) {
@@ -421,27 +436,71 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
421
436
// Does not return.
422
437
} else {
423
438
serial_write_compressed (translate ("Pretending to deep sleep until alarm, CTRL-C or file write.\n" ));
439
+ fake_sleeping = true;
424
440
}
441
+ } else {
442
+ // Loop while checking the time. We can't idle because we don't want to override a
443
+ // time alarm set for the deep sleep.
425
444
}
426
- }
445
+ } else
427
446
#endif
447
+ {
448
+ // Refresh the ePaper display if we have one. That way it'll show an error message.
449
+ #if CIRCUITPY_DISPLAYIO
450
+ if (time_to_epaper_refresh > 0 ) {
451
+ time_to_epaper_refresh = maybe_refresh_epaperdisplay ();
452
+ }
428
453
429
- if (!fake_sleeping ) {
430
- tick_rgb_status_animation (& animation );
431
- } else {
432
- // This waits until a pretend deep sleep alarm occurs. They are set
433
- // during common_hal_alarm_set_deep_sleep_alarms. On some platforms
434
- // it may also return due to another interrupt, that's why we check
435
- // for deep sleep alarms above. If it wasn't a deep sleep alarm,
436
- // then we'll idle here again.
454
+ #if !CIRCUITPY_STATUS_LED
455
+ port_interrupt_after_ticks (time_to_epaper_refresh );
456
+ #endif
457
+ #endif
437
458
438
- #if CIRCUITPY_ALARM
439
- common_hal_alarm_pretending_deep_sleep ();
440
- #else
441
- port_idle_until_interrupt ();
459
+ #if CIRCUITPY_STATUS_LED
460
+ uint32_t tick_diff = supervisor_ticks_ms32 () - pattern_start ;
461
+
462
+ // By default, don't sleep.
463
+ size_t time_to_next_change = 0 ;
464
+ if (tick_diff < blink_time ) {
465
+ uint32_t blink_diff = tick_diff % (single_blink_time );
466
+ if (blink_diff >= BLINK_TIME_MS ) {
467
+ new_status_color (BLACK );
468
+ time_to_next_change = single_blink_time - blink_diff ;
469
+ } else {
470
+ new_status_color (color );
471
+ time_to_next_change = BLINK_TIME_MS - blink_diff ;
472
+ }
473
+ } else if (tick_diff > total_time ) {
474
+ pattern_start = supervisor_ticks_ms32 ();
475
+ } else {
476
+ time_to_next_change = total_time - tick_diff ;
477
+ }
478
+ #if CIRCUITPY_DISPLAYIO
479
+ if (time_to_epaper_refresh > 0 && time_to_next_change > 0 ) {
480
+ time_to_next_change = MIN (time_to_next_change , time_to_epaper_refresh );
481
+ }
442
482
#endif
483
+ if (time_to_next_change > 0 ) {
484
+ // time_to_next_change is in ms and ticks are slightly shorter so
485
+ // we'll undersleep just a little. It shouldn't matter.
486
+ port_interrupt_after_ticks (time_to_next_change );
487
+ }
488
+ #endif
489
+ port_idle_until_interrupt ();
443
490
}
444
491
}
492
+ // Done waiting, start the board back up.
493
+ #if CIRCUITPY_STATUS_LED
494
+ new_status_color (BLACK );
495
+ status_led_deinit ();
496
+ #endif
497
+
498
+ #if CIRCUITPY_ALARM
499
+ if (fake_sleeping ) {
500
+ board_init ();
501
+ }
502
+ #endif
503
+ return skip_repl ;
445
504
}
446
505
447
506
FIL * boot_output_file ;
@@ -458,7 +517,6 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
458
517
bool skip_boot_output = false;
459
518
460
519
if (ok_to_run ) {
461
- new_status_color (BOOT_RUNNING );
462
520
463
521
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
464
522
FIL file_pointer ;
@@ -569,7 +627,16 @@ STATIC int run_repl(void) {
569
627
#endif
570
628
571
629
autoreload_suspend ();
630
+
631
+ // Set the status LED to the REPL color before running the REPL. For
632
+ // NeoPixels and DotStars this will be sticky but for PWM or single LED it
633
+ // won't. This simplifies pin sharing because they won't be in use when
634
+ // actually in the REPL.
635
+ #if CIRCUITPY_STATUS_LED
636
+ status_led_init ();
572
637
new_status_color (REPL_RUNNING );
638
+ status_led_deinit ();
639
+ #endif
573
640
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL ) {
574
641
exit_code = pyexec_raw_repl ();
575
642
} else {
@@ -584,9 +651,8 @@ int __attribute__((used)) main(void) {
584
651
// initialise the cpu and peripherals
585
652
safe_mode_t safe_mode = port_init ();
586
653
587
- // Turn on LEDs
588
- init_status_leds ();
589
- rgb_led_status_init ();
654
+ // Turn on RX and TX LEDs if we have them.
655
+ init_rxtx_leds ();
590
656
591
657
// Wait briefly to give a reset window where we'll enter safe mode after the reset.
592
658
if (safe_mode == NO_SAFE_MODE ) {
0 commit comments