Merge pull request #4743 from tannewt/simplify_status_led

Simplify the status LED to save power
This commit is contained in:
Scott Shawcroft 2021-05-21 10:55:11 -07:00 committed by GitHub
commit 20946d97a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 553 additions and 1221 deletions

196
main.c
View File

@ -53,7 +53,6 @@
#include "supervisor/port.h" #include "supervisor/port.h"
#include "supervisor/serial.h" #include "supervisor/serial.h"
#include "supervisor/shared/autoreload.h" #include "supervisor/shared/autoreload.h"
#include "supervisor/shared/rgb_led_status.h"
#include "supervisor/shared/safe_mode.h" #include "supervisor/shared/safe_mode.h"
#include "supervisor/shared/stack.h" #include "supervisor/shared/stack.h"
#include "supervisor/shared/status_leds.h" #include "supervisor/shared/status_leds.h"
@ -114,7 +113,6 @@ static void reset_devices(void) {
} }
STATIC void start_mp(supervisor_allocation* heap) { STATIC void start_mp(supervisor_allocation* heap) {
reset_status_led();
autoreload_stop(); autoreload_stop();
supervisor_workflow_reset(); supervisor_workflow_reset();
@ -251,7 +249,6 @@ STATIC void cleanup_after_vm(supervisor_allocation* heap) {
#endif #endif
reset_port(); reset_port();
reset_board(); reset_board();
reset_status_led();
} }
STATIC void print_code_py_status_message(safe_mode_t safe_mode) { 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; bool found_main = false;
if (safe_mode == NO_SAFE_MODE) { if (safe_mode == NO_SAFE_MODE) {
new_status_color(MAIN_RUNNING);
static const char * const supported_filenames[] = STRING_LIST( static const char * const supported_filenames[] = STRING_LIST(
"code.txt", "code.py", "main.py", "main.txt"); "code.txt", "code.py", "main.py", "main.txt");
#if CIRCUITPY_FULL_BUILD #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")); serial_write_compressed(translate("WARNING: Your code filename has two extensions\n"));
} }
} }
#else
(void) found_main;
#endif #endif
// Finished executing python code. Cleanup includes a board reset. // 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. // Program has finished running.
bool printed_press_any_key = false; bool printed_press_any_key = false;
#if CIRCUITPY_DISPLAYIO #if CIRCUITPY_DISPLAYIO
bool refreshed_epaper_display = false; size_t time_to_epaper_refresh = 1;
#endif #endif
rgb_status_animation_t animation; // Setup LED blinks.
prep_rgb_status_animation(&result, found_main, safe_mode, &animation); #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; bool fake_sleeping = false;
#endif
bool skip_repl = false;
while (true) { while (true) {
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
// If a reload was requested by the supervisor or autoreload, return // If a reload was requested by the supervisor or autoreload, return
if (reload_requested) { if (reload_requested) {
#if CIRCUITPY_ALARM
if (fake_sleeping) {
board_init();
}
#endif
reload_requested = false; reload_requested = false;
return true; skip_repl = true;
break;
} }
// If interrupted by keyboard, return // If interrupted by keyboard, return
if (serial_connected() && serial_bytes_available()) { if (serial_connected() && serial_bytes_available()) {
#if CIRCUITPY_ALARM
if (fake_sleeping) {
board_init();
}
#endif
// Skip REPL if reload was requested. // Skip REPL if reload was requested.
bool ctrl_d = serial_read() == CHAR_CTRL_D; skip_repl = serial_read() == CHAR_CTRL_D;
if (ctrl_d) { if (skip_repl) {
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); 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 // 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 CIRCUITPY_ALARM
if (fake_sleeping && common_hal_alarm_woken_from_sleep()) { if (fake_sleeping && common_hal_alarm_woken_from_sleep()) {
serial_write_compressed(translate("Woken up by alarm.\n")); serial_write_compressed(translate("Woken up by alarm.\n"));
board_init();
supervisor_set_run_reason(RUN_REASON_STARTUP); supervisor_set_run_reason(RUN_REASON_STARTUP);
return true; skip_repl = true;
break;
} }
#endif #endif
@ -403,26 +420,21 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
printed_press_any_key = false; 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. // Sleep until our next interrupt.
#if CIRCUITPY_ALARM #if CIRCUITPY_ALARM
if (result.return_code & PYEXEC_DEEP_SLEEP) { if (result.return_code & PYEXEC_DEEP_SLEEP) {
// Make sure we have been awake long enough for USB to connect (enumeration delay). // 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); 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 // Until it's safe to decide whether we're real/fake sleeping
if (connecting_delay_ticks < 0 && !fake_sleeping) { if (fake_sleeping) {
fake_sleeping = true; // This waits until a pretend deep sleep alarm occurs. They are set
new_status_color(BLACK); // 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(); board_deinit();
if (!supervisor_workflow_active()) { if (!supervisor_workflow_active()) {
// Enter true deep sleep. When we wake up we'll be back at the // 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. // Does not return.
} else { } else {
serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n")); 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 !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 #endif
if (!fake_sleeping) { // time_to_next_change is in ms and ticks are slightly shorter so
tick_rgb_status_animation(&animation); // we'll undersleep just a little. It shouldn't matter.
} else { port_interrupt_after_ticks(time_to_next_change);
// This waits until a pretend deep sleep alarm occurs. They are set #endif
// during common_hal_alarm_set_deep_sleep_alarms. On some platforms port_idle_until_interrupt();
// 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. // 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 CIRCUITPY_ALARM
common_hal_alarm_pretending_deep_sleep(); if (fake_sleeping) {
#else board_init();
port_idle_until_interrupt(); }
#endif #endif
} return skip_repl;
}
} }
FIL* boot_output_file; 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; bool skip_boot_output = false;
if (ok_to_run) { if (ok_to_run) {
new_status_color(BOOT_RUNNING);
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE #ifdef CIRCUITPY_BOOT_OUTPUT_FILE
FIL file_pointer; FIL file_pointer;
@ -578,13 +647,27 @@ STATIC int run_repl(void) {
#endif #endif
autoreload_suspend(); 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); new_status_color(REPL_RUNNING);
status_led_deinit();
#endif
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
exit_code = pyexec_raw_repl(); exit_code = pyexec_raw_repl();
} else { } else {
exit_code = pyexec_friendly_repl(); exit_code = pyexec_friendly_repl();
} }
cleanup_after_vm(heap); cleanup_after_vm(heap);
#if CIRCUITPY_STATUS_LED
status_led_init();
new_status_color(BLACK);
status_led_deinit();
#endif
autoreload_resume(); autoreload_resume();
return exit_code; return exit_code;
} }
@ -593,9 +676,8 @@ int __attribute__((used)) main(void) {
// initialise the cpu and peripherals // initialise the cpu and peripherals
safe_mode_t safe_mode = port_init(); safe_mode_t safe_mode = port_init();
// Turn on LEDs // Turn on RX and TX LEDs if we have them.
init_status_leds(); init_rxtx_leds();
rgb_led_status_init();
// Wait briefly to give a reset window where we'll enter safe mode after the reset. // Wait briefly to give a reset window where we'll enter safe mode after the reset.
if (safe_mode == NO_SAFE_MODE) { if (safe_mode == NO_SAFE_MODE) {

View File

@ -6,13 +6,14 @@
// Rev E // Rev E
#define MICROPY_HW_LED_STATUS (&pin_PA23) #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. // These are pins not to reset.
// QSPI Data pins // QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) #define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
// QSPI CS, QSPI SCK and NeoPixel pin // 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_C (0)
#define MICROPY_PORT_D (0) #define MICROPY_PORT_D (0)

View File

@ -12,7 +12,7 @@
// QSPI Data pins // QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) #define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
// QSPI CS, QSPI SCK and NeoPixel pin // 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_C (0)
#define MICROPY_PORT_D (0) #define MICROPY_PORT_D (0)

View File

@ -33,10 +33,9 @@
#define DEFAULT_SPI_BUS_SCK (&pin_PA17) #define DEFAULT_SPI_BUS_SCK (&pin_PA17)
#define DEFAULT_SPI_BUS_MOSI (&pin_PA16) #define DEFAULT_SPI_BUS_MOSI (&pin_PA16)
// #define CP_RGB_STATUS_R (&pin_PA06) // #define CIRCUITPY_RGB_STATUS_R (&pin_PA06)
// #define CP_RGB_STATUS_G (&pin_PA05) // #define CIRCUITPY_RGB_STATUS_G (&pin_PA05)
// #define CP_RGB_STATUS_B (&pin_PA07) // #define CIRCUITPY_RGB_STATUS_B (&pin_PA07)
// #define CP_RGB_STATUS_INVERTED_PWM // #define CIRCUITPY_RGB_STATUS_INVERTED_PWM
// #define CP_RGB_STATUS_LED
#define MICROPY_HW_LED_STATUS (&pin_PA06) #define MICROPY_HW_LED_STATUS (&pin_PA06)

View File

@ -25,15 +25,8 @@
*/ */
#include "supervisor/board.h" #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) { 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) { bool board_requests_safe_mode(void) {

View File

@ -2,6 +2,7 @@
#define MICROPY_HW_MCU_NAME "samd21e18" #define MICROPY_HW_MCU_NAME "samd21e18"
#define MICROPY_HW_NEOPIXEL (&pin_PA18) #define MICROPY_HW_NEOPIXEL (&pin_PA18)
#define CIRCUITPY_STATUS_LED_POWER (&pin_PA15)
#define MICROPY_PORT_A (0) #define MICROPY_PORT_A (0)
#define MICROPY_PORT_B (0) #define MICROPY_PORT_B (0)

View File

@ -25,15 +25,8 @@
*/ */
#include "supervisor/board.h" #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) { 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) { bool board_requests_safe_mode(void) {

View File

@ -2,6 +2,7 @@
#define MICROPY_HW_MCU_NAME "samd21e18" #define MICROPY_HW_MCU_NAME "samd21e18"
#define MICROPY_HW_NEOPIXEL (&pin_PA18) #define MICROPY_HW_NEOPIXEL (&pin_PA18)
#define CIRCUITPY_STATUS_LED_POWER (&pin_PA15)
#define MICROPY_PORT_A (0) #define MICROPY_PORT_A (0)
#define MICROPY_PORT_B (0) #define MICROPY_PORT_B (0)

View File

@ -36,7 +36,6 @@
#include "hal/include/hal_gpio.h" #include "hal/include/hal_gpio.h"
#include "hal/include/hal_spi_m_sync.h" #include "hal/include/hal_spi_m_sync.h"
#include "hal/include/hpl_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/dma.h"
#include "samd/sercom.h" #include "samd/sercom.h"
@ -72,11 +71,6 @@ void reset_sercoms(void) {
if (never_reset_sercoms[i]) { if (never_reset_sercoms[i]) {
continue; continue;
} }
#ifdef MICROPY_HW_APA102_SERCOM
if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) {
continue;
}
#endif
// SWRST is same for all modes of SERCOMs. // SWRST is same for all modes of SERCOMs.
sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1; sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1;
} }
@ -122,15 +116,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
continue; continue;
} }
Sercom *potential_sercom = sercom_insts[sercom_index]; Sercom *potential_sercom = sercom_insts[sercom_index];
if ( if (potential_sercom->SPI.CTRLA.bit.ENABLE != 0) {
#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
) {
continue; continue;
} }
clock_pinmux = PINMUX(clock->number, (i == 0) ? MUX_C : MUX_D); 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. // Set up SPI clocks on SERCOM.
samd_peripherals_sercom_clock_init(sercom, sercom_index); 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) { if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) {
mp_raise_OSError(MP_EIO); mp_raise_OSError(MP_EIO);
} }

View File

@ -32,15 +32,7 @@
#include "hal/include/hal_gpio.h" #include "hal/include/hal_gpio.h"
#include "samd/pins.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 #ifdef SPEAKER_ENABLE_PIN
bool speaker_enable_in_use; bool speaker_enable_in_use;
#endif #endif
@ -90,14 +82,6 @@ void reset_all_pins(void) {
gpio_set_pin_function(PIN_PA31, GPIO_PIN_FUNCTION_G); gpio_set_pin_function(PIN_PA31, GPIO_PIN_FUNCTION_G);
#endif #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. // After configuring SWD because it may be shared.
#ifdef SPEAKER_ENABLE_PIN #ifdef SPEAKER_ENABLE_PIN
speaker_enable_in_use = false; 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)); 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 if (pin_number == PIN_PA30
#ifdef SAM_D5X_E5X #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) { 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 #ifdef SPEAKER_ENABLE_PIN
if (pin == SPEAKER_ENABLE_PIN) { if (pin == SPEAKER_ENABLE_PIN) {
speaker_enable_in_use = true; 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) { 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 #ifdef SPEAKER_ENABLE_PIN
if (pin == SPEAKER_ENABLE_PIN) { if (pin == SPEAKER_ENABLE_PIN) {
return !speaker_enable_in_use; return !speaker_enable_in_use;

View File

@ -31,14 +31,6 @@
#include "peripherals/samd/pins.h" #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); void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't // reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer. // need to store a full pointer.

View File

@ -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 " movs r6, #3; d2: sub r6, #1; bne d2;" // delay 3
#endif #endif
#ifdef SAM_D5X_E5X #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 #endif
" tst r4, r5;" // mask&r5 " tst r4, r5;" // mask&r5
" bne skipclr;" " 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 " movs r6, #6; d0: sub r6, #1; bne d0;" // delay 6
#endif #endif
#ifdef SAM_D5X_E5X #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 #endif
" str r1, [r0, #0];" // clr (possibly again, doesn't matter) " str r1, [r0, #0];" // clr (possibly again, doesn't matter)
#ifdef SAMD21 #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 " movs r6, #2; d1: sub r6, #1; bne d1;" // delay 2
#endif #endif
#ifdef SAM_D5X_E5X #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 #endif
" b loopBit;" " b loopBit;"
"nextbyte:" "nextbyte:"
#ifdef SAM_D5X_E5X
" movs r6, #12; d3: subs r6, #1; bne d3;" // delay 2
#endif
" cmp r2, r3;" " cmp r2, r3;"
" bcs neopixel_stop;" " bcs neopixel_stop;"
" b loopLoad;" " 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. // Turn off interrupts of any kind during timing-sensitive code.
mp_hal_disable_all_interrupts(); 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; uint32_t pin = digitalinout->pin->number;
port = &PORT->Group[GPIO_PORT(pin)]; // Convert GPIO # to port register port = &PORT->Group[GPIO_PORT(pin)]; // Convert GPIO # to port register
pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code. pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code.
volatile uint32_t *clr = &(port->OUTCLR.reg); volatile uint32_t *clr = &(port->OUTCLR.reg);
neopixel_send_buffer_core(clr, pinMask, pixels, numBytes); 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. // Update the next start.
next_start_raw_ticks = port_get_raw_ticks(NULL) + 4; next_start_raw_ticks = port_get_raw_ticks(NULL) + 4;

View File

@ -51,21 +51,10 @@
#include "hal/include/hal_flash.h" #include "hal/include/hal_flash.h"
#include "supervisor/flash.h" #include "supervisor/flash.h"
#include "supervisor/shared/rgb_led_status.h"
static struct flash_descriptor supervisor_flash_desc; static struct flash_descriptor supervisor_flash_desc;
void supervisor_flash_init(void) { 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 #ifdef SAM_D5X_E5X
hri_mclk_set_AHBMASK_NVMCTRL_bit(MCLK); hri_mclk_set_AHBMASK_NVMCTRL_bit(MCLK);
#endif #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) { 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 // non-MBR block, copy to cache
int32_t dest = convert_block_to_flash_addr(block); int32_t dest = convert_block_to_flash_addr(block);
if (dest == -1) { if (dest == -1) {
@ -136,10 +121,6 @@ bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) {
if (error_code != ERR_NONE) { if (error_code != ERR_NONE) {
return false; return false;
} }
clear_temp_status();
#ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
#endif
return true; return true;
} }

View File

@ -462,6 +462,8 @@ static uint32_t _get_count(uint64_t *overflow_count) {
return count; return count;
} }
volatile bool _woken_up;
static void _port_interrupt_after_ticks(uint32_t ticks) { static void _port_interrupt_after_ticks(uint32_t ticks) {
uint32_t current_ticks = _get_count(NULL); uint32_t current_ticks = _get_count(NULL);
if (ticks > 1 << 28) { if (ticks > 1 << 28) {
@ -473,9 +475,16 @@ static void _port_interrupt_after_ticks(uint32_t ticks) {
return; return;
} }
#endif #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.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0; RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0;
current_ticks = _get_count(NULL);
_woken_up = current_ticks >= target;
} }
void RTC_Handler(void) { 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 // Our RTC is 32 bits and we're clocking it at 16.384khz which is 16 (2 ** 4) subticks per
// tick. // tick.
overflowed_ticks += (1L << (32 - 4)); overflowed_ticks += (1L << (32 - 4));
}
#ifdef SAM_D5X_E5X #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; RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_PER2;
// Do things common to all ports when the tick occurs // Do things common to all ports when the tick occurs
supervisor_tick(); supervisor_tick();
}
#endif #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 // Clear the interrupt because we may have hit a sleep and _ticks_enabled
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;
_woken_up = true;
#ifdef SAMD21 #ifdef SAMD21
if (_ticks_enabled) { if (_ticks_enabled) {
// Do things common to all ports when the tick occurs. // Do things common to all ports when the tick occurs.
@ -565,7 +577,7 @@ void port_idle_until_interrupt(void) {
} }
#endif #endif
common_hal_mcu_disable_interrupts(); common_hal_mcu_disable_interrupts();
if (!tud_task_event_ready() && !hold_interrupt) { if (!tud_task_event_ready() && !hold_interrupt && !_woken_up) {
__DSB(); __DSB();
__WFI(); __WFI();
} }

View File

@ -30,6 +30,7 @@
#define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_MCU_NAME "ESP32S2"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO33) #define MICROPY_HW_NEOPIXEL (&pin_GPIO33)
#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO21)
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)

View File

@ -30,6 +30,7 @@
#define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_MCU_NAME "ESP32S2"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO33) #define MICROPY_HW_NEOPIXEL (&pin_GPIO33)
#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO21)
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)

View File

@ -30,6 +30,8 @@
#define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_MCU_NAME "ESP32S2"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO1) #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) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)

View File

@ -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_SDA), MP_ROM_PTR(&pin_GPIO33) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO34) }, { 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_POWER), MP_ROM_PTR(&pin_GPIO21) },
{ MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO1) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO1) },

