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:
parent
a84ceb5531
commit
b6aa7d2dd2
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user