1
0
mirror of https://github.com/whowechina/aic_pico.git synced 2024-11-24 14:00:09 +01:00

2 light modes to support future patterns

This commit is contained in:
whowechina 2024-05-09 22:11:34 +08:00
parent a84ceb5531
commit b6aa7d2dd2
3 changed files with 212 additions and 50 deletions

View File

@ -6,6 +6,7 @@
#include "light.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
@ -112,11 +113,118 @@ static void generate_color_wheel()
}
}
static inline uint8_t lerp8u(uint8_t a, uint8_t b, uint8_t t)
static inline uint8_t lerp8b(uint8_t a, uint8_t b, uint8_t t)
{
return a + (b - a) * t / 255;
}
static uint32_t lerp(uint32_t a, uint32_t b, int pos, int range)
{
uint8_t t = pos * 255 / range;
uint32_t c1 = lerp8b((a >> 16) & 0xff, (b >> 16) & 0xff, t);
uint32_t c2 = lerp8b((a >> 8) & 0xff, (b >> 8) & 0xff, t);
uint32_t c3 = lerp8b(a & 0xff, b & 0xff, t);
return c1 << 16 | c2 << 8 | c3;
}
static enum {
MODE_FADE,
MODE_RAINBOW,
} light_mode = MODE_RAINBOW;
static struct {
int repeat;
int step_num;
int curr_step;
uint32_t color;
int elapsed;
struct {
uint32_t from;
uint32_t to;
int duration;
} steps[32];
} fading;
void light_fade_n(int repeat, int count, ...)
{
va_list args;
va_start(args, count);
for (int i = 0; i < count; i++) {
fading.steps[i].from = i == 0 ? fading.color : fading.steps[i - 1].to;
fading.steps[i].to = va_arg(args, uint32_t);
fading.steps[i].duration = va_arg(args, int);
}
va_end(args);
fading.repeat = repeat;
fading.step_num = count;
fading.curr_step = 0;
fading.elapsed = 0;
light_mode = MODE_FADE;
}
void light_fade(uint32_t color, uint32_t fading_ms)
{
light_fade_n(1, 1, color, fading_ms);
}
static void color_control(uint32_t delta_ms)
{
if (fading.repeat == 0) {
return;
}
fading.elapsed += delta_ms;
if (fading.elapsed > fading.steps[fading.curr_step].duration) {
fading.elapsed = 0;
fading.color = fading.steps[fading.curr_step].to;
fading.curr_step++;
if (fading.curr_step == fading.step_num) {
fading.curr_step = 0;
if (fading.repeat > 0) {
fading.repeat--;
}
}
return;
}
uint32_t color = lerp(fading.steps[fading.curr_step].from,
fading.steps[fading.curr_step].to,
fading.elapsed,
fading.steps[fading.curr_step].duration);
fading.color = color;
}
static void color_render()
{
uint32_t color = apply_level(fading.color, aic_cfg->light.max);
for (int i = 0; i < RGB_NUM; i++) {
rgb_buf[i] = color;
}
color &= 0xff;
for (int i = 0; i < LED_NUM; i++) {
led_buf[i] = color;
}
}
static void color_update(uint32_t delta_ms)
{
if (light_mode != MODE_FADE) {
fading.color = 0x000000;
fading.repeat = 0;
return;
}
color_control(delta_ms);
color_render();
}
static struct {
struct {
int current;
@ -137,41 +245,63 @@ 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.smooth_ms = smooth_ms;
rainbow.elapsed = 0;
} else {
rainbow.speed.current = speed;
rainbow.level.current = level;
rainbow.smooth_ms = 0;
rainbow.elapsed = 0;
}
}
light_mode = MODE_RAINBOW;
}
static void rainbow_control()
static int fast_sqrt(int x)
{
static uint64_t last_time;
uint64_t now = time_us_64();
uint32_t delta = (now - last_time) / 1000;
last_time = now;
int left = 0;
int right = x;
int result = 0;
while (left <= right) {
int mid = left + (right - left) / 2;
int64_t sq = (int64_t)mid * mid;
if (sq <= x) {
result = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
static void rainbow_control(uint32_t delta_ms)
{
if ((rainbow.smooth_ms == 0) || (rainbow.elapsed == rainbow.smooth_ms)) {
return;
}
rainbow.elapsed += delta;
rainbow.elapsed += delta_ms;
if (rainbow.elapsed > rainbow.smooth_ms) {
rainbow.elapsed = rainbow.smooth_ms;
}
/* non linear speed change for better visual */
int range = rainbow.speed.to - rainbow.speed.from;
int progress = range * rainbow.elapsed / rainbow.smooth_ms;
rainbow.speed.current = rainbow.speed.from + progress;
int progress = fast_sqrt(rainbow.elapsed * 10000 / rainbow.smooth_ms);
rainbow.speed.current = rainbow.speed.from + range * progress / 100;
range = rainbow.level.to - rainbow.level.from;
progress = range * rainbow.elapsed / rainbow.smooth_ms;
rainbow.level.current = rainbow.level.from + progress;
progress = fast_sqrt(rainbow.elapsed * 10000 / rainbow.smooth_ms);
rainbow.level.current = rainbow.level.from + range * progress / 100;
}
#define RAINBOW_PITCH 37
@ -199,6 +329,18 @@ static void rainbow_render()
}
}
static void rainbow_update(uint32_t delta_ms)
{
if (light_mode != MODE_RAINBOW) {
rainbow.smooth_ms = 0;
rainbow.speed.current = rainbow.speed.to;
rainbow.level.current = rainbow.level.to;
return;
}
rainbow_control(delta_ms);
rainbow_render();
}
static void drive_led()
{
for (int i = 0; i < RGB_NUM; i++) {
@ -264,25 +406,18 @@ void light_init()
generate_color_wheel();
}
static bool rainbow_mode = true;
void light_set_rainbow(bool enable)
{
rainbow_mode = enable;
}
void light_update()
{
static uint64_t last = 0;
static uint64_t last_time = 0;
uint64_t now = time_us_64();
if (now - last < 4000) { // no faster than 250Hz
if (now - last_time < 4000) { // no faster than 250Hz
return;
}
last = now;
uint32_t delta_ms = (now - last_time) / 1000;
last_time = now;
rainbow_control();
color_update(delta_ms);
rainbow_update(delta_ms);
if (rainbow_mode && (time_us_64() > last_hid + 1000000)) {
rainbow_render();
}
drive_led();
}

View File

@ -18,14 +18,9 @@ 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_fade(uint32_t color, uint32_t fading_ms);
void light_fade_n(int 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);
#endif

View File

@ -93,23 +93,31 @@ void report_usb_hid()
report_hid_key();
}
static void light_effect()
static uint64_t last_hid_time = 0;
static bool hid_is_active()
{
if (aime_is_active()) {
light_set_rainbow(false);
light_set_color(aime_led_color());
} else if (bana_is_active()) {
light_set_rainbow(false);
light_set_color(bana_led_color());
} else {
if (memcmp(hid_cardio.current, "\0\0\0\0\0\0\0\0\0", 9) != 0) {
light_rainbow(40, 0, aic_cfg->light.max);
light_rainbow(1, 2500, aic_cfg->light.min);
}
light_set_rainbow(true);
if (last_hid_time == 0) {
return false;
}
return (time_us_64() - last_hid_time) < 2000000;
}
static bool cardio_is_available()
{
return !(hid_is_active() || aime_is_active() || bana_is_active());
}
static void light_mode_update()
{
static bool was_cardio = true;
bool cardio = cardio_is_available();
if (cardio && !was_cardio) {
light_rainbow(1, 1, aic_cfg->light.min);
}
light_update();
was_cardio = cardio;
}
static mutex_t core1_io_lock;
@ -117,9 +125,10 @@ static void core1_loop()
{
while (1) {
if (mutex_try_enter(&core1_io_lock, NULL)) {
light_effect();
light_update();
mutex_exit(&core1_io_lock);
}
light_mode_update();
cli_fps_count(1);
sleep_us(500);
}
@ -142,7 +151,7 @@ static void update_cardio(nfc_card_t *card)
case NFC_CARD_FELICA:
hid_cardio.current[0] = REPORT_ID_FELICA;
memcpy(hid_cardio.current + 1, card->uid, 8);
break;
break;
case NFC_CARD_VICINITY:
hid_cardio.current[0] = REPORT_ID_EAMU;
memcpy(hid_cardio.current + 1, card->uid, 8);
@ -177,6 +186,14 @@ static void cardio_run()
old_card = card;
if (cardio_is_available()) {
if (card.card_type != NFC_CARD_NONE) {
light_rainbow(30, 0, aic_cfg->light.max);
} else {
light_rainbow(1, 3000, aic_cfg->light.min);
}
}
display_card(&card);
update_cardio(&card);
}
@ -234,6 +251,18 @@ static void aime_detect_mode()
}
static void aime_light()
{
static uint32_t old_color = 0;
if (aime_is_active()) {
uint32_t color = aime_led_color();
if (old_color != color) {
light_fade(color, 100);
old_color = color;
}
}
}
static void aime_run()
{
aime_poll_data();
@ -262,6 +291,8 @@ static void aime_run()
break;
}
}
aime_light();
}
void wait_loop()
@ -387,7 +418,8 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id,
if ((report_id == REPORT_ID_LIGHTS) &&
(report_type == HID_REPORT_TYPE_OUTPUT)) {
if (bufsize >= 3) {
light_hid_light(buffer[0], buffer[1], buffer[2]);
last_hid_time = time_us_64();
light_fade(rgb32(buffer[0], buffer[1], buffer[2], false), 0);
}
}
}