View File

@ -30,6 +30,7 @@
#define MICROPY_HW_MCU_NAME "ESP32S2" #define MICROPY_HW_MCU_NAME "ESP32S2"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO1) #define MICROPY_HW_NEOPIXEL (&pin_GPIO1)
#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO2)
#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0)
#define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n") #define BOARD_USER_SAFE_MODE_ACTION translate("pressing boot button at start up.\n")

View File

@ -29,7 +29,6 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/rgb_led_status.h"
static bool spi_never_reset[SOC_SPI_PERIPH_NUM]; static bool spi_never_reset[SOC_SPI_PERIPH_NUM];

View File

@ -27,23 +27,15 @@
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/digitalio/DigitalInOut.h"
#include "supervisor/shared/rgb_led_status.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "components/driver/include/driver/gpio.h" #include "components/driver/include/driver/gpio.h"
#include "components/soc/include/hal/gpio_hal.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 never_reset_pins[2];
STATIC uint32_t in_use[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) { STATIC void floating_gpio_reset(gpio_num_t pin_number) {
// This is the same as gpio_reset_pin(), but without the pullup. // This is the same as gpio_reset_pin(), but without the pullup.
// Note that gpio_config resets the iomatrix to GPIO_FUNC as well. // 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); in_use[pin_number / 32] &= ~(1 << pin_number % 32);
floating_gpio_reset(pin_number); 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) { 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[0] = 0;
in_use[1] = 0; in_use[1] = 0;
#ifdef MICROPY_HW_NEOPIXEL
neopixel_in_use = false;
#endif
} }
void claim_pin(const mcu_pin_obj_t *pin) { void claim_pin(const mcu_pin_obj_t *pin) {
in_use[pin->number / 32] |= (1 << (pin->number % 32)); 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) { 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) { 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; uint8_t offset = pin_number / 32;
uint32_t mask = 1 << (pin_number % 32); uint32_t mask = 1 << (pin_number % 32);
return (in_use[offset] & mask) == 0; return (in_use[offset] & mask) == 0;

View File

@ -31,13 +31,6 @@
#include "peripherals/pins.h" #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); void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't // reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer. // need to store a full pointer.

View File

@ -27,15 +27,6 @@
*/ */
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.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 claimed_pins[IOMUXC_SW_PAD_CTL_PAD_COUNT];
STATIC bool never_reset_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; 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, // 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; claimed_pins[pin->mux_idx] = false;
*(uint32_t *)pin->mux_reg = pin->mux_reset; *(uint32_t *)pin->mux_reg = pin->mux_reset;
*(uint32_t *)pin->cfg_reg = pin->pad_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) { 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) { 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]; 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) { void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
claimed_pins[pin->mux_idx] = true; 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) { void claim_pin(const mcu_pin_obj_t *pin) {

View File

@ -32,14 +32,6 @@
#include "pins.h" #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 reset_all_pins(void);
void claim_pin(const mcu_pin_obj_t *pin); void claim_pin(const mcu_pin_obj_t *pin);

View File

@ -31,9 +31,9 @@
#define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_HW_MCU_NAME "nRF52840"
// RGB LEDs use PWM peripheral, avoid using them to save energy // RGB LEDs use PWM peripheral, avoid using them to save energy
// #define CP_RGB_STATUS_R (&pin_P0_30) #define CIRCUITPY_RGB_STATUS_R (&pin_P0_30)
// #define CP_RGB_STATUS_G (&pin_P0_29) #define CIRCUITPY_RGB_STATUS_G (&pin_P0_29)
// #define CP_RGB_STATUS_B (&pin_P0_31) #define CIRCUITPY_RGB_STATUS_B (&pin_P0_31)
#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10) #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10)
#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14)

View File

@ -32,10 +32,10 @@
#define MICROPY_HW_LED_STATUS (&pin_P1_07) #define MICROPY_HW_LED_STATUS (&pin_P1_07)
#define CP_RGB_STATUS_INVERTED_PWM #define CIRCUITPY_RGB_STATUS_INVERTED_PWM
#define CP_RGB_STATUS_R (&pin_P0_30) #define CIRCUITPY_RGB_STATUS_R (&pin_P0_30)
#define CP_RGB_STATUS_G (&pin_P0_29) #define CIRCUITPY_RGB_STATUS_G (&pin_P0_29)
#define CP_RGB_STATUS_B (&pin_P0_31) #define CIRCUITPY_RGB_STATUS_B (&pin_P0_31)
#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10) #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10)
#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14)

View File

@ -32,9 +32,9 @@
#define MICROPY_HW_LED_STATUS (&pin_P1_12) #define MICROPY_HW_LED_STATUS (&pin_P1_12)
#define CP_RGB_STATUS_R (&pin_P0_13) #define CIRCUITPY_RGB_STATUS_R (&pin_P0_13)
#define CP_RGB_STATUS_G (&pin_P0_14) #define CIRCUITPY_RGB_STATUS_G (&pin_P0_14)
#define CP_RGB_STATUS_B (&pin_P0_15) #define CIRCUITPY_RGB_STATUS_B (&pin_P0_15)
#if QSPI_FLASH_FILESYSTEM #if QSPI_FLASH_FILESYSTEM
#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20) #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20)

View File

@ -31,15 +31,7 @@
#include "py/mphal.h" #include "py/mphal.h"
#include "nrf/pins.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 #ifdef SPEAKER_ENABLE_PIN
bool speaker_enable_in_use; bool speaker_enable_in_use;
#endif #endif
@ -73,14 +65,6 @@ void reset_all_pins(void) {
nrf_gpio_cfg_default(pin); 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. // After configuring SWD because it may be shared.
reset_speaker_enable_pin(); 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)); 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)); 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 #ifdef SPEAKER_ENABLE_PIN
if (pin_number == SPEAKER_ENABLE_PIN->number) { if (pin_number == SPEAKER_ENABLE_PIN->number) {
reset_speaker_enable_pin(); reset_speaker_enable_pin();
@ -144,20 +109,6 @@ void claim_pin(const mcu_pin_obj_t *pin) {
// Set bit in claimed_pins bitmask. // Set bit in claimed_pins bitmask.
claimed_pins[nrf_pin_port(pin->number)] |= 1 << nrf_relative_pin_number(pin->number); 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 #ifdef SPEAKER_ENABLE_PIN
if (pin == SPEAKER_ENABLE_PIN) { if (pin == SPEAKER_ENABLE_PIN) {
speaker_enable_in_use = true; 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) { 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 #ifdef SPEAKER_ENABLE_PIN
if (pin == SPEAKER_ENABLE_PIN) { if (pin == SPEAKER_ENABLE_PIN) {
return !speaker_enable_in_use; return !speaker_enable_in_use;

View File

@ -31,14 +31,6 @@
#include "peripherals/nrf/pins.h" #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); void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't // reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer. // need to store a full pointer.

View File

@ -26,14 +26,7 @@
#include "supervisor/board.h" #include "supervisor/board.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
void board_init(void) { 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) { bool board_requests_safe_mode(void) {

View File

@ -2,6 +2,7 @@
#define MICROPY_HW_MCU_NAME "rp2040" #define MICROPY_HW_MCU_NAME "rp2040"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO17) #define MICROPY_HW_NEOPIXEL (&pin_GPIO17)
#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO16)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO3) #define DEFAULT_I2C_BUS_SCL (&pin_GPIO3)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO2) #define DEFAULT_I2C_BUS_SDA (&pin_GPIO2)

View File

@ -26,14 +26,7 @@
#include "supervisor/board.h" #include "supervisor/board.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
void board_init(void) { 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) { bool board_requests_safe_mode(void) {

View File

@ -2,6 +2,7 @@
#define MICROPY_HW_MCU_NAME "rp2040" #define MICROPY_HW_MCU_NAME "rp2040"
#define MICROPY_HW_NEOPIXEL (&pin_GPIO12) #define MICROPY_HW_NEOPIXEL (&pin_GPIO12)
#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO11)
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO25) #define DEFAULT_I2C_BUS_SCL (&pin_GPIO25)
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO24) #define DEFAULT_I2C_BUS_SDA (&pin_GPIO24)

View File

@ -32,7 +32,6 @@
#include "supervisor/board.h" #include "supervisor/board.h"
#include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h"
#include "supervisor/shared/rgb_led_status.h"
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
#include "src/rp2_common/hardware_dma/include/hardware/dma.h" #include "src/rp2_common/hardware_dma/include/hardware/dma.h"

View File

@ -29,21 +29,8 @@
#include "common-hal/microcontroller/__init__.h" #include "common-hal/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
#include "supervisor/shared/rgb_led_status.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.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; STATIC uint32_t never_reset_pins;
void reset_all_pins(void) { 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_PUE_BITS |
PADS_BANK0_GPIO0_PDE_BITS); PADS_BANK0_GPIO0_PDE_BITS);
hw_set_bits(&padsbank0_hw->io[pin_number], PADS_BANK0_GPIO0_OD_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) { 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) { void claim_pin(const mcu_pin_obj_t *pin) {
#ifdef MICROPY_HW_NEOPIXEL // Nothing to do because all changes will set the GPIO settings.
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
} }
bool pin_number_is_free(uint8_t pin_number) { 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) { 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); return pin_number_is_free(pin->number);
} }

View File

@ -34,14 +34,6 @@
#include "peripherals/pins.h" #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); void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't // reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer. // need to store a full pointer.

View File

@ -62,7 +62,7 @@ void alarm_set_wakeup_reason(stm_sleep_source_t reason) {
true_deep_wake_reason = 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 in light/fake sleep, check modules
if (alarm_pin_pinalarm_woke_this_cycle()) { if (alarm_pin_pinalarm_woke_this_cycle()) {
return STM_WAKEUP_GPIO; return STM_WAKEUP_GPIO;
@ -71,20 +71,20 @@ STATIC stm_sleep_source_t _get_wakeup_cause(void) {
return STM_WAKEUP_RTC; return STM_WAKEUP_RTC;
} }
// Check to see if we woke from deep sleep (reason set in port_init) // 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 true_deep_wake_reason;
} }
return STM_WAKEUP_UNDEF; return STM_WAKEUP_UNDEF;
} }
bool common_hal_alarm_woken_from_sleep(void) { 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) { mp_obj_t common_hal_alarm_create_wake_alarm(void) {
// If woken from deep sleep, create a copy alarm similar to what would have // If woken from deep sleep, create a copy alarm similar to what would have
// been passed in originally. Otherwise, just return none // 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) { switch (cause) {
case STM_WAKEUP_RTC: { case STM_WAKEUP_RTC: {
return alarm_time_timealarm_create_wakeup_alarm(); 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; RUN_BACKGROUND_TASKS;
// Detect if interrupt was alarm or ctrl-C interrupt. // Detect if interrupt was alarm or ctrl-C interrupt.
if (common_hal_alarm_woken_from_sleep()) { 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) { switch (cause) {
case STM_WAKEUP_RTC: { case STM_WAKEUP_RTC: {
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms); 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) { void NORETURN common_hal_alarm_enter_deep_sleep(void) {
alarm_set_wakeup_reason(STM_WAKEUP_UNDEF);
alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_pin_pinalarm_prepare_for_deep_sleep();
alarm_time_timealarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep();
port_disable_tick(); port_disable_tick();
@ -175,6 +176,8 @@ void common_hal_alarm_pretending_deep_sleep(void) {
GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
alarm_set_wakeup_reason(STM_WAKEUP_UNDEF);
port_idle_until_interrupt(); port_idle_until_interrupt();
} }

View File

@ -40,6 +40,7 @@ typedef enum {
#define STM_ALARM_FLAG (RTC->BKP0R) #define STM_ALARM_FLAG (RTC->BKP0R)
extern void alarm_set_wakeup_reason(stm_sleep_source_t reason); 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); extern void alarm_reset(void);
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H #endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H

View File

@ -27,19 +27,10 @@
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/digitalio/DigitalInOut.h"
#include "supervisor/shared/rgb_led_status.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "pins.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) #if defined(TFBGA216)
GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK}; GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK};
#elif defined(LQFP144) #elif defined(LQFP144)
@ -66,14 +57,6 @@ void reset_all_pins(void) {
for (uint8_t i = 0; i < GPIO_PORT_COUNT; i++) { for (uint8_t i = 0; i < GPIO_PORT_COUNT; i++) {
HAL_GPIO_DeInit(ports[i], ~never_reset_pins[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. // 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); claimed_pins[pin_port] &= ~(1 << pin_number);
never_reset_pins[pin_port] &= ~(1 << pin_number); never_reset_pins[pin_port] &= ~(1 << pin_number);
HAL_GPIO_DeInit(ports[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) { 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) { 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); 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) { void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
claim_pin(pin->port, pin->number); 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) { void common_hal_mcu_pin_reset_number(uint8_t pin_no) {

View File

@ -31,14 +31,6 @@
#include "peripherals/pins.h" #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); void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't // reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer. // need to store a full pointer.

View File

@ -27,6 +27,9 @@
#include <math.h> #include <math.h>
#include "py/runtime.h" #include "py/runtime.h"
#if CIRCUITPY_ALARM
#include "common-hal/alarm/__init__.h"
#endif
#include "common-hal/microcontroller/Processor.h" #include "common-hal/microcontroller/Processor.h"
#include "shared-bindings/microcontroller/ResetReason.h" #include "shared-bindings/microcontroller/ResetReason.h"
#include "supervisor/shared/translate.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) { 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; return RESET_REASON_UNKNOWN;
} }

View File

@ -991,6 +991,10 @@ void supervisor_run_background_tasks_if_tick(void);
#define CIRCUITPY_PROCESSOR_COUNT (1) #define CIRCUITPY_PROCESSOR_COUNT (1)
#endif #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_BOOT_OUTPUT_FILE "/boot_out.txt"
#define CIRCUITPY_VERBOSE_BLE 0 #define CIRCUITPY_VERBOSE_BLE 0

View File

@ -29,7 +29,7 @@
#include "lib/utils/interrupt_char.h" #include "lib/utils/interrupt_char.h"
#include "supervisor/shared/autoreload.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/stack.h"
#include "supervisor/shared/translate.h" #include "supervisor/shared/translate.h"
#include "supervisor/shared/workflow.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) { if (brightness_int < 0 || brightness_int > 255) {
mp_raise_ValueError(translate("Brightness must be between 0 and 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; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_set_rgb_status_brightness); MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_set_rgb_status_brightness);

View File

@ -409,7 +409,7 @@ void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t *self) {
gc_collect_ptr((void *)self->stop_sequence); 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++) { for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].epaper_display.base.type != &displayio_epaperdisplay_type || if (displays[i].epaper_display.base.type != &displayio_epaperdisplay_type ||
displays[i].epaper_display.core.current_group != &circuitpython_splash) { displays[i].epaper_display.core.current_group != &circuitpython_splash) {
@ -417,11 +417,16 @@ bool maybe_refresh_epaperdisplay(void) {
continue; continue;
} }
displayio_epaperdisplay_obj_t *display = &displays[i].epaper_display; displayio_epaperdisplay_obj_t *display = &displays[i].epaper_display;
if (common_hal_displayio_epaperdisplay_get_time_to_refresh(display) != 0) { size_t time_to_refresh = common_hal_displayio_epaperdisplay_get_time_to_refresh(display);
return false; 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;
} }
// Return true if no ePaper displays are available to pretend it was updated. // If we could refresh but it failed, then we want to retry.
return true; return 1;
}
// Return 0 if no ePaper displays are available to pretend it was updated.
return 0;
} }

View File

@ -61,7 +61,7 @@ typedef struct {
void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t *self); void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t *self);
void release_epaperdisplay(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); void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t *self);

View File

@ -39,7 +39,6 @@
#include "lib/oofatfs/ff.h" #include "lib/oofatfs/ff.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/memory.h" #include "supervisor/memory.h"
#include "supervisor/shared/rgb_led_status.h"
#define NO_SECTOR_LOADED 0xFFFFFFFF #define NO_SECTOR_LOADED 0xFFFFFFFF
@ -467,7 +466,6 @@ static void spi_flash_flush_keep_cache(bool keep_cache) {
#ifdef MICROPY_HW_LED_MSC #ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, true); port_pin_set_output_level(MICROPY_HW_LED_MSC, true);
#endif #endif
temp_status_color(ACTIVE_WRITE);
// If we've cached to the flash itself flush from there. // If we've cached to the flash itself flush from there.
if (MP_STATE_VM(flash_ram_cache) == NULL) { if (MP_STATE_VM(flash_ram_cache) == NULL) {
flush_scratch_flash(); flush_scratch_flash();
@ -475,7 +473,6 @@ static void spi_flash_flush_keep_cache(bool keep_cache) {
flush_ram_cache(keep_cache); flush_ram_cache(keep_cache);
} }
current_sector = NO_SECTOR_LOADED; current_sector = NO_SECTOR_LOADED;
clear_temp_status();
#ifdef MICROPY_HW_LED_MSC #ifdef MICROPY_HW_LED_MSC
port_pin_set_output_level(MICROPY_HW_LED_MSC, false); port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
#endif #endif

View File

@ -14,28 +14,17 @@
#define PURPLE COLOR(INTENSITY, 0, INTENSITY) #define PURPLE COLOR(INTENSITY, 0, INTENSITY)
#define WHITE COLOR(INTENSITY, INTENSITY, INTENSITY) #define WHITE COLOR(INTENSITY, INTENSITY, INTENSITY)
#define BOOT_RUNNING BLUE
#define MAIN_RUNNING GREEN
#define SAFE_MODE YELLOW
#define ALL_DONE GREEN #define ALL_DONE GREEN
#define EXCEPTION RED
#define SAFE_MODE YELLOW
#define REPL_RUNNING WHITE #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 LED_SLEEP_TIME_MS 5000u
#define EXCEPTION_TYPE_LENGTH_MS 1000u
#define THOUSANDS WHITE #define BLINK_TIME_MS 100u
#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

View File

@ -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.
}

View File

@ -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 <stdint.h>
#include <stdbool.h>
#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

View File

@ -36,7 +36,7 @@
#include "supervisor/serial.h" #include "supervisor/serial.h"
#include "supervisor/shared/rgb_led_colors.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/translate.h"
#include "supervisor/shared/tick.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)); port_set_saved_word(SAFE_MODE_DATA_GUARD | (MANUAL_SAFE_MODE << 8));
// Wait for a while to allow for reset. // Wait for a while to allow for reset.
temp_status_color(SAFE_MODE);
#ifdef MICROPY_HW_LED_STATUS #if CIRCUITPY_STATUS_LED
digitalio_digitalinout_obj_t status_led; status_led_init();
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);
#endif #endif
#ifdef CIRCUITPY_BOOT_BUTTON #ifdef CIRCUITPY_BOOT_BUTTON
digitalio_digitalinout_obj_t boot_button; digitalio_digitalinout_obj_t boot_button;
@ -78,22 +76,32 @@ safe_mode_t wait_for_safe_mode_reset(void) {
#endif #endif
uint64_t start_ticks = supervisor_ticks_ms64(); uint64_t start_ticks = supervisor_ticks_ms64();
uint64_t diff = 0; uint64_t diff = 0;
bool boot_in_safe_mode = false;
while (diff < 1000) { 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 // 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 #endif
#ifdef CIRCUITPY_BOOT_BUTTON #ifdef CIRCUITPY_BOOT_BUTTON
if (!common_hal_digitalio_digitalinout_get_value(&boot_button)) { if (!common_hal_digitalio_digitalinout_get_value(&boot_button)) {
return USER_SAFE_MODE; boot_in_safe_mode = true;
break;
} }
#endif #endif
diff = supervisor_ticks_ms64() - start_ticks; diff = supervisor_ticks_ms64() - start_ticks;
} }
#ifdef MICROPY_HW_LED_STATUS #if CIRCUITPY_STATUS_LED
common_hal_digitalio_digitalinout_deinit(&status_led); new_status_color(BLACK);
status_led_deinit();
#endif #endif
clear_temp_status(); if (boot_in_safe_mode) {
return USER_SAFE_MODE;
}
port_set_saved_word(SAFE_MODE_DATA_GUARD); port_set_saved_word(SAFE_MODE_DATA_GUARD);
return NO_SAFE_MODE; return NO_SAFE_MODE;
} }

View File

@ -3,7 +3,7 @@
* *
* The MIT License (MIT) * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -26,11 +26,81 @@
#include "supervisor/shared/status_leds.h" #include "supervisor/shared/status_leds.h"
#if CIRCUITPY_DIGITALIO #include "mphalport.h"
#include "common-hal/digitalio/DigitalInOut.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" #include "shared-bindings/digitalio/DigitalInOut.h"
static digitalio_digitalinout_obj_t _status_power;
#endif #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 #ifdef MICROPY_HW_LED_RX
digitalio_digitalinout_obj_t rx_led; digitalio_digitalinout_obj_t rx_led;
#endif #endif
@ -38,27 +108,220 @@ digitalio_digitalinout_obj_t rx_led;
#ifdef MICROPY_HW_LED_TX #ifdef MICROPY_HW_LED_TX
digitalio_digitalinout_obj_t tx_led; digitalio_digitalinout_obj_t tx_led;
#endif #endif
#endif
void init_status_leds(void) { #if CIRCUITPY_STATUS_LED
#ifdef MICROPY_HW_LED_RX 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_construct(&rx_led, MICROPY_HW_LED_RX);
common_hal_digitalio_digitalinout_switch_to_output(&rx_led, true, DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_switch_to_output(&rx_led, true, DRIVE_MODE_PUSH_PULL);
#endif #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_construct(&tx_led, MICROPY_HW_LED_TX);
common_hal_digitalio_digitalinout_switch_to_output(&tx_led, true, DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_switch_to_output(&tx_led, true, DRIVE_MODE_PUSH_PULL);
#endif #endif
} }
void toggle_rx_led(void) { 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)); common_hal_digitalio_digitalinout_set_value(&rx_led, !common_hal_digitalio_digitalinout_get_value(&rx_led));
#endif #endif
} }
void toggle_tx_led(void) { 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)); common_hal_digitalio_digitalinout_set_value(&tx_led, !common_hal_digitalio_digitalinout_get_value(&tx_led));
#endif #endif
} }

View File

@ -27,10 +27,35 @@
#ifndef MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H #ifndef MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H
#define MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H #define MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H
void init_status_leds(void); #include <stdint.h>
#include <stdbool.h>
#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_rx_led(void);
void toggle_tx_led(void); void toggle_tx_led(void);
#endif // MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H #endif // MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H

View File

@ -9,7 +9,6 @@ SRC_SUPERVISOR = \
supervisor/shared/flash.c \ supervisor/shared/flash.c \
supervisor/shared/memory.c \ supervisor/shared/memory.c \
supervisor/shared/micropython.c \ supervisor/shared/micropython.c \
supervisor/shared/rgb_led_status.c \
supervisor/shared/safe_mode.c \ supervisor/shared/safe_mode.c \
supervisor/shared/stack.c \ supervisor/shared/stack.c \
supervisor/shared/status_leds.c \ supervisor/shared/status_leds.c \