Update NeoEsp32RmtMethod.h

This commit is contained in:
Michael Miller
2024-04-18 11:20:42 -07:00
parent 38b2f775c3
commit d385fc9bdc

View File

@@ -565,15 +565,17 @@ public:
typedef NeoNoSettings SettingsObject; typedef NeoNoSettings SettingsObject;
NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) : NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizeData(pixelCount * elementSize + settingsSize), _pin(pin),
_pin(pin) _sizeData(pixelCount* elementSize + settingsSize),
_pixelCount(pixelCount)
{ {
construct(); construct();
} }
NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) : NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) :
_sizeData(pixelCount* elementSize + settingsSize),
_pin(pin), _pin(pin),
_sizeData(pixelCount* elementSize + settingsSize),
_pixelCount(pixelCount),
_channel(channel) _channel(channel)
{ {
construct(); construct();
@@ -590,7 +592,6 @@ public:
gpio_matrix_out(_pin, SIG_GPIO_OUT_IDX, false, false); gpio_matrix_out(_pin, SIG_GPIO_OUT_IDX, false, false);
pinMode(_pin, INPUT); pinMode(_pin, INPUT);
free(_dataEditing);
free(_dataSending); free(_dataSending);
} }
@@ -623,67 +624,93 @@ public:
ESP_ERROR_CHECK(rmt_translator_init(_channel.RmtChannelNumber, T_SPEED::Translate)); ESP_ERROR_CHECK(rmt_translator_init(_channel.RmtChannelNumber, T_SPEED::Translate));
} }
void Update(bool maintainBufferConsistency) template <typename T_COLOR_OBJECT,
typename T_COLOR_FEATURE,
typename T_SHADER>
void Update(
T_COLOR_OBJECT* pixels,
size_t countPixels,
const typename T_COLOR_FEATURE::SettingsObject& featureSettings,
const T_SHADER& shader)
{ {
// wait for not actively sending data // wait for not actively sending data
// this will time out at 10 seconds, an arbitrarily long period of time // this will time out at 10 seconds, an arbitrarily long period of time
// and do nothing if this happens // and do nothing if this happens
if (ESP_OK == ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_wait_tx_done(_channel.RmtChannelNumber, 10000 / portTICK_PERIOD_MS))) if (ESP_OK == ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_wait_tx_done(_channel.RmtChannelNumber, 10000 / portTICK_PERIOD_MS)))
{ {
// now start the RMT transmit with the editing buffer before we swap // fill buffer
ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_write_sample(_channel.RmtChannelNumber, _dataEditing, _sizeData, false)); const size_t sendDataSize = T_COLOR_FEATURE::SettingsSize >= T_COLOR_FEATURE::PixelSize ? T_COLOR_FEATURE::SettingsSize : T_COLOR_FEATURE::PixelSize;
uint8_t sendData[sendDataSize];
uint8_t* data = _dataSending;
if (maintainBufferConsistency) // if there are settings at the front
if (T_COLOR_FEATURE::applyFrontSettings(sendData, sendDataSize, featureSettings))
{ {
// copy editing to sending, FillBuffer(sendData, T_COLOR_FEATURE::SettingsSize, &data);
// this maintains the contract that "colors present before will
// be the same after", otherwise GetPixelColor will be inconsistent
memcpy(_dataSending, _dataEditing, _sizeData);
} }
// swap so the user can modify without affecting the async operation // fill primary color data
std::swap(_dataSending, _dataEditing); T_COLOR_OBJECT* pixel = pixels;
const T_COLOR_OBJECT* pixelEnd = pixel + countPixels;
uint16_t stripCount = _pixelCount;
while (stripCount--)
{
typename T_COLOR_FEATURE::ColorObject color = shader.Apply(*pixel);
T_COLOR_FEATURE::applyPixelColor(sendData, sendDataSize, color);
FillBuffer(sendData, T_COLOR_FEATURE::PixelSize, &data);
pixel++;
if (pixel >= pixelEnd)
{
// restart at first
pixel = pixels;
}
}
// if there are settings at the back
if (T_COLOR_FEATURE::applyBackSettings(sendData, sendDataSize, featureSettings))
{
FillBuffer(sendData, T_COLOR_FEATURE::SettingsSize, &data);
}
// now start the RMT transmit with the editing buffer before we swap
ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_write_sample(_channel.RmtChannelNumber, _dataSending, _sizeData, false));
} }
} }
bool AlwaysUpdate()
{
// this method requires update to be called only if changes to buffer
return false;
}
uint8_t* getData() const
{
return _dataEditing;
};
size_t getDataSize() const
{
return _sizeData;
}
void applySettings([[maybe_unused]] const SettingsObject& settings) void applySettings([[maybe_unused]] const SettingsObject& settings)
{ {
} }
private: private:
const size_t _sizeData; // Size of '_data*' buffers
const uint8_t _pin; // output pin number const uint8_t _pin; // output pin number
const uint16_t _pixelCount; // count of pixels in the strip
const size_t _sizeData; // Size of '_data*' buffers
const T_CHANNEL _channel; // holds instance for multi channel support const T_CHANNEL _channel; // holds instance for multi channel support
// Holds data stream which include LED color values and other settings as needed // Holds data stream which include LED color values and other settings as needed
uint8_t* _dataEditing; // exposed for get and set
uint8_t* _dataSending; // used for async send using RMT uint8_t* _dataSending; // used for async send using RMT
void construct() void construct()
{ {
_dataEditing = static_cast<uint8_t*>(malloc(_sizeData));
// data cleared later in Begin()
_dataSending = static_cast<uint8_t*>(malloc(_sizeData)); _dataSending = static_cast<uint8_t*>(malloc(_sizeData));
// no need to initialize it, it gets overwritten on every send // no need to initialize it, it gets overwritten on every send
} }
void FillBuffer(const uint8_t* sendData, size_t sendDataSize, uint8_t** buffer)
{
const uint8_t* pEnd = sendData + sendDataSize;
while (sendData < pEnd)
{
*(*buffer)++ = *sendData++;
}
}
}; };
// normal // normal