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:
parent
dbcd7ddef4
commit
12d710ebe2
Binary file not shown.
@ -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.");
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user