|
- static const char *TAG = "rmt_leds";
- #include <esp_log.h>
-
- #include <freertos/FreeRTOS.h>
- #include <freertos/task.h>
-
- #include "rmt_leds.hpp"
-
-
- RMT_LEDs::RMT_LEDs(int _gpio, int length) :
- LEDStrip(length), gpio(_gpio), channel(NULL), rmt_block(NULL) {
- rmt_tx_channel_config_t config = {
- .gpio_num = gpio,
- .clk_src = RMT_CLK_SRC_DEFAULT,
- .resolution_hz = 3200000, // (1.25 us / 4) => 3.2 MHz
- .mem_block_symbols = 64, // memory block size, 64 * 4 = 256Bytes
- .trans_queue_depth = 1, // We don't really need background transfers
- .flags = {
- .invert_out = false,
- .with_dma = false, // TODO: Why no DMA??
- .io_loop_back = false,
- },
- };
- ESP_ERROR_CHECK(rmt_new_tx_channel(&config, &channel));
- ESP_ERROR_CHECK(rmt_enable(channel));
- configure(length);
- }
-
- void RMT_LEDs::configure(int n_leds) {
- if (rmt_block) {
- delete[] rmt_block;
- rmt_block = NULL;
- }
- if (n_leds <= 0) return;
- rmt_block = new rmt_symbol_word_t[n_leds * 24 + 1];
- }
-
- /*
- static rmt_encoder_handle_t byte_enc;
- static const rmt_bytes_encoder_config_t byte_enc_config = {
- .bit0 = {
- .duration0 = 1,
- .level0 = 1,
- .duration1 = 3,
- .level1 = 0,
- },
- .bit1 = {
- .duration0 = 2,
- .level0 = 1,
- .duration1 = 2,
- .level1 = 0,
- },
- .flags = {
- .msb_first = 1,
- },
- };
- static esp_err_t bytes_enc_ok = rmt_new_bytes_encoder(&byte_enc_config, &byte_enc);
-
- static rmt_encoder_handle_t rst_enc;
- static const rmt_copy_encoder_config_t rst_enc_config = {};
- static esp_err_t rst_enc_ok = rmt_new_copy_encoder(&rst_enc_config, &rst_enc);
- static const rmt_symbol_word_t rst_symbol = {
- .duration0 = 80,
- .level0 = 0,
- .duration1 = 80,
- .level1 = 0,
- };
-
- struct strip_encoder {
- rmt_encoder_t base;
- int state;
- };
-
- static size_t encode_strip(
- rmt_encoder_t *_encoder, rmt_channel_handle_t channel,
- const void *data, size_t n_bytes, rmt_encode_state_t *ret_state
- ) {
- strip_encoder *encoder = __containerof(_encoder, strip_encoder, base);
- size_t n_encoded = 0;
- rmt_encode_state_t substate = 0;
- rmt_encode_state_t state = 0;
-
- switch(encoder->state) {
- case 0:
- n_encoded += byte_enc.encode(&byte_enc, channel, data, n_bytes, &substate);
- if (substate & RMT_ENCODING_COMPLETE) {
- encoder->state = 1;
- break;
- }
-
- case 1:
- n_encoded += rst_enc.encode(
- &rst_enc, channel, &rst_symbol, sizeof(rst_symbol), &substate);
- if (substate & RMT_ENCODING_COMPLETE) {
- encoder->state = 0;
- state |= RMT_ENCODING_COMPLETE;
- }
- if (substate & RMT_ENCODING_MEM_FULL) {
- state |= RMT_ENCODING_MEM_FULL;
- }
- }
-
- *ret_state = state;
- return n_encoded;
- }
-
- static esp_err_t reset_strip_encoder(rmt_encoder_t *encoder) {
- strip_encoder *encoder = __containerof(encoder, strip_encoder, base);
- rmt_encoder_reset(byte_enc);
- rmt_encoder_reset(rst_enc);
- encoder->state = 0;
- return ESP_OK;
- }
-
- static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder) {
- strip_encoder *encoder = __containerof(encoder, strip_encoder, base);
- delete encoder;
- return ESP_OK;
- }
-
- static rmt_encoder_t* make_strip_encoder() {
- enc = new strip_encoder {
- .base = {
- .encode = encode_strip,
- .reset = reset_strip_encoder,
- .del = del_strip_encoder,
- },
- .state = 0
- }
- }
- */
-
-
- static rmt_encoder_handle_t encoder;
- static const rmt_copy_encoder_config_t copy_encoder_config = {};
- static esp_err_t copy_encoder_ok = rmt_new_copy_encoder(
- ©_encoder_config, &encoder
- );
-
- constexpr rmt_symbol_word_t sym_0 = {
- .duration0 = 1,
- .level0 = 1,
- .duration1 = 3,
- .level1 = 0,
- };
-
- constexpr rmt_symbol_word_t sym_1 = {
- .duration0 = 2,
- .level0 = 1,
- .duration1 = 2,
- .level1 = 0,
- };
-
- constexpr rmt_symbol_word_t sym_reset = {
- .duration0 = 80,
- .level0 = 0,
- .duration1 = 80,
- .level1 = 0,
- };
-
- static inline rmt_symbol_word_t* encode_byte(rmt_symbol_word_t *sym, uint8_t x) {
- for (int i = 8; i > 0; --i) {
- *sym = (x & 0x80) ? sym_1 : sym_0;
- x <<= 1;
- ++sym;
- }
- return sym;
- }
-
-
- /*** *** ***
- static std::string termcolor(Color c) {
- return "\x1b[48;2;" +
- std::to_string((int)c.r) + ";" +
- std::to_string((int)c.g) + ";" +
- std::to_string((int)c.b) + "m";
- }
-
- static void show_terminal_LEDs(const Color *pixels, int length) {
- std::string line;
- for (int i = 0; i < length; i++) {
- line += termcolor(pixels[i]) + " ";
- }
- line += "\x1b[0m";
- ESP_LOGI(TAG, "%s", line.c_str());
- }
- *** *** ***/
-
- void RMT_LEDs::show() {
- static const rmt_transmit_config_t config = {
- .loop_count = 0,
- .flags = {
- .eot_level = 0,
- },
- };
-
- rmt_symbol_word_t *sym = rmt_block;
- Color *pixel = pixels;
- for (int i = length; i > 0; --i) {
- sym = encode_byte(sym, pixel->r);
- sym = encode_byte(sym, pixel->g);
- sym = encode_byte(sym, pixel->b);
- ++pixel;
- }
- *sym++ = sym_reset;
-
- //show_terminal_LEDs(pixels, length);
-
- esp_err_t err = rmt_tx_wait_all_done(channel, -1);
- if (err) ESP_LOGE(TAG, "Failed to wait for TX complete: %d", err);
-
- ESP_ERROR_CHECK(rmt_transmit(
- channel, encoder,
- //pixels, length * sizeof(*pixels),
- rmt_block, (length * 24 + 1) * sizeof(*rmt_block),
- &config
- ));
- }
|