|
- static const char *TAG = "rmt_leds";
- #include <esp_log.h>
-
- #include <freertos/FreeRTOS.h>
- #include <freertos/task.h>
-
- #include "rmt_leds.hpp"
-
-
- #define WS2811_PULSE_WIDTH_NS 1250
-
- #define RMT_TX_CHANNEL RMT_CHANNEL_0
-
-
- static int bit_ticks;
-
-
- static void IRAM_ATTR ws2811_rmt_adapter(
- const void *src, rmt_item32_t *dest, size_t src_size,
- size_t wanted_num, size_t *translated_size, size_t *item_num
- ) {
- if (src == NULL || dest == NULL) {
- *translated_size = 0;
- *item_num = 0;
- return;
- }
-
- const uint32_t short_ticks = bit_ticks / 3;
- const uint32_t long_ticks = bit_ticks - short_ticks;
- const rmt_item32_t bit0 = {{{ short_ticks, 1, long_ticks, 0 }}}; // Logical 0
- const rmt_item32_t bit1 = {{{ long_ticks, 1, short_ticks, 0 }}}; // Logical 1
- size_t size = 0;
- size_t num = 0;
- uint8_t *psrc = (uint8_t *)src;
- rmt_item32_t *pdest = dest;
- while (size < src_size && num < wanted_num) {
- for (int i = 0; i < 8; i++) {
- // MSB first
- if (*psrc & (1 << (7 - i))) {
- pdest->val = bit1.val;
- } else {
- pdest->val = bit0.val;
- }
- num++;
- pdest++;
- }
- size++;
- psrc++;
- }
-
- *translated_size = size;
- *item_num = num;
- }
-
-
- RMT_LEDs::RMT_LEDs(gpio_num_t _gpio, int length) :
- LEDStrip(length), gpio(_gpio), channel(RMT_CHANNEL_MAX) {
- rmt_config_t config = RMT_DEFAULT_CONFIG_TX(gpio, RMT_TX_CHANNEL);
- // set counter clock to 40MHz
- config.clk_div = 2;
-
- ESP_ERROR_CHECK(rmt_config(&config));
- channel = config.channel;
- ESP_ERROR_CHECK(rmt_driver_install(channel, 0, 0));
-
- uint32_t counter_clk_hz = 0;
- int err = rmt_get_counter_clock(channel, &counter_clk_hz);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "Failed to read RMT counter: %d", err);
- return;
- }
-
- rmt_translator_init(channel, ws2811_rmt_adapter);
-
- // ns -> ticks
- bit_ticks = ((uint64_t)counter_clk_hz * WS2811_PULSE_WIDTH_NS) / 1e9;
-
- ESP_LOGI(TAG, "Each bit is %d RMT ticks", bit_ticks);
-
- configure(length);
- }
-
- RMT_LEDs::~RMT_LEDs() {
- ESP_ERROR_CHECK(rmt_driver_uninstall(channel));
- }
-
- void RMT_LEDs::configure(int n_leds) {
- // We don't own the RMT buffer
- }
-
- void RMT_LEDs::show() {
- esp_err_t err;
-
- err = rmt_wait_tx_done(channel, 0);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "RMT TX incomplete: %d", err);
- return;
- }
-
- err = rmt_write_sample(channel, (uint8_t*)pixels, length * 3, false);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "Failed to write sample to RMT: %d", err);
- }
- }
|