From 6e8e775d5e7bc3851c7db239099725cd6baacb50 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 26 Jul 2024 16:50:26 -0400 Subject: [PATCH 1/9] checkpointing Grinch support --- ESPixelStick/src/output/OutputCommon.hpp | 2 +- ESPixelStick/src/output/OutputMgr.cpp | 29 ++++++- ESPixelStick/src/output/OutputMgr.hpp | 4 + ESPixelStick/src/output/OutputSpi.cpp | 77 ++++++++++++++++--- ESPixelStick/src/output/OutputSpi.hpp | 15 +++- .../GPIO_Defs_ESP32_DevkitC.hpp | 2 + 6 files changed, 117 insertions(+), 12 deletions(-) diff --git a/ESPixelStick/src/output/OutputCommon.hpp b/ESPixelStick/src/output/OutputCommon.hpp index 4bb8c804e..2ef354000 100644 --- a/ESPixelStick/src/output/OutputCommon.hpp +++ b/ESPixelStick/src/output/OutputCommon.hpp @@ -75,7 +75,7 @@ class c_OutputCommon uint32_t OutputBufferSize = 0; uint32_t FrameCount = 0; - void ReportNewFrame (); + virtual void ReportNewFrame (); inline bool canRefresh () { diff --git a/ESPixelStick/src/output/OutputMgr.cpp b/ESPixelStick/src/output/OutputMgr.cpp index 6d7f8b615..23019bbc4 100644 --- a/ESPixelStick/src/output/OutputMgr.cpp +++ b/ESPixelStick/src/output/OutputMgr.cpp @@ -2,7 +2,7 @@ * OutputMgr.cpp - Output Management class * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2021, 2022 Shelby Merrick +* Copyright (c) 2021, 2024 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -32,6 +32,7 @@ #include "OutputAPA102Spi.hpp" #include "OutputGECEUart.hpp" #include "OutputGECERmt.hpp" +#include "OutputGrinchSpi.hpp" #include "OutputRelay.hpp" #include "OutputSerialUart.hpp" #include "OutputSerialRmt.hpp" @@ -89,6 +90,10 @@ static const OutputTypeXlateMap_t OutputTypeXlateMap[c_OutputMgr::e_OutputType:: {c_OutputMgr::e_OutputType::OutputType_GECE, "GECE"}, #endif // def SUPPORT_OutputType_GECE +#ifdef SUPPORT_OutputType_GRINCH + {c_OutputMgr::e_OutputType::OutputType_GRINCH, "Grinch"}, +#endif // def SUPPORT_OutputType_GRINCH + #ifdef SUPPORT_OutputType_GS8208 {c_OutputMgr::e_OutputType::OutputType_GS8208, "GS8208"}, #endif // def SUPPORT_OutputType_GS8208 @@ -845,6 +850,28 @@ void c_OutputMgr::InstantiateNewOutputChannel(DriverInfo_t & CurrentOutputChanne } #endif // def SUPPORT_OutputType_TM1814 +#ifdef SUPPORT_OutputType_GRINCH + case e_OutputType::OutputType_GRINCH: + { + if (CurrentOutputChannelDriver.PortType == OM_PortType_t::Spi) + { + // logcon (CN_stars + String ((" Starting GRINCH SPI for channel '")) + CurrentOutputChannelDriver.DriverId + "'. " + CN_stars); + CurrentOutputChannelDriver.pOutputChannelDriver = new c_OutputGrinchSpi(CurrentOutputChannelDriver.DriverId, CurrentOutputChannelDriver.GpioPin, CurrentOutputChannelDriver.PortId, OutputType_GRINCH); + // DEBUG_V (); + break; + } + + if (!BuildingNewConfig) + { + logcon(CN_stars + String(MN_07) + F("Grinch") + MN_08 + CurrentOutputChannelDriver.DriverId + "'. " + CN_stars); + } + CurrentOutputChannelDriver.pOutputChannelDriver = new c_OutputDisabled(CurrentOutputChannelDriver.DriverId, CurrentOutputChannelDriver.GpioPin, CurrentOutputChannelDriver.PortId, OutputType_Disabled); + // DEBUG_V (); + + break; + } +#endif // def SUPPORT_OutputType_GRINCH + #ifdef SUPPORT_OutputType_WS2801 case e_OutputType::OutputType_WS2801: { diff --git a/ESPixelStick/src/output/OutputMgr.hpp b/ESPixelStick/src/output/OutputMgr.hpp index cdfd95836..7bd4a0b08 100644 --- a/ESPixelStick/src/output/OutputMgr.hpp +++ b/ESPixelStick/src/output/OutputMgr.hpp @@ -183,6 +183,10 @@ class c_OutputMgr OutputType_TLS3001 = 14, #endif // def SUPPORT_OutputType_TLS3001 + #ifdef SUPPORT_OutputType_GRINCH + OutputType_GRINCH = 15, + #endif // def SUPPORT_OutputType_GRINCH + // Add new types here OutputType_End, // must be last OutputType_Start = OutputType_Disabled, diff --git a/ESPixelStick/src/output/OutputSpi.cpp b/ESPixelStick/src/output/OutputSpi.cpp index df23c829a..b73a12deb 100644 --- a/ESPixelStick/src/output/OutputSpi.cpp +++ b/ESPixelStick/src/output/OutputSpi.cpp @@ -87,16 +87,21 @@ c_OutputSpi::~c_OutputSpi () if(HasBeenInitialized) { spi_transfer_callback_enabled = false; - if (OutputPixel) - { - logcon(CN_stars + String(F(" SPI Interface Shutdown requires a reboot ")) + CN_stars); - RequestReboot(100000); - } + logcon(CN_stars + String(F(" SPI Interface Shutdown requires a reboot ")) + CN_stars); + RequestReboot(100000); } // DEBUG_END; } // ~c_OutputSpi +#if defined(SUPPORT_OutputType_GRINCH) +void c_OutputSpi::Begin (c_OutputGrinch* _OutputGrinch) +{ + OutputGrinch = _OutputGrinch; + Begin ((c_OutputPixel*)nullptr); +} +#endif // defined(SUPPORT_OutputType_GRINCH) + //---------------------------------------------------------------------------- void c_OutputSpi::Begin (c_OutputPixel* _OutputPixel) { @@ -152,13 +157,49 @@ void c_OutputSpi::Begin (c_OutputPixel* _OutputPixel) } // Begin +//---------------------------------------------------------------------------- +bool c_OutputSpi::ISR_MoreDataToSend() +{ + bool response = false; + if(OutputPixel) + { + response = OutputPixel->ISR_MoreDataToSend (); + } +#if defined(SUPPORT_OutputType_GRINCH) + else if(OutputGrinch) + { + response = OutputGrinch->ISR_MoreDataToSend (); + } +#endif // defined(SUPPORT_OutputType_GRINCH) + return response; +} + +//---------------------------------------------------------------------------- +bool c_OutputSpi::ISR_GetNextIntensityToSend(uint32_t& Data) +{ + bool response = false; + + if(OutputPixel) + { + response = OutputPixel->ISR_GetNextIntensityToSend (Data); + } +#if defined(SUPPORT_OutputType_GRINCH) + else if(OutputGrinch) + { + response = OutputGrinch->ISR_GetNextIntensityToSend (Data); + } +#endif // defined(SUPPORT_OutputType_GRINCH) + + return response; +} // ISR_GetNextIntensityToSend + //---------------------------------------------------------------------------- void c_OutputSpi::SendIntensityData () { // DEBUG_START; SendIntensityDataCounter++; - if (OutputPixel->ISR_MoreDataToSend ()) + if (ISR_MoreDataToSend ()) { spi_transaction_t & TransactionToFill = Transactions[NextTransactionToFill]; memset ( (void*)&Transactions[NextTransactionToFill], 0x00, sizeof (spi_transaction_t)); @@ -169,15 +210,15 @@ void c_OutputSpi::SendIntensityData () uint32_t NumEmptyIntensitySlots = SPI_NUM_INTENSITY_PER_TRANSACTION; uint32_t IntensityData = 0; - while ( (NumEmptyIntensitySlots) && (OutputPixel->ISR_MoreDataToSend ())) + while ( (NumEmptyIntensitySlots) && (ISR_MoreDataToSend ())) { - OutputPixel->ISR_GetNextIntensityToSend (IntensityData); + ISR_GetNextIntensityToSend (IntensityData); *pMem++ = byte(IntensityData); --NumEmptyIntensitySlots; } // end while there is space in the buffer TransactionToFill.length = SPI_BITS_PER_INTENSITY * (SPI_NUM_INTENSITY_PER_TRANSACTION - NumEmptyIntensitySlots); - if (!OutputPixel->ISR_MoreDataToSend ()) + if (!ISR_MoreDataToSend ()) { TransactionToFill.length++; } @@ -194,6 +235,24 @@ void c_OutputSpi::SendIntensityData () } // SendIntensityData +//---------------------------------------------------------------------------- +void c_OutputSpi::StartNewFrame() +{ + bool response = false; + + if(OutputPixel) + { + OutputPixel->StartNewFrame (); + } +#if defined(SUPPORT_OutputType_GRINCH) + else if(OutputGrinch) + { + OutputGrinch->StartNewFrame (); + } +#endif // defined(SUPPORT_OutputType_GRINCH) + +} // StartNewFrame + //---------------------------------------------------------------------------- bool c_OutputSpi::Poll () { diff --git a/ESPixelStick/src/output/OutputSpi.hpp b/ESPixelStick/src/output/OutputSpi.hpp index dbce629ec..240a7ae0c 100644 --- a/ESPixelStick/src/output/OutputSpi.hpp +++ b/ESPixelStick/src/output/OutputSpi.hpp @@ -3,7 +3,7 @@ * OutputSpi.h - SPI driver code for ESPixelStick Spi Channel * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2015, 2022 Shelby Merrick +* Copyright (c) 2015, 2024 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -28,6 +28,9 @@ #include "OutputPixel.hpp" #include #include +#if defined(SUPPORT_OutputType_GRINCH) + #include "OutputGrinch.hpp" +#endif // defined(SUPPORT_OutputType_GRINCH) class c_OutputSpi { @@ -38,6 +41,9 @@ class c_OutputSpi // functions to be provided by the derived class void Begin (c_OutputPixel* _OutputPixel); +#if defined(SUPPORT_OutputType_GRINCH) + void Begin (c_OutputGrinch* _OutputSerial); +#endif // defined(SUPPORT_OutputType_GRINCH) bool Poll (); ///< Call from loop (), renders output data TaskHandle_t GetTaskHandle () { return SendIntensityDataTaskHandle; } void GetDriverName (String& Name) { Name = CN_OutputSpi; } @@ -56,6 +62,10 @@ class c_OutputSpi #define SPI_SPI_HOST DEFAULT_SPI_DEVICE #define SPI_SPI_DMA_CHANNEL 2 + bool ISR_MoreDataToSend(); + bool ISR_GetNextIntensityToSend(uint32_t& Data); + void StartNewFrame(); + uint8_t NumIntensityValuesPerInterrupt = 0; uint8_t NumIntensityBitsPerInterrupt = 0; spi_device_handle_t spi_device_handle = 0; @@ -74,6 +84,9 @@ class c_OutputSpi gpio_num_t ClockPin = DEFAULT_SPI_CLOCK_GPIO; c_OutputPixel* OutputPixel = nullptr; +#if defined(SUPPORT_OutputType_GRINCH) + c_OutputGrinch * OutputGrinch = nullptr; +#endif // defined(SUPPORT_OutputType_GRINCH) #ifndef HasBeenInitialized bool HasBeenInitialized = false; diff --git a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_DevkitC.hpp b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_DevkitC.hpp index 34d3ae273..619292557 100644 --- a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_DevkitC.hpp +++ b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_DevkitC.hpp @@ -31,6 +31,7 @@ #define SUPPORT_SPI_OUTPUT #define DEFAULT_SPI_DATA_GPIO gpio_num_t::GPIO_NUM_16 #define DEFAULT_SPI_CLOCK_GPIO gpio_num_t::GPIO_NUM_17 +#define DEFAULT_SPI_CS_GPIO gpio_num_t::GPIO_NUM_0 #define DEFAULT_SPI_DEVICE VSPI_HOST #define DEFAULT_I2C_SDA gpio_num_t::GPIO_NUM_3 @@ -60,3 +61,4 @@ #define SUPPORT_OutputType_WS2811 // UART / RMT #define SUPPORT_OutputType_Relay // GPIO #define SUPPORT_OutputType_Servo_PCA9685 // I2C (default pins) +#define SUPPORT_OutputType_GRINCH // SPI From 77ca655d86037e3c5fc4ec93c2bbb3d1de3da486 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 26 Jul 2024 16:52:31 -0400 Subject: [PATCH 2/9] Checkpoint Grinch Support --- ESPixelStick/src/output/OutputGrinch.cpp | 156 ++++++++++++++++++++ ESPixelStick/src/output/OutputGrinch.hpp | 62 ++++++++ ESPixelStick/src/output/OutputGrinchSpi.cpp | 108 ++++++++++++++ ESPixelStick/src/output/OutputGrinchSpi.hpp | 53 +++++++ 4 files changed, 379 insertions(+) create mode 100644 ESPixelStick/src/output/OutputGrinch.cpp create mode 100644 ESPixelStick/src/output/OutputGrinch.hpp create mode 100644 ESPixelStick/src/output/OutputGrinchSpi.cpp create mode 100644 ESPixelStick/src/output/OutputGrinchSpi.hpp diff --git a/ESPixelStick/src/output/OutputGrinch.cpp b/ESPixelStick/src/output/OutputGrinch.cpp new file mode 100644 index 000000000..4ad0d1ff5 --- /dev/null +++ b/ESPixelStick/src/output/OutputGrinch.cpp @@ -0,0 +1,156 @@ +/* +* OutputGRINCH.cpp - GRINCH driver code for ESPixelStick UART +* +* Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver +* Copyright (c) 2015, 2024 Shelby Merrick +* http://www.forkineye.com +* +* This program is provided free for you to use in any way that you wish, +* subject to the laws and regulations where you are using it. Due diligence +* is strongly suggested before using this code. Please give credit where due. +* +* The Author makes no warranty of any kind, express or implied, with regard +* to this program or the documentation contained in this document. The +* Author shall not be liable in any event for incidental or consequential +* damages in connection with, or arising out of, the furnishing, performance +* or use of these programs. +* +*/ + +#include "../ESPixelStick.h" +#ifdef SUPPORT_OutputType_GRINCH + +#include "OutputGrinch.hpp" + +//---------------------------------------------------------------------------- +c_OutputGrinch::c_OutputGrinch (c_OutputMgr::e_OutputChannelIds OutputChannelId, + gpio_num_t outputGpio, + uart_port_t uart, + c_OutputMgr::e_OutputType outputType) : + c_OutputCommon (OutputChannelId, outputGpio, uart, outputType) +{ + // DEBUG_START; + + // InterFrameGapInMicroSec = GRINCH_MIN_IDLE_TIME_US; + + // DEBUG_END; +} // c_OutputGrinch + +//---------------------------------------------------------------------------- +c_OutputGrinch::~c_OutputGrinch () +{ + // DEBUG_START; + + // DEBUG_END; +} // ~c_OutputGrinch + +//---------------------------------------------------------------------------- +void c_OutputGrinch::GetConfig (ArduinoJson::JsonObject& jsonConfig) +{ + // DEBUG_START; + + c_OutputCommon::GetConfig (jsonConfig); + jsonConfig[CN_cs_pin] = uint8_t (DataStrobe); + jsonConfig[CN_count] = NumberOfGrinchControllers; + + // DEBUG_END; +} // GetConfig + +//---------------------------------------------------------------------------- +void c_OutputGrinch::GetStatus (ArduinoJson::JsonObject& jsonStatus) +{ + c_OutputCommon::GetStatus (jsonStatus); + +} // GetStatus + +//---------------------------------------------------------------------------- +void c_OutputGrinch::SetOutputBufferSize (uint32_t NumChannelsAvailable) +{ + // DEBUG_START; + + c_OutputCommon::SetOutputBufferSize (NumChannelsAvailable); + + // Calculate our refresh time + // SetFrameDurration (((1.0 / float (GRINCH_BIT_RATE)) * MicroSecondsInASecond), BlockSize, BlockDelay); + + // DEBUG_END; + +} // SetBufferSize + +//---------------------------------------------------------------------------- +/* Process the config +* +* needs +* reference to string to process +* returns +* true - config has been accepted +* false - Config rejected. Using defaults for invalid settings +*/ +bool c_OutputGrinch::SetConfig (ArduinoJson::JsonObject& jsonConfig) +{ + // DEBUG_START; + + bool response = c_OutputCommon::SetConfig (jsonConfig); + response |= setFromJSON (DataStrobe, jsonConfig, CN_cs_pin); + response |= setFromJSON (NumberOfGrinchControllers, jsonConfig, CN_count); + + // turn off the outout strobe (latch data) + pinMode(DataStrobe, OUTPUT); + digitalWrite(DataStrobe, HIGH); + + // Calculate our refresh time + // SetFrameDurration (((1.0 / float (GRINCH_BIT_RATE)) * MicroSecondsInASecond), BlockSize, BlockDelay); + + // DEBUG_END; + return response; + +} // SetConfig + +//---------------------------------------------------------------------------- +bool IRAM_ATTR c_OutputGrinch::ISR_GetNextIntensityToSend (uint32_t &DataToSend) +{ + DataToSend = 0x55; + return true; +} + +//---------------------------------------------------------------------------- +void c_OutputGrinch::StartNewFrame() +{ + DEBUG_START; + + // put the shift registers into clock through mode. + digitalWrite(DataStrobe, LOW); + + // build the data frame + uint32_t NumChannelsToProcess = GetNumOutputBufferBytesNeeded(); + uint8_t * pInputData = GetBufferAddress(); + uint64_t OutputData = 0; + uint8_t OutputDataIndex = 0; + uint8_t bitCounter = 0; + + while(NumChannelsToProcess) + { + if(bitCounter >= (sizeof(OutputData) * 8)) + { + // write the output data + OutputDataIndex ++; + + // move to the next controller + bitCounter = 0; + OutputData = 0; + } + + // set the output bit to one if the output is greater than half on + OutputData = (OutputData << 1) | (pInputData[0] < 128); + dataBuffer[OutputDataIndex] = OutputData; + pInputData ++; + bitCounter ++; + NumChannelsToProcess--; + } + + SpiOutputDataIndex = 0; + + DEBUG_END; +} // StartNewFrame + +#endif // def SUPPORT_OutputType_GRINCH diff --git a/ESPixelStick/src/output/OutputGrinch.hpp b/ESPixelStick/src/output/OutputGrinch.hpp new file mode 100644 index 000000000..bc10a6689 --- /dev/null +++ b/ESPixelStick/src/output/OutputGrinch.hpp @@ -0,0 +1,62 @@ +#pragma once +/* +* OutputGrinch.h - Grinch driver code for ESPixelStick +* +* Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver +* Copyright (c) 2015, 2024 Shelby Merrick +* http://www.forkineye.com +* +* This program is provided free for you to use in any way that you wish, +* subject to the laws and regulations where you are using it. Due diligence +* is strongly suggested before using this code. Please give credit where due. +* +* The Author makes no warranty of any kind, express or implied, with regard +* to this program or the documentation contained in this document. The +* Author shall not be liable in any event for incidental or consequential +* damages in connection with, or arising out of, the furnishing, performance +* or use of these programs. +* +* This is a derived class that converts data in the output buffer into +* pixel intensities and then transmits them through the configured serial +* interface. +* +*/ +#include "OutputCommon.hpp" +#ifdef SUPPORT_OutputType_GRINCH + +class c_OutputGrinch : public c_OutputCommon +{ +public: + // These functions are inherited from c_OutputCommon + c_OutputGrinch (c_OutputMgr::e_OutputChannelIds OutputChannelId, + gpio_num_t outputGpio, + uart_port_t uart, + c_OutputMgr::e_OutputType outputType); + virtual ~c_OutputGrinch (); + + // functions to be provided by the derived class + virtual bool SetConfig (ArduinoJson::JsonObject & jsonConfig); ///< Set a new config in the driver + virtual void GetConfig (ArduinoJson::JsonObject & jsonConfig); ///< Get the current config used by the driver + void GetDriverName (String & sDriverName) { sDriverName = F("Grinch"); } + virtual void GetStatus (ArduinoJson::JsonObject & jsonStatus); + virtual void SetOutputBufferSize (uint32_t NumChannelsAvailable); + uint32_t GetNumOutputBufferBytesNeeded () { return (NumberOfGrinchControllers * 64); } + uint32_t GetNumOutputBufferChannelsServiced () { return (NumberOfGrinchControllers * 64); } + + void StartNewFrame(); + inline bool IRAM_ATTR ISR_MoreDataToSend () {return false;} + bool IRAM_ATTR ISR_GetNextIntensityToSend (uint32_t &DataToSend); + +protected: + +#define MAX_NUM_SUPPORTED_GRINCHES 4 +#define DATA_CHANNELS_PER_GRINCH 64 + +private: + uint8_t NumberOfGrinchControllers = 1; + gpio_num_t DataStrobe = DEFAULT_SPI_CS_GPIO; + uint64_t dataBuffer[MAX_NUM_SUPPORTED_GRINCHES]; + uint8_t SpiOutputDataIndex = 0; + +}; // c_OutputGrinch +#endif // def SUPPORT_OutputType_GRINCH diff --git a/ESPixelStick/src/output/OutputGrinchSpi.cpp b/ESPixelStick/src/output/OutputGrinchSpi.cpp new file mode 100644 index 000000000..64ec16f35 --- /dev/null +++ b/ESPixelStick/src/output/OutputGrinchSpi.cpp @@ -0,0 +1,108 @@ +/* +* OutputGrinchSpi.cpp - GRINCH driver code for ESPixelStick SPI Channel +* +* Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver +* Copyright (c) 2015, 2024 Shelby Merrick +* http://www.forkineye.com +* +* This program is provided free for you to use in any way that you wish, +* subject to the laws and regulations where you are using it. Due diligence +* is strongly suggested before using this code. Please give credit where due. +* +* The Author makes no warranty of any kind, express or implied, with regard +* to this program or the documentation contained in this document. The +* Author shall not be liable in any event for incidental or consequential +* damages in connection with, or arising out of, the furnishing, performance +* or use of these programs. +* +*/ + +#include "../ESPixelStick.h" +#if defined (SUPPORT_OutputType_GRINCH) && defined (SUPPORT_SPI_OUTPUT) + +#include "OutputGrinchSpi.hpp" + +//---------------------------------------------------------------------------- +c_OutputGrinchSpi::c_OutputGrinchSpi (c_OutputMgr::e_OutputChannelIds OutputChannelId, + gpio_num_t outputGpio, + uart_port_t uart, + c_OutputMgr::e_OutputType outputType) : + c_OutputGrinch (OutputChannelId, outputGpio, uart, outputType) +{ + // DEBUG_START; + + // update frame calculation + + // DEBUG_END; +} // c_OutputGrinchSpi + +//---------------------------------------------------------------------------- +c_OutputGrinchSpi::~c_OutputGrinchSpi () +{ + // DEBUG_START; + + // DEBUG_END; + +} // ~c_OutputGrinchSpi + +//---------------------------------------------------------------------------- +/* Use the current config to set up the output port +*/ +void c_OutputGrinchSpi::Begin () +{ + // DEBUG_START; + Spi.Begin (this); + + HasBeenInitialized = true; + + // DEBUG_END; + +} // init + +//---------------------------------------------------------------------------- +void c_OutputGrinchSpi::GetConfig (ArduinoJson::JsonObject& jsonConfig) +{ + // DEBUG_START; + + c_OutputGrinch::GetConfig (jsonConfig); + + // DEBUG_END; +} // GetConfig + +//---------------------------------------------------------------------------- +bool c_OutputGrinchSpi::SetConfig (ArduinoJson::JsonObject& jsonConfig) +{ + // DEBUG_START; + + bool response = c_OutputGrinch::SetConfig (jsonConfig); + + // DEBUG_END; + return response; + +} // GetStatus + +//---------------------------------------------------------------------------- +uint32_t c_OutputGrinchSpi::Poll () +{ + // DEBUG_START; + + uint32_t FrameLen = ActualFrameDurationMicroSec; + + if (canRefresh ()) + { + if (Spi.Poll ()) + { + ReportNewFrame (); + } + } + else + { + FrameLen = 0; + } + + // DEBUG_END; + return FrameLen; + +} // render + +#endif // defined (SUPPORT_OutputType_GRINCH) && defined (SUPPORT_SPI_OUTPUT) diff --git a/ESPixelStick/src/output/OutputGrinchSpi.hpp b/ESPixelStick/src/output/OutputGrinchSpi.hpp new file mode 100644 index 000000000..1ae4f4b48 --- /dev/null +++ b/ESPixelStick/src/output/OutputGrinchSpi.hpp @@ -0,0 +1,53 @@ +#pragma once +/* +* OutputGrinchSpi.h - GRINCH driver code for ESPixelStick Spi Channel +* +* Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver +* Copyright (c) 2015, 2024 Shelby Merrick +* http://www.forkineye.com +* +* This program is provided free for you to use in any way that you wish, +* subject to the laws and regulations where you are using it. Due diligence +* is strongly suggested before using this code. Please give credit where due. +* +* The Author makes no warranty of any kind, express or implied, with regard +* to this program or the documentation contained in this document. The +* Author shall not be liable in any event for incidental or consequential +* damages in connection with, or arising out of, the furnishing, performance +* or use of these programs. +* +* This is a derived class that converts data in the output buffer into +* pixel intensities and then transmits them through the configured serial +* interface. +* +*/ +#include "../ESPixelStick.h" +#if defined (SUPPORT_OutputType_GRINCH) && defined (SUPPORT_SPI_OUTPUT) + +#include "OutputGrinch.hpp" +#include "OutputSpi.hpp" + +class c_OutputGrinchSpi : public c_OutputGrinch +{ +public: + // These functions are inherited from c_OutputCommon + c_OutputGrinchSpi (c_OutputMgr::e_OutputChannelIds OutputChannelId, + gpio_num_t outputGpio, + uart_port_t uart, + c_OutputMgr::e_OutputType outputType); + virtual ~c_OutputGrinchSpi (); + + // functions to be provided by the derived class + void Begin (); + void GetConfig (ArduinoJson::JsonObject& jsonConfig); + bool SetConfig (ArduinoJson::JsonObject& jsonConfig); ///< Set a new config in the driver + uint32_t Poll (); ///< Call from loop(), renders output data + void PauseOutput () {}; + +private: + + c_OutputSpi Spi; + +}; // c_OutputGrinchSpi + +#endif // defined (SUPPORT_OutputType_GRINCH) && defined (SUPPORT_SPI_OUTPUT) From 47f8256389c0903162ab99d2a44fdd0ae67a94b8 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 26 Jul 2024 23:32:25 -0400 Subject: [PATCH 3/9] First working version of Grinch support --- ESPixelStick/src/output/OutputGrinch.cpp | 28 +++++++++++--- ESPixelStick/src/output/OutputGrinch.hpp | 10 +++-- ESPixelStick/src/output/OutputSpi.cpp | 2 +- .../GPIO_Defs_ESP32_DevkitC.hpp | 2 +- .../GPIO_Defs_ESP32_LoLin_D32_PRO.hpp | 2 + html/grinch.html | 14 +++++++ html/script.js | 38 +++++++++++++++---- 7 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 html/grinch.html diff --git a/ESPixelStick/src/output/OutputGrinch.cpp b/ESPixelStick/src/output/OutputGrinch.cpp index 4ad0d1ff5..dd643afe7 100644 --- a/ESPixelStick/src/output/OutputGrinch.cpp +++ b/ESPixelStick/src/output/OutputGrinch.cpp @@ -94,6 +94,14 @@ bool c_OutputGrinch::SetConfig (ArduinoJson::JsonObject& jsonConfig) response |= setFromJSON (DataStrobe, jsonConfig, CN_cs_pin); response |= setFromJSON (NumberOfGrinchControllers, jsonConfig, CN_count); + NumberOfGrinchChannels = NumberOfGrinchControllers * DATA_CHANNELS_PER_GRINCH; + NumberOfGrinchDataBytes = NumberOfGrinchChannels / (sizeof(uint8_t) * 8); + + // DEBUG_V(String("NumberOfGrinchControllers: ") + String(NumberOfGrinchControllers)); + // DEBUG_V(String(" NumberOfGrinchChannels: ") + String(NumberOfGrinchChannels)); + // DEBUG_V(String(" NumberOfGrinchDataBytes: ") + String(NumberOfGrinchDataBytes)); + SetOutputBufferSize(NumberOfGrinchChannels); + // turn off the outout strobe (latch data) pinMode(DataStrobe, OUTPUT); digitalWrite(DataStrobe, HIGH); @@ -109,16 +117,24 @@ bool c_OutputGrinch::SetConfig (ArduinoJson::JsonObject& jsonConfig) //---------------------------------------------------------------------------- bool IRAM_ATTR c_OutputGrinch::ISR_GetNextIntensityToSend (uint32_t &DataToSend) { - DataToSend = 0x55; - return true; -} + if(ISR_MoreDataToSend()) + { + // DEBUG_V(String("DataToSend: ") + String(DataToSend)); + DataToSend = ((uint8_t*)&dataBuffer[0])[SpiOutputDataByteIndex-1]; + SpiOutputDataByteIndex--; + } + + return ISR_MoreDataToSend(); +} // ISR_GetNextIntensityToSend //---------------------------------------------------------------------------- void c_OutputGrinch::StartNewFrame() { - DEBUG_START; + // DEBUG_START; // put the shift registers into clock through mode. + digitalWrite(DataStrobe, HIGH); + delay(1); digitalWrite(DataStrobe, LOW); // build the data frame @@ -148,9 +164,9 @@ void c_OutputGrinch::StartNewFrame() NumChannelsToProcess--; } - SpiOutputDataIndex = 0; + SpiOutputDataByteIndex = NumberOfGrinchDataBytes; - DEBUG_END; + // DEBUG_END; } // StartNewFrame #endif // def SUPPORT_OutputType_GRINCH diff --git a/ESPixelStick/src/output/OutputGrinch.hpp b/ESPixelStick/src/output/OutputGrinch.hpp index bc10a6689..7d4f82582 100644 --- a/ESPixelStick/src/output/OutputGrinch.hpp +++ b/ESPixelStick/src/output/OutputGrinch.hpp @@ -40,11 +40,11 @@ class c_OutputGrinch : public c_OutputCommon void GetDriverName (String & sDriverName) { sDriverName = F("Grinch"); } virtual void GetStatus (ArduinoJson::JsonObject & jsonStatus); virtual void SetOutputBufferSize (uint32_t NumChannelsAvailable); - uint32_t GetNumOutputBufferBytesNeeded () { return (NumberOfGrinchControllers * 64); } - uint32_t GetNumOutputBufferChannelsServiced () { return (NumberOfGrinchControllers * 64); } + uint32_t GetNumOutputBufferBytesNeeded () { return (NumberOfGrinchChannels); } + uint32_t GetNumOutputBufferChannelsServiced () { return (NumberOfGrinchChannels); } void StartNewFrame(); - inline bool IRAM_ATTR ISR_MoreDataToSend () {return false;} + inline bool IRAM_ATTR ISR_MoreDataToSend () {return SpiOutputDataByteIndex > 0;} bool IRAM_ATTR ISR_GetNextIntensityToSend (uint32_t &DataToSend); protected: @@ -54,9 +54,11 @@ class c_OutputGrinch : public c_OutputCommon private: uint8_t NumberOfGrinchControllers = 1; + uint8_t NumberOfGrinchChannels = NumberOfGrinchControllers * DATA_CHANNELS_PER_GRINCH; + uint8_t NumberOfGrinchDataBytes = NumberOfGrinchChannels / 8; gpio_num_t DataStrobe = DEFAULT_SPI_CS_GPIO; uint64_t dataBuffer[MAX_NUM_SUPPORTED_GRINCHES]; - uint8_t SpiOutputDataIndex = 0; + uint8_t SpiOutputDataByteIndex = 0; }; // c_OutputGrinch #endif // def SUPPORT_OutputType_GRINCH diff --git a/ESPixelStick/src/output/OutputSpi.cpp b/ESPixelStick/src/output/OutputSpi.cpp index b73a12deb..6f4003274 100644 --- a/ESPixelStick/src/output/OutputSpi.cpp +++ b/ESPixelStick/src/output/OutputSpi.cpp @@ -260,7 +260,7 @@ bool c_OutputSpi::Poll () // DEBUG_START; - OutputPixel->StartNewFrame (); + StartNewFrame (); // fill all the available buffers NextTransactionToFill = 0; diff --git a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_DevkitC.hpp b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_DevkitC.hpp index 619292557..7ee5b32b3 100644 --- a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_DevkitC.hpp +++ b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_DevkitC.hpp @@ -51,6 +51,7 @@ #define SUPPORT_OutputType_APA102 // SPI #define SUPPORT_OutputType_DMX // UART / RMT #define SUPPORT_OutputType_GECE // UART +#define SUPPORT_OutputType_GRINCH // SPI #define SUPPORT_OutputType_GS8208 // UART / RMT #define SUPPORT_OutputType_Renard // UART / RMT #define SUPPORT_OutputType_Serial // UART / RMT @@ -61,4 +62,3 @@ #define SUPPORT_OutputType_WS2811 // UART / RMT #define SUPPORT_OutputType_Relay // GPIO #define SUPPORT_OutputType_Servo_PCA9685 // I2C (default pins) -#define SUPPORT_OutputType_GRINCH // SPI diff --git a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_LoLin_D32_PRO.hpp b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_LoLin_D32_PRO.hpp index 88b380b13..8147da650 100644 --- a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_LoLin_D32_PRO.hpp +++ b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_LoLin_D32_PRO.hpp @@ -28,6 +28,7 @@ #define SUPPORT_SPI_OUTPUT #define DEFAULT_SPI_DATA_GPIO gpio_num_t::GPIO_NUM_27 #define DEFAULT_SPI_CLOCK_GPIO gpio_num_t::GPIO_NUM_32 +#define DEFAULT_SPI_CS_GPIO gpio_num_t::GPIO_NUM_0 #define DEFAULT_SPI_DEVICE VSPI_HOST #define DEFAULT_I2C_SDA gpio_num_t::GPIO_NUM_3 @@ -47,6 +48,7 @@ #define SUPPORT_OutputType_APA102 // SPI #define SUPPORT_OutputType_DMX // UART / RMT #define SUPPORT_OutputType_GECE // UART / RMT +#define SUPPORT_OutputType_GRINCH // SPI #define SUPPORT_OutputType_GS8208 // UART / RMT #define SUPPORT_OutputType_Renard // UART / RMT #define SUPPORT_OutputType_Serial // UART / RMT diff --git a/html/grinch.html b/html/grinch.html new file mode 100644 index 000000000..a639e88d4 --- /dev/null +++ b/html/grinch.html @@ -0,0 +1,14 @@ +
+ Grinch Configuration +
+ +
+ +
+
+ + +
+ +
+
diff --git a/html/script.js b/html/script.js index 9abae4194..de4edbced 100644 --- a/html/script.js +++ b/html/script.js @@ -324,7 +324,7 @@ $(function () { SetServerTime(); }); -function SetServerTime() +function SetServerTime() { // console.info("SetServerTime"); let CurrentDate = Math.floor((new Date()).getTime() / 1000); @@ -368,7 +368,7 @@ function MergeConfig(SourceData, TargetData, FileName, SectionName) } // MergeConfig -function JsonObjectAccess(obj, Path, value, Action) +function JsonObjectAccess(obj, Path, value, Action) { try { @@ -630,11 +630,11 @@ async function RequestConfigFile(FileName) } // RequestConfigFile -function RequestStatusUpdate() +function RequestStatusUpdate() { // console.log("RequestStatusUpdate Start: "); // is the timer running? - if (null === StatusRequestTimer) + if (null === StatusRequestTimer) { // timer runs forever StatusRequestTimer = setTimeout(function () @@ -647,7 +647,7 @@ function RequestStatusUpdate() }, 1000); } // end timer was not running - if ($('#home').is(':visible')) + if ($('#home').is(':visible')) { // ask for a status update from the server let FileName = "HTTP://" + target + "/XJ"; @@ -666,7 +666,7 @@ function RequestStatusUpdate() } // RequestStatusUpdate -async function RequestListOfFiles() +async function RequestListOfFiles() { // console.info("ask for a file list from the server, starting at " + StartingFileIndex); @@ -1139,6 +1139,16 @@ function ProcessModeConfigurationDataRelay(RelayConfig) { } // ProcessModeConfigurationDataRelay +function ProcessModeConfigurationDataGrinch(GrinchConfig) +{ + // console.log("ProcessModeConfigurationDataGrinch"); + // console.info("GrinchConfig: " + JSON.stringify(GrinchConfig)); + + $('#grinch #controller_count' ).val(GrinchConfig.count); + $('#grinch #cs_pin' ).val(GrinchConfig.cs_pin); + +} // ProcessModeConfigurationDataGrinch + function ProcessModeConfigurationDataServoPCA9685(ServoConfig) { // console.log("Servochannelconfigurationtable.rows.length = " + $('#servo_pca9685channelconfigurationtable tr').length); @@ -1213,7 +1223,9 @@ function ProcessInputConfig() { function ProcessModeConfigurationData(channelId, ChannelType, JsonConfig) { // console.info("ProcessModeConfigurationData: Start"); - + // console.info("channelId: " + channelId); + // console.info("ChannelType: " + ChannelType); + // console.info("JsonConfig: " + JSON.stringify(JsonConfig)); // determine the type of in/output that has been selected and populate the form let TypeOfChannelId = parseInt($('#' + ChannelType + channelId + " option:selected").val(), 10); let channelConfigSet = JsonConfig.channels[channelId]; @@ -1279,6 +1291,11 @@ function ProcessModeConfigurationData(channelId, ChannelType, JsonConfig) { ProcessModeConfigurationDataServoPCA9685(channelConfig); } + else if ("grinch" === ChannelTypeName) { + // console.info("ProcessModeConfigurationData: grinch"); + ProcessModeConfigurationDataGrinch(channelConfig); + } + UpdateAdvancedOptionsMode(); UpdateChannelCounts(); @@ -1698,6 +1715,11 @@ function ExtractChannelConfigFromHtmlPage(JsonConfig, SectionName) { ChannelConfig.MarqueeGroups = MarqueeGroups; } + else if(ChannelConfig.type === "Grinch") + { + ChannelConfig.count = $('#grinch #controller_count' ).val(); + ChannelConfig.cs_pin = $('#grinch #cs_pin' ).val(); + } else { ExtractConfigFromHtmlPages(elementids, modeControlName, ChannelConfig); } @@ -1785,7 +1807,7 @@ function int2ip(num) { } // int2ip // Ping every 4sec -function MonitorServerConnection() +function MonitorServerConnection() { // console.info("MonitorServerConnection"); let MonitorTransactionRequestInProgress = false; From 1eca5099de2553ceb1494ad7aa65ddbbfeedd0a5 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 27 Jul 2024 19:02:05 -0400 Subject: [PATCH 4/9] moved CS management into the SPI driver. --- ESPixelStick/src/output/OutputGrinch.cpp | 9 ------- ESPixelStick/src/output/OutputGrinch.hpp | 2 +- ESPixelStick/src/output/OutputGrinchSpi.cpp | 2 +- ESPixelStick/src/output/OutputSpi.cpp | 27 ++++++++++++++++++++- ESPixelStick/src/output/OutputSpi.hpp | 2 ++ 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/ESPixelStick/src/output/OutputGrinch.cpp b/ESPixelStick/src/output/OutputGrinch.cpp index dd643afe7..0733e192c 100644 --- a/ESPixelStick/src/output/OutputGrinch.cpp +++ b/ESPixelStick/src/output/OutputGrinch.cpp @@ -102,10 +102,6 @@ bool c_OutputGrinch::SetConfig (ArduinoJson::JsonObject& jsonConfig) // DEBUG_V(String(" NumberOfGrinchDataBytes: ") + String(NumberOfGrinchDataBytes)); SetOutputBufferSize(NumberOfGrinchChannels); - // turn off the outout strobe (latch data) - pinMode(DataStrobe, OUTPUT); - digitalWrite(DataStrobe, HIGH); - // Calculate our refresh time // SetFrameDurration (((1.0 / float (GRINCH_BIT_RATE)) * MicroSecondsInASecond), BlockSize, BlockDelay); @@ -132,11 +128,6 @@ void c_OutputGrinch::StartNewFrame() { // DEBUG_START; - // put the shift registers into clock through mode. - digitalWrite(DataStrobe, HIGH); - delay(1); - digitalWrite(DataStrobe, LOW); - // build the data frame uint32_t NumChannelsToProcess = GetNumOutputBufferBytesNeeded(); uint8_t * pInputData = GetBufferAddress(); diff --git a/ESPixelStick/src/output/OutputGrinch.hpp b/ESPixelStick/src/output/OutputGrinch.hpp index 7d4f82582..87d8bbc5c 100644 --- a/ESPixelStick/src/output/OutputGrinch.hpp +++ b/ESPixelStick/src/output/OutputGrinch.hpp @@ -51,12 +51,12 @@ class c_OutputGrinch : public c_OutputCommon #define MAX_NUM_SUPPORTED_GRINCHES 4 #define DATA_CHANNELS_PER_GRINCH 64 + gpio_num_t DataStrobe = DEFAULT_SPI_CS_GPIO; private: uint8_t NumberOfGrinchControllers = 1; uint8_t NumberOfGrinchChannels = NumberOfGrinchControllers * DATA_CHANNELS_PER_GRINCH; uint8_t NumberOfGrinchDataBytes = NumberOfGrinchChannels / 8; - gpio_num_t DataStrobe = DEFAULT_SPI_CS_GPIO; uint64_t dataBuffer[MAX_NUM_SUPPORTED_GRINCHES]; uint8_t SpiOutputDataByteIndex = 0; diff --git a/ESPixelStick/src/output/OutputGrinchSpi.cpp b/ESPixelStick/src/output/OutputGrinchSpi.cpp index 64ec16f35..69e5e83f9 100644 --- a/ESPixelStick/src/output/OutputGrinchSpi.cpp +++ b/ESPixelStick/src/output/OutputGrinchSpi.cpp @@ -52,7 +52,7 @@ void c_OutputGrinchSpi::Begin () { // DEBUG_START; Spi.Begin (this); - + Spi.SetCsPin(DataStrobe); HasBeenInitialized = true; // DEBUG_END; diff --git a/ESPixelStick/src/output/OutputSpi.cpp b/ESPixelStick/src/output/OutputSpi.cpp index 6f4003274..0d22f1e18 100644 --- a/ESPixelStick/src/output/OutputSpi.cpp +++ b/ESPixelStick/src/output/OutputSpi.cpp @@ -140,7 +140,7 @@ void c_OutputSpi::Begin (c_OutputPixel* _OutputPixel) SpiDeviceConfiguration.clock_speed_hz = SPI_SPI_MASTER_FREQ_1M; SpiDeviceConfiguration.mode = 0; // SPI mode 0 SpiDeviceConfiguration.spics_io_num = -1; // we will NOT use CS pin - SpiDeviceConfiguration.queue_size = 10 * SPI_NUM_TRANSACTIONS; // We want to be able to queue 2 transactions at a time + SpiDeviceConfiguration.queue_size = 1; // We want to be able to queue 2 transactions at a time // SpiDeviceConfiguration.pre_cb = nullptr; // Specify pre-transfer callback to handle D/C line SpiDeviceConfiguration.post_cb = spi_transfer_callback; // Specify post-transfer callback to handle D/C line // SpiDeviceConfiguration.flags = 0; @@ -223,12 +223,30 @@ void c_OutputSpi::SendIntensityData () TransactionToFill.length++; } + if(gpio_num_t(-1) != cs_pin) + { + // turn on the output strobe (latch data) + digitalWrite(cs_pin, LOW); + } + ESP_ERROR_CHECK (spi_device_queue_trans (spi_device_handle, &Transactions[NextTransactionToFill], portMAX_DELAY)); if (++NextTransactionToFill >= SPI_NUM_TRANSACTIONS) { NextTransactionToFill = 0; } + + if(gpio_num_t(-1) != cs_pin) + { + if (!ISR_MoreDataToSend ()) + { + spi_transaction_t * pspi_transaction = &TransactionToFill; + spi_device_get_trans_result(spi_device_handle, &pspi_transaction, 100); + + // turn on the output strobe (latch data) + digitalWrite(cs_pin, HIGH); + } + } } // DEBUG_END; @@ -262,6 +280,12 @@ bool c_OutputSpi::Poll () StartNewFrame (); + if(gpio_num_t(-1) != cs_pin) + { + // turn on the output strobe (latch data) + pinMode(cs_pin, OUTPUT); + } + // fill all the available buffers NextTransactionToFill = 0; for (auto& TransactionToFill : Transactions) @@ -271,6 +295,7 @@ bool c_OutputSpi::Poll () vTaskResume (SendIntensityDataTaskHandle); } } + spi_transfer_callback_enabled = true; Response = true; diff --git a/ESPixelStick/src/output/OutputSpi.hpp b/ESPixelStick/src/output/OutputSpi.hpp index 240a7ae0c..d4ccd4af2 100644 --- a/ESPixelStick/src/output/OutputSpi.hpp +++ b/ESPixelStick/src/output/OutputSpi.hpp @@ -49,6 +49,7 @@ class c_OutputSpi void GetDriverName (String& Name) { Name = CN_OutputSpi; } void DataOutputTask (void* pvParameters); void SendIntensityData (); + void SetCsPin(gpio_num_t _cs_pin) {cs_pin = _cs_pin;} uint32_t DataTaskcounter = 0; uint32_t DataCbCounter = 0; @@ -69,6 +70,7 @@ class c_OutputSpi uint8_t NumIntensityValuesPerInterrupt = 0; uint8_t NumIntensityBitsPerInterrupt = 0; spi_device_handle_t spi_device_handle = 0; + gpio_num_t cs_pin = gpio_num_t(-1); // uint32_t FrameStartCounter = 0; uint32_t SendIntensityDataCounter = 0; From 8e6bfacfc7b380e67346a509e046ea7273d534dd Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 28 Jul 2024 11:06:00 -0400 Subject: [PATCH 5/9] Added missing file manager flag. --- ESPixelStick/src/FileMgr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ESPixelStick/src/FileMgr.cpp b/ESPixelStick/src/FileMgr.cpp index 10eeb1730..4794e9163 100644 --- a/ESPixelStick/src/FileMgr.cpp +++ b/ESPixelStick/src/FileMgr.cpp @@ -1705,7 +1705,7 @@ void c_FileMgr::BuildFseqList() // open output file, erase old data ESP_SD.chdir(); // Set to sd root - FileMgr.DeleteSdFile(String(FSEQFILELIST)); + DeleteSdFile(String(FSEQFILELIST)); FsFile OutputFile; if(!OutputFile.open (String(F(FSEQFILELIST)).c_str(), O_WRITE | O_CREAT)) @@ -1810,7 +1810,7 @@ void c_FileMgr::BuildFseqList() OutputFile.print(String("], \"usedBytes\" : ") + int64String(usedBytes)); // LOG_PORT.print(String("], \"usedBytes\" : ") + int64String(usedBytes)); OutputFile.print(String(", \"numFiles\" : ") + String(numFiles)); - // LOG_PORT.print(String(", \"numFiles\" : ") + String(numFiles)); + OutputFile.print(String(", \"SdCardPresent\" : true")); // close the data section OutputFile.print("}"); From af096965ad58b837faa46a2a8b2a75a25a5cdcf7 Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 28 Jul 2024 11:06:30 -0400 Subject: [PATCH 6/9] Fixed a comment --- ESPixelStick/src/output/OutputGrinch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ESPixelStick/src/output/OutputGrinch.cpp b/ESPixelStick/src/output/OutputGrinch.cpp index 0733e192c..9cb33b171 100644 --- a/ESPixelStick/src/output/OutputGrinch.cpp +++ b/ESPixelStick/src/output/OutputGrinch.cpp @@ -147,8 +147,8 @@ void c_OutputGrinch::StartNewFrame() OutputData = 0; } - // set the output bit to one if the output is greater than half on - OutputData = (OutputData << 1) | (pInputData[0] < 128); + // set the output bit to ON (zero) if the output is greater than 50% intensity + OutputData = (OutputData << 1) | (*pInputData < 128); dataBuffer[OutputDataIndex] = OutputData; pInputData ++; bitCounter ++; From a08285c26f8312cbb9ca7356c33f5642cb1db063 Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 28 Jul 2024 12:37:13 -0400 Subject: [PATCH 7/9] Added Grinch support to more platforms --- .../src/platformDefinitions/GPIO_Defs_ESP32_BreakDanceV2.hpp | 2 ++ .../platformDefinitions/GPIO_Defs_ESP32_MH_ET_LIVE_MiniKit.hpp | 2 ++ .../src/platformDefinitions/GPIO_Defs_ESP32_Tetra2go.hpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_BreakDanceV2.hpp b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_BreakDanceV2.hpp index f23cfc1a0..28234ea0e 100644 --- a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_BreakDanceV2.hpp +++ b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_BreakDanceV2.hpp @@ -28,6 +28,7 @@ #define SUPPORT_SPI_OUTPUT #define DEFAULT_SPI_DATA_GPIO gpio_num_t::GPIO_NUM_27 #define DEFAULT_SPI_CLOCK_GPIO gpio_num_t::GPIO_NUM_32 +#define DEFAULT_SPI_CS_GPIO gpio_num_t::GPIO_NUM_0 #define DEFAULT_SPI_DEVICE VSPI_HOST #define DEFAULT_I2C_SDA gpio_num_t::GPIO_NUM_3 @@ -47,6 +48,7 @@ #define SUPPORT_OutputType_APA102 // SPI #define SUPPORT_OutputType_DMX // UART / RMT #define SUPPORT_OutputType_GECE // UART / RMT +#define SUPPORT_OutputType_GRINCH // SPI #define SUPPORT_OutputType_GS8208 // UART / RMT #define SUPPORT_OutputType_Renard // UART / RMT #define SUPPORT_OutputType_Serial // UART / RMT diff --git a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_MH_ET_LIVE_MiniKit.hpp b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_MH_ET_LIVE_MiniKit.hpp index 6812e4ce6..629da7cce 100644 --- a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_MH_ET_LIVE_MiniKit.hpp +++ b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_MH_ET_LIVE_MiniKit.hpp @@ -33,6 +33,7 @@ #define SUPPORT_SPI_OUTPUT #define DEFAULT_SPI_DATA_GPIO gpio_num_t::GPIO_NUM_16 #define DEFAULT_SPI_CLOCK_GPIO gpio_num_t::GPIO_NUM_17 +#define DEFAULT_SPI_CS_GPIO gpio_num_t::GPIO_NUM_0 #define DEFAULT_SPI_DEVICE VSPI_HOST #define DEFAULT_I2C_SDA gpio_num_t::GPIO_NUM_21 @@ -51,6 +52,7 @@ #define SUPPORT_OutputType_DMX // UART #define SUPPORT_OutputType_GECE // UART #define SUPPORT_OutputType_GS8208 // UART / RMT +#define SUPPORT_OutputType_GRINCH // SPI #define SUPPORT_OutputType_Renard // UART #define SUPPORT_OutputType_Serial // UART #define SUPPORT_OutputType_TM1814 // UART / RMT diff --git a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_Tetra2go.hpp b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_Tetra2go.hpp index d42a5cc9e..61613f533 100644 --- a/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_Tetra2go.hpp +++ b/ESPixelStick/src/platformDefinitions/GPIO_Defs_ESP32_Tetra2go.hpp @@ -28,6 +28,7 @@ #define SUPPORT_SPI_OUTPUT #define DEFAULT_SPI_DATA_GPIO gpio_num_t::GPIO_NUM_15 #define DEFAULT_SPI_CLOCK_GPIO gpio_num_t::GPIO_NUM_25 +#define DEFAULT_SPI_CS_GPIO gpio_num_t::GPIO_NUM_0 #define DEFAULT_SPI_DEVICE VSPI_HOST #define DEFAULT_I2C_SDA gpio_num_t::GPIO_NUM_21 @@ -46,6 +47,7 @@ #define SUPPORT_OutputType_DMX // UART #define SUPPORT_OutputType_GECE // UART #define SUPPORT_OutputType_GS8208 // UART / RMT +#define SUPPORT_OutputType_GRINCH // SPI #define SUPPORT_OutputType_Renard // UART #define SUPPORT_OutputType_Serial // UART #define SUPPORT_OutputType_TM1814 // UART / RMT From 8d3f403e33432d6b7e87f4d1010497dd59f6fb58 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 2 Aug 2024 11:26:58 -0400 Subject: [PATCH 8/9] Moved to using GIT for 64 bit string library --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 109b01d98..408d2363a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -24,12 +24,12 @@ lib_compat_mode = strict lib_deps = adafruit/Adafruit PWM Servo Driver Library @ 2.4.0 https://github.com/bblanchon/ArduinoJson @ 7.1.0 - djgrrr/Int64String @ 1.1.1 + https://github.com/djGrrr/Int64String @ 1.1.1 https://github.com/esphome/ESPAsyncWebServer#4fd0a1fdf421664214a27373c0eb0247f94b7a79 https://github.com/forkineye/ESPAsyncE131 ottowinter/AsyncMqttClient-esphome @ 0.8.6 https://github.com/MartinMueller2003/Artnet - https://github.com/MartinMueller2003/Espalexa ; pull latest + https://github.com/MartinMueller2003/Espalexa https://github.com/PaulStoffregen/Time https://github.com/greiman/SdFat @ 2.2.3 https://github.com/MartinMueller2003/SimpleFTPServer From 0ff6d975db0e24bd5d274eae0267e8f4d5c56550 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 2 Aug 2024 11:31:04 -0400 Subject: [PATCH 9/9] Style change to satisfy the style checker --- ESPixelStick/src/output/OutputGrinch.cpp | 14 ++++++++------ ESPixelStick/src/output/OutputGrinch.hpp | 23 ++++++++++++++++++----- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/ESPixelStick/src/output/OutputGrinch.cpp b/ESPixelStick/src/output/OutputGrinch.cpp index 9cb33b171..8d71eb457 100644 --- a/ESPixelStick/src/output/OutputGrinch.cpp +++ b/ESPixelStick/src/output/OutputGrinch.cpp @@ -33,6 +33,7 @@ c_OutputGrinch::c_OutputGrinch (c_OutputMgr::e_OutputChannelIds OutputChannelId, // InterFrameGapInMicroSec = GRINCH_MIN_IDLE_TIME_US; + memset(dataBuffer, 0x00, sizeof(dataBuffer)); // DEBUG_END; } // c_OutputGrinch @@ -116,7 +117,7 @@ bool IRAM_ATTR c_OutputGrinch::ISR_GetNextIntensityToSend (uint32_t &DataToSend) if(ISR_MoreDataToSend()) { // DEBUG_V(String("DataToSend: ") + String(DataToSend)); - DataToSend = ((uint8_t*)&dataBuffer[0])[SpiOutputDataByteIndex-1]; + DataToSend = dataBuffer[0].Data[SpiOutputDataByteIndex-1]; SpiOutputDataByteIndex--; } @@ -131,8 +132,8 @@ void c_OutputGrinch::StartNewFrame() // build the data frame uint32_t NumChannelsToProcess = GetNumOutputBufferBytesNeeded(); uint8_t * pInputData = GetBufferAddress(); - uint64_t OutputData = 0; - uint8_t OutputDataIndex = 0; + uint8_t OutputData = 0; + uint8_t OutputDataByteIndex = 0; uint8_t bitCounter = 0; while(NumChannelsToProcess) @@ -140,16 +141,17 @@ void c_OutputGrinch::StartNewFrame() if(bitCounter >= (sizeof(OutputData) * 8)) { // write the output data - OutputDataIndex ++; + OutputDataByteIndex ++; - // move to the next controller + // move to the next data byte bitCounter = 0; + // clear the starting data OutputData = 0; } // set the output bit to ON (zero) if the output is greater than 50% intensity OutputData = (OutputData << 1) | (*pInputData < 128); - dataBuffer[OutputDataIndex] = OutputData; + dataBuffer[0].Data[OutputDataByteIndex] = OutputData; pInputData ++; bitCounter ++; NumChannelsToProcess--; diff --git a/ESPixelStick/src/output/OutputGrinch.hpp b/ESPixelStick/src/output/OutputGrinch.hpp index 87d8bbc5c..3896587bb 100644 --- a/ESPixelStick/src/output/OutputGrinch.hpp +++ b/ESPixelStick/src/output/OutputGrinch.hpp @@ -54,11 +54,24 @@ class c_OutputGrinch : public c_OutputCommon gpio_num_t DataStrobe = DEFAULT_SPI_CS_GPIO; private: - uint8_t NumberOfGrinchControllers = 1; - uint8_t NumberOfGrinchChannels = NumberOfGrinchControllers * DATA_CHANNELS_PER_GRINCH; - uint8_t NumberOfGrinchDataBytes = NumberOfGrinchChannels / 8; - uint64_t dataBuffer[MAX_NUM_SUPPORTED_GRINCHES]; - uint8_t SpiOutputDataByteIndex = 0; + uint8_t NumberOfGrinchControllers = 1; + uint8_t NumberOfGrinchChannels = NumberOfGrinchControllers * DATA_CHANNELS_PER_GRINCH; + uint8_t NumberOfGrinchDataBytes = NumberOfGrinchChannels / 8; + uint8_t SpiOutputDataByteIndex = 0; + + union GrinchData_s + { + struct GrinchLatchData + { + uint8_t LatchChan_01_08 = 0; + uint8_t LatchChan_09_16 = 0; + uint8_t LatchChan_17_24 = 0; + uint8_t LatchChan_25_32 = 0; + }; + uint8_t Data[4]; + }; + GrinchData_s dataBuffer[MAX_NUM_SUPPORTED_GRINCHES]; + }; // c_OutputGrinch #endif // def SUPPORT_OutputType_GRINCH