forked from Makuna/NeoPixelBus
Update NeoEsp32RmtMethod.h
This commit is contained in:
@@ -565,15 +565,17 @@ public:
|
||||
typedef NeoNoSettings SettingsObject;
|
||||
|
||||
NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
||||
_pin(pin),
|
||||
_sizeData(pixelCount* elementSize + settingsSize),
|
||||
_pin(pin)
|
||||
_pixelCount(pixelCount)
|
||||
{
|
||||
construct();
|
||||
}
|
||||
|
||||
NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) :
|
||||
_sizeData(pixelCount* elementSize + settingsSize),
|
||||
_pin(pin),
|
||||
_sizeData(pixelCount* elementSize + settingsSize),
|
||||
_pixelCount(pixelCount),
|
||||
_channel(channel)
|
||||
{
|
||||
construct();
|
||||
@@ -590,7 +592,6 @@ public:
|
||||
gpio_matrix_out(_pin, SIG_GPIO_OUT_IDX, false, false);
|
||||
pinMode(_pin, INPUT);
|
||||
|
||||
free(_dataEditing);
|
||||
free(_dataSending);
|
||||
}
|
||||
|
||||
@@ -623,43 +624,61 @@ public:
|
||||
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
|
||||
// this will time out at 10 seconds, an arbitrarily long period of time
|
||||
// and do nothing if this happens
|
||||
if (ESP_OK == ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_wait_tx_done(_channel.RmtChannelNumber, 10000 / portTICK_PERIOD_MS)))
|
||||
{
|
||||
// fill buffer
|
||||
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 there are settings at the front
|
||||
if (T_COLOR_FEATURE::applyFrontSettings(sendData, sendDataSize, featureSettings))
|
||||
{
|
||||
FillBuffer(sendData, T_COLOR_FEATURE::SettingsSize, &data);
|
||||
}
|
||||
|
||||
// fill primary color data
|
||||
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, _dataEditing, _sizeData, false));
|
||||
|
||||
if (maintainBufferConsistency)
|
||||
{
|
||||
// copy editing to sending,
|
||||
// this maintains the contract that "colors present before will
|
||||
// be the same after", otherwise GetPixelColor will be inconsistent
|
||||
memcpy(_dataSending, _dataEditing, _sizeData);
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_write_sample(_channel.RmtChannelNumber, _dataSending, _sizeData, false));
|
||||
}
|
||||
|
||||
// swap so the user can modify without affecting the async operation
|
||||
std::swap(_dataSending, _dataEditing);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -667,23 +686,31 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const size_t _sizeData; // Size of '_data*' buffers
|
||||
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
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
void construct()
|
||||
{
|
||||
_dataEditing = static_cast<uint8_t*>(malloc(_sizeData));
|
||||
// data cleared later in Begin()
|
||||
|
||||
_dataSending = static_cast<uint8_t*>(malloc(_sizeData));
|
||||
// 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
|
||||
|
Reference in New Issue
Block a user