From 80f98be0b25f26f696a28ea4683f93680aaf6c2d Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sat, 20 Apr 2024 22:47:37 -0700 Subject: [PATCH] esp8266 compiles --- src/internal/methods/NeoEsp32RmtMethod.h | 10 +- src/internal/methods/NeoEsp8266DmaMethod.h | 211 ++++++++---------- .../methods/NeoEsp8266I2sMethodCore.h | 2 +- 3 files changed, 98 insertions(+), 125 deletions(-) diff --git a/src/internal/methods/NeoEsp32RmtMethod.h b/src/internal/methods/NeoEsp32RmtMethod.h index 67cadbf..7099ddc 100644 --- a/src/internal/methods/NeoEsp32RmtMethod.h +++ b/src/internal/methods/NeoEsp32RmtMethod.h @@ -566,7 +566,7 @@ public: NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) : _pin(pin), - _sizeData(pixelCount* elementSize + settingsSize), + _sizeDataSending(pixelCount* elementSize + settingsSize), _pixelCount(pixelCount) { construct(); @@ -574,7 +574,7 @@ public: NeoEsp32RmtMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) : _pin(pin), - _sizeData(pixelCount* elementSize + settingsSize), + _sizeDataSending(pixelCount* elementSize + settingsSize), _pixelCount(pixelCount), _channel(channel) { @@ -677,7 +677,7 @@ public: } // 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)); + ESP_ERROR_CHECK_WITHOUT_ABORT(rmt_write_sample(_channel.RmtChannelNumber, _dataSending, _sizeDataSending, false)); } } @@ -688,7 +688,7 @@ public: private: 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 size_t _sizeDataSending; // Size of '_data*' buffers const T_CHANNEL _channel; // holds instance for multi channel support @@ -698,7 +698,7 @@ private: void construct() { - _dataSending = static_cast(malloc(_sizeData)); + _dataSending = static_cast(malloc(_sizeDataSending)); // no need to initialize it, it gets overwritten on every send } diff --git a/src/internal/methods/NeoEsp8266DmaMethod.h b/src/internal/methods/NeoEsp8266DmaMethod.h index f1ba009..e893624 100644 --- a/src/internal/methods/NeoEsp8266DmaMethod.h +++ b/src/internal/methods/NeoEsp8266DmaMethod.h @@ -141,7 +141,6 @@ public: const static uint32_t I2sBaseClockDivisor = 10; // 0-63 const static uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element const static uint32_t ResetTimeUs = 12470; - const static uint32_t InterPixelTimeUs = 20; }; class NeoEsp8266DmaInvertedSpeed800KbpsBase : public NeoEsp8266DmaInvertedSpeedBase @@ -216,80 +215,17 @@ public: const static uint32_t I2sBaseClockDivisor = 10; // 0-63 const static uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed const static uint32_t ResetTimeUs = 12470; - const static uint32_t InterPixelTimeUs = 20; }; -template class NeoEsp8266DmaEncode : public T_SPEED -{ -public: - static size_t SpacingPixelSize(size_t sizePixel) - { - return sizePixel; - } - - static void FillBuffers(uint8_t* i2sBuffer, - const uint8_t* data, - size_t sizeData, - [[maybe_unused]] size_t sizePixel) - { - uint16_t* pDma = (uint16_t*)i2sBuffer; - const uint8_t* pEnd = data + sizeData; - for (const uint8_t* pData = data; pData < pEnd; pData++) - { - *(pDma++) = T_SPEED::Convert(((*pData) & 0x0f)); - *(pDma++) = T_SPEED::Convert(((*pData) >> 4) & 0x0f); - } - } -}; - -template class NeoEsp8266DmaPixelSpacingEncode : public T_SPEED -{ -public: - static size_t SpacingPixelSize(size_t sizePixel) - { - return sizePixel + T_SPEED::InterPixelTimeUs / T_SPEED::ByteSendTimeUs; - } - - static void FillBuffers(uint8_t* i2sBuffer, - const uint8_t* data, - size_t sizeData, - size_t sizePixel) - { - uint16_t* pDma = (uint16_t*)i2sBuffer; - const uint8_t* pEnd = data + sizeData; - uint8_t element = 0; - for (const uint8_t* pData = data; pData < pEnd; pData++) - { - *(pDma++) = T_SPEED::Convert(((*pData) & 0x0f)); - *(pDma++) = T_SPEED::Convert(((*pData) >> 4) & 0x0f); - - element++; - if (element == sizePixel) - { - element = 0; - - for (uint8_t padding = 0; - padding < (T_SPEED::InterPixelTimeUs / T_SPEED::ByteSendTimeUs); - padding++) - { - *(pDma++) = T_SPEED::IdleLevel * 0xffff; - *(pDma++) = T_SPEED::IdleLevel * 0xffff; - } - } - } - } -}; - -template class NeoEsp8266DmaMethodBase : NeoEsp8266I2sMethodCore +template class NeoEsp8266DmaMethodBase : NeoEsp8266I2sMethodCore { public: typedef NeoNoSettings SettingsObject; NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) : - _sizePixel(elementSize), - _sizeData(pixelCount * elementSize + settingsSize) + _pixelCount(pixelCount) { - size_t dmaPixelSize = DmaBytesPerPixelBytes * T_ENCODER::SpacingPixelSize(_sizePixel); + size_t dmaPixelSize = DmaBytesPerPixelBytes * elementSize; size_t dmaSettingsSize = DmaBytesPerPixelBytes * settingsSize; size_t i2sBufferSize = pixelCount * dmaPixelSize + dmaSettingsSize; @@ -297,15 +233,12 @@ public: i2sBufferSize = NeoUtil::RoundUp(i2sBufferSize, c_I2sByteBoundarySize); // calculate a buffer size that takes reset amount of time - size_t i2sResetSize = T_ENCODER::ResetTimeUs * DmaBytesPerPixelBytes / T_ENCODER::ByteSendTimeUs; + size_t i2sResetSize = T_SPEED::ResetTimeUs * DmaBytesPerPixelBytes / T_SPEED::ByteSendTimeUs; // size is rounded up to nearest c_I2sByteBoundarySize i2sResetSize = NeoUtil::RoundUp(i2sResetSize, c_I2sByteBoundarySize); size_t is2BufMaxBlockSize = (c_maxDmaBlockSize / dmaPixelSize) * dmaPixelSize; - _data = static_cast(malloc(_sizeData)); - // data cleared later in Begin() - - AllocateI2s(i2sBufferSize, i2sResetSize, is2BufMaxBlockSize, T_ENCODER::IdleLevel); + AllocateI2s(i2sBufferSize, i2sResetSize, is2BufMaxBlockSize, T_SPEED::IdleLevel); } NeoEsp8266DmaMethodBase([[maybe_unused]] uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) : @@ -323,16 +256,14 @@ public: } // wait for any pending sends to complete - // due to internal i2s caching/send delays, this can more that once the data size + // due to internal i2s caching/send delays, this can more than once the data size uint32_t time = micros(); - while ((micros() - time) < ((getPixelTime() + T_ENCODER::ResetTimeUs) * waits)) + while ((micros() - time) < ((getPixelTime() + T_SPEED::ResetTimeUs) * waits)) { yield(); } FreeI2s(); - - free(_data); } bool IsReadyToUpdate() const @@ -342,37 +273,66 @@ public: void Initialize() { - InitializeI2s(T_ENCODER::I2sClockDivisor, T_ENCODER::I2sBaseClockDivisor); + InitializeI2s(T_SPEED::I2sClockDivisor, T_SPEED::I2sBaseClockDivisor); } - void IRAM_ATTR Update(bool) + template + 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 while (!IsReadyToUpdate()) { yield(); } - T_ENCODER::FillBuffers(_i2sBuffer, _data, _sizeData, _sizePixel); + + 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* dma = _i2sBuffer; + + // if there are settings at the front + // + if (T_COLOR_FEATURE::applyFrontSettings(sendData, sendDataSize, featureSettings)) + { + FillBuffer(sendData, T_COLOR_FEATURE::SettingsSize, &dma); + } + + // 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, &dma); + + 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, &dma); + } WriteI2s(); } - bool AlwaysUpdate() - { - // this method requires update to be called only if changes to buffer - return false; - } - - uint8_t* getData() const - { - return _data; - }; - - size_t getDataSize() const - { - return _sizeData; - } - void applySettings([[maybe_unused]] const SettingsObject& settings) { } @@ -380,46 +340,59 @@ public: private: // due to encoding required for i2s, we need 4 bytes to encode the pulses static const uint16_t DmaBytesPerPixelBytes = 4; - - const size_t _sizePixel; // size of a pixel in _data - const size_t _sizeData; // Size of '_data' buffer - uint8_t* _data; // Holds LED color values + const uint16_t _pixelCount; // count of pixels in the strip uint32_t getPixelTime() const { - return (T_ENCODER::ByteSendTimeUs * GetSendSize() / DmaBytesPerPixelBytes); + return (T_SPEED::ByteSendTimeUs * GetSendSize() / DmaBytesPerPixelBytes); }; + void FillBuffer( + const uint8_t* sendData, + size_t sendDataSize, + uint8_t** i2sBuffer) + { + uint16_t* pDma = reinterpret_cast(*i2sBuffer); + const uint8_t* pEnd = sendData + sendDataSize; + + while (sendData < pEnd) + { + *(pDma++) = T_SPEED::Convert(((*sendData) & 0x0f)); + *(pDma++) = T_SPEED::Convert(((*sendData) >> 4) & 0x0f); + sendData++; + } + + *i2sBuffer = reinterpret_cast(pDma); + } }; // normal -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaWs2812xMethod; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaWs2805Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaWs2812xMethod; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaWs2805Method; typedef NeoEsp8266DmaWs2805Method NeoEsp8266DmaWs2814Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaSk6812Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaTm1814Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaTm1829Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaSk6812Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaTm1814Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaTm1829Method; typedef NeoEsp8266DmaTm1814Method NeoEsp8266DmaTm1914Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266Dma800KbpsMethod; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266Dma400KbpsMethod; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaApa106Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaIntertekMethod; - +typedef NeoEsp8266DmaMethodBase NeoEsp8266Dma800KbpsMethod; +typedef NeoEsp8266DmaMethodBase NeoEsp8266Dma400KbpsMethod; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaApa106Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaIntertekMethod; // inverted -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInvertedWs2812xMethod; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInvertedWs2805Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInvertedWs2812xMethod; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInvertedWs2805Method; typedef NeoEsp8266DmaInvertedWs2805Method NeoEsp8266DmaInvertedWs2814Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInvertedSk6812Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInvertedTm1814Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInvertedTm1829Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInvertedSk6812Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInvertedTm1814Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInvertedTm1829Method; typedef NeoEsp8266DmaInvertedTm1814Method NeoEsp8266DmaInvertedTm1914Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInverted800KbpsMethod; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInverted400KbpsMethod; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInvertedApa106Method; -typedef NeoEsp8266DmaMethodBase> NeoEsp8266DmaInvertedIntertekMethod; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInverted800KbpsMethod; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInverted400KbpsMethod; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInvertedApa106Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaInvertedIntertekMethod; // Dma method is the default method for Esp8266 typedef NeoEsp8266DmaWs2812xMethod NeoWs2813Method; diff --git a/src/internal/methods/NeoEsp8266I2sMethodCore.h b/src/internal/methods/NeoEsp8266I2sMethodCore.h index db67126..0464408 100644 --- a/src/internal/methods/NeoEsp8266I2sMethodCore.h +++ b/src/internal/methods/NeoEsp8266I2sMethodCore.h @@ -326,7 +326,7 @@ protected: I2SC |= I2STXS; // Start transmission } - void WriteI2s() + void IRAM_ATTR WriteI2s() { // first two items are the state blocks slc_queue_item* itemLoopBreaker = &(_i2sBufDesc[1]);