Compare commits
2 Commits
a08dba780a
...
0f62418d93
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f62418d93 | |||
| 12b8acf81c |
@ -20,17 +20,22 @@ static animation_mode_t current_mode = ANIM_BLACK;
|
|||||||
static uint8_t global_hue = 0;
|
static uint8_t global_hue = 0;
|
||||||
static uint32_t frame_counter = 0;
|
static uint32_t frame_counter = 0;
|
||||||
|
|
||||||
// Beat calculation helper (similar to FastLED beatsin16)
|
// Beat calculation helper
|
||||||
static int16_t beatsin16(uint8_t bpm, int16_t min_val, int16_t max_val)
|
static int16_t beatsin16(uint8_t bpm, int16_t min_val, int16_t max_val)
|
||||||
{
|
{
|
||||||
uint32_t ms = esp_timer_get_time() / 1000;
|
// Use uint64_t to prevent overflow
|
||||||
uint32_t beat = (ms * bpm * 256) / 60000;
|
uint64_t us = esp_timer_get_time(); // Microseconds
|
||||||
uint8_t beat8 = (beat >> 8) & 0xFF;
|
|
||||||
|
|
||||||
// Sin approximation
|
// Calculate beat phase (0-65535 repeating at BPM rate)
|
||||||
float angle = (beat8 / 255.0f) * 2.0f * M_PI;
|
// beats_per_minute → beats_per_microsecond = bpm / 60,000,000
|
||||||
|
uint64_t beat_phase = (us * (uint64_t)bpm * 65536ULL) / 60000000ULL;
|
||||||
|
uint16_t beat16 = (uint16_t)(beat_phase & 0xFFFF);
|
||||||
|
|
||||||
|
// Convert to angle (0 to 2π)
|
||||||
|
float angle = (beat16 / 65535.0f) * 2.0f * M_PI;
|
||||||
float sin_val = sinf(angle);
|
float sin_val = sinf(angle);
|
||||||
|
|
||||||
|
// Map sin (-1 to +1) to output range (min_val to max_val)
|
||||||
int16_t range = max_val - min_val;
|
int16_t range = max_val - min_val;
|
||||||
int16_t result = min_val + (int16_t)((sin_val + 1.0f) * range / 2.0f);
|
int16_t result = min_val + (int16_t)((sin_val + 1.0f) * range / 2.0f);
|
||||||
|
|
||||||
@ -94,7 +99,7 @@ static void anim_white(void)
|
|||||||
|
|
||||||
static void anim_rainbow(void)
|
static void anim_rainbow(void)
|
||||||
{
|
{
|
||||||
// FastLED's built-in rainbow generator
|
// Rainbow generator
|
||||||
uint16_t num_leds_a = led_get_num_leds_a();
|
uint16_t num_leds_a = led_get_num_leds_a();
|
||||||
uint16_t num_leds_b = led_get_num_leds_b();
|
uint16_t num_leds_b = led_get_num_leds_b();
|
||||||
|
|
||||||
@ -163,14 +168,14 @@ static void anim_sinelon(void)
|
|||||||
led_fade_to_black(20);
|
led_fade_to_black(20);
|
||||||
|
|
||||||
uint16_t num_leds = led_get_num_leds_a() + led_get_num_leds_b();
|
uint16_t num_leds = led_get_num_leds_a() + led_get_num_leds_b();
|
||||||
int16_t pos = beatsin16(13, 0, num_leds - 1);
|
int16_t pos = beatsin16(13, 0, num_leds);
|
||||||
|
|
||||||
hsv_t hsv = {global_hue, 255, 192};
|
hsv_t hsv = {global_hue, 255, 192};
|
||||||
rgb_t color = led_hsv_to_rgb(hsv);
|
rgb_t color = led_hsv_to_rgb(hsv);
|
||||||
|
|
||||||
if (pos < led_get_num_leds_a())
|
if (pos < led_get_num_leds_a())
|
||||||
{
|
{
|
||||||
led_add_pixel_a(pos, color);
|
led_add_pixel_a(led_get_num_leds_a() - pos - 1, color);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -211,9 +216,7 @@ static void anim_bpm(void)
|
|||||||
|
|
||||||
static void anim_navigation(void)
|
static void anim_navigation(void)
|
||||||
{
|
{
|
||||||
// Navigation lights: left red, right green, with blinking white
|
// Navigation lights: left red, right green
|
||||||
static uint8_t blink_state = 0;
|
|
||||||
|
|
||||||
led_clear_all();
|
led_clear_all();
|
||||||
|
|
||||||
uint16_t num_leds_a = led_get_num_leds_a();
|
uint16_t num_leds_a = led_get_num_leds_a();
|
||||||
@ -221,51 +224,22 @@ static void anim_navigation(void)
|
|||||||
|
|
||||||
rgb_t red = {255, 0, 0};
|
rgb_t red = {255, 0, 0};
|
||||||
rgb_t green = {0, 255, 0};
|
rgb_t green = {0, 255, 0};
|
||||||
rgb_t white = {255, 255, 255};
|
|
||||||
|
|
||||||
// Left side red (first 3 LEDs of strip A)
|
// Side red (last 3 LEDs of strip A)
|
||||||
if (num_leds_a >= 3)
|
if (num_leds_a >= 3)
|
||||||
{
|
{
|
||||||
led_set_pixel_a(0, red);
|
led_set_pixel_a(num_leds_a - 1, red);
|
||||||
led_set_pixel_a(1, red);
|
led_set_pixel_a(num_leds_a - 2, red);
|
||||||
led_set_pixel_a(2, red);
|
led_set_pixel_a(num_leds_a - 3, red);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right side green (last 3 LEDs)
|
// Side green (last 3 LEDs of strip B)
|
||||||
if (num_leds_b >= 3)
|
if (num_leds_b >= 3)
|
||||||
{
|
{
|
||||||
led_set_pixel_b(num_leds_b - 1, green);
|
led_set_pixel_b(num_leds_b - 1, green);
|
||||||
led_set_pixel_b(num_leds_b - 2, green);
|
led_set_pixel_b(num_leds_b - 2, green);
|
||||||
led_set_pixel_b(num_leds_b - 3, green);
|
led_set_pixel_b(num_leds_b - 3, green);
|
||||||
}
|
}
|
||||||
else if (num_leds_a >= 6)
|
|
||||||
{
|
|
||||||
led_set_pixel_a(num_leds_a - 1, green);
|
|
||||||
led_set_pixel_a(num_leds_a - 2, green);
|
|
||||||
led_set_pixel_a(num_leds_a - 3, green);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blinking white lights (positions 5-6 and 37-38 from original)
|
|
||||||
if (blink_state < FRAMES_PER_SECOND / 2)
|
|
||||||
{
|
|
||||||
if (num_leds_a > 6)
|
|
||||||
{
|
|
||||||
led_set_pixel_a(5, white);
|
|
||||||
led_set_pixel_a(6, white);
|
|
||||||
}
|
|
||||||
if (num_leds_b > 2)
|
|
||||||
{
|
|
||||||
led_set_pixel_b(1, white);
|
|
||||||
led_set_pixel_b(2, white);
|
|
||||||
}
|
|
||||||
else if (num_leds_a > 38)
|
|
||||||
{
|
|
||||||
led_set_pixel_a(37, white);
|
|
||||||
led_set_pixel_a(38, white);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blink_state = (blink_state + 1) % FRAMES_PER_SECOND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void anim_chase(void)
|
static void anim_chase(void)
|
||||||
@ -357,31 +331,26 @@ static void anim_random(void)
|
|||||||
esp_err_t animation_init(void)
|
esp_err_t animation_init(void)
|
||||||
{
|
{
|
||||||
current_mode = ANIM_BLACK;
|
current_mode = ANIM_BLACK;
|
||||||
global_hue = 0;
|
global_hue = 0U;
|
||||||
frame_counter = 0;
|
frame_counter = 0U;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Animation system initialized");
|
ESP_LOGI(TAG, "Animation initialized");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void animation_set_mode(animation_mode_t mode)
|
void animation_set_mode(animation_mode_t mode)
|
||||||
{
|
{
|
||||||
if (mode >= ANIM_MODE_COUNT)
|
if ((mode >= ANIM_MODE_COUNT) || (mode < 0U))
|
||||||
{
|
{
|
||||||
mode = ANIM_BLACK;
|
mode = ANIM_BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_mode = mode;
|
current_mode = mode;
|
||||||
frame_counter = 0;
|
frame_counter = 0U;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Animation mode set to: %s", animation_get_mode_name(mode));
|
ESP_LOGI(TAG, "Animation mode set to: %s", animation_get_mode_name(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
animation_mode_t animation_get_mode(void)
|
|
||||||
{
|
|
||||||
return current_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void animation_update(void)
|
void animation_update(void)
|
||||||
{
|
{
|
||||||
// Update global hue every frame (slowly cycles colors)
|
// Update global hue every frame (slowly cycles colors)
|
||||||
@ -410,31 +379,31 @@ void animation_update(void)
|
|||||||
anim_white();
|
anim_white();
|
||||||
break;
|
break;
|
||||||
case ANIM_RAINBOW:
|
case ANIM_RAINBOW:
|
||||||
anim_rainbow();
|
// anim_rainbow();
|
||||||
break;
|
break;
|
||||||
case ANIM_RAINBOW_GLITTER:
|
case ANIM_RAINBOW_GLITTER:
|
||||||
anim_rainbow_glitter();
|
// anim_rainbow_glitter();
|
||||||
break;
|
break;
|
||||||
case ANIM_CONFETTI:
|
case ANIM_CONFETTI:
|
||||||
anim_confetti();
|
// anim_confetti();
|
||||||
break;
|
break;
|
||||||
case ANIM_SINELON:
|
case ANIM_SINELON:
|
||||||
anim_sinelon();
|
anim_sinelon();
|
||||||
break;
|
break;
|
||||||
case ANIM_BPM:
|
case ANIM_BPM:
|
||||||
anim_bpm();
|
// anim_bpm();
|
||||||
break;
|
break;
|
||||||
case ANIM_NAVIGATION:
|
case ANIM_NAVIGATION:
|
||||||
anim_navigation();
|
anim_navigation();
|
||||||
break;
|
break;
|
||||||
case ANIM_CHASE:
|
case ANIM_CHASE:
|
||||||
anim_chase();
|
// anim_chase();
|
||||||
break;
|
break;
|
||||||
case ANIM_CHASE_RGB:
|
case ANIM_CHASE_RGB:
|
||||||
anim_chase_rgb();
|
// anim_chase_rgb();
|
||||||
break;
|
break;
|
||||||
case ANIM_RANDOM:
|
case ANIM_RANDOM:
|
||||||
anim_random();
|
// anim_random();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
anim_black();
|
anim_black();
|
||||||
@ -456,7 +425,7 @@ const char *animation_get_mode_name(animation_mode_t mode)
|
|||||||
"Rainbow with Glitter",
|
"Rainbow with Glitter",
|
||||||
"Confetti",
|
"Confetti",
|
||||||
"Sinelon",
|
"Sinelon",
|
||||||
"BPM",
|
"33BPM",
|
||||||
"Navigation",
|
"Navigation",
|
||||||
"Chase",
|
"Chase",
|
||||||
"Chase RGB",
|
"Chase RGB",
|
||||||
|
|||||||
@ -43,12 +43,6 @@ esp_err_t animation_init(void);
|
|||||||
*/
|
*/
|
||||||
void animation_set_mode(animation_mode_t mode);
|
void animation_set_mode(animation_mode_t mode);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current animation mode
|
|
||||||
* @return Current mode
|
|
||||||
*/
|
|
||||||
animation_mode_t animation_get_mode(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update animation (call periodically, e.g., 30-60 FPS)
|
* @brief Update animation (call periodically, e.g., 30-60 FPS)
|
||||||
*/
|
*/
|
||||||
@ -59,6 +53,6 @@ void animation_update(void);
|
|||||||
* @param mode Animation mode
|
* @param mode Animation mode
|
||||||
* @return Mode name string
|
* @return Mode name string
|
||||||
*/
|
*/
|
||||||
const char* animation_get_mode_name(animation_mode_t mode);
|
const char *animation_get_mode_name(animation_mode_t mode);
|
||||||
|
|
||||||
#endif // ANIMATION_H
|
#endif // ANIMATION_H
|
||||||
|
|||||||
@ -24,15 +24,6 @@ static void on_mode_change()
|
|||||||
animation_set_mode((animation_mode_t)current_animation_mode);
|
animation_set_mode((animation_mode_t)current_animation_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void control_set_animation_mode(uint8_t mode)
|
|
||||||
{
|
|
||||||
if (mode >= ANIM_MODE_COUNT)
|
|
||||||
{
|
|
||||||
mode = 0;
|
|
||||||
}
|
|
||||||
on_mode_change(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t control_get_animation_mode(void)
|
uint8_t control_get_animation_mode(void)
|
||||||
{
|
{
|
||||||
return current_animation_mode;
|
return current_animation_mode;
|
||||||
@ -58,7 +49,7 @@ esp_err_t control_init(void)
|
|||||||
|
|
||||||
// Initialize LED strips
|
// Initialize LED strips
|
||||||
ret = led_init(current_config.led_pin_strip_a, current_config.led_pin_strip_b,
|
ret = led_init(current_config.led_pin_strip_a, current_config.led_pin_strip_b,
|
||||||
current_config.led_count_strip_a, current_config.led_count_strip_a);
|
current_config.led_count_strip_a, current_config.led_count_strip_b);
|
||||||
if (ret != ESP_OK)
|
if (ret != ESP_OK)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "LED init failed: %s", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "LED init failed: %s", esp_err_to_name(ret));
|
||||||
|
|||||||
@ -18,12 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
esp_err_t control_init(void);
|
esp_err_t control_init(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set animation mode manually
|
|
||||||
* @param mode Animation mode (0-13)
|
|
||||||
*/
|
|
||||||
void control_set_animation_mode(uint8_t mode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get current animation mode
|
* @brief Get current animation mode
|
||||||
* @return Current mode (0-13)
|
* @return Current mode (0-13)
|
||||||
|
|||||||
19
main/led.c
19
main/led.c
@ -321,7 +321,10 @@ static void show_strip(led_strip_t *strip)
|
|||||||
// Convert RGB to GRB for WS2812B
|
// Convert RGB to GRB for WS2812B
|
||||||
uint8_t *grb_data = malloc(strip->num_leds * 3);
|
uint8_t *grb_data = malloc(strip->num_leds * 3);
|
||||||
if (!grb_data)
|
if (!grb_data)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to allocate GRB buffer");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint16_t i = 0; i < strip->num_leds; i++)
|
for (uint16_t i = 0; i < strip->num_leds; i++)
|
||||||
{
|
{
|
||||||
@ -334,7 +337,21 @@ static void show_strip(led_strip_t *strip)
|
|||||||
.loop_count = 0,
|
.loop_count = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
rmt_transmit(strip->rmt_channel, strip->encoder, grb_data, strip->num_leds * 3, &tx_config);
|
esp_err_t ret = rmt_transmit(strip->rmt_channel, strip->encoder, grb_data, strip->num_leds * 3, &tx_config);
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "RMT transmit failed: %s", esp_err_to_name(ret));
|
||||||
|
free(grb_data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for transmission to complete before freeing buffer
|
||||||
|
ret = rmt_tx_wait_all_done(strip->rmt_channel, pdMS_TO_TICKS(100));
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "RMT wait timeout");
|
||||||
|
}
|
||||||
|
|
||||||
free(grb_data);
|
free(grb_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,6 +76,8 @@ void app_main(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
animation_set_mode((animation_mode_t)control_get_animation_mode());
|
||||||
|
|
||||||
ESP_LOGI(TAG, "System initialized successfully");
|
ESP_LOGI(TAG, "System initialized successfully");
|
||||||
|
|
||||||
// Main loop - just monitor system status
|
// Main loop - just monitor system status
|
||||||
@ -84,6 +86,6 @@ void app_main(void)
|
|||||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||||
|
|
||||||
// Periodic status logging
|
// Periodic status logging
|
||||||
ESP_LOGI(TAG, "Status - Mode: %d", control_get_animation_mode());
|
ESP_LOGI(TAG, "Animation Mode set to: %s", animation_get_mode_name(control_get_animation_mode()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user