ESP32 Native version of Blinky, featureful controller code for WS2811/WS2812/NeoPixels
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

105 行
2.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. #define WS2811_PULSE_WIDTH_NS 1250
  7. #define RMT_TX_CHANNEL RMT_CHANNEL_0
  8. static int bit_ticks;
  9. static void IRAM_ATTR ws2811_rmt_adapter(
  10. const void *src, rmt_item32_t *dest, size_t src_size,
  11. size_t wanted_num, size_t *translated_size, size_t *item_num
  12. ) {
  13. if (src == NULL || dest == NULL) {
  14. *translated_size = 0;
  15. *item_num = 0;
  16. return;
  17. }
  18. const uint32_t short_ticks = bit_ticks / 3;
  19. const uint32_t long_ticks = bit_ticks - short_ticks;
  20. const rmt_item32_t bit0 = {{{ short_ticks, 1, long_ticks, 0 }}}; // Logical 0
  21. const rmt_item32_t bit1 = {{{ long_ticks, 1, short_ticks, 0 }}}; // Logical 1
  22. size_t size = 0;
  23. size_t num = 0;
  24. uint8_t *psrc = (uint8_t *)src;
  25. rmt_item32_t *pdest = dest;
  26. while (size < src_size && num < wanted_num) {
  27. for (int i = 0; i < 8; i++) {
  28. // MSB first
  29. if (*psrc & (1 << (7 - i))) {
  30. pdest->val = bit1.val;
  31. } else {
  32. pdest->val = bit0.val;
  33. }
  34. num++;
  35. pdest++;
  36. }
  37. size++;
  38. psrc++;
  39. }
  40. *translated_size = size;
  41. *item_num = num;
  42. }
  43. RMT_LEDs::RMT_LEDs(gpio_num_t _gpio, int length) :
  44. LEDStrip(length), gpio(_gpio), channel(RMT_CHANNEL_MAX) {
  45. rmt_config_t config = RMT_DEFAULT_CONFIG_TX(gpio, RMT_TX_CHANNEL);
  46. // set counter clock to 40MHz
  47. config.clk_div = 2;
  48. ESP_ERROR_CHECK(rmt_config(&config));
  49. channel = config.channel;
  50. ESP_ERROR_CHECK(rmt_driver_install(channel, 0, 0));
  51. uint32_t counter_clk_hz = 0;
  52. int err = rmt_get_counter_clock(channel, &counter_clk_hz);
  53. if (err != ESP_OK) {
  54. ESP_LOGE(TAG, "Failed to read RMT counter: %d", err);
  55. return;
  56. }
  57. rmt_translator_init(channel, ws2811_rmt_adapter);
  58. // ns -> ticks
  59. bit_ticks = ((uint64_t)counter_clk_hz * WS2811_PULSE_WIDTH_NS) / 1e9;
  60. ESP_LOGI(TAG, "Each bit is %d RMT ticks", bit_ticks);
  61. configure(length);
  62. }
  63. RMT_LEDs::~RMT_LEDs() {
  64. ESP_ERROR_CHECK(rmt_driver_uninstall(channel));
  65. }
  66. void RMT_LEDs::configure(int n_leds) {
  67. // We don't own the RMT buffer
  68. }
  69. void RMT_LEDs::show() {
  70. esp_err_t err;
  71. err = rmt_wait_tx_done(channel, 0);
  72. if (err != ESP_OK) {
  73. ESP_LOGE(TAG, "RMT TX incomplete: %d", err);
  74. return;
  75. }
  76. err = rmt_write_sample(channel, (uint8_t*)pixels, length * 3, false);
  77. if (err != ESP_OK) {
  78. ESP_LOGE(TAG, "Failed to write sample to RMT: %d", err);
  79. }
  80. }