You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

80 lines
2.2 KiB

// Copyright 2022 Andrew Dunai (@and3rson)
// SPDX-License-Identifier: GPL-2.0-or-later
#include "endgame48.h"
#include "smoothled.h"
#include "math.h"
#include "string.h"
static LED_TYPE source[RGBLED_NUM] = {};
static LED_TYPE current[RGBLED_NUM] = {};
static LED_TYPE target[RGBLED_NUM] = {};
static uint32_t duration = 1500;
static int32_t smoothledTimer = -1;
static animFunc_t animFunc;
const float RGBLED_STEP = 1.0f / ((float)RGBLED_NUM);
void smoothled_set(uint32_t color, uint32_t newDuration, animFunc_t newAnimFunc) {
smoothledTimer = timer_read32();
LED_TYPE next = {.r = (color >> 16) & 0xFF, .g = (color >> 8) & 0xFF, .b = color & 0xFF};
for (uint8_t p = 0; p < RGBLED_NUM; p++) {
source[p] = current[p];
target[p] = next;
}
duration = newDuration;
animFunc = newAnimFunc;
}
LED_TYPE swimOut(LED_TYPE a, LED_TYPE b, float k, uint8_t x) {
k = pow(k, 2);
/* Center */
x = fabs(5.5 - ((float)x));
/* Time range for current LED */
float start = RGBLED_STEP * x;
float end = RGBLED_STEP * (x + 1);
if (k <= start) {
k = 0;
} else if (k >= end) {
k = 1;
} else {
k = (k - start) / RGBLED_STEP;
}
float rk = 1.0f - k;
return (LED_TYPE){
.r = rk * a.r + k * b.r,
.g = rk * a.g + k * b.g,
.b = rk * a.b + k * b.b,
};
}
LED_TYPE swimIn(LED_TYPE a, LED_TYPE b, float k, uint8_t x) {
if (x < RGBLED_NUM / 2) {
x = RGBLED_NUM / 2 - x - 1;
} else {
x = RGBLED_NUM - (x - RGBLED_NUM / 2 - 1);
}
return swimOut(a, b, k, x);
}
void smoothled_process(void) {
if (smoothledTimer == -1) {
return;
}
smoothled_render();
}
void smoothled_render(void) {
uint32_t passed = timer_elapsed32(smoothledTimer);
if (passed > duration) {
passed = duration;
smoothledTimer = -1;
}
float k = ((float)passed) / duration;
for (uint8_t p = 0; p < RGBLED_NUM; p++) {
current[p] = animFunc(source[p], target[p], k, p);
/* This is much faster than calling rgblight_setrgb_at every iteration */
led[p] = current[p];
}
rgblight_set();
}