132 lines
3.0 KiB
C
132 lines
3.0 KiB
C
#include "led_driver.h"
|
|
#include "driver/rmt_tx.h"
|
|
#include "driver/gpio.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include <string.h>
|
|
|
|
#define LED_PIN 18 // <-- CERTIFICA-TE disto
|
|
#define RMT_RESOLUTION_HZ 10000000 // 10 MHz (1 tick = 0.1us)
|
|
|
|
typedef struct {
|
|
uint8_t r,g,b;
|
|
} led_color_t;
|
|
|
|
static led_color_t leds[LED_COUNT];
|
|
|
|
static rmt_channel_handle_t rmt_chan = NULL;
|
|
static rmt_encoder_handle_t encoder = NULL;
|
|
|
|
static rmt_transmit_config_t tx_config = {
|
|
.loop_count = 0
|
|
};
|
|
|
|
void led_driver_init(void)
|
|
{
|
|
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
|
|
|
|
rmt_tx_channel_config_t chan_cfg = {
|
|
.gpio_num = LED_PIN,
|
|
.clk_src = RMT_CLK_SRC_DEFAULT,
|
|
.resolution_hz = RMT_RESOLUTION_HZ,
|
|
.mem_block_symbols = 64,
|
|
.trans_queue_depth = 1,
|
|
};
|
|
|
|
ESP_ERROR_CHECK(rmt_new_tx_channel(&chan_cfg, &rmt_chan));
|
|
ESP_ERROR_CHECK(rmt_enable(rmt_chan));
|
|
|
|
// WS2812B timings (EXATOS)
|
|
rmt_bytes_encoder_config_t enc_cfg = {
|
|
.bit0 = {
|
|
.duration0 = 4, .level0 = 1, // 0.4us HIGH
|
|
.duration1 = 9, .level1 = 0 // 0.9us LOW
|
|
},
|
|
.bit1 = {
|
|
.duration0 = 9, .level0 = 1, // 0.9us HIGH
|
|
.duration1 = 4, .level1 = 0 // 0.4us LOW
|
|
},
|
|
.flags.msb_first = 1
|
|
};
|
|
|
|
ESP_ERROR_CHECK(rmt_new_bytes_encoder(&enc_cfg, &encoder));
|
|
|
|
memset(leds, 0, sizeof(leds));
|
|
led_show();
|
|
}
|
|
|
|
void led_set_pixel(int index, uint8_t r, uint8_t g, uint8_t b)
|
|
{
|
|
if (index < 0 || index >= LED_COUNT) return;
|
|
leds[index].r = r;
|
|
leds[index].g = g;
|
|
leds[index].b = b;
|
|
}
|
|
|
|
void led_clear(void)
|
|
{
|
|
memset(leds, 0, sizeof(leds));
|
|
}
|
|
|
|
static void hw_update(void)
|
|
{
|
|
uint8_t buf[LED_COUNT * 3];
|
|
|
|
// MOST common format is GRB
|
|
for (int i = 0; i < LED_COUNT; i++) {
|
|
buf[i*3 + 0] = leds[i].g;
|
|
buf[i*3 + 1] = leds[i].r;
|
|
buf[i*3 + 2] = leds[i].b;
|
|
}
|
|
|
|
ESP_ERROR_CHECK(rmt_transmit(rmt_chan, encoder, buf, sizeof(buf), &tx_config));
|
|
rmt_tx_wait_all_done(rmt_chan, -1);
|
|
|
|
// Reset time > 50us
|
|
esp_rom_delay_us(60);
|
|
|
|
}
|
|
|
|
void led_show(void)
|
|
{
|
|
hw_update();
|
|
}
|
|
|
|
int led_get_count(void)
|
|
{
|
|
return LED_COUNT;
|
|
}
|
|
void led_spin_to(uint16_t target, int min_spins, int max_spins, int base_delay_ms)
|
|
{
|
|
int n = LED_COUNT;
|
|
if (min_spins < 1) min_spins = 1;
|
|
if (max_spins < min_spins) max_spins = min_spins;
|
|
|
|
int extra = 0;
|
|
if (max_spins > min_spins)
|
|
extra = rand() % (max_spins - min_spins + 1);
|
|
|
|
int total_steps = (min_spins + extra) * n + (target % n);
|
|
int delay = base_delay_ms;
|
|
|
|
for (int step = 0; step <= total_steps; step++) {
|
|
int pos = step % n;
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
if (i == pos)
|
|
led_set_pixel(i, 0, 40, 0); // verde fraco no cursor
|
|
else
|
|
led_set_pixel(i, 0, 0, 0);
|
|
}
|
|
|
|
led_show();
|
|
|
|
if (step < total_steps / 3 && delay > 3)
|
|
delay--;
|
|
else if (step > (2 * total_steps) / 3)
|
|
delay++;
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(delay));
|
|
}
|
|
}
|