#include "drivers/Esp32DriverRGBW.h" #include #include // Timing constants static constexpr uint16_t DIVIDER = 4; static constexpr double RMT_DURATION_NS = 12.5; // Minimum time of a single RMT duration based on clock ns static constexpr uint32_t T0H = 300; static constexpr uint32_t T0L = 900; static constexpr uint32_t T1H = 600; static constexpr uint32_t T1L = 600; static constexpr uint32_t TRS = 80000; static constexpr rmt_item32_t bit0Data = {uint32_t(T0H / (RMT_DURATION_NS * DIVIDER)), 1, uint32_t(T0L / (RMT_DURATION_NS * DIVIDER)), 0}; static constexpr rmt_item32_t bit1Data = {uint32_t(T1H / (RMT_DURATION_NS * DIVIDER)), 1, uint32_t(T1L / (RMT_DURATION_NS * DIVIDER)), 0}; // Function registered at the RMT driver that converts regular uint8_t values containing r,g,b,w values // to rmt_item32_t for each bit. (8 bit -> 32 * 8 bit) static void IRAM_ATTR uint8ToRmtAdaptor(const void *src, rmt_item32_t *dest, size_t srcSize, size_t wantedNum, size_t *translatedSize, size_t *itemNum) { if (src == NULL || dest == NULL) { *translatedSize = 0; *itemNum = 0; return; } size_t size = 0; size_t num = 0; uint8_t *psrc = (uint8_t *)src; rmt_item32_t *pdest = dest; while (size < srcSize && num < wantedNum) { for (int i = 0; i < 8; i++) { // MSB first const bool isBitSet = *psrc & (1 << (7 - i)); pdest->val = isBitSet ? bit1Data.val : bit0Data.val; num++; pdest++; } size++; psrc++; } *translatedSize = size; *itemNum = num; } void Esp32DriverRGBW::begin(int gpio, int rmtChannel) { rmtChannel_ = rmtChannel; transmitting_ = false; rmt_config_t rmt_tx; rmt_tx.channel = static_cast(rmtChannel); rmt_tx.gpio_num = static_cast(gpio); rmt_tx.rmt_mode = RMT_MODE_TX; rmt_tx.mem_block_num = 1; rmt_tx.clk_div = DIVIDER; rmt_tx.tx_config.loop_en = false; rmt_tx.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW; rmt_tx.tx_config.carrier_en = false; rmt_tx.tx_config.idle_level = RMT_IDLE_LEVEL_LOW; rmt_tx.tx_config.idle_output_en = true; ESP_ERROR_CHECK(rmt_config(&rmt_tx)); ESP_ERROR_CHECK(rmt_driver_install(rmt_tx.channel, 0, 0)); rmt_translator_init((rmt_channel_t)rmtChannel, uint8ToRmtAdaptor); } void Esp32DriverRGBW::end() { ESP_ERROR_CHECK(rmt_driver_uninstall((rmt_channel_t)rmtChannel_)); } void Esp32DriverRGBW::writeSync(const uint32_t *rgbwData, int numLeds) { waitForTransmissionToFinish(); auto data = reinterpret_cast(rgbwData); ESP_ERROR_CHECK(rmt_write_sample((rmt_channel_t)rmtChannel_, data, numLeds * 4, true)); } void Esp32DriverRGBW::writeAsync(const uint32_t *rgbwData, int numLeds) { waitForTransmissionToFinish(); auto data = reinterpret_cast(rgbwData); ESP_ERROR_CHECK(rmt_write_sample((rmt_channel_t)rmtChannel_, data, numLeds * 4, false)); transmitting_ = true; } bool Esp32DriverRGBW::waitForTransmissionToFinish(int waitMs) { if (!transmitting_) return true; auto ret = rmt_wait_tx_done((rmt_channel_t)rmtChannel_, waitMs / portTICK_PERIOD_MS); if (ret == ESP_OK) { transmitting_ = false; return true; } else return false; }