musicmouse/espmusicmouse/lib/ledtl/Esp32DriverRGBW.cpp

109 lines
3.2 KiB
C++
Raw Normal View History

2021-11-19 17:22:09 +01:00
#ifndef PLATFORM_NATIVE
2021-11-16 22:04:22 +01:00
#include "drivers/Esp32DriverRGBW.h"
#include <driver/gpio.h>
#include <driver/rmt.h>
// 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<rmt_channel_t>(rmtChannel);
rmt_tx.gpio_num = static_cast<gpio_num_t>(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<const uint8_t *>(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<const uint8_t *>(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;
}
2021-11-19 17:22:09 +01:00
#endif