diff --git a/main.c b/main.c index f963c2c250..94d35fb8d7 100755 --- a/main.c +++ b/main.c @@ -53,7 +53,6 @@ #include "supervisor/port.h" #include "supervisor/serial.h" #include "supervisor/shared/autoreload.h" -#include "supervisor/shared/rgb_led_status.h" #include "supervisor/shared/safe_mode.h" #include "supervisor/shared/stack.h" #include "supervisor/shared/status_leds.h" @@ -114,7 +113,6 @@ static void reset_devices(void) { } STATIC void start_mp(supervisor_allocation* heap) { - reset_status_led(); autoreload_stop(); supervisor_workflow_reset(); @@ -251,7 +249,6 @@ STATIC void cleanup_after_vm(supervisor_allocation* heap) { #endif reset_port(); reset_board(); - reset_status_led(); } STATIC void print_code_py_status_message(safe_mode_t safe_mode) { @@ -286,8 +283,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { bool found_main = false; if (safe_mode == NO_SAFE_MODE) { - new_status_color(MAIN_RUNNING); - static const char * const supported_filenames[] = STRING_LIST( "code.txt", "code.py", "main.py", "main.txt"); #if CIRCUITPY_FULL_BUILD @@ -317,6 +312,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { serial_write_compressed(translate("WARNING: Your code filename has two extensions\n")); } } + #else + (void) found_main; #endif // Finished executing python code. Cleanup includes a board reset. @@ -334,42 +331,62 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { } // Program has finished running. - bool printed_press_any_key = false; #if CIRCUITPY_DISPLAYIO - bool refreshed_epaper_display = false; + size_t time_to_epaper_refresh = 1; #endif - rgb_status_animation_t animation; - prep_rgb_status_animation(&result, found_main, safe_mode, &animation); + // Setup LED blinks. + #if CIRCUITPY_STATUS_LED + uint32_t color; + uint8_t blink_count; + bool led_active = false; + #if CIRCUITPY_ALARM + if (result.return_code & PYEXEC_DEEP_SLEEP) { + color = BLACK; + blink_count = 0; + } else + #endif + if (result.return_code != PYEXEC_EXCEPTION) { + if (safe_mode == NO_SAFE_MODE) { + color = ALL_DONE; + blink_count = ALL_DONE_BLINKS; + } else { + color = SAFE_MODE; + blink_count = SAFE_MODE_BLINKS; + } + } else { + color = EXCEPTION; + blink_count = EXCEPTION_BLINKS; + } + size_t pattern_start = supervisor_ticks_ms32(); + size_t single_blink_time = (OFF_ON_RATIO + 1) * BLINK_TIME_MS; + size_t blink_time = single_blink_time * blink_count; + size_t total_time = blink_time + LED_SLEEP_TIME_MS; + #endif + + #if CIRCUITPY_ALARM bool fake_sleeping = false; + #endif + bool skip_repl = false; while (true) { RUN_BACKGROUND_TASKS; // If a reload was requested by the supervisor or autoreload, return if (reload_requested) { - #if CIRCUITPY_ALARM - if (fake_sleeping) { - board_init(); - } - #endif reload_requested = false; - return true; + skip_repl = true; + break; } // If interrupted by keyboard, return if (serial_connected() && serial_bytes_available()) { - #if CIRCUITPY_ALARM - if (fake_sleeping) { - board_init(); - } - #endif // Skip REPL if reload was requested. - bool ctrl_d = serial_read() == CHAR_CTRL_D; - if (ctrl_d) { + skip_repl = serial_read() == CHAR_CTRL_D; + if (skip_repl) { supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); } - return ctrl_d; + break; } // Check for a deep sleep alarm and restart the VM. This can happen if @@ -378,9 +395,9 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { #if CIRCUITPY_ALARM if (fake_sleeping && common_hal_alarm_woken_from_sleep()) { serial_write_compressed(translate("Woken up by alarm.\n")); - board_init(); supervisor_set_run_reason(RUN_REASON_STARTUP); - return true; + skip_repl = true; + break; } #endif @@ -403,26 +420,21 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { printed_press_any_key = false; } - // Refresh the ePaper display if we have one. That way it'll show an error message. - #if CIRCUITPY_DISPLAYIO - // Don't refresh the display if we're about to deep sleep. - #if CIRCUITPY_ALARM - refreshed_epaper_display = refreshed_epaper_display || result.return_code & PYEXEC_DEEP_SLEEP; - #endif - if (!refreshed_epaper_display) { - refreshed_epaper_display = maybe_refresh_epaperdisplay(); - } - #endif - // Sleep until our next interrupt. #if CIRCUITPY_ALARM if (result.return_code & PYEXEC_DEEP_SLEEP) { // Make sure we have been awake long enough for USB to connect (enumeration delay). int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL); - // Until it's safe to decide whether we're real/fake sleeping, just run the RGB - if (connecting_delay_ticks < 0 && !fake_sleeping) { - fake_sleeping = true; - new_status_color(BLACK); + // Until it's safe to decide whether we're real/fake sleeping + if (fake_sleeping) { + // This waits until a pretend deep sleep alarm occurs. They are set + // during common_hal_alarm_set_deep_sleep_alarms. On some platforms + // it may also return due to another interrupt, that's why we check + // for deep sleep alarms above. If it wasn't a deep sleep alarm, + // then we'll idle here again. + common_hal_alarm_pretending_deep_sleep(); + } else if (connecting_delay_ticks < 0) { + // Entering deep sleep (may be fake or real.) board_deinit(); if (!supervisor_workflow_active()) { // Enter true deep sleep. When we wake up we'll be back at the @@ -431,27 +443,85 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { // Does not return. } else { serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n")); + fake_sleeping = true; } + } else { + // Loop while checking the time. We can't idle because we don't want to override a + // time alarm set for the deep sleep. } - } + } else #endif + { + // Refresh the ePaper display if we have one. That way it'll show an error message. + #if CIRCUITPY_DISPLAYIO + if (time_to_epaper_refresh > 0) { + time_to_epaper_refresh = maybe_refresh_epaperdisplay(); + } - if (!fake_sleeping) { - tick_rgb_status_animation(&animation); - } else { - // This waits until a pretend deep sleep alarm occurs. They are set - // during common_hal_alarm_set_deep_sleep_alarms. On some platforms - // it may also return due to another interrupt, that's why we check - // for deep sleep alarms above. If it wasn't a deep sleep alarm, - // then we'll idle here again. - - #if CIRCUITPY_ALARM - common_hal_alarm_pretending_deep_sleep(); - #else - port_idle_until_interrupt(); + #if !CIRCUITPY_STATUS_LED + port_interrupt_after_ticks(time_to_epaper_refresh); #endif + #endif + + #if CIRCUITPY_STATUS_LED + uint32_t tick_diff = supervisor_ticks_ms32() - pattern_start; + + // By default, don't sleep. + size_t time_to_next_change = 0; + if (tick_diff < blink_time) { + uint32_t blink_diff = tick_diff % (single_blink_time); + if (blink_diff >= BLINK_TIME_MS) { + if (led_active) { + new_status_color(BLACK); + status_led_deinit(); + led_active = false; + } + time_to_next_change = single_blink_time - blink_diff; + } else { + if (!led_active) { + status_led_init(); + new_status_color(color); + led_active = true; + } + time_to_next_change = BLINK_TIME_MS - blink_diff; + } + } else if (tick_diff > total_time) { + pattern_start = supervisor_ticks_ms32(); + } else { + if (led_active) { + new_status_color(BLACK); + status_led_deinit(); + led_active = false; + } + time_to_next_change = total_time - tick_diff; + } + #if CIRCUITPY_DISPLAYIO + if (time_to_epaper_refresh > 0 && time_to_next_change > 0) { + time_to_next_change = MIN(time_to_next_change, time_to_epaper_refresh); + } + #endif + + // time_to_next_change is in ms and ticks are slightly shorter so + // we'll undersleep just a little. It shouldn't matter. + port_interrupt_after_ticks(time_to_next_change); + #endif + port_idle_until_interrupt(); } } + // Done waiting, start the board back up. + #if CIRCUITPY_STATUS_LED + if (led_active) { + new_status_color(BLACK); + status_led_deinit(); + } + #endif + + #if CIRCUITPY_ALARM + if (fake_sleeping) { + board_init(); + } + #endif + return skip_repl; } FIL* boot_output_file; @@ -468,7 +538,6 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { bool skip_boot_output = false; if (ok_to_run) { - new_status_color(BOOT_RUNNING); #ifdef CIRCUITPY_BOOT_OUTPUT_FILE FIL file_pointer; @@ -578,13 +647,27 @@ STATIC int run_repl(void) { #endif autoreload_suspend(); + + // Set the status LED to the REPL color before running the REPL. For + // NeoPixels and DotStars this will be sticky but for PWM or single LED it + // won't. This simplifies pin sharing because they won't be in use when + // actually in the REPL. + #if CIRCUITPY_STATUS_LED + status_led_init(); new_status_color(REPL_RUNNING); + status_led_deinit(); + #endif if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { exit_code = pyexec_raw_repl(); } else { exit_code = pyexec_friendly_repl(); } cleanup_after_vm(heap); + #if CIRCUITPY_STATUS_LED + status_led_init(); + new_status_color(BLACK); + status_led_deinit(); + #endif autoreload_resume(); return exit_code; } @@ -593,9 +676,8 @@ int __attribute__((used)) main(void) { // initialise the cpu and peripherals safe_mode_t safe_mode = port_init(); - // Turn on LEDs - init_status_leds(); - rgb_led_status_init(); + // Turn on RX and TX LEDs if we have them. + init_rxtx_leds(); // Wait briefly to give a reset window where we'll enter safe mode after the reset. if (safe_mode == NO_SAFE_MODE) { diff --git a/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.h index 20c4670e25..4cf4c57859 100644 --- a/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.h @@ -6,13 +6,14 @@ // Rev E #define MICROPY_HW_LED_STATUS (&pin_PA23) -#define MICROPY_HW_NEOPIXEL (&pin_PB03) +#define MICROPY_HW_NEOPIXEL (&pin_PB02) +#define CIRCUITPY_STATUS_LED_POWER (&pin_PB03) // These are pins not to reset. // QSPI Data pins #define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) // QSPI CS, QSPI SCK and NeoPixel pin -#define MICROPY_PORT_B (PORT_PB03 | PORT_PB10 | PORT_PB11) +#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h index a57b18e24a..ef4a556227 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h @@ -12,7 +12,7 @@ // QSPI Data pins #define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) // QSPI CS, QSPI SCK and NeoPixel pin -#define MICROPY_PORT_B (PORT_PB03 | PORT_PB10 | PORT_PB11) +#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) diff --git a/ports/atmel-samd/boards/picoplanet/mpconfigboard.h b/ports/atmel-samd/boards/picoplanet/mpconfigboard.h index 30a9169e04..153150d1e1 100644 --- a/ports/atmel-samd/boards/picoplanet/mpconfigboard.h +++ b/ports/atmel-samd/boards/picoplanet/mpconfigboard.h @@ -33,10 +33,9 @@ #define DEFAULT_SPI_BUS_SCK (&pin_PA17) #define DEFAULT_SPI_BUS_MOSI (&pin_PA16) -// #define CP_RGB_STATUS_R (&pin_PA06) -// #define CP_RGB_STATUS_G (&pin_PA05) -// #define CP_RGB_STATUS_B (&pin_PA07) -// #define CP_RGB_STATUS_INVERTED_PWM -// #define CP_RGB_STATUS_LED +// #define CIRCUITPY_RGB_STATUS_R (&pin_PA06) +// #define CIRCUITPY_RGB_STATUS_G (&pin_PA05) +// #define CIRCUITPY_RGB_STATUS_B (&pin_PA07) +// #define CIRCUITPY_RGB_STATUS_INVERTED_PWM #define MICROPY_HW_LED_STATUS (&pin_PA06) diff --git a/ports/atmel-samd/boards/qtpy_m0/board.c b/ports/atmel-samd/boards/qtpy_m0/board.c index 6b948a9a7a..84960e73cf 100644 --- a/ports/atmel-samd/boards/qtpy_m0/board.c +++ b/ports/atmel-samd/boards/qtpy_m0/board.c @@ -25,15 +25,8 @@ */ #include "supervisor/board.h" -#include "common-hal/microcontroller/Pin.h" -#include "supervisor/shared/board.h" -#include "hal/include/hal_gpio.h" void board_init(void) { - gpio_set_pin_function(PIN_PA15, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(PIN_PA15, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA15, true); // Turn on neopixel by default - never_reset_pin_number(PIN_PA15); } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/qtpy_m0/mpconfigboard.h b/ports/atmel-samd/boards/qtpy_m0/mpconfigboard.h index 713d2c03eb..305a9b55f6 100644 --- a/ports/atmel-samd/boards/qtpy_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/qtpy_m0/mpconfigboard.h @@ -2,6 +2,7 @@ #define MICROPY_HW_MCU_NAME "samd21e18" #define MICROPY_HW_NEOPIXEL (&pin_PA18) +#define CIRCUITPY_STATUS_LED_POWER (&pin_PA15) #define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) diff --git a/ports/atmel-samd/boards/qtpy_m0_haxpress/board.c b/ports/atmel-samd/boards/qtpy_m0_haxpress/board.c index 6b948a9a7a..84960e73cf 100644 --- a/ports/atmel-samd/boards/qtpy_m0_haxpress/board.c +++ b/ports/atmel-samd/boards/qtpy_m0_haxpress/board.c @@ -25,15 +25,8 @@ */ #include "supervisor/board.h" -#include "common-hal/microcontroller/Pin.h" -#include "supervisor/shared/board.h" -#include "hal/include/hal_gpio.h" void board_init(void) { - gpio_set_pin_function(PIN_PA15, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(PIN_PA15, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA15, true); // Turn on neopixel by default - never_reset_pin_number(PIN_PA15); } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.h index 4e557751fc..c3434e22f0 100644 --- a/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.h @@ -2,6 +2,7 @@ #define MICROPY_HW_MCU_NAME "samd21e18" #define MICROPY_HW_NEOPIXEL (&pin_PA18) +#define CIRCUITPY_STATUS_LED_POWER (&pin_PA15) #define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index 7b4034d156..48ca8f843d 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -36,7 +36,6 @@ #include "hal/include/hal_gpio.h" #include "hal/include/hal_spi_m_sync.h" #include "hal/include/hpl_spi_m_sync.h" -#include "supervisor/shared/rgb_led_status.h" #include "samd/dma.h" #include "samd/sercom.h" @@ -72,11 +71,6 @@ void reset_sercoms(void) { if (never_reset_sercoms[i]) { continue; } - #ifdef MICROPY_HW_APA102_SERCOM - if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) { - continue; - } - #endif // SWRST is same for all modes of SERCOMs. sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1; } @@ -122,15 +116,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, continue; } Sercom *potential_sercom = sercom_insts[sercom_index]; - if ( - #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102 - (potential_sercom->SPI.CTRLA.bit.ENABLE != 0 && - potential_sercom != status_apa102.spi_desc.dev.prvt && - !apa102_sck_in_use) - #else - potential_sercom->SPI.CTRLA.bit.ENABLE != 0 - #endif - ) { + if (potential_sercom->SPI.CTRLA.bit.ENABLE != 0) { continue; } clock_pinmux = PINMUX(clock->number, (i == 0) ? MUX_C : MUX_D); @@ -181,10 +167,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, // Set up SPI clocks on SERCOM. samd_peripherals_sercom_clock_init(sercom, sercom_index); - #if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102 - // if we're re-using the dotstar sercom, make sure it is disabled or the init will fail out - hri_sercomspi_clear_CTRLA_ENABLE_bit(sercom); - #endif if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) { mp_raise_OSError(MP_EIO); } diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.c b/ports/atmel-samd/common-hal/microcontroller/Pin.c index 564d037e03..8032673d03 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.c +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.c @@ -32,15 +32,7 @@ #include "hal/include/hal_gpio.h" #include "samd/pins.h" -#include "supervisor/shared/rgb_led_status.h" -#ifdef MICROPY_HW_NEOPIXEL -bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -bool apa102_sck_in_use; -bool apa102_mosi_in_use; -#endif #ifdef SPEAKER_ENABLE_PIN bool speaker_enable_in_use; #endif @@ -90,14 +82,6 @@ void reset_all_pins(void) { gpio_set_pin_function(PIN_PA31, GPIO_PIN_FUNCTION_G); #endif - #ifdef MICROPY_HW_NEOPIXEL - neopixel_in_use = false; - #endif - #ifdef MICROPY_HW_APA102_MOSI - apa102_sck_in_use = false; - apa102_mosi_in_use = false; - #endif - // After configuring SWD because it may be shared. #ifdef SPEAKER_ENABLE_PIN speaker_enable_in_use = false; @@ -122,25 +106,6 @@ void reset_pin_number(uint8_t pin_number) { never_reset_pins[GPIO_PORT(pin_number)] &= ~(1 << GPIO_PIN(pin_number)); - #ifdef MICROPY_HW_NEOPIXEL - if (pin_number == MICROPY_HW_NEOPIXEL->number) { - neopixel_in_use = false; - rgb_led_status_init(); - return; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin_number == MICROPY_HW_APA102_MOSI->number || - pin_number == MICROPY_HW_APA102_SCK->number) { - apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number; - apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number; - if (!apa102_sck_in_use && !apa102_mosi_in_use) { - rgb_led_status_init(); - } - return; - } - #endif - if (pin_number == PIN_PA30 #ifdef SAM_D5X_E5X ) { @@ -176,20 +141,6 @@ void common_hal_reset_pin(const mcu_pin_obj_t* pin) { } void claim_pin(const mcu_pin_obj_t* pin) { - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - neopixel_in_use = true; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI) { - apa102_mosi_in_use = true; - } - if (pin == MICROPY_HW_APA102_SCK) { - apa102_sck_in_use = true; - } - #endif - #ifdef SPEAKER_ENABLE_PIN if (pin == SPEAKER_ENABLE_PIN) { speaker_enable_in_use = true; @@ -223,26 +174,6 @@ bool pin_number_is_free(uint8_t pin_number) { } bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin) { - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - // Special case for Metro M0 where the NeoPixel is also SWCLK -#ifndef IGNORE_PIN_PA30 - if (MICROPY_HW_NEOPIXEL == &pin_PA30 && DSU->STATUSB.bit.DBGPRES == 1) { - return false; - } -#endif - return !neopixel_in_use; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI) { - return !apa102_mosi_in_use; - } - if (pin == MICROPY_HW_APA102_SCK) { - return !apa102_sck_in_use; - } - #endif - #ifdef SPEAKER_ENABLE_PIN if (pin == SPEAKER_ENABLE_PIN) { return !speaker_enable_in_use; diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.h b/ports/atmel-samd/common-hal/microcontroller/Pin.h index 6e313acfd3..76da10852f 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.h +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.h @@ -31,14 +31,6 @@ #include "peripherals/samd/pins.h" -#ifdef MICROPY_HW_NEOPIXEL -extern bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -extern bool apa102_sck_in_use; -extern bool apa102_mosi_in_use; -#endif - void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't // need to store a full pointer. diff --git a/ports/atmel-samd/common-hal/neopixel_write/__init__.c b/ports/atmel-samd/common-hal/neopixel_write/__init__.c index 4677437f90..754bc97fdf 100644 --- a/ports/atmel-samd/common-hal/neopixel_write/__init__.c +++ b/ports/atmel-samd/common-hal/neopixel_write/__init__.c @@ -60,7 +60,7 @@ static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMa " movs r6, #3; d2: sub r6, #1; bne d2;" // delay 3 #endif #ifdef SAM_D5X_E5X - " movs r6, #3; d2: subs r6, #1; bne d2;" // delay 3 + " movs r6, #16; d2: subs r6, #1; bne d2;" // delay 3 #endif " tst r4, r5;" // mask&r5 " bne skipclr;" @@ -70,7 +70,7 @@ static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMa " movs r6, #6; d0: sub r6, #1; bne d0;" // delay 6 #endif #ifdef SAM_D5X_E5X - " movs r6, #6; d0: subs r6, #1; bne d0;" // delay 6 + " movs r6, #16; d0: subs r6, #1; bne d0;" // delay 6 #endif " str r1, [r0, #0];" // clr (possibly again, doesn't matter) #ifdef SAMD21 @@ -85,10 +85,13 @@ static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMa " movs r6, #2; d1: sub r6, #1; bne d1;" // delay 2 #endif #ifdef SAM_D5X_E5X - " movs r6, #2; d1: subs r6, #1; bne d1;" // delay 2 + " movs r6, #15; d1: subs r6, #1; bne d1;" // delay 2 #endif " b loopBit;" "nextbyte:" + #ifdef SAM_D5X_E5X + " movs r6, #12; d3: subs r6, #1; bne d3;" // delay 2 + #endif " cmp r2, r3;" " bcs neopixel_stop;" " b loopLoad;" @@ -114,42 +117,12 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout, // Turn off interrupts of any kind during timing-sensitive code. mp_hal_disable_all_interrupts(); - - #ifdef SAM_D5X_E5X - // When this routine is positioned at certain addresses, the timing logic - // below can be too fast by about 2.5x. This is some kind of (un)fortunate code - // positioning with respect to a cache line. - // Theoretically we should turn on off the CMCC caches and the - // NVM caches to ensure consistent timing. Testing shows the the NVMCTRL - // cache disabling seems to make the difference. But turn both off to make sure. - // It's difficult to test because additions to the code before the timing loop - // below change instruction placement. (though this should be less true now that - // the main code is in the cache-aligned function neopixel_send_buffer_core) - // Testing was done by adding cache changes below the loop (so only the - // first time through is wrong). - // - // Turn off instruction, data, and NVM caches to force consistent timing. - // Invalidate existing cache entries. - hri_cmcc_set_CFG_reg(CMCC, CMCC_CFG_DCDIS | CMCC_CFG_ICDIS); - hri_cmcc_write_MAINT0_reg(CMCC, CMCC_MAINT0_INVALL); - hri_nvmctrl_set_CTRLA_CACHEDIS0_bit(NVMCTRL); - hri_nvmctrl_set_CTRLA_CACHEDIS1_bit(NVMCTRL); - #endif - uint32_t pin = digitalinout->pin->number; port = &PORT->Group[GPIO_PORT(pin)]; // Convert GPIO # to port register pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code. volatile uint32_t *clr = &(port->OUTCLR.reg); neopixel_send_buffer_core(clr, pinMask, pixels, numBytes); - #ifdef SAM_D5X_E5X - // Turn instruction, data, and NVM caches back on. - hri_cmcc_clear_CFG_reg(CMCC, CMCC_CFG_DCDIS | CMCC_CFG_ICDIS); - hri_nvmctrl_clear_CTRLA_CACHEDIS0_bit(NVMCTRL); - hri_nvmctrl_clear_CTRLA_CACHEDIS1_bit(NVMCTRL); - - #endif - // Update the next start. next_start_raw_ticks = port_get_raw_ticks(NULL) + 4; diff --git a/ports/atmel-samd/supervisor/internal_flash.c b/ports/atmel-samd/supervisor/internal_flash.c index 98d7892c9f..afac001232 100644 --- a/ports/atmel-samd/supervisor/internal_flash.c +++ b/ports/atmel-samd/supervisor/internal_flash.c @@ -51,21 +51,10 @@ #include "hal/include/hal_flash.h" #include "supervisor/flash.h" -#include "supervisor/shared/rgb_led_status.h" static struct flash_descriptor supervisor_flash_desc; void supervisor_flash_init(void) { - // Activity LED for flash writes. - #ifdef MICROPY_HW_LED_MSC - struct port_config pin_conf; - port_get_config_defaults(&pin_conf); - - pin_conf.direction = PORT_PIN_DIR_OUTPUT; - port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf); - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); - #endif - #ifdef SAM_D5X_E5X hri_mclk_set_AHBMASK_NVMCTRL_bit(MCLK); #endif @@ -114,10 +103,6 @@ bool supervisor_flash_read_block(uint8_t *dest, uint32_t block) { } bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) { - #ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, true); - #endif - temp_status_color(ACTIVE_WRITE); // non-MBR block, copy to cache int32_t dest = convert_block_to_flash_addr(block); if (dest == -1) { @@ -136,10 +121,6 @@ bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) { if (error_code != ERR_NONE) { return false; } - clear_temp_status(); - #ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); - #endif return true; } diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 15112f5ba7..0ba6019e07 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -462,6 +462,8 @@ static uint32_t _get_count(uint64_t *overflow_count) { return count; } +volatile bool _woken_up; + static void _port_interrupt_after_ticks(uint32_t ticks) { uint32_t current_ticks = _get_count(NULL); if (ticks > 1 << 28) { @@ -473,9 +475,16 @@ static void _port_interrupt_after_ticks(uint32_t ticks) { return; } #endif - RTC->MODE0.COMP[0].reg = current_ticks + (ticks << 4); + uint32_t target = current_ticks + (ticks << 4); + RTC->MODE0.COMP[0].reg = target; + #ifdef SAM_D5X_E5X + while ((RTC->MODE0.SYNCBUSY.reg & (RTC_MODE0_SYNCBUSY_COMP0)) != 0) { + } + #endif RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0; + current_ticks = _get_count(NULL); + _woken_up = current_ticks >= target; } void RTC_Handler(void) { @@ -485,15 +494,18 @@ void RTC_Handler(void) { // Our RTC is 32 bits and we're clocking it at 16.384khz which is 16 (2 ** 4) subticks per // tick. overflowed_ticks += (1L << (32 - 4)); + } #ifdef SAM_D5X_E5X - } else if (intflag & RTC_MODE0_INTFLAG_PER2) { + if (intflag & RTC_MODE0_INTFLAG_PER2) { RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_PER2; // Do things common to all ports when the tick occurs supervisor_tick(); + } #endif - } else if (intflag & RTC_MODE0_INTFLAG_CMP0) { + if (intflag & RTC_MODE0_INTFLAG_CMP0) { // Clear the interrupt because we may have hit a sleep and _ticks_enabled RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; + _woken_up = true; #ifdef SAMD21 if (_ticks_enabled) { // Do things common to all ports when the tick occurs. @@ -565,7 +577,7 @@ void port_idle_until_interrupt(void) { } #endif common_hal_mcu_disable_interrupts(); - if (!tud_task_event_ready() && !hold_interrupt) { + if (!tud_task_event_ready() && !hold_interrupt && !_woken_up) { __DSB(); __WFI(); } diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.h b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.h index a04065d25b..d2cd01a681 100644 --- a/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.h +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_nopsram/mpconfigboard.h @@ -30,6 +30,7 @@ #define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_NEOPIXEL (&pin_GPIO33) +#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO21) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) diff --git a/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.h b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.h index a04065d25b..d2cd01a681 100644 --- a/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.h +++ b/ports/esp32s2/boards/adafruit_feather_esp32s2_tftback_nopsram/mpconfigboard.h @@ -30,6 +30,7 @@ #define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_NEOPIXEL (&pin_GPIO33) +#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO21) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) diff --git a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h index 4d3e8c0972..d0d1864993 100644 --- a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h +++ b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h @@ -30,6 +30,8 @@ #define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_NEOPIXEL (&pin_GPIO1) +#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO21) +#define CIRCUITPY_STATUS_LED_POWER_INVERTED (1) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) diff --git a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c index 1fb1f11945..990cfd9957 100644 --- a/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c +++ b/ports/esp32s2/boards/adafruit_magtag_2.9_grayscale/pins.c @@ -44,6 +44,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO33) }, { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER_INVERTED), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO1) }, diff --git a/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.h b/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.h index e7d50f0894..64ef084ccd 100644 --- a/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.h +++ b/ports/esp32s2/boards/unexpectedmaker_tinys2/mpconfigboard.h @@ -30,6 +30,7 @@ #define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_NEOPIXEL (&pin_GPIO1) +#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO2) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) #define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n") diff --git a/ports/esp32s2/common-hal/busio/SPI.c b/ports/esp32s2/common-hal/busio/SPI.c index 917b391112..0e69d9f520 100644 --- a/ports/esp32s2/common-hal/busio/SPI.c +++ b/ports/esp32s2/common-hal/busio/SPI.c @@ -29,7 +29,6 @@ #include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/rgb_led_status.h" static bool spi_never_reset[SOC_SPI_PERIPH_NUM]; diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.c b/ports/esp32s2/common-hal/microcontroller/Pin.c index 5c00ca49e1..402de227d2 100644 --- a/ports/esp32s2/common-hal/microcontroller/Pin.c +++ b/ports/esp32s2/common-hal/microcontroller/Pin.c @@ -27,23 +27,15 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#include "supervisor/shared/rgb_led_status.h" #include "py/mphal.h" #include "components/driver/include/driver/gpio.h" #include "components/soc/include/hal/gpio_hal.h" -#ifdef MICROPY_HW_NEOPIXEL -bool neopixel_in_use; -#endif - STATIC uint32_t never_reset_pins[2]; STATIC uint32_t in_use[2]; -bool apa102_mosi_in_use; -bool apa102_sck_in_use; - STATIC void floating_gpio_reset(gpio_num_t pin_number) { // This is the same as gpio_reset_pin(), but without the pullup. // Note that gpio_config resets the iomatrix to GPIO_FUNC as well. @@ -78,14 +70,6 @@ void reset_pin_number(gpio_num_t pin_number) { in_use[pin_number / 32] &= ~(1 << pin_number % 32); floating_gpio_reset(pin_number); - - #ifdef MICROPY_HW_NEOPIXEL - if (pin_number == MICROPY_HW_NEOPIXEL->number) { - neopixel_in_use = false; - rgb_led_status_init(); - return; - } - #endif } void common_hal_reset_pin(const mcu_pin_obj_t *pin) { @@ -106,19 +90,10 @@ void reset_all_pins(void) { } in_use[0] = 0; in_use[1] = 0; - - #ifdef MICROPY_HW_NEOPIXEL - neopixel_in_use = false; - #endif } void claim_pin(const mcu_pin_obj_t *pin) { in_use[pin->number / 32] |= (1 << (pin->number % 32)); - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - neopixel_in_use = true; - } - #endif } void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) { @@ -126,12 +101,6 @@ void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) { } bool pin_number_is_free(gpio_num_t pin_number) { - #ifdef MICROPY_HW_NEOPIXEL - if (pin_number == MICROPY_HW_NEOPIXEL->number) { - return !neopixel_in_use; - } - #endif - uint8_t offset = pin_number / 32; uint32_t mask = 1 << (pin_number % 32); return (in_use[offset] & mask) == 0; diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.h b/ports/esp32s2/common-hal/microcontroller/Pin.h index e7b488f048..e82b28f282 100644 --- a/ports/esp32s2/common-hal/microcontroller/Pin.h +++ b/ports/esp32s2/common-hal/microcontroller/Pin.h @@ -31,13 +31,6 @@ #include "peripherals/pins.h" -extern bool apa102_mosi_in_use; -extern bool apa102_sck_in_use; - -#ifdef MICROPY_HW_NEOPIXEL -extern bool neopixel_in_use; -#endif - void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't // need to store a full pointer. diff --git a/ports/mimxrt10xx/common-hal/microcontroller/Pin.c b/ports/mimxrt10xx/common-hal/microcontroller/Pin.c index b55ab6e862..53e92d4105 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/Pin.c +++ b/ports/mimxrt10xx/common-hal/microcontroller/Pin.c @@ -27,15 +27,6 @@ */ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/rgb_led_status.h" - -#ifdef MICROPY_HW_NEOPIXEL -bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -bool apa102_sck_in_use; -bool apa102_mosi_in_use; -#endif STATIC bool claimed_pins[IOMUXC_SW_PAD_CTL_PAD_COUNT]; STATIC bool never_reset_pins[IOMUXC_SW_PAD_CTL_PAD_COUNT]; @@ -54,14 +45,6 @@ void reset_all_pins(void) { IOMUXC->SW_PAD_CTL_PAD[i] = ((mcu_pin_obj_t *)(mcu_pin_globals.map.table[i].value))->pad_reset; } } - - #ifdef MICROPY_HW_NEOPIXEL - neopixel_in_use = false; - #endif - #ifdef MICROPY_HW_APA102_MOSI - apa102_sck_in_use = false; - apa102_mosi_in_use = false; - #endif } // Since i.MX pins need extra register and reset information to reset properly, @@ -74,25 +57,6 @@ void common_hal_reset_pin(const mcu_pin_obj_t *pin) { claimed_pins[pin->mux_idx] = false; *(uint32_t *)pin->mux_reg = pin->mux_reset; *(uint32_t *)pin->cfg_reg = pin->pad_reset; - - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - neopixel_in_use = false; - rgb_led_status_init(); - return; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin->mux_idx == MICROPY_HW_APA102_MOSI->mux_idx || - pin->mux_idx == MICROPY_HW_APA102_SCK->mux_idx) { - apa102_mosi_in_use = apa102_mosi_in_use && pin->mux_idx != MICROPY_HW_APA102_MOSI->mux_idx; - apa102_sck_in_use = apa102_sck_in_use && pin->mux_idx != MICROPY_HW_APA102_SCK->mux_idx; - if (!apa102_sck_in_use && !apa102_mosi_in_use) { - rgb_led_status_init(); - } - return; - } - #endif } void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) { @@ -100,20 +64,6 @@ void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) { } bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - return !neopixel_in_use; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI) { - return !apa102_mosi_in_use; - } - if (pin == MICROPY_HW_APA102_SCK) { - return !apa102_sck_in_use; - } - #endif - return !claimed_pins[pin->mux_idx]; } @@ -123,20 +73,6 @@ uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t *pin) { void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) { claimed_pins[pin->mux_idx] = true; - - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - neopixel_in_use = true; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI) { - apa102_mosi_in_use = true; - } - if (pin == MICROPY_HW_APA102_SCK) { - apa102_sck_in_use = true; - } - #endif } void claim_pin(const mcu_pin_obj_t *pin) { diff --git a/ports/mimxrt10xx/common-hal/microcontroller/Pin.h b/ports/mimxrt10xx/common-hal/microcontroller/Pin.h index fde7fc8b8f..2638eb89b8 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/Pin.h +++ b/ports/mimxrt10xx/common-hal/microcontroller/Pin.h @@ -32,14 +32,6 @@ #include "pins.h" -#ifdef MICROPY_HW_NEOPIXEL -extern bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -extern bool apa102_sck_in_use; -extern bool apa102_mosi_in_use; -#endif - void reset_all_pins(void); void claim_pin(const mcu_pin_obj_t *pin); diff --git a/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h index 4fb6049c5f..23a98c948b 100644 --- a/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h +++ b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h @@ -31,9 +31,9 @@ #define MICROPY_HW_MCU_NAME "nRF52840" // RGB LEDs use PWM peripheral, avoid using them to save energy -// #define CP_RGB_STATUS_R (&pin_P0_30) -// #define CP_RGB_STATUS_G (&pin_P0_29) -// #define CP_RGB_STATUS_B (&pin_P0_31) +#define CIRCUITPY_RGB_STATUS_R (&pin_P0_30) +#define CIRCUITPY_RGB_STATUS_G (&pin_P0_29) +#define CIRCUITPY_RGB_STATUS_B (&pin_P0_31) #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14) diff --git a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.h b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.h index dab2ff042b..c398ce83dc 100644 --- a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.h +++ b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.h @@ -32,10 +32,10 @@ #define MICROPY_HW_LED_STATUS (&pin_P1_07) -#define CP_RGB_STATUS_INVERTED_PWM -#define CP_RGB_STATUS_R (&pin_P0_30) -#define CP_RGB_STATUS_G (&pin_P0_29) -#define CP_RGB_STATUS_B (&pin_P0_31) +#define CIRCUITPY_RGB_STATUS_INVERTED_PWM +#define CIRCUITPY_RGB_STATUS_R (&pin_P0_30) +#define CIRCUITPY_RGB_STATUS_G (&pin_P0_29) +#define CIRCUITPY_RGB_STATUS_B (&pin_P0_31) #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14) diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/particle_xenon/mpconfigboard.h index f0d12bb0b9..b2221e163a 100644 --- a/ports/nrf/boards/particle_xenon/mpconfigboard.h +++ b/ports/nrf/boards/particle_xenon/mpconfigboard.h @@ -32,9 +32,9 @@ #define MICROPY_HW_LED_STATUS (&pin_P1_12) -#define CP_RGB_STATUS_R (&pin_P0_13) -#define CP_RGB_STATUS_G (&pin_P0_14) -#define CP_RGB_STATUS_B (&pin_P0_15) +#define CIRCUITPY_RGB_STATUS_R (&pin_P0_13) +#define CIRCUITPY_RGB_STATUS_G (&pin_P0_14) +#define CIRCUITPY_RGB_STATUS_B (&pin_P0_15) #if QSPI_FLASH_FILESYSTEM #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20) diff --git a/ports/nrf/common-hal/microcontroller/Pin.c b/ports/nrf/common-hal/microcontroller/Pin.c index aea4f63eae..39ee601428 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.c +++ b/ports/nrf/common-hal/microcontroller/Pin.c @@ -31,15 +31,7 @@ #include "py/mphal.h" #include "nrf/pins.h" -#include "supervisor/shared/rgb_led_status.h" -#ifdef MICROPY_HW_NEOPIXEL -bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -bool apa102_sck_in_use; -bool apa102_mosi_in_use; -#endif #ifdef SPEAKER_ENABLE_PIN bool speaker_enable_in_use; #endif @@ -73,14 +65,6 @@ void reset_all_pins(void) { nrf_gpio_cfg_default(pin); } - #ifdef MICROPY_HW_NEOPIXEL - neopixel_in_use = false; - #endif - #ifdef MICROPY_HW_APA102_MOSI - apa102_sck_in_use = false; - apa102_mosi_in_use = false; - #endif - // After configuring SWD because it may be shared. reset_speaker_enable_pin(); } @@ -95,25 +79,6 @@ void reset_pin_number(uint8_t pin_number) { claimed_pins[nrf_pin_port(pin_number)] &= ~(1 << nrf_relative_pin_number(pin_number)); never_reset_pins[nrf_pin_port(pin_number)] &= ~(1 << nrf_relative_pin_number(pin_number)); - #ifdef MICROPY_HW_NEOPIXEL - if (pin_number == MICROPY_HW_NEOPIXEL->number) { - neopixel_in_use = false; - rgb_led_status_init(); - return; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin_number == MICROPY_HW_APA102_MOSI->number || - pin_number == MICROPY_HW_APA102_SCK->number) { - apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number; - apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number; - if (!apa102_sck_in_use && !apa102_mosi_in_use) { - rgb_led_status_init(); - } - return; - } - #endif - #ifdef SPEAKER_ENABLE_PIN if (pin_number == SPEAKER_ENABLE_PIN->number) { reset_speaker_enable_pin(); @@ -144,20 +109,6 @@ void claim_pin(const mcu_pin_obj_t *pin) { // Set bit in claimed_pins bitmask. claimed_pins[nrf_pin_port(pin->number)] |= 1 << nrf_relative_pin_number(pin->number); - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - neopixel_in_use = true; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI) { - apa102_mosi_in_use = true; - } - if (pin == MICROPY_HW_APA102_SCK) { - apa102_sck_in_use = true; - } - #endif - #ifdef SPEAKER_ENABLE_PIN if (pin == SPEAKER_ENABLE_PIN) { speaker_enable_in_use = true; @@ -171,20 +122,6 @@ bool pin_number_is_free(uint8_t pin_number) { } bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - return !neopixel_in_use; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI) { - return !apa102_mosi_in_use; - } - if (pin == MICROPY_HW_APA102_SCK) { - return !apa102_sck_in_use; - } - #endif - #ifdef SPEAKER_ENABLE_PIN if (pin == SPEAKER_ENABLE_PIN) { return !speaker_enable_in_use; diff --git a/ports/nrf/common-hal/microcontroller/Pin.h b/ports/nrf/common-hal/microcontroller/Pin.h index 888ab6a8c4..f4623aa2dc 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.h +++ b/ports/nrf/common-hal/microcontroller/Pin.h @@ -31,14 +31,6 @@ #include "peripherals/nrf/pins.h" -#ifdef MICROPY_HW_NEOPIXEL -extern bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -extern bool apa102_sck_in_use; -extern bool apa102_mosi_in_use; -#endif - void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't // need to store a full pointer. diff --git a/ports/raspberrypi/boards/adafruit_itsybitsy_rp2040/board.c b/ports/raspberrypi/boards/adafruit_itsybitsy_rp2040/board.c index e05589883d..67486d4c23 100644 --- a/ports/raspberrypi/boards/adafruit_itsybitsy_rp2040/board.c +++ b/ports/raspberrypi/boards/adafruit_itsybitsy_rp2040/board.c @@ -26,14 +26,7 @@ #include "supervisor/board.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" - void board_init(void) { - common_hal_never_reset_pin(&pin_GPIO16); - gpio_init(16); - gpio_set_dir(16, GPIO_OUT); - gpio_put(16, true); } bool board_requests_safe_mode(void) { diff --git a/ports/raspberrypi/boards/adafruit_itsybitsy_rp2040/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_itsybitsy_rp2040/mpconfigboard.h index dad4e2eae8..131ddc8cee 100644 --- a/ports/raspberrypi/boards/adafruit_itsybitsy_rp2040/mpconfigboard.h +++ b/ports/raspberrypi/boards/adafruit_itsybitsy_rp2040/mpconfigboard.h @@ -2,6 +2,7 @@ #define MICROPY_HW_MCU_NAME "rp2040" #define MICROPY_HW_NEOPIXEL (&pin_GPIO17) +#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO16) #define DEFAULT_I2C_BUS_SCL (&pin_GPIO3) #define DEFAULT_I2C_BUS_SDA (&pin_GPIO2) diff --git a/ports/raspberrypi/boards/adafruit_qtpy_rp2040/board.c b/ports/raspberrypi/boards/adafruit_qtpy_rp2040/board.c index 332145ab84..67486d4c23 100644 --- a/ports/raspberrypi/boards/adafruit_qtpy_rp2040/board.c +++ b/ports/raspberrypi/boards/adafruit_qtpy_rp2040/board.c @@ -26,14 +26,7 @@ #include "supervisor/board.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" - void board_init(void) { - common_hal_never_reset_pin(&pin_GPIO11); - gpio_init(11); - gpio_set_dir(11, GPIO_OUT); - gpio_put(11, true); } bool board_requests_safe_mode(void) { diff --git a/ports/raspberrypi/boards/adafruit_qtpy_rp2040/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_qtpy_rp2040/mpconfigboard.h index a1947deaeb..5d3795dd5d 100644 --- a/ports/raspberrypi/boards/adafruit_qtpy_rp2040/mpconfigboard.h +++ b/ports/raspberrypi/boards/adafruit_qtpy_rp2040/mpconfigboard.h @@ -2,6 +2,7 @@ #define MICROPY_HW_MCU_NAME "rp2040" #define MICROPY_HW_NEOPIXEL (&pin_GPIO12) +#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO11) #define DEFAULT_I2C_BUS_SCL (&pin_GPIO25) #define DEFAULT_I2C_BUS_SDA (&pin_GPIO24) diff --git a/ports/raspberrypi/common-hal/busio/SPI.c b/ports/raspberrypi/common-hal/busio/SPI.c index 0fc71136e6..23030cbd0d 100644 --- a/ports/raspberrypi/common-hal/busio/SPI.c +++ b/ports/raspberrypi/common-hal/busio/SPI.c @@ -32,7 +32,6 @@ #include "supervisor/board.h" #include "common-hal/microcontroller/Pin.h" -#include "supervisor/shared/rgb_led_status.h" #include "shared-bindings/microcontroller/Pin.h" #include "src/rp2_common/hardware_dma/include/hardware/dma.h" diff --git a/ports/raspberrypi/common-hal/microcontroller/Pin.c b/ports/raspberrypi/common-hal/microcontroller/Pin.c index 271966c2fe..d40c1f43b5 100644 --- a/ports/raspberrypi/common-hal/microcontroller/Pin.c +++ b/ports/raspberrypi/common-hal/microcontroller/Pin.c @@ -29,21 +29,8 @@ #include "common-hal/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "supervisor/shared/rgb_led_status.h" - #include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" -#ifdef MICROPY_HW_NEOPIXEL -bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -bool apa102_sck_in_use; -bool apa102_mosi_in_use; -#endif -#ifdef SPEAKER_ENABLE_PIN -bool speaker_enable_in_use; -#endif - STATIC uint32_t never_reset_pins; void reset_all_pins(void) { @@ -77,31 +64,6 @@ void reset_pin_number(uint8_t pin_number) { PADS_BANK0_GPIO0_PUE_BITS | PADS_BANK0_GPIO0_PDE_BITS); hw_set_bits(&padsbank0_hw->io[pin_number], PADS_BANK0_GPIO0_OD_BITS); - - #ifdef MICROPY_HW_NEOPIXEL - if (pin_number == MICROPY_HW_NEOPIXEL->number) { - neopixel_in_use = false; - rgb_led_status_init(); - return; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin_number == MICROPY_HW_APA102_MOSI->number || - pin_number == MICROPY_HW_APA102_SCK->number) { - apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number; - apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number; - if (!apa102_sck_in_use && !apa102_mosi_in_use) { - rgb_led_status_init(); - } - return; - } - #endif - - #ifdef SPEAKER_ENABLE_PIN - if (pin_number == SPEAKER_ENABLE_PIN->number) { - speaker_enable_in_use = false; - } - #endif } void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) { @@ -113,25 +75,7 @@ void common_hal_reset_pin(const mcu_pin_obj_t *pin) { } void claim_pin(const mcu_pin_obj_t *pin) { - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - neopixel_in_use = true; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI) { - apa102_mosi_in_use = true; - } - if (pin == MICROPY_HW_APA102_SCK) { - apa102_sck_in_use = true; - } - #endif - - #ifdef SPEAKER_ENABLE_PIN - if (pin == SPEAKER_ENABLE_PIN) { - speaker_enable_in_use = true; - } - #endif + // Nothing to do because all changes will set the GPIO settings. } bool pin_number_is_free(uint8_t pin_number) { @@ -145,26 +89,6 @@ bool pin_number_is_free(uint8_t pin_number) { } bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - return !neopixel_in_use; - } - #endif - #ifdef MICROPY_HW_APA102_MOSI - if (pin == MICROPY_HW_APA102_MOSI) { - return !apa102_mosi_in_use; - } - if (pin == MICROPY_HW_APA102_SCK) { - return !apa102_sck_in_use; - } - #endif - - #ifdef SPEAKER_ENABLE_PIN - if (pin == SPEAKER_ENABLE_PIN) { - return !speaker_enable_in_use; - } - #endif - return pin_number_is_free(pin->number); } diff --git a/ports/raspberrypi/common-hal/microcontroller/Pin.h b/ports/raspberrypi/common-hal/microcontroller/Pin.h index 7da3a2b88b..3e2287dc5d 100644 --- a/ports/raspberrypi/common-hal/microcontroller/Pin.h +++ b/ports/raspberrypi/common-hal/microcontroller/Pin.h @@ -34,14 +34,6 @@ #include "peripherals/pins.h" -#ifdef MICROPY_HW_NEOPIXEL -extern bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -extern bool apa102_sck_in_use; -extern bool apa102_mosi_in_use; -#endif - void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't // need to store a full pointer. diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 70a2c63e56..3ec546f52b 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -62,7 +62,7 @@ void alarm_set_wakeup_reason(stm_sleep_source_t reason) { true_deep_wake_reason = reason; } -STATIC stm_sleep_source_t _get_wakeup_cause(void) { +stm_sleep_source_t alarm_get_wakeup_cause(void) { // If in light/fake sleep, check modules if (alarm_pin_pinalarm_woke_this_cycle()) { return STM_WAKEUP_GPIO; @@ -71,20 +71,20 @@ STATIC stm_sleep_source_t _get_wakeup_cause(void) { return STM_WAKEUP_RTC; } // Check to see if we woke from deep sleep (reason set in port_init) - if (true_deep_wake_reason) { + if (true_deep_wake_reason != STM_WAKEUP_UNDEF) { return true_deep_wake_reason; } return STM_WAKEUP_UNDEF; } bool common_hal_alarm_woken_from_sleep(void) { - return _get_wakeup_cause() != STM_WAKEUP_UNDEF; + return alarm_get_wakeup_cause() != STM_WAKEUP_UNDEF; } mp_obj_t common_hal_alarm_create_wake_alarm(void) { // If woken from deep sleep, create a copy alarm similar to what would have // been passed in originally. Otherwise, just return none - stm_sleep_source_t cause = _get_wakeup_cause(); + stm_sleep_source_t cause = alarm_get_wakeup_cause(); switch (cause) { case STM_WAKEUP_RTC: { return alarm_time_timealarm_create_wakeup_alarm(); @@ -115,7 +115,7 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj RUN_BACKGROUND_TASKS; // Detect if interrupt was alarm or ctrl-C interrupt. if (common_hal_alarm_woken_from_sleep()) { - stm_sleep_source_t cause = _get_wakeup_cause(); + stm_sleep_source_t cause = alarm_get_wakeup_cause(); switch (cause) { case STM_WAKEUP_RTC: { wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms); @@ -149,6 +149,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala } void NORETURN common_hal_alarm_enter_deep_sleep(void) { + alarm_set_wakeup_reason(STM_WAKEUP_UNDEF); alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); port_disable_tick(); @@ -175,6 +176,8 @@ void common_hal_alarm_pretending_deep_sleep(void) { GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + alarm_set_wakeup_reason(STM_WAKEUP_UNDEF); + port_idle_until_interrupt(); } diff --git a/ports/stm/common-hal/alarm/__init__.h b/ports/stm/common-hal/alarm/__init__.h index 4ec7222d2e..6c72364fc3 100644 --- a/ports/stm/common-hal/alarm/__init__.h +++ b/ports/stm/common-hal/alarm/__init__.h @@ -40,6 +40,7 @@ typedef enum { #define STM_ALARM_FLAG (RTC->BKP0R) extern void alarm_set_wakeup_reason(stm_sleep_source_t reason); +stm_sleep_source_t alarm_get_wakeup_cause(void); extern void alarm_reset(void); #endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H diff --git a/ports/stm/common-hal/microcontroller/Pin.c b/ports/stm/common-hal/microcontroller/Pin.c index 80cb9defc8..fa03a7a210 100644 --- a/ports/stm/common-hal/microcontroller/Pin.c +++ b/ports/stm/common-hal/microcontroller/Pin.c @@ -27,19 +27,10 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#include "supervisor/shared/rgb_led_status.h" #include "py/mphal.h" #include "pins.h" -#ifdef MICROPY_HW_NEOPIXEL -bool neopixel_in_use; -#endif -#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) -bool apa102_sck_in_use; -bool apa102_mosi_in_use; -#endif - #if defined(TFBGA216) GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK}; #elif defined(LQFP144) @@ -66,14 +57,6 @@ void reset_all_pins(void) { for (uint8_t i = 0; i < GPIO_PORT_COUNT; i++) { HAL_GPIO_DeInit(ports[i], ~never_reset_pins[i]); } - - #ifdef MICROPY_HW_NEOPIXEL - neopixel_in_use = false; - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - apa102_sck_in_use = false; - apa102_mosi_in_use = false; - #endif } // Mark pin as free and return it to a quiescent state. @@ -89,25 +72,6 @@ void reset_pin_number(uint8_t pin_port, uint8_t pin_number) { claimed_pins[pin_port] &= ~(1 << pin_number); never_reset_pins[pin_port] &= ~(1 << pin_number); HAL_GPIO_DeInit(ports[pin_port], 1 << pin_number); - - #ifdef MICROPY_HW_NEOPIXEL - if (pin_port == MICROPY_HW_NEOPIXEL->port && pin_number == MICROPY_HW_NEOPIXEL->number) { - neopixel_in_use = false; - rgb_led_status_init(); - return; - } - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - if ( - (pin_port == MICROPY_HW_APA102_MOSI->port && pin_number == MICROPY_HW_APA102_MOSI->number) - || (pin_port == MICROPY_HW_APA102_SCK->port && pin_number == MICROPY_HW_APA102_MOSI->number) - ) { - apa102_mosi_in_use = false; - apa102_sck_in_use = false; - rgb_led_status_init(); - return; - } - #endif } void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number) { @@ -140,20 +104,6 @@ bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number) { } bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - return !neopixel_in_use; - } - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - if (pin == MICROPY_HW_APA102_MOSI) { - return !apa102_mosi_in_use; - } - if (pin == MICROPY_HW_APA102_SCK) { - return !apa102_sck_in_use; - } - #endif - return pin_number_is_free(pin->port, pin->number); } @@ -171,19 +121,6 @@ uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t *pin) { void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) { claim_pin(pin->port, pin->number); - #ifdef MICROPY_HW_NEOPIXEL - if (pin == MICROPY_HW_NEOPIXEL) { - neopixel_in_use = true; - } - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - if (pin == MICROPY_HW_APA102_MOSI) { - apa102_mosi_in_use = true; - } - if (pin == MICROPY_HW_APA102_SCK) { - apa102_sck_in_use = true; - } - #endif } void common_hal_mcu_pin_reset_number(uint8_t pin_no) { diff --git a/ports/stm/common-hal/microcontroller/Pin.h b/ports/stm/common-hal/microcontroller/Pin.h index 4a33979421..52c6efd712 100644 --- a/ports/stm/common-hal/microcontroller/Pin.h +++ b/ports/stm/common-hal/microcontroller/Pin.h @@ -31,14 +31,6 @@ #include "peripherals/pins.h" -#ifdef MICROPY_HW_NEOPIXEL -extern bool neopixel_in_use; -#endif -#ifdef MICROPY_HW_APA102_MOSI -extern bool apa102_sck_in_use; -extern bool apa102_mosi_in_use; -#endif - void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't // need to store a full pointer. diff --git a/ports/stm/common-hal/microcontroller/Processor.c b/ports/stm/common-hal/microcontroller/Processor.c index b33d96e736..13c661a60a 100644 --- a/ports/stm/common-hal/microcontroller/Processor.c +++ b/ports/stm/common-hal/microcontroller/Processor.c @@ -27,6 +27,9 @@ #include #include "py/runtime.h" +#if CIRCUITPY_ALARM +#include "common-hal/alarm/__init__.h" +#endif #include "common-hal/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" #include "supervisor/shared/translate.h" @@ -143,5 +146,10 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { } mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + #if CIRCUITPY_ALARM + if (alarm_get_wakeup_cause() != STM_WAKEUP_UNDEF) { + return RESET_REASON_DEEP_SLEEP_ALARM; + } + #endif return RESET_REASON_UNKNOWN; } diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 18a1480a10..c71cad6aeb 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -991,6 +991,10 @@ void supervisor_run_background_tasks_if_tick(void); #define CIRCUITPY_PROCESSOR_COUNT (1) #endif +#ifndef CIRCUITPY_STATUS_LED_POWER_INVERTED +#define CIRCUITPY_STATUS_LED_POWER_INVERTED (0) +#endif + #define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt" #define CIRCUITPY_VERBOSE_BLE 0 diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index 28ac68d629..b3b00f68d5 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -29,7 +29,7 @@ #include "lib/utils/interrupt_char.h" #include "supervisor/shared/autoreload.h" -#include "supervisor/shared/rgb_led_status.h" +#include "supervisor/shared/status_leds.h" #include "supervisor/shared/stack.h" #include "supervisor/shared/translate.h" #include "supervisor/shared/workflow.h" @@ -79,7 +79,7 @@ STATIC mp_obj_t supervisor_set_rgb_status_brightness(mp_obj_t lvl) { if (brightness_int < 0 || brightness_int > 255) { mp_raise_ValueError(translate("Brightness must be between 0 and 255")); } - set_rgb_status_brightness((uint8_t)brightness_int); + set_status_brightness((uint8_t)brightness_int); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_set_rgb_status_brightness); diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index 7eff587757..826fe9b8ea 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -409,7 +409,7 @@ void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t *self) { gc_collect_ptr((void *)self->stop_sequence); } -bool maybe_refresh_epaperdisplay(void) { +size_t maybe_refresh_epaperdisplay(void) { for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { if (displays[i].epaper_display.base.type != &displayio_epaperdisplay_type || displays[i].epaper_display.core.current_group != &circuitpython_splash) { @@ -417,11 +417,16 @@ bool maybe_refresh_epaperdisplay(void) { continue; } displayio_epaperdisplay_obj_t *display = &displays[i].epaper_display; - if (common_hal_displayio_epaperdisplay_get_time_to_refresh(display) != 0) { - return false; + size_t time_to_refresh = common_hal_displayio_epaperdisplay_get_time_to_refresh(display); + if (time_to_refresh > 0) { + return time_to_refresh; } - return common_hal_displayio_epaperdisplay_refresh(display); + if (common_hal_displayio_epaperdisplay_refresh(display)) { + return 0; + } + // If we could refresh but it failed, then we want to retry. + return 1; } - // Return true if no ePaper displays are available to pretend it was updated. - return true; + // Return 0 if no ePaper displays are available to pretend it was updated. + return 0; } diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h index 988cc57fa3..f200813626 100644 --- a/shared-module/displayio/EPaperDisplay.h +++ b/shared-module/displayio/EPaperDisplay.h @@ -61,7 +61,7 @@ typedef struct { void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t *self); void release_epaperdisplay(displayio_epaperdisplay_obj_t *self); -bool maybe_refresh_epaperdisplay(void); +size_t maybe_refresh_epaperdisplay(void); void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t *self); diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index 722393ce65..56a7f25b30 100644 --- a/supervisor/shared/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -39,7 +39,6 @@ #include "lib/oofatfs/ff.h" #include "shared-bindings/microcontroller/__init__.h" #include "supervisor/memory.h" -#include "supervisor/shared/rgb_led_status.h" #define NO_SECTOR_LOADED 0xFFFFFFFF @@ -467,7 +466,6 @@ static void spi_flash_flush_keep_cache(bool keep_cache) { #ifdef MICROPY_HW_LED_MSC port_pin_set_output_level(MICROPY_HW_LED_MSC, true); #endif - temp_status_color(ACTIVE_WRITE); // If we've cached to the flash itself flush from there. if (MP_STATE_VM(flash_ram_cache) == NULL) { flush_scratch_flash(); @@ -475,7 +473,6 @@ static void spi_flash_flush_keep_cache(bool keep_cache) { flush_ram_cache(keep_cache); } current_sector = NO_SECTOR_LOADED; - clear_temp_status(); #ifdef MICROPY_HW_LED_MSC port_pin_set_output_level(MICROPY_HW_LED_MSC, false); #endif diff --git a/supervisor/shared/rgb_led_colors.h b/supervisor/shared/rgb_led_colors.h index 581c177442..56dc0f48d1 100644 --- a/supervisor/shared/rgb_led_colors.h +++ b/supervisor/shared/rgb_led_colors.h @@ -14,28 +14,17 @@ #define PURPLE COLOR(INTENSITY, 0, INTENSITY) #define WHITE COLOR(INTENSITY, INTENSITY, INTENSITY) -#define BOOT_RUNNING BLUE -#define MAIN_RUNNING GREEN -#define SAFE_MODE YELLOW #define ALL_DONE GREEN +#define EXCEPTION RED +#define SAFE_MODE YELLOW #define REPL_RUNNING WHITE -#define ACTIVE_WRITE 0x200000 +#define ALL_DONE_BLINKS 1 +#define EXCEPTION_BLINKS 2 +#define SAFE_MODE_BLINKS 3 -#define ALL_GOOD_CYCLE_MS 2000u +#define OFF_ON_RATIO 3 -#define LINE_NUMBER_TOGGLE_LENGTH 300u -#define EXCEPTION_TYPE_LENGTH_MS 1000u +#define LED_SLEEP_TIME_MS 5000u -#define THOUSANDS WHITE -#define HUNDREDS BLUE -#define TENS YELLOW -#define ONES CYAN - -#define INDENTATION_ERROR GREEN -#define SYNTAX_ERROR CYAN -#define NAME_ERROR WHITE -#define OS_ERROR ORANGE -#define VALUE_ERROR PURPLE -#define MPY_ERROR BLUE -#define OTHER_ERROR YELLOW +#define BLINK_TIME_MS 100u diff --git a/supervisor/shared/rgb_led_status.c b/supervisor/shared/rgb_led_status.c deleted file mode 100644 index d6e11c2aef..0000000000 --- a/supervisor/shared/rgb_led_status.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "mphalport.h" -#include "shared-bindings/microcontroller/Pin.h" -#include "rgb_led_status.h" -#include "supervisor/shared/tick.h" -#include "py/obj.h" - -#ifdef MICROPY_HW_NEOPIXEL -uint8_t rgb_status_brightness = 63; -#include "shared-bindings/digitalio/DigitalInOut.h" -#include "shared-bindings/neopixel_write/__init__.h" -static uint8_t status_neopixel_color[3]; -static digitalio_digitalinout_obj_t status_neopixel; -#endif - - -#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) -uint8_t rgb_status_brightness = 50; - -#define APA102_BUFFER_LENGTH 12 -static uint8_t status_apa102_color[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff}; - -#if CIRCUITPY_BITBANG_APA102 -#include "shared-bindings/bitbangio/SPI.h" -static bitbangio_spi_obj_t status_apa102 = { - .base = { - .type = &bitbangio_spi_type, - }, -}; -#else -#include "shared-bindings/busio/SPI.h" -busio_spi_obj_t status_apa102 = { - .base = { - .type = &busio_spi_type, - }, -}; -#endif -#endif - -#if defined(CP_RGB_STATUS_R) || defined(CP_RGB_STATUS_G) || defined(CP_RGB_STATUS_B) -#define CP_RGB_STATUS_LED - -#include "shared-bindings/pwmio/PWMOut.h" -#include "shared-bindings/microcontroller/Pin.h" - -pwmio_pwmout_obj_t rgb_status_r = { - .base = { - .type = &pwmio_pwmout_type, - }, -}; -pwmio_pwmout_obj_t rgb_status_g = { - .base = { - .type = &pwmio_pwmout_type, - }, -}; -pwmio_pwmout_obj_t rgb_status_b = { - .base = { - .type = &pwmio_pwmout_type, - }, -}; - -uint8_t rgb_status_brightness = 0xFF; - -uint16_t status_rgb_color[3] = { - 0 /* red */, 0 /* green */, 0 /* blue */ -}; -#endif - -#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) -static uint32_t current_status_color = 0; -#endif - -static bool rgb_led_status_init_in_progress = false; -void rgb_led_status_init() { - if (rgb_led_status_init_in_progress) { - // Avoid recursion. - return; - } - rgb_led_status_init_in_progress = true; - - #ifdef MICROPY_HW_NEOPIXEL - common_hal_digitalio_digitalinout_construct(&status_neopixel, MICROPY_HW_NEOPIXEL); - // Pretend we aren't using the pins. digitalio.DigitalInOut - // will mark them as used. - neopixel_in_use = false; - common_hal_digitalio_digitalinout_switch_to_output(&status_neopixel, false, DRIVE_MODE_PUSH_PULL); - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - #if CIRCUITPY_BITBANG_APA102 - shared_module_bitbangio_spi_construct(&status_apa102, - MICROPY_HW_APA102_SCK, - MICROPY_HW_APA102_MOSI, - NULL); - #else - if (!common_hal_busio_spi_deinited(&status_apa102)) { - // This may call us recursively if common_hal_reset_pin() is called, - // The rgb_led_status_init_in_progress guard will prevent further recursion. - common_hal_busio_spi_deinit(&status_apa102); - } - common_hal_busio_spi_construct(&status_apa102, - MICROPY_HW_APA102_SCK, - MICROPY_HW_APA102_MOSI, - NULL); - common_hal_busio_spi_never_reset(&status_apa102); - #endif - // Pretend we aren't using the pins. bitbangio.SPI will - // mark them as used. - apa102_mosi_in_use = false; - apa102_sck_in_use = false; - #if CIRCUITPY_BITBANG_APA102 - shared_module_bitbangio_spi_try_lock(&status_apa102); - // Use 1MHz for clock rate. Some APA102's are spec'd 800kHz-1200kHz, - // though many can run much faster. bitbang will probably run slower. - shared_module_bitbangio_spi_configure(&status_apa102, 1000000, 0, 0, 8); - #else - common_hal_busio_spi_try_lock(&status_apa102); - common_hal_busio_spi_configure(&status_apa102, 1000000, 0, 0, 8); - #endif - #endif - - - #if defined(CP_RGB_STATUS_LED) - if (common_hal_mcu_pin_is_free(CP_RGB_STATUS_R)) { - pwmout_result_t red_result = common_hal_pwmio_pwmout_construct(&rgb_status_r, CP_RGB_STATUS_R, 0, 50000, false); - - if (PWMOUT_OK == red_result) { - common_hal_pwmio_pwmout_never_reset(&rgb_status_r); - } - } - - if (common_hal_mcu_pin_is_free(CP_RGB_STATUS_G)) { - pwmout_result_t green_result = common_hal_pwmio_pwmout_construct(&rgb_status_g, CP_RGB_STATUS_G, 0, 50000, false); - - if (PWMOUT_OK == green_result) { - common_hal_pwmio_pwmout_never_reset(&rgb_status_g); - } - } - - if (common_hal_mcu_pin_is_free(CP_RGB_STATUS_B)) { - pwmout_result_t blue_result = common_hal_pwmio_pwmout_construct(&rgb_status_b, CP_RGB_STATUS_B, 0, 50000, false); - - if (PWMOUT_OK == blue_result) { - common_hal_pwmio_pwmout_never_reset(&rgb_status_b); - } - } - #endif - - #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) - // Force a write of the current status color. - uint32_t rgb = current_status_color; - current_status_color = 0x1000000; // Not a valid color - new_status_color(rgb); - #endif - - rgb_led_status_init_in_progress = false; -} - -void reset_status_led() { - #ifdef MICROPY_HW_NEOPIXEL - common_hal_reset_pin(MICROPY_HW_NEOPIXEL); - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - common_hal_reset_pin(MICROPY_HW_APA102_MOSI); - common_hal_reset_pin(MICROPY_HW_APA102_SCK); - #endif - #if defined(CP_RGB_STATUS_LED) - // TODO: Support sharing status LED with user. - #endif -} - -void new_status_color(uint32_t rgb) { - #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) - if (current_status_color == rgb) { - return; - } - uint32_t rgb_adjusted = color_brightness(rgb, rgb_status_brightness); - current_status_color = rgb; - #endif - - #ifdef MICROPY_HW_NEOPIXEL - if (neopixel_in_use) { - return; - } - status_neopixel_color[0] = (rgb_adjusted >> 8) & 0xff; - status_neopixel_color[1] = (rgb_adjusted >> 16) & 0xff; - status_neopixel_color[2] = rgb_adjusted & 0xff; - common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3); - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - if (apa102_mosi_in_use || apa102_sck_in_use) { - return; - } - status_apa102_color[5] = rgb_adjusted & 0xff; - status_apa102_color[6] = (rgb_adjusted >> 8) & 0xff; - status_apa102_color[7] = (rgb_adjusted >> 16) & 0xff; - - #if CIRCUITPY_BITBANG_APA102 - shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH); - #else - common_hal_busio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH); - #endif - #endif - - #if defined(CP_RGB_STATUS_LED) - uint8_t red_u8 = (rgb_adjusted >> 16) & 0xFF; - uint8_t green_u8 = (rgb_adjusted >> 8) & 0xFF; - uint8_t blue_u8 = rgb_adjusted & 0xFF; - - #if defined(CP_RGB_STATUS_INVERTED_PWM) - status_rgb_color[0] = (1 << 16) - 1 - ((uint16_t)(red_u8 << 8) + red_u8); - status_rgb_color[1] = (1 << 16) - 1 - ((uint16_t)(green_u8 << 8) + green_u8); - status_rgb_color[2] = (1 << 16) - 1 - ((uint16_t)(blue_u8 << 8) + blue_u8); - #else - status_rgb_color[0] = (uint16_t)(red_u8 << 8) + red_u8; - status_rgb_color[1] = (uint16_t)(green_u8 << 8) + green_u8; - status_rgb_color[2] = (uint16_t)(blue_u8 << 8) + blue_u8; - #endif - - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_r, status_rgb_color[0]); - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_g, status_rgb_color[1]); - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_b, status_rgb_color[2]); - #endif -} - -void temp_status_color(uint32_t rgb) { - #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) - uint32_t rgb_adjusted = rgb; - rgb_adjusted = color_brightness(rgb, rgb_status_brightness); - #endif - #ifdef MICROPY_HW_NEOPIXEL - if (neopixel_in_use) { - return; - } - uint8_t colors[3] = {(rgb_adjusted >> 8) & 0xff, (rgb_adjusted >> 16) & 0xff, rgb_adjusted & 0xff}; - common_hal_neopixel_write(&status_neopixel, colors, 3); - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - if (apa102_mosi_in_use || apa102_sck_in_use) { - return; - } - uint8_t colors[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, rgb_adjusted & 0xff, (rgb_adjusted >> 8) & 0xff, (rgb_adjusted >> 16) & 0xff, 0xff, 0xff, 0xff, 0xff}; - #if CIRCUITPY_BITBANG_APA102 - shared_module_bitbangio_spi_write(&status_apa102, colors, APA102_BUFFER_LENGTH); - #else - common_hal_busio_spi_write(&status_apa102, colors, APA102_BUFFER_LENGTH); - #endif - #endif - #if defined(CP_RGB_STATUS_LED) - uint8_t red_u8 = (rgb_adjusted >> 16) & 0xFF; - uint8_t green_u8 = (rgb_adjusted >> 8) & 0xFF; - uint8_t blue_u8 = rgb_adjusted & 0xFF; - - uint16_t temp_status_color_rgb[3] = {0}; - - #if defined(CP_RGB_STATUS_INVERTED_PWM) - temp_status_color_rgb[0] = (1 << 16) - 1 - ((uint16_t)(red_u8 << 8) + red_u8); - temp_status_color_rgb[1] = (1 << 16) - 1 - ((uint16_t)(green_u8 << 8) + green_u8); - temp_status_color_rgb[2] = (1 << 16) - 1 - ((uint16_t)(blue_u8 << 8) + blue_u8); - #else - temp_status_color_rgb[0] = (uint16_t)(red_u8 << 8) + red_u8; - temp_status_color_rgb[1] = (uint16_t)(green_u8 << 8) + green_u8; - temp_status_color_rgb[2] = (uint16_t)(blue_u8 << 8) + blue_u8; - #endif - - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_r, temp_status_color_rgb[0]); - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_g, temp_status_color_rgb[1]); - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_b, temp_status_color_rgb[2]); - #endif -} - -void clear_temp_status() { - #ifdef MICROPY_HW_NEOPIXEL - if (neopixel_in_use) { - return; - } - common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3); - #endif - #if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) - if (apa102_mosi_in_use || apa102_sck_in_use) { - return; - } - #if CIRCUITPY_BITBANG_APA102 - shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH); - #else - common_hal_busio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH); - #endif - #endif - #if defined(CP_RGB_STATUS_LED) - - uint16_t red = 0; - uint16_t green = 0; - uint16_t blue = 0; - - #if defined(CP_RGB_STATUS_INVERTED_PWM) - red = (1 << 16) - 1 - status_rgb_color[0]; - green = (1 << 16) - 1 - status_rgb_color[1]; - blue = (1 << 16) - 1 - status_rgb_color[2]; - #else - red = status_rgb_color[0]; - green = status_rgb_color[1]; - blue = status_rgb_color[2]; - #endif - - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_r, red); - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_g, green); - common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_b, blue); - #endif -} - -uint32_t color_brightness(uint32_t color, uint8_t brightness) { - #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) - uint32_t result = ((color & 0xff0000) * brightness / 255) & 0xff0000; - result += ((color & 0xff00) * brightness / 255) & 0xff00; - result += ((color & 0xff) * brightness / 255) & 0xff; - return result; - #else - return color; - #endif -} - -void set_rgb_status_brightness(uint8_t level) { - #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) - rgb_status_brightness = level; - uint32_t current_color = current_status_color; - // Temporarily change the current color global to force the new_status_color call to update the - // LED. Usually duplicate calls of the same color are ignored without regard to brightness - // changes. - current_status_color = 0; - new_status_color(current_color); - #endif -} - -void prep_rgb_status_animation(const pyexec_result_t *result, - bool found_main, - safe_mode_t safe_mode, - rgb_status_animation_t *status) { - #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) - new_status_color(ALL_DONE); - status->pattern_start = supervisor_ticks_ms32(); - status->safe_mode = safe_mode; - status->found_main = found_main; - status->total_exception_cycle = 0; - status->ok = result->return_code != PYEXEC_EXCEPTION; - if (status->ok) { - // If this isn't an exception, skip exception sorting and handling - return; - } - status->ones = result->exception_line % 10; - status->ones += status->ones > 0 ? 1 : 0; - status->tens = (result->exception_line / 10) % 10; - status->tens += status->tens > 0 ? 1 : 0; - status->hundreds = (result->exception_line / 100) % 10; - status->hundreds += status->hundreds > 0 ? 1 : 0; - status->thousands = (result->exception_line / 1000) % 10; - status->thousands += status->thousands > 0 ? 1 : 0; - status->digit_sum = status->ones + status->tens + status->hundreds + status->thousands; - uint8_t num_places = 0; - uint16_t line = result->exception_line; - for (int i = 0; i < 4; i++) { - if ((line % 10) > 0) { - num_places++; - } - line /= 10; - } - if (!status->ok) { - status->total_exception_cycle = EXCEPTION_TYPE_LENGTH_MS * 3 + LINE_NUMBER_TOGGLE_LENGTH * status->digit_sum + LINE_NUMBER_TOGGLE_LENGTH * num_places; - } - if (!result->exception_type) { - status->exception_color = OTHER_ERROR; - } else if (mp_obj_is_subclass_fast(result->exception_type, &mp_type_IndentationError)) { - status->exception_color = INDENTATION_ERROR; - } else if (mp_obj_is_subclass_fast(result->exception_type, &mp_type_SyntaxError)) { - status->exception_color = SYNTAX_ERROR; - } else if (mp_obj_is_subclass_fast(result->exception_type, &mp_type_NameError)) { - status->exception_color = NAME_ERROR; - } else if (mp_obj_is_subclass_fast(result->exception_type, &mp_type_OSError)) { - status->exception_color = OS_ERROR; - } else if (mp_obj_is_subclass_fast(result->exception_type, &mp_type_ValueError)) { - status->exception_color = VALUE_ERROR; - } else if (mp_obj_is_subclass_fast(result->exception_type, &mp_type_MpyError)) { - status->exception_color = MPY_ERROR; - } else { - status->exception_color = OTHER_ERROR; - } - #endif -} - -bool tick_rgb_status_animation(rgb_status_animation_t *status) { - #if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED)) - uint32_t tick_diff = supervisor_ticks_ms32() - status->pattern_start; - if (status->ok) { - // All is good. Ramp ALL_DONE up and down. - if (tick_diff > ALL_GOOD_CYCLE_MS) { - status->pattern_start = supervisor_ticks_ms32(); - new_status_color(BLACK); - return true; - } - - uint16_t brightness = tick_diff * 255 / (ALL_GOOD_CYCLE_MS / 2); - if (brightness > 255) { - brightness = 511 - brightness; - } - if (status->safe_mode == NO_SAFE_MODE) { - new_status_color(color_brightness(ALL_DONE, brightness)); - } else { - new_status_color(color_brightness(SAFE_MODE, brightness)); - } - } else { - if (tick_diff > status->total_exception_cycle) { - status->pattern_start = supervisor_ticks_ms32(); - return true; - } - // First flash the file color. - if (tick_diff < EXCEPTION_TYPE_LENGTH_MS) { - if (status->found_main) { - new_status_color(MAIN_RUNNING); - } else { - new_status_color(BOOT_RUNNING); - } - // Next flash the exception color. - } else if (tick_diff < EXCEPTION_TYPE_LENGTH_MS * 2) { - new_status_color(status->exception_color); - // Finally flash the line number digits from highest to lowest. - // Zeroes will not produce a flash but can be read by the absence of - // a color from the sequence. - } else if (tick_diff < (EXCEPTION_TYPE_LENGTH_MS * 2 + LINE_NUMBER_TOGGLE_LENGTH * status->digit_sum)) { - uint32_t digit_diff = tick_diff - EXCEPTION_TYPE_LENGTH_MS * 2; - if ((digit_diff % LINE_NUMBER_TOGGLE_LENGTH) < (LINE_NUMBER_TOGGLE_LENGTH / 2)) { - new_status_color(BLACK); - } else if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * status->thousands) { - if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH) { - new_status_color(BLACK); - } else { - new_status_color(THOUSANDS); - } - } else if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (status->thousands + status->hundreds)) { - if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (status->thousands + 1)) { - new_status_color(BLACK); - } else { - new_status_color(HUNDREDS); - } - } else if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (status->thousands + status->hundreds + status->tens)) { - if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (status->thousands + status->hundreds + 1)) { - new_status_color(BLACK); - } else { - new_status_color(TENS); - } - } else { - if (digit_diff < LINE_NUMBER_TOGGLE_LENGTH * (status->thousands + status->hundreds + status->tens + 1)) { - new_status_color(BLACK); - } else { - new_status_color(ONES); - } - } - } else { - new_status_color(BLACK); - } - } - #endif - return false; // Animation is not finished. -} diff --git a/supervisor/shared/rgb_led_status.h b/supervisor/shared/rgb_led_status.h deleted file mode 100644 index 753a1167cb..0000000000 --- a/supervisor/shared/rgb_led_status.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_SUPERVISOR_RGB_LED_STATUS_H -#define MICROPY_INCLUDED_SUPERVISOR_RGB_LED_STATUS_H - -#include -#include - -#include "lib/utils/pyexec.h" -#include "supervisor/port.h" - -#include "py/mpconfig.h" -#include "rgb_led_colors.h" - -#include "supervisor/shared/safe_mode.h" - -// Overall, the time module must be implemented. -// To work with a DotStar, one must have MICROPY_HW_APA102_SCK and -// MICROPY_HW_APA102_MOSI defined and bitbangio.SPI or busio.SPI implemented. -// To work with a NeoPixel, one must have MICROPY_HW_NEOPIXEL defined and -// neopixel_write implemented. - -#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) && !CIRCUITPY_BITBANG_APA102 -#include "common-hal/busio/SPI.h" -extern busio_spi_obj_t status_apa102; -#endif - -void rgb_led_status_init(void); -void reset_status_led(void); -void new_status_color(uint32_t rgb); -void temp_status_color(uint32_t rgb); -void clear_temp_status(void); - -uint32_t color_brightness(uint32_t color, uint8_t brightness); -void set_rgb_status_brightness(uint8_t level); - -typedef struct { - bool ok; - uint32_t pattern_start; - uint32_t total_exception_cycle; - safe_mode_t safe_mode; - uint8_t digit_sum; - uint8_t ones; - uint8_t tens; - uint8_t hundreds; - uint8_t thousands; - uint32_t exception_color; - bool found_main; -} rgb_status_animation_t; - -void prep_rgb_status_animation(const pyexec_result_t *result, - bool found_main, - safe_mode_t safe_mode, - rgb_status_animation_t *status); -bool tick_rgb_status_animation(rgb_status_animation_t *status); - -#endif // MICROPY_INCLUDED_SUPERVISOR_RGB_LED_STATUS_H diff --git a/supervisor/shared/safe_mode.c b/supervisor/shared/safe_mode.c index e53b6a9da4..e2a77a3f29 100644 --- a/supervisor/shared/safe_mode.c +++ b/supervisor/shared/safe_mode.c @@ -36,7 +36,7 @@ #include "supervisor/serial.h" #include "supervisor/shared/rgb_led_colors.h" -#include "supervisor/shared/rgb_led_status.h" +#include "supervisor/shared/status_leds.h" #include "supervisor/shared/translate.h" #include "supervisor/shared/tick.h" @@ -65,11 +65,9 @@ safe_mode_t wait_for_safe_mode_reset(void) { } port_set_saved_word(SAFE_MODE_DATA_GUARD | (MANUAL_SAFE_MODE << 8)); // Wait for a while to allow for reset. - temp_status_color(SAFE_MODE); - #ifdef MICROPY_HW_LED_STATUS - digitalio_digitalinout_obj_t status_led; - common_hal_digitalio_digitalinout_construct(&status_led, MICROPY_HW_LED_STATUS); - common_hal_digitalio_digitalinout_switch_to_output(&status_led, true, DRIVE_MODE_PUSH_PULL); + + #if CIRCUITPY_STATUS_LED + status_led_init(); #endif #ifdef CIRCUITPY_BOOT_BUTTON digitalio_digitalinout_obj_t boot_button; @@ -78,22 +76,32 @@ safe_mode_t wait_for_safe_mode_reset(void) { #endif uint64_t start_ticks = supervisor_ticks_ms64(); uint64_t diff = 0; + bool boot_in_safe_mode = false; while (diff < 1000) { - #ifdef MICROPY_HW_LED_STATUS + #ifdef CIRCUITPY_STATUS_LED // Blink on for 100, off for 100, on for 100, off for 100 and on for 200 - common_hal_digitalio_digitalinout_set_value(&status_led, diff > 100 && diff / 100 != 2 && diff / 100 != 4); + bool led_on = diff > 100 && diff / 100 != 2 && diff / 100 != 4; + if (led_on) { + new_status_color(SAFE_MODE); + } else { + new_status_color(BLACK); + } #endif #ifdef CIRCUITPY_BOOT_BUTTON if (!common_hal_digitalio_digitalinout_get_value(&boot_button)) { - return USER_SAFE_MODE; + boot_in_safe_mode = true; + break; } #endif diff = supervisor_ticks_ms64() - start_ticks; } - #ifdef MICROPY_HW_LED_STATUS - common_hal_digitalio_digitalinout_deinit(&status_led); + #if CIRCUITPY_STATUS_LED + new_status_color(BLACK); + status_led_deinit(); #endif - clear_temp_status(); + if (boot_in_safe_mode) { + return USER_SAFE_MODE; + } port_set_saved_word(SAFE_MODE_DATA_GUARD); return NO_SAFE_MODE; } diff --git a/supervisor/shared/status_leds.c b/supervisor/shared/status_leds.c index 672242a963..e8b0983d9b 100644 --- a/supervisor/shared/status_leds.c +++ b/supervisor/shared/status_leds.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2017-2021 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,11 +26,81 @@ #include "supervisor/shared/status_leds.h" -#if CIRCUITPY_DIGITALIO -#include "common-hal/digitalio/DigitalInOut.h" +#include "mphalport.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "supervisor/shared/tick.h" +#include "py/obj.h" + + +#ifdef CIRCUITPY_STATUS_LED_POWER #include "shared-bindings/digitalio/DigitalInOut.h" +static digitalio_digitalinout_obj_t _status_power; #endif +#ifdef MICROPY_HW_NEOPIXEL +uint8_t rgb_status_brightness = 63; + #include "shared-bindings/digitalio/DigitalInOut.h" + #include "shared-bindings/neopixel_write/__init__.h" +static uint8_t status_neopixel_color[3]; +static digitalio_digitalinout_obj_t status_neopixel; + +#elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) +uint8_t rgb_status_brightness = 50; + + #define APA102_BUFFER_LENGTH 12 +static uint8_t status_apa102_color[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff}; + + #if CIRCUITPY_BITBANG_APA102 + #include "shared-bindings/bitbangio/SPI.h" +static bitbangio_spi_obj_t status_apa102 = { + .base = { + .type = &bitbangio_spi_type, + }, +}; + #else + #include "shared-bindings/busio/SPI.h" +busio_spi_obj_t status_apa102 = { + .base = { + .type = &busio_spi_type, + }, +}; + #endif + +#elif CIRCUITPY_PWM_RGB_LED + #include "shared-bindings/pwmio/PWMOut.h" + #include "shared-bindings/microcontroller/Pin.h" + +pwmio_pwmout_obj_t rgb_status_r = { + .base = { + .type = &pwmio_pwmout_type, + }, +}; +pwmio_pwmout_obj_t rgb_status_g = { + .base = { + .type = &pwmio_pwmout_type, + }, +}; +pwmio_pwmout_obj_t rgb_status_b = { + .base = { + .type = &pwmio_pwmout_type, + }, +}; + +uint8_t rgb_status_brightness = 0xFF; + +uint16_t status_rgb_color[3] = { + 0 /* red */, 0 /* green */, 0 /* blue */ +}; +#elif CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_STATUS) +#include "shared-bindings/digitalio/DigitalInOut.h" +digitalio_digitalinout_obj_t single_color_led; + +uint8_t rgb_status_brightness = 0xff; +#endif + +#if CIRCUITPY_DIGITALIO && (defined(MICROPY_HW_LED_RX) || defined(MICROPY_HW_LED_TX)) +#include "shared-bindings/digitalio/DigitalInOut.h" + #ifdef MICROPY_HW_LED_RX digitalio_digitalinout_obj_t rx_led; #endif @@ -38,27 +108,220 @@ digitalio_digitalinout_obj_t rx_led; #ifdef MICROPY_HW_LED_TX digitalio_digitalinout_obj_t tx_led; #endif +#endif -void init_status_leds(void) { - #ifdef MICROPY_HW_LED_RX +#if CIRCUITPY_STATUS_LED +static uint32_t current_status_color = 0; +#endif + +static bool status_led_init_in_progress = false; +void status_led_init() { + if (status_led_init_in_progress) { + // Avoid recursion. + return; + } + status_led_init_in_progress = true; + + #ifdef CIRCUITPY_STATUS_LED_POWER + common_hal_digitalio_digitalinout_construct(&_status_power, CIRCUITPY_STATUS_LED_POWER); + common_hal_digitalio_digitalinout_switch_to_output(&_status_power, + CIRCUITPY_STATUS_LED_POWER_INVERTED == 0, DRIVE_MODE_PUSH_PULL); + #endif + + #ifdef MICROPY_HW_NEOPIXEL + common_hal_digitalio_digitalinout_construct(&status_neopixel, MICROPY_HW_NEOPIXEL); + common_hal_digitalio_digitalinout_switch_to_output(&status_neopixel, false, DRIVE_MODE_PUSH_PULL); + #elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) + #if CIRCUITPY_BITBANG_APA102 + shared_module_bitbangio_spi_construct(&status_apa102, + MICROPY_HW_APA102_SCK, + MICROPY_HW_APA102_MOSI, + NULL); + #else + if (!common_hal_busio_spi_deinited(&status_apa102)) { + common_hal_busio_spi_deinit(&status_apa102); + } + common_hal_busio_spi_construct(&status_apa102, + MICROPY_HW_APA102_SCK, + MICROPY_HW_APA102_MOSI, + NULL); + #endif + #if CIRCUITPY_BITBANG_APA102 + shared_module_bitbangio_spi_try_lock(&status_apa102); + // Use 1MHz for clock rate. Some APA102's are spec'd 800kHz-1200kHz, + // though many can run much faster. bitbang will probably run slower. + shared_module_bitbangio_spi_configure(&status_apa102, 1000000, 0, 0, 8); + #else + common_hal_busio_spi_try_lock(&status_apa102); + common_hal_busio_spi_configure(&status_apa102, 1000000, 0, 0, 8); + #endif + + + #elif CIRCUITPY_PWM_RGB_LED + if (common_hal_mcu_pin_is_free(CIRCUITPY_RGB_STATUS_R)) { + pwmout_result_t red_result = common_hal_pwmio_pwmout_construct(&rgb_status_r, CIRCUITPY_RGB_STATUS_R, 0, 50000, false); + + if (PWMOUT_OK == red_result) { + common_hal_pwmio_pwmout_never_reset(&rgb_status_r); + } + } + + if (common_hal_mcu_pin_is_free(CIRCUITPY_RGB_STATUS_G)) { + pwmout_result_t green_result = common_hal_pwmio_pwmout_construct(&rgb_status_g, CIRCUITPY_RGB_STATUS_G, 0, 50000, false); + + if (PWMOUT_OK == green_result) { + common_hal_pwmio_pwmout_never_reset(&rgb_status_g); + } + } + + if (common_hal_mcu_pin_is_free(CIRCUITPY_RGB_STATUS_B)) { + pwmout_result_t blue_result = common_hal_pwmio_pwmout_construct(&rgb_status_b, CIRCUITPY_RGB_STATUS_B, 0, 50000, false); + + if (PWMOUT_OK == blue_result) { + common_hal_pwmio_pwmout_never_reset(&rgb_status_b); + } + } + + #elif defined(MICROPY_HW_LED_STATUS) + common_hal_digitalio_digitalinout_construct(&single_color_led, MICROPY_HW_LED_STATUS); + common_hal_digitalio_digitalinout_switch_to_output(&single_color_led, true, DRIVE_MODE_PUSH_PULL); + #endif + + #if CIRCUITPY_DIGITALIO && CIRCUITPY_STATUS_LED + // Force a write of the current status color. + uint32_t rgb = current_status_color; + current_status_color = 0x1000000; // Not a valid color + new_status_color(rgb); + #endif + + status_led_init_in_progress = false; +} + +void status_led_deinit() { + #ifdef MICROPY_HW_NEOPIXEL + common_hal_reset_pin(MICROPY_HW_NEOPIXEL); + + #elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) + #if CIRCUITPY_BITBANG_APA102 + shared_module_bitbangio_spi_deinit(&status_apa102); + #else + common_hal_busio_spi_deinit(&status_apa102); + #endif + + #elif CIRCUITPY_PWM_RGB_LED + if (!common_hal_mcu_pin_is_free(CIRCUITPY_RGB_STATUS_R)) { + common_hal_pwmio_pwmout_deinit(&rgb_status_r); + } + + if (!common_hal_mcu_pin_is_free(CIRCUITPY_RGB_STATUS_G)) { + common_hal_pwmio_pwmout_deinit(&rgb_status_g); + } + + if (!common_hal_mcu_pin_is_free(CIRCUITPY_RGB_STATUS_B)) { + common_hal_pwmio_pwmout_deinit(&rgb_status_b); + } + + #elif defined(MICROPY_HW_LED_STATUS) + common_hal_digitalio_digitalinout_deinit(&single_color_led); + #endif + + #ifdef CIRCUITPY_STATUS_LED_POWER + common_hal_digitalio_digitalinout_deinit(&_status_power); + #endif +} + +void new_status_color(uint32_t rgb) { + #if CIRCUITPY_STATUS_LED + if (current_status_color == rgb) { + return; + } + uint32_t rgb_adjusted = color_brightness(rgb, rgb_status_brightness); + current_status_color = rgb; + #endif + + #ifdef MICROPY_HW_NEOPIXEL + status_neopixel_color[0] = (rgb_adjusted >> 8) & 0xff; + status_neopixel_color[1] = (rgb_adjusted >> 16) & 0xff; + status_neopixel_color[2] = rgb_adjusted & 0xff; + common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3); + + #elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK) + status_apa102_color[5] = rgb_adjusted & 0xff; + status_apa102_color[6] = (rgb_adjusted >> 8) & 0xff; + status_apa102_color[7] = (rgb_adjusted >> 16) & 0xff; + + #if CIRCUITPY_BITBANG_APA102 + shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH); + #else + common_hal_busio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH); + #endif + + #elif CIRCUITPY_PWM_RGB_LED + uint8_t red_u8 = (rgb_adjusted >> 16) & 0xFF; + uint8_t green_u8 = (rgb_adjusted >> 8) & 0xFF; + uint8_t blue_u8 = rgb_adjusted & 0xFF; + + #ifdef CIRCUITPY_RGB_STATUS_INVERTED_PWM + status_rgb_color[0] = (1 << 16) - 1 - ((uint16_t)(red_u8 << 8) + red_u8); + status_rgb_color[1] = (1 << 16) - 1 - ((uint16_t)(green_u8 << 8) + green_u8); + status_rgb_color[2] = (1 << 16) - 1 - ((uint16_t)(blue_u8 << 8) + blue_u8); + #else + status_rgb_color[0] = (uint16_t)(red_u8 << 8) + red_u8; + status_rgb_color[1] = (uint16_t)(green_u8 << 8) + green_u8; + status_rgb_color[2] = (uint16_t)(blue_u8 << 8) + blue_u8; + #endif + + common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_r, status_rgb_color[0]); + common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_g, status_rgb_color[1]); + common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_b, status_rgb_color[2]); + #elif CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_STATUS) + common_hal_digitalio_digitalinout_set_value(&single_color_led, rgb_adjusted > 0); + #endif +} + +uint32_t color_brightness(uint32_t color, uint8_t brightness) { + #if CIRCUITPY_STATUS_LED + uint32_t result = ((color & 0xff0000) * brightness / 255) & 0xff0000; + result += ((color & 0xff00) * brightness / 255) & 0xff00; + result += ((color & 0xff) * brightness / 255) & 0xff; + return result; + #else + return color; + #endif +} + +void set_status_brightness(uint8_t level) { + #if CIRCUITPY_STATUS_LED + rgb_status_brightness = level; + uint32_t current_color = current_status_color; + // Temporarily change the current color global to force the new_status_color call to update the + // LED. Usually duplicate calls of the same color are ignored without regard to brightness + // changes. + current_status_color = 0; + new_status_color(current_color); + #endif +} + +void init_rxtx_leds(void) { + #if CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_RX) common_hal_digitalio_digitalinout_construct(&rx_led, MICROPY_HW_LED_RX); common_hal_digitalio_digitalinout_switch_to_output(&rx_led, true, DRIVE_MODE_PUSH_PULL); #endif - #ifdef MICROPY_HW_LED_TX + #if CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_TX) common_hal_digitalio_digitalinout_construct(&tx_led, MICROPY_HW_LED_TX); common_hal_digitalio_digitalinout_switch_to_output(&tx_led, true, DRIVE_MODE_PUSH_PULL); #endif } void toggle_rx_led(void) { - #ifdef MICROPY_HW_LED_RX + #if CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_RX) common_hal_digitalio_digitalinout_set_value(&rx_led, !common_hal_digitalio_digitalinout_get_value(&rx_led)); #endif } void toggle_tx_led(void) { - #ifdef MICROPY_HW_LED_TX + #if CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_TX) common_hal_digitalio_digitalinout_set_value(&tx_led, !common_hal_digitalio_digitalinout_get_value(&tx_led)); #endif } diff --git a/supervisor/shared/status_leds.h b/supervisor/shared/status_leds.h index 30132753f3..4a55922845 100644 --- a/supervisor/shared/status_leds.h +++ b/supervisor/shared/status_leds.h @@ -27,10 +27,35 @@ #ifndef MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H #define MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H -void init_status_leds(void); +#include +#include +#include "lib/utils/pyexec.h" +#include "supervisor/port.h" + +#include "py/mpconfig.h" +#include "rgb_led_colors.h" + +#include "supervisor/shared/safe_mode.h" + +// Overall, the time module must be implemented. +// To work with a DotStar, one must have MICROPY_HW_APA102_SCK and +// MICROPY_HW_APA102_MOSI defined and bitbangio.SPI or busio.SPI implemented. +// To work with a NeoPixel, one must have MICROPY_HW_NEOPIXEL defined and +// neopixel_write implemented. + +#define CIRCUITPY_PWM_RGB_LED defined(CIRCUITPY_RGB_STATUS_R) || defined(CIRCUITPY_RGB_STATUS_G) || defined(CIRCUITPY_RGB_STATUS_B) +#define CIRCUITPY_STATUS_LED (CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_STATUS)) || defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || CIRCUITPY_PWM_RGB_LED + +void status_led_init(void); +void status_led_deinit(void); +void new_status_color(uint32_t rgb); + +uint32_t color_brightness(uint32_t color, uint8_t brightness); +void set_status_brightness(uint8_t level); + +void init_rxtx_leds(void); void toggle_rx_led(void); - void toggle_tx_led(void); #endif // MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index 1ca937cdab..0815a9ffc4 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -9,7 +9,6 @@ SRC_SUPERVISOR = \ supervisor/shared/flash.c \ supervisor/shared/memory.c \ supervisor/shared/micropython.c \ - supervisor/shared/rgb_led_status.c \ supervisor/shared/safe_mode.c \ supervisor/shared/stack.c \ supervisor/shared/status_leds.c \