ESP32 Native version of Blinky, featureful controller code for WS2811/WS2812/NeoPixels
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

219 líneas
5.6KB

  1. static const char *TAG = "rmt_leds";
  2. #include <esp_log.h>
  3. #include <freertos/FreeRTOS.h>
  4. #include <freertos/task.h>
  5. #include "rmt_leds.hpp"
  6. RMT_LEDs::RMT_LEDs(int _gpio, int length) :
  7. LEDStrip(length), gpio(_gpio), channel(NULL), rmt_block(NULL) {
  8. rmt_tx_channel_config_t config = {
  9. .gpio_num = gpio,
  10. .clk_src = RMT_CLK_SRC_DEFAULT,
  11. .resolution_hz = 3200000, // (1.25 us / 4) => 3.2 MHz
  12. .mem_block_symbols = 64, // memory block size, 64 * 4 = 256Bytes
  13. .trans_queue_depth = 1, // We don't really need background transfers
  14. .flags = {
  15. .invert_out = false,
  16. .with_dma = false, // TODO: Why no DMA??
  17. .io_loop_back = false,
  18. },
  19. };
  20. ESP_ERROR_CHECK(rmt_new_tx_channel(&config, &channel));
  21. ESP_ERROR_CHECK(rmt_enable(channel));
  22. configure(length);
  23. }
  24. void RMT_LEDs::configure(int n_leds) {
  25. if (rmt_block) {
  26. delete[] rmt_block;
  27. rmt_block = NULL;
  28. }
  29. if (n_leds <= 0) return;
  30. rmt_block = new rmt_symbol_word_t[n_leds * 24 + 1];
  31. }
  32. /*
  33. static rmt_encoder_handle_t byte_enc;
  34. static const rmt_bytes_encoder_config_t byte_enc_config = {
  35. .bit0 = {
  36. .duration0 = 1,
  37. .level0 = 1,
  38. .duration1 = 3,
  39. .level1 = 0,
  40. },
  41. .bit1 = {
  42. .duration0 = 2,
  43. .level0 = 1,
  44. .duration1 = 2,
  45. .level1 = 0,
  46. },
  47. .flags = {
  48. .msb_first = 1,
  49. },
  50. };
  51. static esp_err_t bytes_enc_ok = rmt_new_bytes_encoder(&byte_enc_config, &byte_enc);
  52. static rmt_encoder_handle_t rst_enc;
  53. static const rmt_copy_encoder_config_t rst_enc_config = {};
  54. static esp_err_t rst_enc_ok = rmt_new_copy_encoder(&rst_enc_config, &rst_enc);
  55. static const rmt_symbol_word_t rst_symbol = {
  56. .duration0 = 80,
  57. .level0 = 0,
  58. .duration1 = 80,
  59. .level1 = 0,
  60. };
  61. struct strip_encoder {
  62. rmt_encoder_t base;
  63. int state;
  64. };
  65. static size_t encode_strip(
  66. rmt_encoder_t *_encoder, rmt_channel_handle_t channel,
  67. const void *data, size_t n_bytes, rmt_encode_state_t *ret_state
  68. ) {
  69. strip_encoder *encoder = __containerof(_encoder, strip_encoder, base);
  70. size_t n_encoded = 0;
  71. rmt_encode_state_t substate = 0;
  72. rmt_encode_state_t state = 0;
  73. switch(encoder->state) {
  74. case 0:
  75. n_encoded += byte_enc.encode(&byte_enc, channel, data, n_bytes, &substate);
  76. if (substate & RMT_ENCODING_COMPLETE) {
  77. encoder->state = 1;
  78. break;
  79. }
  80. case 1:
  81. n_encoded += rst_enc.encode(
  82. &rst_enc, channel, &rst_symbol, sizeof(rst_symbol), &substate);
  83. if (substate & RMT_ENCODING_COMPLETE) {
  84. encoder->state = 0;
  85. state |= RMT_ENCODING_COMPLETE;
  86. }
  87. if (substate & RMT_ENCODING_MEM_FULL) {
  88. state |= RMT_ENCODING_MEM_FULL;
  89. }
  90. }
  91. *ret_state = state;
  92. return n_encoded;
  93. }
  94. static esp_err_t reset_strip_encoder(rmt_encoder_t *encoder) {
  95. strip_encoder *encoder = __containerof(encoder, strip_encoder, base);
  96. rmt_encoder_reset(byte_enc);
  97. rmt_encoder_reset(rst_enc);
  98. encoder->state = 0;
  99. return ESP_OK;
  100. }
  101. static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder) {
  102. strip_encoder *encoder = __containerof(encoder, strip_encoder, base);
  103. delete encoder;
  104. return ESP_OK;
  105. }
  106. static rmt_encoder_t* make_strip_encoder() {
  107. enc = new strip_encoder {
  108. .base = {
  109. .encode = encode_strip,
  110. .reset = reset_strip_encoder,
  111. .del = del_strip_encoder,
  112. },
  113. .state = 0
  114. }
  115. }
  116. */
  117. static rmt_encoder_handle_t encoder;
  118. static const rmt_copy_encoder_config_t copy_encoder_config = {};
  119. static esp_err_t copy_encoder_ok = rmt_new_copy_encoder(
  120. &copy_encoder_config, &encoder
  121. );
  122. constexpr rmt_symbol_word_t sym_0 = {
  123. .duration0 = 1,
  124. .level0 = 1,
  125. .duration1 = 3,
  126. .level1 = 0,
  127. };
  128. constexpr rmt_symbol_word_t sym_1 = {
  129. .duration0 = 2,
  130. .level0 = 1,
  131. .duration1 = 2,
  132. .level1 = 0,
  133. };
  134. constexpr rmt_symbol_word_t sym_reset = {
  135. .duration0 = 80,
  136. .level0 = 0,
  137. .duration1 = 80,
  138. .level1 = 0,
  139. };
  140. static inline rmt_symbol_word_t* encode_byte(rmt_symbol_word_t *sym, uint8_t x) {
  141. for (int i = 8; i > 0; --i) {
  142. *sym = (x & 0x80) ? sym_1 : sym_0;
  143. x <<= 1;
  144. ++sym;
  145. }
  146. return sym;
  147. }
  148. /*** *** ***
  149. static std::string termcolor(Color c) {
  150. return "\x1b[48;2;" +
  151. std::to_string((int)c.r) + ";" +
  152. std::to_string((int)c.g) + ";" +
  153. std::to_string((int)c.b) + "m";
  154. }
  155. static void show_terminal_LEDs(const Color *pixels, int length) {
  156. std::string line;
  157. for (int i = 0; i < length; i++) {
  158. line += termcolor(pixels[i]) + " ";
  159. }
  160. line += "\x1b[0m";
  161. ESP_LOGI(TAG, "%s", line.c_str());
  162. }
  163. *** *** ***/
  164. void RMT_LEDs::show() {
  165. static const rmt_transmit_config_t config = {
  166. .loop_count = 0,
  167. .flags = {
  168. .eot_level = 0,
  169. },
  170. };
  171. rmt_symbol_word_t *sym = rmt_block;
  172. Color *pixel = pixels;
  173. for (int i = length; i > 0; --i) {
  174. sym = encode_byte(sym, pixel->r);
  175. sym = encode_byte(sym, pixel->g);
  176. sym = encode_byte(sym, pixel->b);
  177. ++pixel;
  178. }
  179. *sym++ = sym_reset;
  180. //show_terminal_LEDs(pixels, length);
  181. esp_err_t err = rmt_tx_wait_all_done(channel, -1);
  182. if (err) ESP_LOGE(TAG, "Failed to wait for TX complete: %d", err);
  183. ESP_ERROR_CHECK(rmt_transmit(
  184. channel, encoder,
  185. //pixels, length * sizeof(*pixels),
  186. rmt_block, (length * 24 + 1) * sizeof(*rmt_block),
  187. &config
  188. ));
  189. }