Merge pull request #1925 from C47D/rgb_status
Initial support for RGB led as Status indicator, fixes #1382
This commit is contained in:
commit
6fad383367
@ -35,9 +35,9 @@
|
||||
|
||||
#define MICROPY_HW_LED_STATUS (&pin_P1_12)
|
||||
|
||||
#define MICROPY_HW_RGB_LED_RED (&pin_P0_13)
|
||||
#define MICROPY_HW_RGB_LED_GREEN (&pin_P0_14)
|
||||
#define MICROPY_HW_RGB_LED_BLUE (&pin_P0_15)
|
||||
#define CP_RGB_STATUS_R (&pin_P0_13)
|
||||
#define CP_RGB_STATUS_G (&pin_P0_14)
|
||||
#define CP_RGB_STATUS_B (&pin_P0_15)
|
||||
|
||||
#if QSPI_FLASH_FILESYSTEM
|
||||
#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20)
|
||||
|
@ -77,33 +77,37 @@ void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) {
|
||||
}
|
||||
}
|
||||
|
||||
void reset_single_pwmout(uint8_t i) {
|
||||
NRF_PWM_Type* pwm = pwms[i];
|
||||
|
||||
pwm->ENABLE = 0;
|
||||
pwm->MODE = PWM_MODE_UPDOWN_Up;
|
||||
pwm->DECODER = PWM_DECODER_LOAD_Individual;
|
||||
pwm->LOOP = 0;
|
||||
pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1; // default is 500 hz
|
||||
pwm->COUNTERTOP = (PWM_MAX_FREQ/500); // default is 500 hz
|
||||
|
||||
pwm->SEQ[0].PTR = (uint32_t) pwm_seq[i];
|
||||
pwm->SEQ[0].CNT = CHANNELS_PER_PWM; // default mode is Individual --> count must be 4
|
||||
pwm->SEQ[0].REFRESH = 0;
|
||||
pwm->SEQ[0].ENDDELAY = 0;
|
||||
|
||||
pwm->SEQ[1].PTR = 0;
|
||||
pwm->SEQ[1].CNT = 0;
|
||||
pwm->SEQ[1].REFRESH = 0;
|
||||
pwm->SEQ[1].ENDDELAY = 0;
|
||||
|
||||
for(int ch =0; ch < CHANNELS_PER_PWM; ch++) {
|
||||
pwm_seq[i][ch] = (1 << 15); // polarity = 0
|
||||
}
|
||||
}
|
||||
|
||||
void pwmout_reset(void) {
|
||||
for(size_t i=0; i < MP_ARRAY_SIZE(pwms); i++) {
|
||||
if (never_reset_pwm[i] > 0) {
|
||||
continue;
|
||||
}
|
||||
NRF_PWM_Type* pwm = pwms[i];
|
||||
|
||||
pwm->ENABLE = 0;
|
||||
pwm->MODE = PWM_MODE_UPDOWN_Up;
|
||||
pwm->DECODER = PWM_DECODER_LOAD_Individual;
|
||||
pwm->LOOP = 0;
|
||||
pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1; // default is 500 hz
|
||||
pwm->COUNTERTOP = (PWM_MAX_FREQ/500); // default is 500 hz
|
||||
|
||||
pwm->SEQ[0].PTR = (uint32_t) pwm_seq[i];
|
||||
pwm->SEQ[0].CNT = CHANNELS_PER_PWM; // default mode is Individual --> count must be 4
|
||||
pwm->SEQ[0].REFRESH = 0;
|
||||
pwm->SEQ[0].ENDDELAY = 0;
|
||||
|
||||
pwm->SEQ[1].PTR = 0;
|
||||
pwm->SEQ[1].CNT = 0;
|
||||
pwm->SEQ[1].REFRESH = 0;
|
||||
pwm->SEQ[1].ENDDELAY = 0;
|
||||
|
||||
for(int ch =0; ch < CHANNELS_PER_PWM; ch++) {
|
||||
pwm_seq[i][ch] = (1 << 15); // polarity = 0
|
||||
}
|
||||
reset_single_pwmout(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,9 +152,9 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
|
||||
self->channel = CHANNELS_PER_PWM; // out-of-range value.
|
||||
bool pwm_already_in_use;
|
||||
NRF_PWM_Type* pwm;
|
||||
|
||||
for (size_t i = 0 ; i < MP_ARRAY_SIZE(pwms); i++) {
|
||||
pwm = pwms[i];
|
||||
size_t pwm_index = 0;
|
||||
for (; pwm_index < MP_ARRAY_SIZE(pwms); pwm_index++) {
|
||||
pwm = pwms[pwm_index];
|
||||
pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk;
|
||||
if (pwm_already_in_use) {
|
||||
if (variable_frequency) {
|
||||
@ -199,6 +203,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
|
||||
nrf_pwm_disable(pwm);
|
||||
|
||||
if (!pwm_already_in_use) {
|
||||
reset_single_pwmout(pwm_index);
|
||||
nrf_pwm_configure(pwm, base_clock, NRF_PWM_MODE_UP, countertop);
|
||||
}
|
||||
|
||||
|
@ -50,10 +50,28 @@ busio_spi_obj_t status_apa102;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK))
|
||||
#if defined(CP_RGB_STATUS_R) || defined(CP_RGB_STATUS_G) || defined(CP_RGB_STATUS_B)
|
||||
#define CP_RGB_STATUS_LED
|
||||
|
||||
#include "shared-bindings/pulseio/PWMOut.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
pulseio_pwmout_obj_t rgb_status_r;
|
||||
pulseio_pwmout_obj_t rgb_status_g;
|
||||
pulseio_pwmout_obj_t rgb_status_b;
|
||||
|
||||
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
|
||||
|
||||
|
||||
void rgb_led_status_init() {
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
common_hal_digitalio_digitalinout_construct(&status_neopixel, MICROPY_HW_NEOPIXEL);
|
||||
@ -93,7 +111,34 @@ void rgb_led_status_init() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK))
|
||||
|
||||
#if defined(CP_RGB_STATUS_LED)
|
||||
if (common_hal_mcu_pin_is_free(CP_RGB_STATUS_R)) {
|
||||
pwmout_result_t red_result = common_hal_pulseio_pwmout_construct(&rgb_status_r, CP_RGB_STATUS_R, 0, 50000, false);
|
||||
|
||||
if (PWMOUT_OK == red_result) {
|
||||
common_hal_pulseio_pwmout_never_reset(&rgb_status_r);
|
||||
}
|
||||
}
|
||||
|
||||
if (common_hal_mcu_pin_is_free(CP_RGB_STATUS_G)) {
|
||||
pwmout_result_t green_result = common_hal_pulseio_pwmout_construct(&rgb_status_g, CP_RGB_STATUS_G, 0, 50000, false);
|
||||
|
||||
if (PWMOUT_OK == green_result) {
|
||||
common_hal_pulseio_pwmout_never_reset(&rgb_status_g);
|
||||
}
|
||||
}
|
||||
|
||||
if (common_hal_mcu_pin_is_free(CP_RGB_STATUS_B)) {
|
||||
pwmout_result_t blue_result = common_hal_pulseio_pwmout_construct(&rgb_status_b, CP_RGB_STATUS_B, 0, 50000, false);
|
||||
|
||||
if (PWMOUT_OK == blue_result) {
|
||||
common_hal_pulseio_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
|
||||
@ -109,10 +154,13 @@ void reset_status_led() {
|
||||
reset_pin_number(MICROPY_HW_APA102_MOSI->number);
|
||||
reset_pin_number(MICROPY_HW_APA102_SCK->number);
|
||||
#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))
|
||||
#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;
|
||||
}
|
||||
@ -143,10 +191,30 @@ void new_status_color(uint32_t rgb) {
|
||||
common_hal_busio_spi_write(&status_apa102, status_apa102_color, 8);
|
||||
#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_pulseio_pwmout_set_duty_cycle(&rgb_status_r, status_rgb_color[0]);
|
||||
common_hal_pulseio_pwmout_set_duty_cycle(&rgb_status_g, status_rgb_color[1]);
|
||||
common_hal_pulseio_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))
|
||||
#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
|
||||
@ -168,6 +236,27 @@ void temp_status_color(uint32_t rgb) {
|
||||
common_hal_busio_spi_write(&status_apa102, colors, 12);
|
||||
#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_pulseio_pwmout_set_duty_cycle(&rgb_status_r, temp_status_color_rgb[0]);
|
||||
common_hal_pulseio_pwmout_set_duty_cycle(&rgb_status_g, temp_status_color_rgb[1]);
|
||||
common_hal_pulseio_pwmout_set_duty_cycle(&rgb_status_b, temp_status_color_rgb[2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void clear_temp_status() {
|
||||
@ -181,10 +270,30 @@ void clear_temp_status() {
|
||||
common_hal_busio_spi_write(&status_apa102, status_apa102_color, 8);
|
||||
#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_pulseio_pwmout_set_duty_cycle(&rgb_status_r, red);
|
||||
common_hal_pulseio_pwmout_set_duty_cycle(&rgb_status_g, green);
|
||||
common_hal_pulseio_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))
|
||||
#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;
|
||||
@ -195,7 +304,7 @@ uint32_t color_brightness(uint32_t color, uint8_t brightness) {
|
||||
}
|
||||
|
||||
void set_rgb_status_brightness(uint8_t level){
|
||||
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK))
|
||||
#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
|
||||
@ -210,7 +319,7 @@ 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))
|
||||
#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 = ticks_ms;
|
||||
status->safe_mode = safe_mode;
|
||||
@ -256,7 +365,7 @@ void prep_rgb_status_animation(const pyexec_result_t* result,
|
||||
}
|
||||
|
||||
void tick_rgb_status_animation(rgb_status_animation_t* status) {
|
||||
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK))
|
||||
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED))
|
||||
uint32_t tick_diff = ticks_ms - status->pattern_start;
|
||||
if (status->ok) {
|
||||
// All is good. Ramp ALL_DONE up and down.
|
||||
|
Loading…
x
Reference in New Issue
Block a user