1
0
mirror of https://github.com/whowechina/aic_pico.git synced 2025-02-17 19:09:24 +01:00

Better LED control

This commit is contained in:
whowechina 2023-11-18 10:45:47 +08:00
parent dbcd7ddef4
commit 12d710ebe2
7 changed files with 93 additions and 38 deletions

Binary file not shown.

View File

@ -33,7 +33,10 @@ void fps_count(int core)
static void handle_display()
{
printf("[Config]\n");
printf(" LED level: %d\n", aic_cfg->led.level);
printf(" Light: RGB-%s LED-%s\n",
aic_cfg->light.rgb ? "ON" : "OFF",
aic_cfg->light.led ? "ON" : "OFF");
printf(" Level: [%d ~ %d]\n", aic_cfg->light.min, aic_cfg->light.max);
}
static void handle_save()
@ -79,21 +82,66 @@ static void handle_nfc()
printf("\n");
}
static void handle_light(int argc, char *argv[])
{
const char *usage = "Usage: light <rgb|led|both|off>\n";
if (argc != 1) {
printf("%s", usage);
return;
}
const char *commands[] = { "rgb", "led", "both", "off" };
int match = cli_match_prefix(commands, 4, argv[0]);
switch (match) {
case 0:
aic_cfg->light.rgb = true;
aic_cfg->light.led = false;
break;
case 1:
aic_cfg->light.rgb = false;
aic_cfg->light.led = true;
break;
case 2:
aic_cfg->light.rgb = true;
aic_cfg->light.led = true;
break;
case 3:
aic_cfg->light.rgb = false;
aic_cfg->light.led = false;
break;
default:
printf("%s", usage);
return;
}
config_changed();
}
static void handle_level(int argc, char *argv[])
{
const char *usage = "Usage: level <0..255>\n";
if (argc != 1) {
const char *usage = "Usage: level <0..255> <0..255>\n";
if (argc != 2) {
printf(usage);
return;
}
int level = cli_extract_non_neg_int(argv[0], 0);
if ((level < 0) || (level > 255)) {
int min = cli_extract_non_neg_int(argv[0], 0);
if ((min < 0) || (min > 255)) {
printf(usage);
return;
}
int max = cli_extract_non_neg_int(argv[1], 0);
if (max > 255) {
printf(usage);
return;
}
aic_cfg->led.level = level;
if (max < min) {
max = min;
}
aic_cfg->light.min = min;
aic_cfg->light.max = max;
config_changed();
handle_display();
}
@ -104,5 +152,6 @@ void commands_init()
cli_register("save", handle_save, "Save config to flash.");
cli_register("factory", handle_factory_reset, "Reset everything to default.");
cli_register("nfc", handle_nfc, "NFC debug.");
cli_register("level", handle_level, "Set LED level.");
cli_register("light", handle_light, "Turn on/off lights.");
cli_register("level", handle_level, "Set light level.");
}

View File

@ -12,13 +12,17 @@
aic_cfg_t *aic_cfg;
static aic_cfg_t default_cfg = {
.led = { .level = 127, }
.light = { .min = 0, .max = 128, .rgb = true, .led = true }
};
aic_runtime_t *aic_runtime;
static void config_loaded()
{
if (aic_cfg->light.min > aic_cfg->light.max) {
aic_cfg->light = default_cfg.light;
config_changed();
}
}
void config_changed()

View File

@ -11,8 +11,11 @@
typedef struct __attribute__((packed)) {
struct {
uint8_t level;
} led;
uint8_t min;
uint8_t max;
bool rgb;
bool led;
} light;
uint32_t reserved;
} aic_cfg_t;

View File

