Phase 7: EC11 encoder, life counter views, WS2812B RMT + LEDC buzzer feedback, E2E UI state machine; document build/hardware notes

This commit is contained in:
2026-09-09 18:36:17 +02:00
parent 8a95e1735a
commit 01c24d17b6
14 changed files with 914 additions and 29 deletions

90
main/led_manager.c Normal file
View File

@@ -0,0 +1,90 @@
/*
* MTG RFID Companion - WS2812B Neopixel LED manager (RMT)
*/
#include "esp_log.h"
#include "driver/rmt_tx.h"
#include "driver/rmt_encoder.h"
#include "hw_pins.h"
#include "led_manager.h"
static const char *TAG = "led";
static rmt_channel_handle_t s_tx_chan = NULL;
static rmt_encoder_handle_t s_enc = NULL;
esp_err_t led_manager_init(void)
{
if (s_tx_chan != NULL) {
return ESP_OK;
}
rmt_tx_channel_config_t chan_cfg = {
.gpio_num = HW_NEOPIXEL_GPIO,
.clk_src = RMT_CLK_SRC_DEFAULT,
.resolution_hz = 10 * 1000 * 1000, /* 100 ns per tick */
.mem_block_symbols = 64,
.trans_queue_depth = 4,
};
esp_err_t ret = rmt_new_tx_channel(&chan_cfg, &s_tx_chan);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "rmt_new_tx_channel failed: %s", esp_err_to_name(ret));
return ret;
}
rmt_bytes_encoder_config_t enc_cfg = {
.bit0 = {
.duration0 = 4, /* T0H ~ 400 ns */
.level0 = 1,
.duration1 = 8, /* T0L ~ 800 ns */
.level1 = 0,
},
.bit1 = {
.duration0 = 9, /* T1H ~ 900 ns */
.level0 = 1,
.duration1 = 4, /* T1L ~ 400 ns */
.level1 = 0,
},
};
ret = rmt_new_bytes_encoder(&enc_cfg, &s_enc);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "rmt_new_bytes_encoder failed: %s", esp_err_to_name(ret));
return ret;
}
ret = rmt_enable(s_tx_chan);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "rmt_enable failed: %s", esp_err_to_name(ret));
return ret;
}
ESP_LOGI(TAG, "WS2812B LED ready on GPIO %d", HW_NEOPIXEL_GPIO);
return ESP_OK;
}
esp_err_t led_manager_set_color(uint8_t r, uint8_t g, uint8_t b)
{
if (s_tx_chan == NULL) {
esp_err_t ret = led_manager_init();
if (ret != ESP_OK) {
return ret;
}
}
/* WS2812B expects GRB byte order */
uint8_t txbuf[3] = { g, r, b };
rmt_transmit_config_t tx_cfg = {
.loop_count = 0, /* one-shot; LED latches and holds the level */
};
esp_err_t ret = rmt_transmit(s_tx_chan, s_enc, txbuf, sizeof(txbuf), &tx_cfg);
if (ret != ESP_OK) {
return ret;
}
return rmt_tx_wait_all_done(s_tx_chan, pdMS_TO_TICKS(50));
}
esp_err_t led_manager_off(void)
{
return led_manager_set_color(0, 0, 0);
}