From 8062b3a7ceb30e0e7ab9a9b714b280fd06f5801f Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Mon, 18 Mar 2024 17:20:10 -0700 Subject: [PATCH] Tlc59711 tune (#785) * a little duplication of constants * Update Tlc59711GenericMethod.h remove temp buffer and just send words reversed add custom default speed that works without flicker --- src/internal/features/Tlc59711RgbFeatures.h | 37 ++++------- src/internal/methods/Tlc59711GenericMethod.h | 69 ++++++++++---------- 2 files changed, 47 insertions(+), 59 deletions(-) diff --git a/src/internal/features/Tlc59711RgbFeatures.h b/src/internal/features/Tlc59711RgbFeatures.h index 0a0b80c..506aaf1 100644 --- a/src/internal/features/Tlc59711RgbFeatures.h +++ b/src/internal/features/Tlc59711RgbFeatures.h @@ -84,6 +84,8 @@ public: { } static constexpr uint8_t MaxBrightness = 127; + static constexpr size_t c_dataPerChipSize = 24; + static constexpr size_t c_settingsPerChipSize = 4; const uint8_t RedGroupBrightness; const uint8_t GreenGroupBrightness; @@ -96,27 +98,13 @@ class Tlc59711ElementsSettings public: typedef Tlc69711Settings SettingsObject; - static constexpr size_t SettingsPerChipSize = 4; - static constexpr size_t SettingsSize = 2 * SettingsPerChipSize; - static void Encode(uint8_t* encoded, const SettingsObject& settings, bool emiAlternate = false) + static constexpr size_t SettingsSize = Tlc69711Settings::c_settingsPerChipSize; + + static void Encode(uint8_t* encoded, const SettingsObject& settings) { uint8_t control = settings.Control; - if (emiAlternate) - { - if (control & Tlc69711_Control_EmiRisingEdge) - { - // clear the flag - control &= ~Tlc69711_Control_EmiRisingEdge; - } - else - { - // set the flag - control |= Tlc69711_Control_EmiRisingEdge; - } - } - *encoded++ = 0b10010100 | (control & Tlc69711_Control_Mask1); *encoded++ = (control & Tlc69711_Control_Mask2) | settings.BlueGroupBrightness >> 2; *encoded++ = settings.BlueGroupBrightness << 6 | settings.GreenGroupBrightness >> 1; @@ -137,7 +125,7 @@ public: // but the Tlc59711Method will store in a member variable // BUT methods don't know anything about the feature settings - // Thought C: (Winner winner, chicken dinner) + // Thought C: // Leave all current work alone // Set SettingsSize to 2 times SettingsPerChipSize // Consider it at the front of the data buffer @@ -145,13 +133,14 @@ public: // have our Tlc59711Method know about the two and send the // already interleaving settings and data + // Thought D: (current) + // Leave all current work alone + // Use one settings at the front of data + // have the method know details how to duplicate it if needed for emi + // as it already neeeds to interleaving settings per chip with data + // settings are at the front of the data stream - uint8_t* pSet = pData; - - // encode two, for alternating use for EMI reduction - Encode(pSet, settings, false); - pSet += SettingsPerChipSize; - Encode(pSet, settings, true); + Encode(pData, settings); } static uint8_t* pixels([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData) diff --git a/src/internal/methods/Tlc59711GenericMethod.h b/src/internal/methods/Tlc59711GenericMethod.h index fafb7da..de2477a 100644 --- a/src/internal/methods/Tlc59711GenericMethod.h +++ b/src/internal/methods/Tlc59711GenericMethod.h @@ -34,6 +34,19 @@ License along with NeoPixel. If not, see #include "TwoWireDebugImple.h" #endif +// this custom faster speed works while 3Mhz doesn't +// by works, meaning no flicker between chips +// so it used as the default when speed isn't specified in the method +class SpiSpeed3600Khz +{ +public: + typedef NeoNoSettings SettingsObject; + SpiSpeed3600Khz() {}; + + static void applySettings([[maybe_unused]] const SettingsObject& settings) {} + + static constexpr uint32_t Clock = 3600000L; +}; template class Tlc59711MethodBase @@ -46,8 +59,7 @@ public: uint16_t pixelCount, size_t elementSize, size_t settingsSize) : - _sizeData(NeoUtil::RoundUp(pixelCount * elementSize, c_dataPerChipSize) + settingsSize), - _sizeSettings(settingsSize), + _sizeData(NeoUtil::RoundUp(pixelCount * elementSize, Tlc69711Settings::c_dataPerChipSize) + settingsSize), _wire(pinClock, pinData) { _data = static_cast(malloc(_sizeData)); @@ -104,43 +116,33 @@ public: #endif } - const size_t sizeSetting = (_sizeSettings / 2); // we have two variants - const uint8_t* pSettingsA = _data; - const uint8_t* pSettingsB = _data + sizeSetting; - const uint8_t* pSettings = pSettingsA; + const uint8_t* pSettings = _data; // settings at front - uint8_t reversedData[c_dataPerChipSize]; + // note pSrc is pre-decremented before first use uint16_t* pSrc = reinterpret_cast(_data + _sizeData); - uint16_t* pSrcEnd = reinterpret_cast(_data + _sizeSettings); + uint16_t* pSrcEnd = reinterpret_cast(_data + Tlc69711Settings::c_settingsPerChipSize); _wire.beginTransaction(); while (pSrc > pSrcEnd) { - // data needs to be in reverse order when sent - // copy it in reverse order to temp buffer reversedData - // but it is also 16 bit that retains order - uint16_t* pDest = reinterpret_cast(reversedData); - uint16_t* pDestEnd = reinterpret_cast(reversedData + c_dataPerChipSize); - while (pDest < pDestEnd) - { - *pDest++ = *(--pSrc); - } - // settings - _wire.transmitBytes(pSettings, sizeSetting); + _wire.transmitBytes(pSettings, Tlc69711Settings::c_settingsPerChipSize); - // send this chips "fixed order" data - _wire.transmitBytes(reversedData, c_dataPerChipSize); + // data needs to be in reverse order when sent + // but it is also 16 bit that retains order + // (don't go changing endian) + uint16_t dest; + uint16_t* pSrcChipEnd = pSrc - (Tlc69711Settings::c_dataPerChipSize / 2); + + while (pSrc > pSrcChipEnd) + { + // note pre-decrement on pSrc + dest = *(--pSrc); - // toggle settings varient for next chip - if (pSettings == pSettingsA) - { - pSettings = pSettingsB; - } - else - { - pSettings = pSettingsA; + // send this chips "fixed order" data + _wire.transmitByte(dest >> 8); + _wire.transmitByte(dest); } } @@ -171,10 +173,7 @@ public: } private: - static constexpr size_t c_dataPerChipSize = 24; - const size_t _sizeData; // Size of '_data' buffer below - const size_t _sizeSettings; T_TWOWIRE _wire; uint8_t* _data; // Holds Settings and LED color values @@ -194,7 +193,7 @@ typedef Tlc59711MethodBase> Tlc59711Spi1MhzMethod; typedef Tlc59711MethodBase> Tlc59711Spi500KhzMethod; typedef Tlc59711MethodBase> Tlc59711SpiHzMethod; -typedef Tlc59711Spi2MhzMethod Tlc59711SpiMethod; +typedef Tlc59711MethodBase> Tlc59711SpiMethod; #endif #if defined(ARDUINO_ARCH_ESP32) @@ -208,7 +207,7 @@ typedef Tlc59711MethodBase> Tlc59711Esp32Vspi1MhzM typedef Tlc59711MethodBase> Tlc59711Esp32Vspi500KhzMethod; typedef Tlc59711MethodBase> Tlc59711Esp32VspiHzMethod; -typedef Tlc59711Spi2MhzMethod Tlc59711Esp32VspiMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32VspiMethod; #include "TwoWireHspiImple.h" typedef Tlc59711MethodBase> Tlc59711Esp32Hspi40MhzMethod; @@ -220,5 +219,5 @@ typedef Tlc59711MethodBase> Tlc59711Esp32Hspi1Mhz typedef Tlc59711MethodBase> Tlc59711Esp32Hspi500KhzMethod; typedef Tlc59711MethodBase> Tlc59711Esp32HspiHzMethod; -typedef Tlc59711Esp32Hspi2MhzMethod Tlc59711Esp32HspiMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32HspiMethod; #endif