1
0
mirror of https://github.com/whowechina/aic_pico.git synced 2024-11-28 07:20:49 +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 "light.h"
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.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; 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 { static struct {
struct { struct {
int current; int current;
@ -137,41 +245,63 @@ void light_rainbow(int8_t speed, uint32_t smooth_ms, uint8_t level)
if (smooth_ms != 0) { if (smooth_ms != 0) {
rainbow.speed.from = rainbow.speed.current; rainbow.speed.from = rainbow.speed.current;
rainbow.speed.to = speed; rainbow.speed.to = speed;
rainbow.smooth_ms = smooth_ms;
rainbow.level.from = rainbow.level.current; rainbow.level.from = rainbow.level.current;
rainbow.level.to = level; rainbow.level.to = level;
rainbow.smooth_ms = smooth_ms;
rainbow.elapsed = 0; rainbow.elapsed = 0;
} else { } else {
rainbow.speed.current = speed; rainbow.speed.current = speed;
rainbow.level.current = level; rainbow.level.current = level;
rainbow.smooth_ms = 0; rainbow.smooth_ms = 0;
rainbow.elapsed = 0; rainbow.elapsed = 0;
} }
light_mode = MODE_RAINBOW;
} }
static void rainbow_control() static int fast_sqrt(int x)
{ {
static uint64_t last_time; int left = 0;
uint64_t now = time_us_64(); int right = x;
uint32_t delta = (now - last_time) / 1000; int result = 0;
last_time = now;
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)) { if ((rainbow.smooth_ms == 0) || (rainbow.elapsed == rainbow.smooth_ms)) {
return; return;
} }
rainbow.elapsed += delta; rainbow.elapsed += delta_ms;
if (rainbow.elapsed > rainbow.smooth_ms) { if (rainbow.elapsed > rainbow.smooth_ms) {
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 range = rainbow.speed.to - rainbow.speed.from;
int progress = range * rainbow.elapsed / rainbow.smooth_ms; int progress = fast_sqrt(rainbow.elapsed * 10000 / rainbow.smooth_ms);
rainbow.speed.current = rainbow.speed.from + progress; rainbow.speed.current = rainbow.speed.from + range * progress / 100;
range = rainbow.level.to - rainbow.level.from; range = rainbow.level.to - rainbow.level.from;
progress = range * rainbow.elapsed / rainbow.smooth_ms; progress = fast_sqrt(rainbow.elapsed * 10000 / rainbow.smooth_ms);
rainbow.level.current = rainbow.level.from + progress; rainbow.level.current = rainbow.level.from + range * progress / 100;
} }
#define RAINBOW_PITCH 37 #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() static void drive_led()
{ {
for (int i = 0; i < RGB_NUM; i++) { for (int i = 0; i < RGB_NUM; i++) {
@ -264,25 +406,18 @@ void light_init()
generate_color_wheel(); generate_color_wheel();
} }
static bool rainbow_mode = true;
void light_set_rainbow(bool enable)
{
rainbow_mode = enable;
}
void light_update() void light_update()
{ {
static uint64_t last = 0; static uint64_t last_time = 0;
uint64_t now = time_us_64(); uint64_t now = time_us_64();
if (now - last < 4000) { // no faster than 250Hz if (now - last_time < 4000) { // no faster than 250Hz
return; 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(); 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(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); 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_fade(uint32_t color, uint32_t fading_ms);
void light_color_n(uint32_t repeat, int count, ...); void light_fade_n(int repeat, int count, ...);
void light_rainbow(int8_t speed, uint32_t smooth_ms, uint8_t level); 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 #endif

View File

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