Simplify the status LED to save power
This also removes the need to pin share because we don't use the status LED while user code is running. The status flashes fallback to the HW_STATUS LED if no RGB LED is present. Each status has a unique blink pattern as well. One caveat is the REPL state. In order to not pin share, we set the RGB color once. PWM and single color will be shutoff immediately but DotStars and NeoPixels will hold the color until the user overrides it. Fixes #4133
This commit is contained in:
parent
35ee4add63
commit
1a0b4193b7
180
main.c
180
main.c
@ -53,7 +53,6 @@
|
||||
#include "supervisor/port.h"
|
||||
#include "supervisor/serial.h"
|
||||
#include "supervisor/shared/autoreload.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
#include "supervisor/shared/safe_mode.h"
|
||||
#include "supervisor/shared/stack.h"
|
||||
#include "supervisor/shared/status_leds.h"
|
||||
@ -114,7 +113,6 @@ static void reset_devices(void) {
|
||||
}
|
||||
|
||||
STATIC void start_mp(supervisor_allocation* heap) {
|
||||
reset_status_led();
|
||||
autoreload_stop();
|
||||
supervisor_workflow_reset();
|
||||
|
||||
@ -251,7 +249,6 @@ STATIC void cleanup_after_vm(supervisor_allocation* heap) {
|
||||
#endif
|
||||
reset_port();
|
||||
reset_board();
|
||||
reset_status_led();
|
||||
}
|
||||
|
||||
STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
|
||||
@ -284,8 +281,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
bool found_main = false;
|
||||
|
||||
if (safe_mode == NO_SAFE_MODE) {
|
||||
new_status_color(MAIN_RUNNING);
|
||||
|
||||
static const char * const supported_filenames[] = STRING_LIST(
|
||||
"code.txt", "code.py", "main.py", "main.txt");
|
||||
#if CIRCUITPY_FULL_BUILD
|
||||
@ -315,6 +310,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
serial_write_compressed(translate("WARNING: Your code filename has two extensions\n"));
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void) found_main;
|
||||
#endif
|
||||
|
||||
// Finished executing python code. Cleanup includes a board reset.
|
||||
@ -332,42 +329,64 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
}
|
||||
|
||||
// Program has finished running.
|
||||
|
||||
bool printed_press_any_key = false;
|
||||
#if CIRCUITPY_DISPLAYIO
|
||||
bool refreshed_epaper_display = false;
|
||||
size_t time_to_epaper_refresh = 1;
|
||||
#endif
|
||||
|
||||
rgb_status_animation_t animation;
|
||||
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
|
||||
// Setup LED blinks.
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
uint32_t color;
|
||||
uint8_t blink_count;
|
||||
#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;
|
||||
if (blink_count > 0) {
|
||||
status_led_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_ALARM
|
||||
bool fake_sleeping = false;
|
||||
#endif
|
||||
bool skip_repl = false;
|
||||
while (true) {
|
||||
RUN_BACKGROUND_TASKS;
|
||||
|
||||
// If a reload was requested by the supervisor or autoreload, return
|
||||
if (reload_requested) {
|
||||
#if CIRCUITPY_ALARM
|
||||
if (fake_sleeping) {
|
||||
board_init();
|
||||
}
|
||||
#endif
|
||||
reload_requested = false;
|
||||
return true;
|
||||
skip_repl = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// If interrupted by keyboard, return
|
||||
if (serial_connected() && serial_bytes_available()) {
|
||||
#if CIRCUITPY_ALARM
|
||||
if (fake_sleeping) {
|
||||
board_init();
|
||||
}
|
||||
#endif
|
||||
// Skip REPL if reload was requested.
|
||||
bool ctrl_d = serial_read() == CHAR_CTRL_D;
|
||||
if (ctrl_d) {
|
||||
skip_repl = serial_read() == CHAR_CTRL_D;
|
||||
if (skip_repl) {
|
||||
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
|
||||
}
|
||||
return ctrl_d;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for a deep sleep alarm and restart the VM. This can happen if
|
||||
@ -376,9 +395,9 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
#if CIRCUITPY_ALARM
|
||||
if (fake_sleeping && common_hal_alarm_woken_from_sleep()) {
|
||||
serial_write_compressed(translate("Woken up by alarm.\n"));
|
||||
board_init();
|
||||
supervisor_set_run_reason(RUN_REASON_STARTUP);
|
||||
return true;
|
||||
skip_repl = true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -398,25 +417,21 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
printed_press_any_key = false;
|
||||
}
|
||||
|
||||
// Refresh the ePaper display if we have one. That way it'll show an error message.
|
||||
#if CIRCUITPY_DISPLAYIO
|
||||
// Don't refresh the display if we're about to deep sleep.
|
||||
#if CIRCUITPY_ALARM
|
||||
refreshed_epaper_display = refreshed_epaper_display || result.return_code & PYEXEC_DEEP_SLEEP;
|
||||
#endif
|
||||
if (!refreshed_epaper_display) {
|
||||
refreshed_epaper_display = maybe_refresh_epaperdisplay();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sleep until our next interrupt.
|
||||
#if CIRCUITPY_ALARM
|
||||
if (result.return_code & PYEXEC_DEEP_SLEEP) {
|
||||
// Make sure we have been awake long enough for USB to connect (enumeration delay).
|
||||
int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL);
|
||||
// Until it's safe to decide whether we're real/fake sleeping, just run the RGB
|
||||
if (connecting_delay_ticks < 0 && !fake_sleeping) {
|
||||
fake_sleeping = true;
|
||||
// Until it's safe to decide whether we're real/fake sleeping
|
||||
if (fake_sleeping) {
|
||||
// This waits until a pretend deep sleep alarm occurs. They are set
|
||||
// during common_hal_alarm_set_deep_sleep_alarms. On some platforms
|
||||
// it may also return due to another interrupt, that's why we check
|
||||
// for deep sleep alarms above. If it wasn't a deep sleep alarm,
|
||||
// then we'll idle here again.
|
||||
common_hal_alarm_pretending_deep_sleep();
|
||||
} else if (connecting_delay_ticks < 0) {
|
||||
// Entering deep sleep (may be fake or real.)
|
||||
new_status_color(BLACK);
|
||||
board_deinit();
|
||||
if (!supervisor_workflow_active()) {
|
||||
@ -426,27 +441,71 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||
// Does not return.
|
||||
} else {
|
||||
serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n"));
|
||||
fake_sleeping = true;
|
||||
}
|
||||
} else {
|
||||
// Loop while checking the time. We can't idle because we don't want to override a
|
||||
// time alarm set for the deep sleep.
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Refresh the ePaper display if we have one. That way it'll show an error message.
|
||||
#if CIRCUITPY_DISPLAYIO
|
||||
if (time_to_epaper_refresh > 0) {
|
||||
time_to_epaper_refresh = maybe_refresh_epaperdisplay();
|
||||
}
|
||||
|
||||
if (!fake_sleeping) {
|
||||
tick_rgb_status_animation(&animation);
|
||||
} else {
|
||||
// This waits until a pretend deep sleep alarm occurs. They are set
|
||||
// during common_hal_alarm_set_deep_sleep_alarms. On some platforms
|
||||
// it may also return due to another interrupt, that's why we check
|
||||
// for deep sleep alarms above. If it wasn't a deep sleep alarm,
|
||||
// then we'll idle here again.
|
||||
|
||||
#if CIRCUITPY_ALARM
|
||||
common_hal_alarm_pretending_deep_sleep();
|
||||
#else
|
||||
port_idle_until_interrupt();
|
||||
#if !CIRCUITPY_STATUS_LED
|
||||
port_interrupt_after_ticks(time_to_epaper_refresh);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
uint32_t tick_diff = supervisor_ticks_ms32() - pattern_start;
|
||||
|
||||
// By default, don't sleep.
|
||||
size_t time_to_next_change = 0;
|
||||
if (tick_diff < blink_time) {
|
||||
uint32_t blink_diff = tick_diff % (single_blink_time);
|
||||
if (blink_diff >= BLINK_TIME_MS) {
|
||||
new_status_color(BLACK);
|
||||
time_to_next_change = single_blink_time - blink_diff;
|
||||
} else {
|
||||
new_status_color(color);
|
||||
time_to_next_change = BLINK_TIME_MS - blink_diff;
|
||||
}
|
||||
} else if (tick_diff > total_time) {
|
||||
pattern_start = supervisor_ticks_ms32();
|
||||
} else {
|
||||
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
|
||||
if (time_to_next_change > 0) {
|
||||
// time_to_next_change is in ms and ticks are slightly shorter so
|
||||
// we'll undersleep just a little. It shouldn't matter.
|
||||
port_interrupt_after_ticks(time_to_next_change);
|
||||
}
|
||||
#endif
|
||||
port_idle_until_interrupt();
|
||||
}
|
||||
}
|
||||
// Done waiting, start the board back up.
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
new_status_color(BLACK);
|
||||
status_led_deinit();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_ALARM
|
||||
if (fake_sleeping) {
|
||||
board_init();
|
||||
}
|
||||
#endif
|
||||
return skip_repl;
|
||||
}
|
||||
|
||||
FIL* boot_output_file;
|
||||
@ -463,7 +522,6 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
|
||||
bool skip_boot_output = false;
|
||||
|
||||
if (ok_to_run) {
|
||||
new_status_color(BOOT_RUNNING);
|
||||
|
||||
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
|
||||
FIL file_pointer;
|
||||
@ -574,7 +632,16 @@ STATIC int run_repl(void) {
|
||||
#endif
|
||||
|
||||
autoreload_suspend();
|
||||
|
||||
// Set the status LED to the REPL color before running the REPL. For
|
||||
// NeoPixels and DotStars this will be sticky but for PWM or single LED it
|
||||
// won't. This simplifies pin sharing because they won't be in use when
|
||||
// actually in the REPL.
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
status_led_init();
|
||||
new_status_color(REPL_RUNNING);
|
||||
status_led_deinit();
|
||||
#endif
|
||||
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
|
||||
exit_code = pyexec_raw_repl();
|
||||
} else {
|
||||
@ -589,9 +656,8 @@ int __attribute__((used)) main(void) {
|
||||
// initialise the cpu and peripherals
|
||||
safe_mode_t safe_mode = port_init();
|
||||
|
||||
// Turn on LEDs
|
||||
init_status_leds();
|
||||
rgb_led_status_init();
|
||||
// Turn on RX and TX LEDs if we have them.
|
||||
init_rxtx_leds();
|
||||
|
||||
// Wait briefly to give a reset window where we'll enter safe mode after the reset.
|
||||
if (safe_mode == NO_SAFE_MODE) {
|
||||
|
@ -33,10 +33,9 @@
|
||||
#define DEFAULT_SPI_BUS_SCK (&pin_PA17)
|
||||
#define DEFAULT_SPI_BUS_MOSI (&pin_PA16)
|
||||
|
||||
// #define CP_RGB_STATUS_R (&pin_PA06)
|
||||
// #define CP_RGB_STATUS_G (&pin_PA05)
|
||||
// #define CP_RGB_STATUS_B (&pin_PA07)
|
||||
// #define CP_RGB_STATUS_INVERTED_PWM
|
||||
// #define CP_RGB_STATUS_LED
|
||||
// #define CIRCUITPY_RGB_STATUS_R (&pin_PA06)
|
||||
// #define CIRCUITPY_RGB_STATUS_G (&pin_PA05)
|
||||
// #define CIRCUITPY_RGB_STATUS_B (&pin_PA07)
|
||||
// #define CIRCUITPY_RGB_STATUS_INVERTED_PWM
|
||||
|
||||
#define MICROPY_HW_LED_STATUS (&pin_PA06)
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "hal/include/hal_gpio.h"
|
||||
#include "hal/include/hal_spi_m_sync.h"
|
||||
#include "hal/include/hpl_spi_m_sync.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
#include "samd/dma.h"
|
||||
#include "samd/sercom.h"
|
||||
@ -72,11 +71,6 @@ void reset_sercoms(void) {
|
||||
if (never_reset_sercoms[i]) {
|
||||
continue;
|
||||
}
|
||||
#ifdef MICROPY_HW_APA102_SERCOM
|
||||
if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
// SWRST is same for all modes of SERCOMs.
|
||||
sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1;
|
||||
}
|
||||
@ -122,15 +116,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
continue;
|
||||
}
|
||||
Sercom *potential_sercom = sercom_insts[sercom_index];
|
||||
if (
|
||||
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102
|
||||
(potential_sercom->SPI.CTRLA.bit.ENABLE != 0 &&
|
||||
potential_sercom != status_apa102.spi_desc.dev.prvt &&
|
||||
!apa102_sck_in_use)
|
||||
#else
|
||||
potential_sercom->SPI.CTRLA.bit.ENABLE != 0
|
||||
#endif
|
||||
) {
|
||||
if (potential_sercom->SPI.CTRLA.bit.ENABLE != 0) {
|
||||
continue;
|
||||
}
|
||||
clock_pinmux = PINMUX(clock->number, (i == 0) ? MUX_C : MUX_D);
|
||||
@ -181,10 +167,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
|
||||
// Set up SPI clocks on SERCOM.
|
||||
samd_peripherals_sercom_clock_init(sercom, sercom_index);
|
||||
|
||||
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102
|
||||
// if we're re-using the dotstar sercom, make sure it is disabled or the init will fail out
|
||||
hri_sercomspi_clear_CTRLA_ENABLE_bit(sercom);
|
||||
#endif
|
||||
if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
|
@ -32,15 +32,7 @@
|
||||
#include "hal/include/hal_gpio.h"
|
||||
|
||||
#include "samd/pins.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
bool apa102_sck_in_use;
|
||||
bool apa102_mosi_in_use;
|
||||
#endif
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
bool speaker_enable_in_use;
|
||||
#endif
|
||||
@ -90,14 +82,6 @@ void reset_all_pins(void) {
|
||||
gpio_set_pin_function(PIN_PA31, GPIO_PIN_FUNCTION_G);
|
||||
#endif
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
neopixel_in_use = false;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
apa102_sck_in_use = false;
|
||||
apa102_mosi_in_use = false;
|
||||
#endif
|
||||
|
||||
// After configuring SWD because it may be shared.
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
speaker_enable_in_use = false;
|
||||
@ -122,25 +106,6 @@ void reset_pin_number(uint8_t pin_number) {
|
||||
|
||||
never_reset_pins[GPIO_PORT(pin_number)] &= ~(1 << GPIO_PIN(pin_number));
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin_number == MICROPY_HW_NEOPIXEL->number) {
|
||||
neopixel_in_use = false;
|
||||
rgb_led_status_init();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin_number == MICROPY_HW_APA102_MOSI->number ||
|
||||
pin_number == MICROPY_HW_APA102_SCK->number) {
|
||||
apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number;
|
||||
apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number;
|
||||
if (!apa102_sck_in_use && !apa102_mosi_in_use) {
|
||||
rgb_led_status_init();
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pin_number == PIN_PA30
|
||||
#ifdef SAM_D5X_E5X
|
||||
) {
|
||||
@ -176,20 +141,6 @@ void common_hal_reset_pin(const mcu_pin_obj_t* pin) {
|
||||
}
|
||||
|
||||
void claim_pin(const mcu_pin_obj_t* pin) {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
neopixel_in_use = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
apa102_mosi_in_use = true;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
apa102_sck_in_use = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
if (pin == SPEAKER_ENABLE_PIN) {
|
||||
speaker_enable_in_use = true;
|
||||
@ -223,26 +174,6 @@ bool pin_number_is_free(uint8_t pin_number) {
|
||||
}
|
||||
|
||||
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin) {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
// Special case for Metro M0 where the NeoPixel is also SWCLK
|
||||
#ifndef IGNORE_PIN_PA30
|
||||
if (MICROPY_HW_NEOPIXEL == &pin_PA30 && DSU->STATUSB.bit.DBGPRES == 1) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return !neopixel_in_use;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
return !apa102_mosi_in_use;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
return !apa102_sck_in_use;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
if (pin == SPEAKER_ENABLE_PIN) {
|
||||
return !speaker_enable_in_use;
|
||||
|
@ -31,14 +31,6 @@
|
||||
|
||||
#include "peripherals/samd/pins.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
extern bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
extern bool apa102_sck_in_use;
|
||||
extern bool apa102_mosi_in_use;
|
||||
#endif
|
||||
|
||||
void reset_all_pins(void);
|
||||
// reset_pin_number takes the pin number instead of the pointer so that objects don't
|
||||
// need to store a full pointer.
|
||||
|
@ -51,21 +51,10 @@
|
||||
#include "hal/include/hal_flash.h"
|
||||
|
||||
#include "supervisor/flash.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
static struct flash_descriptor supervisor_flash_desc;
|
||||
|
||||
void supervisor_flash_init(void) {
|
||||
// Activity LED for flash writes.
|
||||
#ifdef MICROPY_HW_LED_MSC
|
||||
struct port_config pin_conf;
|
||||
port_get_config_defaults(&pin_conf);
|
||||
|
||||
pin_conf.direction = PORT_PIN_DIR_OUTPUT;
|
||||
port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf);
|
||||
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
|
||||
#endif
|
||||
|
||||
#ifdef SAM_D5X_E5X
|
||||
hri_mclk_set_AHBMASK_NVMCTRL_bit(MCLK);
|
||||
#endif
|
||||
@ -114,10 +103,6 @@ bool supervisor_flash_read_block(uint8_t *dest, uint32_t block) {
|
||||
}
|
||||
|
||||
bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) {
|
||||
#ifdef MICROPY_HW_LED_MSC
|
||||
port_pin_set_output_level(MICROPY_HW_LED_MSC, true);
|
||||
#endif
|
||||
temp_status_color(ACTIVE_WRITE);
|
||||
// non-MBR block, copy to cache
|
||||
int32_t dest = convert_block_to_flash_addr(block);
|
||||
if (dest == -1) {
|
||||
@ -136,10 +121,6 @@ bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) {
|
||||
if (error_code != ERR_NONE) {
|
||||
return false;
|
||||
}
|
||||
clear_temp_status();
|
||||
#ifdef MICROPY_HW_LED_MSC
|
||||
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
static bool spi_never_reset[SOC_SPI_PERIPH_NUM];
|
||||
|
||||
|
@ -27,23 +27,15 @@
|
||||
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "components/driver/include/driver/gpio.h"
|
||||
#include "components/soc/include/hal/gpio_hal.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
bool neopixel_in_use;
|
||||
#endif
|
||||
|
||||
STATIC uint32_t never_reset_pins[2];
|
||||
STATIC uint32_t in_use[2];
|
||||
|
||||
bool apa102_mosi_in_use;
|
||||
bool apa102_sck_in_use;
|
||||
|
||||
STATIC void floating_gpio_reset(gpio_num_t pin_number) {
|
||||
// This is the same as gpio_reset_pin(), but without the pullup.
|
||||
// Note that gpio_config resets the iomatrix to GPIO_FUNC as well.
|
||||
@ -78,14 +70,6 @@ void reset_pin_number(gpio_num_t pin_number) {
|
||||
in_use[pin_number / 32] &= ~(1 << pin_number % 32);
|
||||
|
||||
floating_gpio_reset(pin_number);
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin_number == MICROPY_HW_NEOPIXEL->number) {
|
||||
neopixel_in_use = false;
|
||||
rgb_led_status_init();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void common_hal_reset_pin(const mcu_pin_obj_t *pin) {
|
||||
@ -106,19 +90,10 @@ void reset_all_pins(void) {
|
||||
}
|
||||
in_use[0] = 0;
|
||||
in_use[1] = 0;
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
neopixel_in_use = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void claim_pin(const mcu_pin_obj_t *pin) {
|
||||
in_use[pin->number / 32] |= (1 << (pin->number % 32));
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
neopixel_in_use = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
|
||||
@ -126,12 +101,6 @@ void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
|
||||
}
|
||||
|
||||
bool pin_number_is_free(gpio_num_t pin_number) {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin_number == MICROPY_HW_NEOPIXEL->number) {
|
||||
return !neopixel_in_use;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t offset = pin_number / 32;
|
||||
uint32_t mask = 1 << (pin_number % 32);
|
||||
return (in_use[offset] & mask) == 0;
|
||||
|
@ -31,13 +31,6 @@
|
||||
|
||||
#include "peripherals/pins.h"
|
||||
|
||||
extern bool apa102_mosi_in_use;
|
||||
extern bool apa102_sck_in_use;
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
extern bool neopixel_in_use;
|
||||
#endif
|
||||
|
||||
void reset_all_pins(void);
|
||||
// reset_pin_number takes the pin number instead of the pointer so that objects don't
|
||||
// need to store a full pointer.
|
||||
|
@ -27,15 +27,6 @@
|
||||
*/
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
bool apa102_sck_in_use;
|
||||
bool apa102_mosi_in_use;
|
||||
#endif
|
||||
|
||||
STATIC bool claimed_pins[IOMUXC_SW_PAD_CTL_PAD_COUNT];
|
||||
STATIC bool never_reset_pins[IOMUXC_SW_PAD_CTL_PAD_COUNT];
|
||||
@ -54,14 +45,6 @@ void reset_all_pins(void) {
|
||||
IOMUXC->SW_PAD_CTL_PAD[i] = ((mcu_pin_obj_t *)(mcu_pin_globals.map.table[i].value))->pad_reset;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
neopixel_in_use = false;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
apa102_sck_in_use = false;
|
||||
apa102_mosi_in_use = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Since i.MX pins need extra register and reset information to reset properly,
|
||||
@ -74,25 +57,6 @@ void common_hal_reset_pin(const mcu_pin_obj_t *pin) {
|
||||
claimed_pins[pin->mux_idx] = false;
|
||||
*(uint32_t *)pin->mux_reg = pin->mux_reset;
|
||||
*(uint32_t *)pin->cfg_reg = pin->pad_reset;
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
neopixel_in_use = false;
|
||||
rgb_led_status_init();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin->mux_idx == MICROPY_HW_APA102_MOSI->mux_idx ||
|
||||
pin->mux_idx == MICROPY_HW_APA102_SCK->mux_idx) {
|
||||
apa102_mosi_in_use = apa102_mosi_in_use && pin->mux_idx != MICROPY_HW_APA102_MOSI->mux_idx;
|
||||
apa102_sck_in_use = apa102_sck_in_use && pin->mux_idx != MICROPY_HW_APA102_SCK->mux_idx;
|
||||
if (!apa102_sck_in_use && !apa102_mosi_in_use) {
|
||||
rgb_led_status_init();
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) {
|
||||
@ -100,20 +64,6 @@ void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) {
|
||||
}
|
||||
|
||||
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
return !neopixel_in_use;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
return !apa102_mosi_in_use;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
return !apa102_sck_in_use;
|
||||
}
|
||||
#endif
|
||||
|
||||
return !claimed_pins[pin->mux_idx];
|
||||
}
|
||||
|
||||
@ -123,20 +73,6 @@ uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t *pin) {
|
||||
|
||||
void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
|
||||
claimed_pins[pin->mux_idx] = true;
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
neopixel_in_use = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
apa102_mosi_in_use = true;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
apa102_sck_in_use = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void claim_pin(const mcu_pin_obj_t *pin) {
|
||||
|
@ -32,14 +32,6 @@
|
||||
|
||||
#include "pins.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
extern bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
extern bool apa102_sck_in_use;
|
||||
extern bool apa102_mosi_in_use;
|
||||
#endif
|
||||
|
||||
void reset_all_pins(void);
|
||||
void claim_pin(const mcu_pin_obj_t *pin);
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express"
|
||||
#define MICROPY_HW_MCU_NAME "nRF52840"
|
||||
|
||||
#define MICROPY_HW_NEOPIXEL (&pin_P0_16)
|
||||
// #define MICROPY_HW_NEOPIXEL (&pin_P0_16)
|
||||
|
||||
#define MICROPY_HW_LED_STATUS (&pin_P1_15)
|
||||
|
||||
|
@ -31,9 +31,9 @@
|
||||
#define MICROPY_HW_MCU_NAME "nRF52840"
|
||||
|
||||
// RGB LEDs use PWM peripheral, avoid using them to save energy
|
||||
// #define CP_RGB_STATUS_R (&pin_P0_30)
|
||||
// #define CP_RGB_STATUS_G (&pin_P0_29)
|
||||
// #define CP_RGB_STATUS_B (&pin_P0_31)
|
||||
#define CIRCUITPY_RGB_STATUS_R (&pin_P0_30)
|
||||
#define CIRCUITPY_RGB_STATUS_G (&pin_P0_29)
|
||||
#define CIRCUITPY_RGB_STATUS_B (&pin_P0_31)
|
||||
|
||||
#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10)
|
||||
#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14)
|
||||
|
@ -32,10 +32,10 @@
|
||||
|
||||
#define MICROPY_HW_LED_STATUS (&pin_P1_07)
|
||||
|
||||
#define CP_RGB_STATUS_INVERTED_PWM
|
||||
#define CP_RGB_STATUS_R (&pin_P0_30)
|
||||
#define CP_RGB_STATUS_G (&pin_P0_29)
|
||||
#define CP_RGB_STATUS_B (&pin_P0_31)
|
||||
#define CIRCUITPY_RGB_STATUS_INVERTED_PWM
|
||||
#define CIRCUITPY_RGB_STATUS_R (&pin_P0_30)
|
||||
#define CIRCUITPY_RGB_STATUS_G (&pin_P0_29)
|
||||
#define CIRCUITPY_RGB_STATUS_B (&pin_P0_31)
|
||||
|
||||
#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10)
|
||||
#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14)
|
||||
|
@ -32,9 +32,9 @@
|
||||
|
||||
#define MICROPY_HW_LED_STATUS (&pin_P1_12)
|
||||
|
||||
#define CP_RGB_STATUS_R (&pin_P0_13)
|
||||
#define CP_RGB_STATUS_G (&pin_P0_14)
|
||||
#define CP_RGB_STATUS_B (&pin_P0_15)
|
||||
#define CIRCUITPY_RGB_STATUS_R (&pin_P0_13)
|
||||
#define CIRCUITPY_RGB_STATUS_G (&pin_P0_14)
|
||||
#define CIRCUITPY_RGB_STATUS_B (&pin_P0_15)
|
||||
|
||||
#if QSPI_FLASH_FILESYSTEM
|
||||
#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20)
|
||||
|
@ -31,15 +31,7 @@
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "nrf/pins.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
bool apa102_sck_in_use;
|
||||
bool apa102_mosi_in_use;
|
||||
#endif
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
bool speaker_enable_in_use;
|
||||
#endif
|
||||
@ -73,14 +65,6 @@ void reset_all_pins(void) {
|
||||
nrf_gpio_cfg_default(pin);
|
||||
}
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
neopixel_in_use = false;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
apa102_sck_in_use = false;
|
||||
apa102_mosi_in_use = false;
|
||||
#endif
|
||||
|
||||
// After configuring SWD because it may be shared.
|
||||
reset_speaker_enable_pin();
|
||||
}
|
||||
@ -95,25 +79,6 @@ void reset_pin_number(uint8_t pin_number) {
|
||||
claimed_pins[nrf_pin_port(pin_number)] &= ~(1 << nrf_relative_pin_number(pin_number));
|
||||
never_reset_pins[nrf_pin_port(pin_number)] &= ~(1 << nrf_relative_pin_number(pin_number));
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin_number == MICROPY_HW_NEOPIXEL->number) {
|
||||
neopixel_in_use = false;
|
||||
rgb_led_status_init();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin_number == MICROPY_HW_APA102_MOSI->number ||
|
||||
pin_number == MICROPY_HW_APA102_SCK->number) {
|
||||
apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number;
|
||||
apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number;
|
||||
if (!apa102_sck_in_use && !apa102_mosi_in_use) {
|
||||
rgb_led_status_init();
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
if (pin_number == SPEAKER_ENABLE_PIN->number) {
|
||||
reset_speaker_enable_pin();
|
||||
@ -144,20 +109,6 @@ void claim_pin(const mcu_pin_obj_t *pin) {
|
||||
// Set bit in claimed_pins bitmask.
|
||||
claimed_pins[nrf_pin_port(pin->number)] |= 1 << nrf_relative_pin_number(pin->number);
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
neopixel_in_use = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
apa102_mosi_in_use = true;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
apa102_sck_in_use = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
if (pin == SPEAKER_ENABLE_PIN) {
|
||||
speaker_enable_in_use = true;
|
||||
@ -171,20 +122,6 @@ bool pin_number_is_free(uint8_t pin_number) {
|
||||
}
|
||||
|
||||
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
return !neopixel_in_use;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
return !apa102_mosi_in_use;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
return !apa102_sck_in_use;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
if (pin == SPEAKER_ENABLE_PIN) {
|
||||
return !speaker_enable_in_use;
|
||||
|
@ -31,14 +31,6 @@
|
||||
|
||||
#include "peripherals/nrf/pins.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
extern bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
extern bool apa102_sck_in_use;
|
||||
extern bool apa102_mosi_in_use;
|
||||
#endif
|
||||
|
||||
void reset_all_pins(void);
|
||||
// reset_pin_number takes the pin number instead of the pointer so that objects don't
|
||||
// need to store a full pointer.
|
||||
|
@ -32,7 +32,6 @@
|
||||
|
||||
#include "supervisor/board.h"
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
#include "src/rp2_common/hardware_dma/include/hardware/dma.h"
|
||||
|
@ -29,21 +29,8 @@
|
||||
#include "common-hal/microcontroller/__init__.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
bool apa102_sck_in_use;
|
||||
bool apa102_mosi_in_use;
|
||||
#endif
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
bool speaker_enable_in_use;
|
||||
#endif
|
||||
|
||||
STATIC uint32_t never_reset_pins;
|
||||
|
||||
void reset_all_pins(void) {
|
||||
@ -77,31 +64,6 @@ void reset_pin_number(uint8_t pin_number) {
|
||||
PADS_BANK0_GPIO0_PUE_BITS |
|
||||
PADS_BANK0_GPIO0_PDE_BITS);
|
||||
hw_set_bits(&padsbank0_hw->io[pin_number], PADS_BANK0_GPIO0_OD_BITS);
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin_number == MICROPY_HW_NEOPIXEL->number) {
|
||||
neopixel_in_use = false;
|
||||
rgb_led_status_init();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin_number == MICROPY_HW_APA102_MOSI->number ||
|
||||
pin_number == MICROPY_HW_APA102_SCK->number) {
|
||||
apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number;
|
||||
apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number;
|
||||
if (!apa102_sck_in_use && !apa102_mosi_in_use) {
|
||||
rgb_led_status_init();
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
if (pin_number == SPEAKER_ENABLE_PIN->number) {
|
||||
speaker_enable_in_use = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) {
|
||||
@ -113,25 +75,7 @@ void common_hal_reset_pin(const mcu_pin_obj_t *pin) {
|
||||
}
|
||||
|
||||
void claim_pin(const mcu_pin_obj_t *pin) {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
neopixel_in_use = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
apa102_mosi_in_use = true;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
apa102_sck_in_use = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
if (pin == SPEAKER_ENABLE_PIN) {
|
||||
speaker_enable_in_use = true;
|
||||
}
|
||||
#endif
|
||||
// Nothing to do because all changes will set the GPIO settings.
|
||||
}
|
||||
|
||||
bool pin_number_is_free(uint8_t pin_number) {
|
||||
@ -145,26 +89,6 @@ bool pin_number_is_free(uint8_t pin_number) {
|
||||
}
|
||||
|
||||
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
return !neopixel_in_use;
|
||||
}
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
return !apa102_mosi_in_use;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
return !apa102_sck_in_use;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPEAKER_ENABLE_PIN
|
||||
if (pin == SPEAKER_ENABLE_PIN) {
|
||||
return !speaker_enable_in_use;
|
||||
}
|
||||
#endif
|
||||
|
||||
return pin_number_is_free(pin->number);
|
||||
}
|
||||
|
||||
|
@ -34,14 +34,6 @@
|
||||
|
||||
#include "peripherals/pins.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
extern bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
extern bool apa102_sck_in_use;
|
||||
extern bool apa102_mosi_in_use;
|
||||
#endif
|
||||
|
||||
void reset_all_pins(void);
|
||||
// reset_pin_number takes the pin number instead of the pointer so that objects don't
|
||||
// need to store a full pointer.
|
||||
|
@ -27,19 +27,10 @@
|
||||
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "pins.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
bool neopixel_in_use;
|
||||
#endif
|
||||
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
|
||||
bool apa102_sck_in_use;
|
||||
bool apa102_mosi_in_use;
|
||||
#endif
|
||||
|
||||
#if defined(TFBGA216)
|
||||
GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK};
|
||||
#elif defined(LQFP144)
|
||||
@ -66,14 +57,6 @@ void reset_all_pins(void) {
|
||||
for (uint8_t i = 0; i < GPIO_PORT_COUNT; i++) {
|
||||
HAL_GPIO_DeInit(ports[i], ~never_reset_pins[i]);
|
||||
}
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
neopixel_in_use = false;
|
||||
#endif
|
||||
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
|
||||
apa102_sck_in_use = false;
|
||||
apa102_mosi_in_use = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Mark pin as free and return it to a quiescent state.
|
||||
@ -89,25 +72,6 @@ void reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
|
||||
claimed_pins[pin_port] &= ~(1 << pin_number);
|
||||
never_reset_pins[pin_port] &= ~(1 << pin_number);
|
||||
HAL_GPIO_DeInit(ports[pin_port], 1 << pin_number);
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin_port == MICROPY_HW_NEOPIXEL->port && pin_number == MICROPY_HW_NEOPIXEL->number) {
|
||||
neopixel_in_use = false;
|
||||
rgb_led_status_init();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
|
||||
if (
|
||||
(pin_port == MICROPY_HW_APA102_MOSI->port && pin_number == MICROPY_HW_APA102_MOSI->number)
|
||||
|| (pin_port == MICROPY_HW_APA102_SCK->port && pin_number == MICROPY_HW_APA102_MOSI->number)
|
||||
) {
|
||||
apa102_mosi_in_use = false;
|
||||
apa102_sck_in_use = false;
|
||||
rgb_led_status_init();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
|
||||
@ -140,20 +104,6 @@ bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number) {
|
||||
}
|
||||
|
||||
bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
return !neopixel_in_use;
|
||||
}
|
||||
#endif
|
||||
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
return !apa102_mosi_in_use;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
return !apa102_sck_in_use;
|
||||
}
|
||||
#endif
|
||||
|
||||
return pin_number_is_free(pin->port, pin->number);
|
||||
}
|
||||
|
||||
@ -171,19 +121,6 @@ uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t *pin) {
|
||||
|
||||
void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) {
|
||||
claim_pin(pin->port, pin->number);
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
if (pin == MICROPY_HW_NEOPIXEL) {
|
||||
neopixel_in_use = true;
|
||||
}
|
||||
#endif
|
||||
#if defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
|
||||
if (pin == MICROPY_HW_APA102_MOSI) {
|
||||
apa102_mosi_in_use = true;
|
||||
}
|
||||
if (pin == MICROPY_HW_APA102_SCK) {
|
||||
apa102_sck_in_use = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void common_hal_mcu_pin_reset_number(uint8_t pin_no) {
|
||||
|
@ -31,14 +31,6 @@
|
||||
|
||||
#include "peripherals/pins.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
extern bool neopixel_in_use;
|
||||
#endif
|
||||
#ifdef MICROPY_HW_APA102_MOSI
|
||||
extern bool apa102_sck_in_use;
|
||||
extern bool apa102_mosi_in_use;
|
||||
#endif
|
||||
|
||||
void reset_all_pins(void);
|
||||
// reset_pin_number takes the pin number instead of the pointer so that objects don't
|
||||
// need to store a full pointer.
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "supervisor/shared/autoreload.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
#include "supervisor/shared/status_leds.h"
|
||||
#include "supervisor/shared/stack.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
#include "supervisor/shared/workflow.h"
|
||||
@ -79,7 +79,7 @@ STATIC mp_obj_t supervisor_set_rgb_status_brightness(mp_obj_t lvl) {
|
||||
if (brightness_int < 0 || brightness_int > 255) {
|
||||
mp_raise_ValueError(translate("Brightness must be between 0 and 255"));
|
||||
}
|
||||
set_rgb_status_brightness((uint8_t)brightness_int);
|
||||
set_status_brightness((uint8_t)brightness_int);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_set_rgb_status_brightness);
|
||||
|
@ -409,7 +409,7 @@ void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t *self) {
|
||||
gc_collect_ptr((void *)self->stop_sequence);
|
||||
}
|
||||
|
||||
bool maybe_refresh_epaperdisplay(void) {
|
||||
size_t maybe_refresh_epaperdisplay(void) {
|
||||
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
|
||||
if (displays[i].epaper_display.base.type != &displayio_epaperdisplay_type ||
|
||||
displays[i].epaper_display.core.current_group != &circuitpython_splash) {
|
||||
@ -417,11 +417,16 @@ bool maybe_refresh_epaperdisplay(void) {
|
||||
continue;
|
||||
}
|
||||
displayio_epaperdisplay_obj_t *display = &displays[i].epaper_display;
|
||||
if (common_hal_displayio_epaperdisplay_get_time_to_refresh(display) != 0) {
|
||||
return false;
|
||||
size_t time_to_refresh = common_hal_displayio_epaperdisplay_get_time_to_refresh(display);
|
||||
if (time_to_refresh > 0) {
|
||||
return time_to_refresh;
|
||||
}
|
||||
return common_hal_displayio_epaperdisplay_refresh(display);
|
||||
if (common_hal_displayio_epaperdisplay_refresh(display)) {
|
||||
return 0;
|
||||
}
|
||||
// If we could refresh but it failed, then we want to retry.
|
||||
return 1;
|
||||
}
|
||||
// Return true if no ePaper displays are available to pretend it was updated.
|
||||
return true;
|
||||
// Return 0 if no ePaper displays are available to pretend it was updated.
|
||||
return 0;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ typedef struct {
|
||||
|
||||
void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t *self);
|
||||
void release_epaperdisplay(displayio_epaperdisplay_obj_t *self);
|
||||
bool maybe_refresh_epaperdisplay(void);
|
||||
size_t maybe_refresh_epaperdisplay(void);
|
||||
|
||||
void displayio_epaperdisplay_collect_ptrs(displayio_epaperdisplay_obj_t *self);
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "lib/oofatfs/ff.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "supervisor/memory.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
|
||||
#define NO_SECTOR_LOADED 0xFFFFFFFF
|
||||
|
||||
@ -467,7 +466,6 @@ static void spi_flash_flush_keep_cache(bool keep_cache) {
|
||||
#ifdef MICROPY_HW_LED_MSC
|
||||
port_pin_set_output_level(MICROPY_HW_LED_MSC, true);
|
||||
#endif
|
||||
temp_status_color(ACTIVE_WRITE);
|
||||
// If we've cached to the flash itself flush from there.
|
||||
if (MP_STATE_VM(flash_ram_cache) == NULL) {
|
||||
flush_scratch_flash();
|
||||
@ -475,7 +473,6 @@ static void spi_flash_flush_keep_cache(bool keep_cache) {
|
||||
flush_ram_cache(keep_cache);
|
||||
}
|
||||
current_sector = NO_SECTOR_LOADED;
|
||||
clear_temp_status();
|
||||
#ifdef MICROPY_HW_LED_MSC
|
||||
port_pin_set_output_level(MICROPY_HW_LED_MSC, false);
|
||||
#endif
|
||||
|
@ -14,28 +14,17 @@
|
||||
#define PURPLE COLOR(INTENSITY, 0, INTENSITY)
|
||||
#define WHITE COLOR(INTENSITY, INTENSITY, INTENSITY)
|
||||
|
||||
#define BOOT_RUNNING BLUE
|
||||
#define MAIN_RUNNING GREEN
|
||||
#define SAFE_MODE YELLOW
|
||||
#define ALL_DONE GREEN
|
||||
#define EXCEPTION RED
|
||||
#define SAFE_MODE YELLOW
|
||||
#define REPL_RUNNING WHITE
|
||||
|
||||
#define ACTIVE_WRITE 0x200000
|
||||
#define ALL_DONE_BLINKS 1
|
||||
#define EXCEPTION_BLINKS 2
|
||||
#define SAFE_MODE_BLINKS 3
|
||||
|
||||
#define ALL_GOOD_CYCLE_MS 2000u
|
||||
#define OFF_ON_RATIO 3
|
||||
|
||||
#define LINE_NUMBER_TOGGLE_LENGTH 300u
|
||||
#define EXCEPTION_TYPE_LENGTH_MS 1000u
|
||||
#define LED_SLEEP_TIME_MS 5000u
|
||||
|
||||
#define THOUSANDS WHITE
|
||||
#define HUNDREDS BLUE
|
||||
#define TENS YELLOW
|
||||
#define ONES CYAN
|
||||
|
||||
#define INDENTATION_ERROR GREEN
|
||||
#define SYNTAX_ERROR CYAN
|
||||
#define NAME_ERROR WHITE
|
||||
#define OS_ERROR ORANGE
|
||||
#define VALUE_ERROR PURPLE
|
||||
#define MPY_ERROR BLUE
|
||||
#define OTHER_ERROR YELLOW
|
||||
#define BLINK_TIME_MS 100u
|
||||
|
@ -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.
|
||||
}
|
@ -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
|
@ -36,7 +36,7 @@
|
||||
|
||||
#include "supervisor/serial.h"
|
||||
#include "supervisor/shared/rgb_led_colors.h"
|
||||
#include "supervisor/shared/rgb_led_status.h"
|
||||
#include "supervisor/shared/status_leds.h"
|
||||
#include "supervisor/shared/translate.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
@ -65,11 +65,9 @@ safe_mode_t wait_for_safe_mode_reset(void) {
|
||||
}
|
||||
port_set_saved_word(SAFE_MODE_DATA_GUARD | (MANUAL_SAFE_MODE << 8));
|
||||
// Wait for a while to allow for reset.
|
||||
temp_status_color(SAFE_MODE);
|
||||
#ifdef MICROPY_HW_LED_STATUS
|
||||
digitalio_digitalinout_obj_t status_led;
|
||||
common_hal_digitalio_digitalinout_construct(&status_led, MICROPY_HW_LED_STATUS);
|
||||
common_hal_digitalio_digitalinout_switch_to_output(&status_led, true, DRIVE_MODE_PUSH_PULL);
|
||||
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
status_led_init();
|
||||
#endif
|
||||
#ifdef CIRCUITPY_BOOT_BUTTON
|
||||
digitalio_digitalinout_obj_t boot_button;
|
||||
@ -78,22 +76,32 @@ safe_mode_t wait_for_safe_mode_reset(void) {
|
||||
#endif
|
||||
uint64_t start_ticks = supervisor_ticks_ms64();
|
||||
uint64_t diff = 0;
|
||||
bool boot_in_safe_mode = false;
|
||||
while (diff < 700) {
|
||||
#ifdef MICROPY_HW_LED_STATUS
|
||||
#ifdef CIRCUITPY_STATUS_LED
|
||||
// Blink on for 100, off for 100, on for 100, off for 100 and on for 200
|
||||
common_hal_digitalio_digitalinout_set_value(&status_led, diff > 100 && diff / 100 != 2 && diff / 100 != 4);
|
||||
bool led_on = diff > 100 && diff / 100 != 2 && diff / 100 != 4;
|
||||
if (led_on) {
|
||||
new_status_color(SAFE_MODE);
|
||||
} else {
|
||||
new_status_color(BLACK);
|
||||
}
|
||||
#endif
|
||||
#ifdef CIRCUITPY_BOOT_BUTTON
|
||||
if (!common_hal_digitalio_digitalinout_get_value(&boot_button)) {
|
||||
return USER_SAFE_MODE;
|
||||
boot_in_safe_mode = true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
diff = supervisor_ticks_ms64() - start_ticks;
|
||||
}
|
||||
#ifdef MICROPY_HW_LED_STATUS
|
||||
common_hal_digitalio_digitalinout_deinit(&status_led);
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
new_status_color(BLACK);
|
||||
status_led_deinit();
|
||||
#endif
|
||||
clear_temp_status();
|
||||
if (boot_in_safe_mode) {
|
||||
return USER_SAFE_MODE;
|
||||
}
|
||||
port_set_saved_word(SAFE_MODE_DATA_GUARD);
|
||||
return NO_SAFE_MODE;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Scott Shawcroft for Adafruit Industries
|
||||
* Copyright (c) 2017-2021 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -26,11 +26,75 @@
|
||||
|
||||
#include "supervisor/shared/status_leds.h"
|
||||
|
||||
#if CIRCUITPY_DIGITALIO
|
||||
#include "common-hal/digitalio/DigitalInOut.h"
|
||||
#include "mphalport.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
#include "py/obj.h"
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
uint8_t rgb_status_brightness = 63;
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
#include "shared-bindings/neopixel_write/__init__.h"
|
||||
static uint8_t status_neopixel_color[3];
|
||||
static digitalio_digitalinout_obj_t status_neopixel;
|
||||
|
||||
#elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
|
||||
uint8_t rgb_status_brightness = 50;
|
||||
|
||||
#define APA102_BUFFER_LENGTH 12
|
||||
static uint8_t status_apa102_color[APA102_BUFFER_LENGTH] = {0, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
#if CIRCUITPY_BITBANG_APA102
|
||||
#include "shared-bindings/bitbangio/SPI.h"
|
||||
static bitbangio_spi_obj_t status_apa102 = {
|
||||
.base = {
|
||||
.type = &bitbangio_spi_type,
|
||||
},
|
||||
};
|
||||
#else
|
||||
#include "shared-bindings/busio/SPI.h"
|
||||
busio_spi_obj_t status_apa102 = {
|
||||
.base = {
|
||||
.type = &busio_spi_type,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#elif CIRCUITPY_PWM_RGB_LED
|
||||
#include "shared-bindings/pwmio/PWMOut.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
pwmio_pwmout_obj_t rgb_status_r = {
|
||||
.base = {
|
||||
.type = &pwmio_pwmout_type,
|
||||
},
|
||||
};
|
||||
pwmio_pwmout_obj_t rgb_status_g = {
|
||||
.base = {
|
||||
.type = &pwmio_pwmout_type,
|
||||
},
|
||||
};
|
||||
pwmio_pwmout_obj_t rgb_status_b = {
|
||||
.base = {
|
||||
.type = &pwmio_pwmout_type,
|
||||
},
|
||||
};
|
||||
|
||||
uint8_t rgb_status_brightness = 0xFF;
|
||||
|
||||
uint16_t status_rgb_color[3] = {
|
||||
0 /* red */, 0 /* green */, 0 /* blue */
|
||||
};
|
||||
#elif CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_STATUS)
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
digitalio_digitalinout_obj_t single_color_led;
|
||||
|
||||
uint8_t rgb_status_brightness = 0xff;
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_DIGITALIO && (defined(MICROPY_HW_LED_RX) || defined(MICROPY_HW_LED_TX))
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
|
||||
#ifdef MICROPY_HW_LED_RX
|
||||
digitalio_digitalinout_obj_t rx_led;
|
||||
#endif
|
||||
@ -38,27 +102,210 @@ digitalio_digitalinout_obj_t rx_led;
|
||||
#ifdef MICROPY_HW_LED_TX
|
||||
digitalio_digitalinout_obj_t tx_led;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void init_status_leds(void) {
|
||||
#ifdef MICROPY_HW_LED_RX
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
static uint32_t current_status_color = 0;
|
||||
#endif
|
||||
|
||||
static bool status_led_init_in_progress = false;
|
||||
void status_led_init() {
|
||||
if (status_led_init_in_progress) {
|
||||
// Avoid recursion.
|
||||
return;
|
||||
}
|
||||
status_led_init_in_progress = true;
|
||||
|
||||
#ifdef 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
|
||||
}
|
||||
|
||||
void new_status_color(uint32_t rgb) {
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
if (current_status_color == rgb) {
|
||||
return;
|
||||
}
|
||||
uint32_t rgb_adjusted = color_brightness(rgb, rgb_status_brightness);
|
||||
current_status_color = rgb;
|
||||
#endif
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
status_neopixel_color[0] = (rgb_adjusted >> 8) & 0xff;
|
||||
status_neopixel_color[1] = (rgb_adjusted >> 16) & 0xff;
|
||||
status_neopixel_color[2] = rgb_adjusted & 0xff;
|
||||
common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3);
|
||||
|
||||
#elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
|
||||
status_apa102_color[5] = rgb_adjusted & 0xff;
|
||||
status_apa102_color[6] = (rgb_adjusted >> 8) & 0xff;
|
||||
status_apa102_color[7] = (rgb_adjusted >> 16) & 0xff;
|
||||
|
||||
#if CIRCUITPY_BITBANG_APA102
|
||||
shared_module_bitbangio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH);
|
||||
#else
|
||||
common_hal_busio_spi_write(&status_apa102, status_apa102_color, APA102_BUFFER_LENGTH);
|
||||
#endif
|
||||
|
||||
#elif CIRCUITPY_PWM_RGB_LED
|
||||
uint8_t red_u8 = (rgb_adjusted >> 16) & 0xFF;
|
||||
uint8_t green_u8 = (rgb_adjusted >> 8) & 0xFF;
|
||||
uint8_t blue_u8 = rgb_adjusted & 0xFF;
|
||||
|
||||
#ifdef CIRCUITPY_RGB_STATUS_INVERTED_PWM
|
||||
status_rgb_color[0] = (1 << 16) - 1 - ((uint16_t)(red_u8 << 8) + red_u8);
|
||||
status_rgb_color[1] = (1 << 16) - 1 - ((uint16_t)(green_u8 << 8) + green_u8);
|
||||
status_rgb_color[2] = (1 << 16) - 1 - ((uint16_t)(blue_u8 << 8) + blue_u8);
|
||||
#else
|
||||
status_rgb_color[0] = (uint16_t)(red_u8 << 8) + red_u8;
|
||||
status_rgb_color[1] = (uint16_t)(green_u8 << 8) + green_u8;
|
||||
status_rgb_color[2] = (uint16_t)(blue_u8 << 8) + blue_u8;
|
||||
#endif
|
||||
|
||||
common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_r, status_rgb_color[0]);
|
||||
common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_g, status_rgb_color[1]);
|
||||
common_hal_pwmio_pwmout_set_duty_cycle(&rgb_status_b, status_rgb_color[2]);
|
||||
#elif CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_STATUS)
|
||||
common_hal_digitalio_digitalinout_set_value(&single_color_led, rgb_adjusted > 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t color_brightness(uint32_t color, uint8_t brightness) {
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
uint32_t result = ((color & 0xff0000) * brightness / 255) & 0xff0000;
|
||||
result += ((color & 0xff00) * brightness / 255) & 0xff00;
|
||||
result += ((color & 0xff) * brightness / 255) & 0xff;
|
||||
return result;
|
||||
#else
|
||||
return color;
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_status_brightness(uint8_t level) {
|
||||
#if CIRCUITPY_STATUS_LED
|
||||
rgb_status_brightness = level;
|
||||
uint32_t current_color = current_status_color;
|
||||
// Temporarily change the current color global to force the new_status_color call to update the
|
||||
// LED. Usually duplicate calls of the same color are ignored without regard to brightness
|
||||
// changes.
|
||||
current_status_color = 0;
|
||||
new_status_color(current_color);
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_rxtx_leds(void) {
|
||||
#if CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_RX)
|
||||
common_hal_digitalio_digitalinout_construct(&rx_led, MICROPY_HW_LED_RX);
|
||||
common_hal_digitalio_digitalinout_switch_to_output(&rx_led, true, DRIVE_MODE_PUSH_PULL);
|
||||
#endif
|
||||
#ifdef MICROPY_HW_LED_TX
|
||||
#if CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_TX)
|
||||
common_hal_digitalio_digitalinout_construct(&tx_led, MICROPY_HW_LED_TX);
|
||||
common_hal_digitalio_digitalinout_switch_to_output(&tx_led, true, DRIVE_MODE_PUSH_PULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void toggle_rx_led(void) {
|
||||
#ifdef MICROPY_HW_LED_RX
|
||||
#if CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_RX)
|
||||
common_hal_digitalio_digitalinout_set_value(&rx_led, !common_hal_digitalio_digitalinout_get_value(&rx_led));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void toggle_tx_led(void) {
|
||||
#ifdef MICROPY_HW_LED_TX
|
||||
#if CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_TX)
|
||||
common_hal_digitalio_digitalinout_set_value(&tx_led, !common_hal_digitalio_digitalinout_get_value(&tx_led));
|
||||
#endif
|
||||
}
|
||||
|
@ -27,10 +27,35 @@
|
||||
#ifndef 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_tx_led(void);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H
|
||||
|
@ -9,7 +9,6 @@ SRC_SUPERVISOR = \
|
||||
supervisor/shared/flash.c \
|
||||
supervisor/shared/memory.c \
|
||||
supervisor/shared/micropython.c \
|
||||
supervisor/shared/rgb_led_status.c \
|
||||
supervisor/shared/safe_mode.c \
|
||||
supervisor/shared/stack.c \
|
||||
supervisor/shared/status_leds.c \
|
||||
|
Loading…
Reference in New Issue
Block a user