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

Refactoring rainbow effect for future patterns

This commit is contained in:
whowechina 2024-05-09 16:21:07 +08:00
parent 53a23921ce
commit a84ceb5531
3 changed files with 93 additions and 56 deletions

View File

@ -86,7 +86,7 @@ uint32_t rgb32_from_hsv(uint8_t h, uint8_t s, uint8_t v)
}
}
static inline uint32_t apply_level_by(uint32_t color, uint8_t level)
static inline uint32_t apply_level(uint32_t color, uint8_t level)
{
unsigned r = (color >> 16) & 0xff;
unsigned g = (color >> 8) & 0xff;
@ -99,12 +99,6 @@ static inline uint32_t apply_level_by(uint32_t color, uint8_t level)
return r << 16 | g << 8 | b;
}
static uint8_t curr_level = 0;
static inline uint32_t apply_level(uint32_t color)
{
return apply_level_by(color, curr_level);
}
/* 6 segment regular hsv color wheel, better color cycle
* https://www.arnevogel.com/rgb-rainbow/
* https://www.instructables.com/How-to-Make-Proper-Rainbow-and-Random-Colors-With-/
@ -118,11 +112,71 @@ static void generate_color_wheel()
}
}
#define RAINBOW_PITCH 37
#define RAINBOW_MIN_SPEED 1
static uint32_t curr_speed = RAINBOW_MIN_SPEED;
static inline uint8_t lerp8u(uint8_t a, uint8_t b, uint8_t t)
{
return a + (b - a) * t / 255;
}
static void rainbow_update()
static struct {
struct {
int current;
int from;
int to;
} speed;
struct {
int current;
int from;
int to;
} level;
int smooth_ms;
int elapsed;
} rainbow = { { 1, 1, 1 }, { 255, 255, 255 }, 0, 0 };
void light_rainbow(int8_t speed, uint32_t smooth_ms, uint8_t level)
{
if (smooth_ms != 0) {
rainbow.speed.from = rainbow.speed.current;
rainbow.speed.to = speed;
rainbow.smooth_ms = smooth_ms;
rainbow.level.from = rainbow.level.current;
rainbow.level.to = level;
rainbow.elapsed = 0;
} else {
rainbow.speed.current = speed;
rainbow.level.current = level;
rainbow.smooth_ms = 0;
rainbow.elapsed = 0;
}
}
static void rainbow_control()
{
static uint64_t last_time;
uint64_t now = time_us_64();
uint32_t delta = (now - last_time) / 1000;
last_time = now;
if ((rainbow.smooth_ms == 0) || (rainbow.elapsed == rainbow.smooth_ms)) {
return;
}
rainbow.elapsed += delta;
if (rainbow.elapsed > rainbow.smooth_ms) {
rainbow.elapsed = rainbow.smooth_ms;
}
int range = rainbow.speed.to - rainbow.speed.from;
int progress = range * rainbow.elapsed / rainbow.smooth_ms;
rainbow.speed.current = rainbow.speed.from + progress;
range = rainbow.level.to - rainbow.level.from;
progress = range * rainbow.elapsed / rainbow.smooth_ms;
rainbow.level.current = rainbow.level.from + progress;
}
#define RAINBOW_PITCH 37
static void rainbow_render()
{
static uint64_t last = 0;
uint64_t now = time_us_64();
@ -132,53 +186,21 @@ static void rainbow_update()
last = now;
static uint32_t rotator = 0;
rotator = (rotator + curr_speed) % COLOR_WHEEL_SIZE;
rotator = (rotator + rainbow.speed.current) % COLOR_WHEEL_SIZE;
for (int i = 0; i < RGB_NUM; i++) {
uint32_t index = (rotator + RAINBOW_PITCH * i) % COLOR_WHEEL_SIZE;
rgb_buf[i] = apply_level(color_wheel[index]);
rgb_buf[i] = apply_level(color_wheel[index], rainbow.level.current);
}
for (int i = 0; i < LED_NUM; i++) {
uint32_t index = (rotator + RAINBOW_PITCH * 2 * i) % COLOR_WHEEL_SIZE;
led_buf[i] = apply_level(color_wheel[index]) & 0xff;
}
}
void light_stimulate()
{
curr_speed = 48;
curr_level = aic_cfg->light.max;
}
static void rainbow_fade()
{
static uint64_t last = 0;
uint64_t now = time_us_64();
if (now - last < 200000) {
return;
}
last = now;
if (curr_speed > RAINBOW_MIN_SPEED) {
curr_speed = curr_speed * 90 / 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;
led_buf[i] = apply_level(color_wheel[index], rainbow.level.current) & 0xff;
}
}
static void drive_led()
{
static uint64_t last = 0;
uint64_t now = time_us_64();
if (now - last < 4000) { // no faster than 250Hz
return;
}
last = now;
for (int i = 0; i < RGB_NUM; i++) {
uint32_t color = aic_cfg->light.rgb ? rgb_buf[i] << 8u : 0;
pio_sm_put_blocking(pio0, 0, color);
@ -193,7 +215,7 @@ static void drive_led()
void light_set_color(uint32_t color)
{
for (int i = 0; i < RGB_NUM; i++) {
rgb_buf[i] = apply_level_by(color, aic_cfg->light.max);
rgb_buf[i] = apply_level(color, aic_cfg->light.max);
}
}
@ -216,7 +238,8 @@ void light_set_brg(unsigned index, const uint8_t *brg_array, size_t num)
uint8_t b = brg_array[i * 3 + 0];
uint8_t r = brg_array[i * 3 + 1];
uint8_t g = brg_array[i * 3 + 2];
rgb_buf[index + i] = apply_level(rgb32(r, g, b, false));
uint32_t color = apply_level(rgb32(r, g, b, false), aic_cfg->light.max);
rgb_buf[index + i] = color;
}
}
@ -238,21 +261,28 @@ void light_init()
pwm_init(slice, &cfg, true);
}
curr_level = aic_cfg->light.min;
generate_color_wheel();
}
static bool rainbow = true;
static bool rainbow_mode = true;
void light_set_rainbow(bool enable)
{
rainbow = enable;
rainbow_mode = enable;
}
void light_update()
{
if (rainbow && (time_us_64() > last_hid + 1000000)) {
rainbow_update();
static uint64_t last = 0;
uint64_t now = time_us_64();
if (now - last < 4000) { // no faster than 250Hz
return;
}
last = now;
rainbow_control();
if (rainbow_mode && (time_us_64() > last_hid + 1000000)) {
rainbow_render();
}
rainbow_fade();
drive_led();
}

View File

@ -18,10 +18,14 @@ void light_update();
uint32_t rgb32(uint32_t r, uint32_t g, uint32_t b, bool gamma_fix);
uint32_t rgb32_from_hsv(uint8_t h, uint8_t s, uint8_t v);
void light_color(uint32_t color, uint32_t fading_ms);
void light_color_n(uint32_t repeat, int count, ...);
void light_rainbow(int8_t speed, uint32_t smooth_ms, uint8_t level);
void light_set_color(uint32_t color);
void light_hid_light(uint8_t r, uint8_t g, uint8_t b);
void light_set_rainbow(bool enable);
void light_stimulate();
#endif

View File

@ -103,7 +103,8 @@ static void light_effect()
light_set_color(bana_led_color());
} else {
if (memcmp(hid_cardio.current, "\0\0\0\0\0\0\0\0\0", 9) != 0) {
light_stimulate();
light_rainbow(40, 0, aic_cfg->light.max);
light_rainbow(1, 2500, aic_cfg->light.min);
}
light_set_rainbow(true);
}
@ -304,6 +305,8 @@ void init()
save_init(0xca340a1c, &core1_io_lock);
light_init();
light_rainbow(1, 0, aic_cfg->light.min);
keypad_init();
nfc_init_i2c(I2C_PORT, I2C_SCL, I2C_SDA, I2C_FREQ);