From 3417f1e5bf4537281bddeb0e6ef4517e20d68c5f Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sat, 16 Mar 2024 11:21:56 -0700 Subject: [PATCH] Tlc59711 (#783) * 2Mhz max due to timing requirements with a clock based signal?! --- src/internal/NeoColorFeatures.h | 1 + src/internal/NeoMethods.h | 1 + src/internal/features/Tlc59711RgbFeatures.h | 185 +++++++++++++++ src/internal/methods/DotStarGenericMethod.h | 4 +- src/internal/methods/Tlc59711GenericMethod.h | 224 +++++++++++++++++++ src/internal/methods/TwoWireDebugImple.h | 209 +++++++++++++++++ src/internal/methods/TwoWireSpiImple.h | 23 +- 7 files changed, 634 insertions(+), 13 deletions(-) create mode 100644 src/internal/features/Tlc59711RgbFeatures.h create mode 100644 src/internal/methods/Tlc59711GenericMethod.h create mode 100644 src/internal/methods/TwoWireDebugImple.h diff --git a/src/internal/NeoColorFeatures.h b/src/internal/NeoColorFeatures.h index 4795aee..f822441 100644 --- a/src/internal/NeoColorFeatures.h +++ b/src/internal/NeoColorFeatures.h @@ -76,6 +76,7 @@ typedef NeoGrb48Feature NeoGrbWs2816Feature; #include "features/Lpd8806RgbFeatures.h" #include "features/P9813BgrFeature.h" +#include "features/Tlc59711RgbFeatures.h" // 7 Segment Features // diff --git a/src/internal/NeoMethods.h b/src/internal/NeoMethods.h index 49c953d..89d2c28 100644 --- a/src/internal/NeoMethods.h +++ b/src/internal/NeoMethods.h @@ -34,6 +34,7 @@ License along with NeoPixel. If not, see #include "methods/Ws2801GenericMethod.h" #include "methods/P9813GenericMethod.h" #include "methods/Tlc5947GenericMethod.h" +#include "methods/Tlc59711GenericMethod.h" #include "methods/Sm16716GenericMethod.h" #include "methods/Mbi6033GenericMethod.h" diff --git a/src/internal/features/Tlc59711RgbFeatures.h b/src/internal/features/Tlc59711RgbFeatures.h new file mode 100644 index 0000000..0a0b80c --- /dev/null +++ b/src/internal/features/Tlc59711RgbFeatures.h @@ -0,0 +1,185 @@ +/*------------------------------------------------------------------------- +Tlc59711RgbFeatures provides feature classes to describe color order and +color depth for NeoPixelBus template class specific to the TLC59711 chip + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +// Four byte settings header per 24 bytes color data +// 12 channel, 16 bit, grouped in chip and data reversed order +// (BGR3,BGR2,BGR1,BGR0) +// +// Write Command +// | OUTTMG - 1 rising edge, 0 falling edge +// | | EXTGCK - 0 internal clock, 1 SCKI clock +// | | | TMGRST - 0/1 enable display timer reset mode +// | | | | DSPRPT - 0/1 enabled auto display repeat +// | | | | | BLANK - 0 enabled, 1 blank +// | | | | | | BC (3x7) RGB Brightness control +// | | | | | | | blue green red +// | | | | | | | | | | color data (24 bytes) -> +// 100101 1 0 1 1 0 1111111 1111111 1111111 xxxxxxxx xxxxxxxx +// 765432 1 0 7 6 5 4321076 5432107 6543210 <- bit order within byte + +enum Tlc69711_Control +{ + // based on info above, but applied to + // individual bytes + Tlc69711_Control_EmiFallingEdge = 0x00, + Tlc69711_Control_EmiRisingEdge = 0x02, + Tlc69711_Control_ExternalClock = 0x01, + + Tlc69711_Control_DisplayTimerReset = 0x80, + Tlc69711_Control_AutoDisplayRepeat = 0x40, // keep the last request displayed + Tlc69711_Control_Blank = 0x20, + + Tlc69711_Control_Default = Tlc69711_Control_EmiRisingEdge | + Tlc69711_Control_DisplayTimerReset | + Tlc69711_Control_AutoDisplayRepeat +}; + +class Tlc69711Settings +{ +public: + Tlc69711Settings( + uint8_t groupsBrightness = MaxBrightness, + uint8_t control = Tlc69711_Control_Default) : + RedGroupBrightness(groupsBrightness & 0x7f), + GreenGroupBrightness(groupsBrightness & 0x7f), + BlueGroupBrightness(groupsBrightness & 0x7f), + Control(control) + { + } + + Tlc69711Settings( + uint8_t redGroupBrightness, + uint8_t greenGroupBrightness, + uint8_t blueGroupBrightness, + uint8_t control = Tlc69711_Control_Default) : + RedGroupBrightness(redGroupBrightness & 0x7f), + GreenGroupBrightness(greenGroupBrightness & 0x7f), + BlueGroupBrightness(blueGroupBrightness & 0x7f), + Control(control) + { + } + static constexpr uint8_t MaxBrightness = 127; + + const uint8_t RedGroupBrightness; + const uint8_t GreenGroupBrightness; + const uint8_t BlueGroupBrightness; + const uint8_t Control; +}; + +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) + { + 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; + *encoded = settings.GreenGroupBrightness << 7 | settings.RedGroupBrightness; + } + + static void applySettings([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData, [[maybe_unused]] const SettingsObject& settings) + { + // how the hell do we store the setting that doesn't go into the data stream' + // Thought A: + // Add a new method to Methods, getSettingsData() that for most will just + // return the front of the data stream, but for this it will return the pointer + // to a member variable that is a SettingsObject, where this just copies it + + // Thought B: + // add a new method to Methods, setPixelSettings that all current methods + // just have an empty set + // 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) + // Leave all current work alone + // Set SettingsSize to 2 times SettingsPerChipSize + // Consider it at the front of the data buffer + // call encode twice, into pData and then pData + SettingsPerChipSize + // have our Tlc59711Method know about the two and send the + // already interleaving settings and 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); + } + + static uint8_t* pixels([[maybe_unused]] uint8_t* pData, [[maybe_unused]] size_t sizeData) + { + // settings are at the front of the data stream + return pData + SettingsSize; + } + + static const uint8_t* pixels([[maybe_unused]] const uint8_t* pData, [[maybe_unused]] size_t sizeData) + { + // settings are at the front of the data stream + return pData + SettingsSize; + } + +private: + static constexpr uint8_t Tlc69711_Control_Mask1 = 0x03; // mask of this enum for first byte of encoded settings + static constexpr uint8_t Tlc69711_Control_Mask2 = 0xe0; // mask of this enum for second byte of encoded settings + +}; + +class Tlc59711RgbFeature : + public Neo3WordFeature, + public Tlc59711ElementsSettings +{ +}; + +class Tlc59711RgbwFeature : + public Neo4WordFeature, + public Tlc59711ElementsSettings +{ +}; diff --git a/src/internal/methods/DotStarGenericMethod.h b/src/internal/methods/DotStarGenericMethod.h index 5470864..e48aba1 100644 --- a/src/internal/methods/DotStarGenericMethod.h +++ b/src/internal/methods/DotStarGenericMethod.h @@ -90,11 +90,11 @@ public: // data _wire.transmitBytes(_data, _sizeData); - // reset frame + // reset frame _wire.transmitBytes(resetFrame, sizeof(resetFrame)); // end frame - + // // one bit for every two pixels with no less than 1 byte for (size_t endFrameByte = 0; endFrameByte < _sizeEndFrame; endFrameByte++) { diff --git a/src/internal/methods/Tlc59711GenericMethod.h b/src/internal/methods/Tlc59711GenericMethod.h new file mode 100644 index 0000000..fdf0b86 --- /dev/null +++ b/src/internal/methods/Tlc59711GenericMethod.h @@ -0,0 +1,224 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for Tlc59711 + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +// must also check for arm due to Teensy incorrectly having ARDUINO_ARCH_AVR set +#if defined(ARDUINO_ARCH_AVR) && !defined(__arm__) +#include "TwoWireBitBangImpleAvr.h" +#else +#include "TwoWireBitBangImple.h" +#include "TwoWireDebugImple.h" +#endif + + +template +class Tlc59711MethodBase +{ +public: + typedef typename T_TWOWIRE::SettingsObject SettingsObject; + + Tlc59711MethodBase(uint8_t pinClock, + uint8_t pinData, + uint16_t pixelCount, + size_t elementSize, + size_t settingsSize) : + _sizeData(NeoUtil::RoundUp(pixelCount * elementSize, c_dataPerChipSize) + settingsSize), + _sizeSettings(settingsSize), + _wire(pinClock, pinData) + { + _data = static_cast(malloc(_sizeData)); + // data cleared later in Begin() + } + +#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny) + Tlc59711MethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) : + Tlc59711MethodBase(SCK, MOSI, pixelCount, elementSize, settingsSize) + { + } +#endif + + ~Tlc59711MethodBase() + { + free(_data); + } + + bool IsReadyToUpdate() const + { + // need 8 clock periods plus 1.34us for the chips to all latch + // slowest clock is 2us clock period, so 8x2+1.24 = ~17.24 + // since we don't have access to actual clock value at this level + // the slowest will be used until a refactor can be made to allow + // the actual wire clock (or bitbang estimate of it) at this level + + uint32_t delta = micros() - _endTime; + + return (delta >= 20); + } + +#if defined(ARDUINO_ARCH_ESP32) + void Initialize(int8_t sck, int8_t miso, int8_t mosi, int8_t ss) + { + _wire.begin(sck, miso, mosi, ss); + + _endTime = micros(); + } +#endif + + void Initialize() + { + _wire.begin(); + + _endTime = micros(); + } + + void Update(bool) + { + while (!IsReadyToUpdate()) + { +#if !defined(ARDUINO_TEEONARDU_LEO) && !defined(ARDUINO_TEEONARDU_FLORA) + yield(); // allows for system yield if needed +#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; + + uint8_t reversedData[c_dataPerChipSize]; + uint16_t* pSrc = reinterpret_cast(_data + _sizeData); + uint16_t* pSrcEnd = reinterpret_cast(_data + _sizeSettings); + + _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); + + // send this chips "fixed order" data + _wire.transmitBytes(reversedData, c_dataPerChipSize); + + // toggle settings varient for next chip + if (pSettings == pSettingsA) + { + pSettings = pSettingsB; + } + else + { + pSettings = pSettingsA; + } + } + + _wire.endTransaction(); + + _endTime = micros(); + } + + 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) + { + _wire.applySettings(settings); + } + +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 + uint32_t _endTime; // Latch timing reference +}; + +typedef Tlc59711MethodBase Tlc59711Method; + +#if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny) +#include "TwoWireSpiImple.h" +typedef Tlc59711MethodBase> Tlc59711Spi40MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Spi20MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Spi10MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Spi5MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Spi2MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Spi1MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Spi500KhzMethod; +typedef Tlc59711MethodBase> Tlc59711SpiHzMethod; + +typedef Tlc59711Spi2MhzMethod Tlc59711SpiMethod; +#endif + +#if defined(ARDUINO_ARCH_ESP32) +// Give option to use Vspi alias of Spi class if wanting to specify which SPI peripheral is used on the ESP32 +typedef Tlc59711MethodBase> Tlc59711Esp32Vspi40MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Vspi20MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Vspi10MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Vspi5MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Vspi2MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Vspi1MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Vspi500KhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32VspiHzMethod; + +typedef Tlc59711Spi2MhzMethod Tlc59711Esp32VspiMethod; + +#include "TwoWireHspiImple.h" +typedef Tlc59711MethodBase> Tlc59711Esp32Hspi40MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Hspi20MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Hspi10MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Hspi5MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Hspi2MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Hspi1MhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32Hspi500KhzMethod; +typedef Tlc59711MethodBase> Tlc59711Esp32HspiHzMethod; + +typedef Tlc59711Esp32Hspi2MhzMethod Tlc59711Esp32HspiMethod; +#endif diff --git a/src/internal/methods/TwoWireDebugImple.h b/src/internal/methods/TwoWireDebugImple.h new file mode 100644 index 0000000..ed5c4ec --- /dev/null +++ b/src/internal/methods/TwoWireDebugImple.h @@ -0,0 +1,209 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for DotStars using general Pins (APA102/LPD8806). + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + + +class TwoWireDebugImple +{ +public: + typedef NeoNoSettings SettingsObject; + + TwoWireDebugImple(uint8_t pinClock, uint8_t pinData) : + _pinClock(pinClock), + _pinData(pinData) + { + } + + ~TwoWireDebugImple() + { + } +#if defined(ARDUINO_ARCH_ESP32) + void begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss) + { + Serial.print("TwoWireDebugImple(sck = "); + Serial.print(sck); + Serial.print(", mosi = "); + Serial.print(mosi); + Serial.println(")"); + } +#endif + + void begin() + { + Serial.print("TwoWireDebugImple(pinClock = "); + Serial.print(_pinClock); + Serial.print(", pinData = "); + Serial.print(_pinData); + Serial.println(")"); + } + + void beginTransaction() + { + Serial.println("TwoWireDebugImple beginTransaction:"); + } + + void endTransaction() + { + Serial.println("TwoWireDebugImple EndTransaction:"); + Serial.println(); + } + + void transmitBit(uint8_t bit) + { + Serial.print(" b"); + Serial.println(bit); + } + + void transmitByte(uint8_t data) + { + Serial.print(" 0x"); + + Serial.print(data >> 4, HEX); + Serial.print(data & 0x0f, HEX); + Serial.print(" b"); + + for (int bit = 7; bit >= 0; bit--) + { + Serial.print((data & 0x80) ? 1 : 0); + data <<= 1; + } + Serial.println(); + } + + void transmitBytes(const uint8_t* data, size_t dataSize) + { + const uint8_t* endData = data + dataSize; + while (data < endData) + { + transmitByte(*data++); + } + } + + void applySettings([[maybe_unused]] const SettingsObject& settings) + { + } + +private: + const uint8_t _pinClock; // output pin number for clock line + const uint8_t _pinData; // output pin number for data line +}; + + +template +class TwoWireDebugShimImple : public T_TWOWIRE +{ +public: + TwoWireDebugShimImple(uint8_t pinClock, uint8_t pinData) : + T_TWOWIRE(pinClock, pinData), + _pinClock(pinClock), + _pinData(pinData) + { + } + +#if defined(ARDUINO_ARCH_ESP32) + void begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss) + { + Serial.print("TwoWireDebugImple(sck = "); + Serial.print(sck); + Serial.print(", mosi = "); + Serial.print(mosi); + Serial.println(")"); + + T_TWOWIRE::begin(sck, miso, mosi, ss); + } +#endif + + void begin() + { + Serial.print("TwoWireDebugImple(pinClock = "); + Serial.print(_pinClock); + Serial.print(", pinData = "); + Serial.print(_pinData); + Serial.println(")"); + + T_TWOWIRE::begin(); + } + + void beginTransaction() + { + Serial.println("TwoWireDebugImple beginTransaction:"); + + T_TWOWIRE::beginTransaction(); + } + + void endTransaction() + { + Serial.println("TwoWireDebugImple EndTransaction:"); + Serial.println(); + + T_TWOWIRE::endTransaction(); + } + + void transmitBit(uint8_t bit) + { + Serial.print(" b"); + Serial.println(bit); + + T_TWOWIRE::transmitBit(bit); + } + + void transmitByte(uint8_t data) + { + Serial.print(" 0x"); + + Serial.print(data >> 4, HEX); + Serial.print(data & 0x0f, HEX); + Serial.print(" b"); + + uint8_t shift = data; + + for (int bit = 7; bit >= 0; bit--) + { + Serial.print((shift & 0x80) ? 1 : 0); + shift <<= 1; + } + Serial.println(); + + T_TWOWIRE::transmitByte(data); + } + + void transmitBytes(const uint8_t* data, size_t dataSize) + { + const uint8_t* endData = data + dataSize; + const uint8_t* dataSrc = data; + + while (dataSrc < endData) + { + transmitByte(*dataSrc++); + } + T_TWOWIRE::transmitBytes(data, dataSize); + } + +private: + const uint8_t _pinClock; // output pin number for clock line + const uint8_t _pinData; // output pin number for data line +}; \ No newline at end of file diff --git a/src/internal/methods/TwoWireSpiImple.h b/src/internal/methods/TwoWireSpiImple.h index 546b6c8..930fa0f 100644 --- a/src/internal/methods/TwoWireSpiImple.h +++ b/src/internal/methods/TwoWireSpiImple.h @@ -36,7 +36,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 40000000L; + static constexpr uint32_t Clock = 40000000L; }; class SpiSpeed30Mhz @@ -47,7 +47,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 30000000L; + static constexpr uint32_t Clock = 30000000L; }; class SpiSpeed20Mhz @@ -58,7 +58,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 20000000L; + static constexpr uint32_t Clock = 20000000L; }; class SpiSpeed15Mhz @@ -69,7 +69,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 15000000L; + static constexpr uint32_t Clock = 15000000L; }; class SpiSpeed10Mhz @@ -80,7 +80,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 10000000L; + static constexpr uint32_t Clock = 10000000L; }; class SpiSpeed5Mhz @@ -91,7 +91,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 5000000L; + static constexpr uint32_t Clock = 5000000L; }; class SpiSpeed2Mhz @@ -102,7 +102,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 2000000L; + static constexpr uint32_t Clock = 2000000L; }; class SpiSpeed1Mhz @@ -113,7 +113,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 1000000L; + static constexpr uint32_t Clock = 1000000L; }; class SpiSpeed500Khz @@ -124,7 +124,7 @@ public: static void applySettings([[maybe_unused]] const SettingsObject& settings) {} - static const uint32_t Clock = 500000L; + static constexpr uint32_t Clock = 500000L; }; class NeoSpiSettings @@ -143,7 +143,7 @@ public: typedef NeoSpiSettings SettingsObject; SpiSpeedHz() : - Clock(10000000) + Clock(SpiSpeed10Mhz::Clock) {}; void applySettings([[maybe_unused]] const SettingsObject& settings) @@ -154,7 +154,8 @@ public: uint32_t Clock; }; -template class TwoWireSpiImple +template +class TwoWireSpiImple { public: typedef typename T_SPISPEED::SettingsObject SettingsObject;