@ -85,15 +85,17 @@ uint32_t rgb32_from_hsv(uint8_t h, uint8_t s, uint8_t v)
}
}
static uint8_t curr_level = 0;
static inline uint32_t apply_level(uint32_t color)
{
unsigned r = (color >> 16) & 0xff;
unsigned g = (color >> 8) & 0xff;
unsigned b = color & 0xff;
r = r * aic_cfg->led.level / 255;
g = g * aic_cfg->led.level / 255;
b = b * aic_cfg->led.level / 255;
r = r * curr_level / 255;
g = g * curr_level / 255;
b = b * curr_level / 255;
return r << 16 | g << 8 | b;
}
@ -106,21 +108,14 @@ static inline uint32_t apply_level(uint32_t color)
static uint32_t color_wheel[COLOR_WHEEL_SIZE];
static void generate_color_wheel()
{
static uint8_t old_level = 0;
if (old_level == aic_cfg->led.level) {
return;
}
old_level = aic_cfg->led.level;
for (int i = 0; i < COLOR_WHEEL_SIZE; i++) {
color_wheel[i] = rgb32_from_hsv(i, 208, 255);
color_wheel[i] = apply_level(color_wheel[i]);
}
}
#define RAINBOW_PITCH 37
#define RAINBOW_MIN_SPEED 1
static uint32_t rainbow_speed = RAINBOW_MIN_SPEED;
static uint32_t curr_speed = RAINBOW_MIN_SPEED;
static void rainbow_update()
{
@ -132,26 +127,27 @@ static void rainbow_update()
last = now;
static uint32_t rotator = 0;
rotator = (rotator + rainbow_speed) % COLOR_WHEEL_SIZE;
rotator = (rotator + curr_speed) % COLOR_WHEEL_SIZE;
for (int i = 0; i < RGB_NUM; i++) {
uint32_t index = (rotator + RAINBOW_PITCH * i) % COLOR_WHEEL_SIZE;
rgb_buf[i] = color_wheel[index];
rgb_buf[i] = apply_level(color_wheel[index]);
}
/* LED just follows rgb */
for (int i = 0; (i < LED_NUM) && (i < RGB_NUM); i++) {
int level = rgb_buf[i] & 0xff;
pwm_set_gpio_level(led_gpio[i], level * level);
uint32_t index = (rotator + RAINBOW_PITCH * 2 * i) % COLOR_WHEEL_SIZE;
int level = apply_level(color_wheel[index]) & 0xff;
pwm_set_gpio_level(led_gpio[i], aic_cfg->light.led ? level * level : 0);
}
}
void light_set_rainbow_speed(uint8_t speed)
void light_stimulate()
{
rainbow_speed = speed / 8;
curr_speed = 48;
curr_level = aic_cfg->light.max;
}
static void rainbow_speed_down()
static void rainbow_fade()
{
static uint64_t last = 0;
uint64_t now = time_us_64();
@ -160,8 +156,13 @@ static void rainbow_speed_down()
}
last = now;
if (rainbow_speed > RAINBOW_MIN_SPEED) {
rainbow_speed = rainbow_speed * 95 / 100;
if (curr_speed > RAINBOW_MIN_SPEED) {
curr_speed = curr_speed * 95 / 100;
}
if (curr_level > aic_cfg->light.min) {
curr_level -= (curr_level - aic_cfg->light.min) / 10 + 1;
} else if (curr_level < aic_cfg->light.min) {
curr_level += (aic_cfg->light.min - curr_level) / 10 + 1;
}
}
@ -175,7 +176,8 @@ static void drive_led()
last = now;
for (int i = 0; i < RGB_NUM; i++) {
pio_sm_put_blocking(pio0, 0, rgb_buf[i] << 8u);
uint32_t color = aic_cfg->light.rgb ? rgb_buf[i] << 8u : 0;
pio_sm_put_blocking(pio0, 0, color);
}
}
@ -227,15 +229,12 @@ void light_init()
pwm_config_set_clkdiv(&cfg, 4.f);
pwm_init(slice, &cfg, true);
}
generate_color_wheel();
}
void light_update()
{
generate_color_wheel();
rainbow_update();
rainbow_speed_down();
rainbow_fade();
drive_led();
}

View File

@ -20,6 +20,6 @@ uint32_t rgb32_from_hsv(uint8_t h, uint8_t s, uint8_t v);
void light_set_color(unsigned index, uint32_t color);
void light_set_color_all(uint32_t color);
void light_set_rainbow_speed(uint8_t speed);
void light_stimulate();
#endif

View File

@ -48,7 +48,7 @@ void report_hid_cardio()
uint64_t now = time_us_64();
if (memcmp(hid_cardio.current, "\0\0\0\0\0\0\0\0\0", 9) != 0) {
light_set_rainbow_speed(255);
light_stimulate();
}
if ((memcmp(hid_cardio.current, hid_cardio.reported, 9) != 0) &&