Skip to content

Commit

Permalink
Merge pull request #779 from MartinMueller2003/main
Browse files Browse the repository at this point in the history
Added Grinch support
  • Loading branch information
forkineye authored Aug 2, 2024
2 parents 5fcc1b7 + 0ff6d97 commit 4a86c5d
Show file tree
Hide file tree
Showing 18 changed files with 605 additions and 26 deletions.
4 changes: 2 additions & 2 deletions ESPixelStick/src/FileMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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("}");
Expand Down
2 changes: 1 addition & 1 deletion ESPixelStick/src/output/OutputCommon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class c_OutputCommon
uint32_t OutputBufferSize = 0;
uint32_t FrameCount = 0;

void ReportNewFrame ();
virtual void ReportNewFrame ();

inline bool canRefresh ()
{
Expand Down
165 changes: 165 additions & 0 deletions ESPixelStick/src/output/OutputGrinch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* 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;

memset(dataBuffer, 0x00, sizeof(dataBuffer));
// 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);

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);

// 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)
{
if(ISR_MoreDataToSend())
{
// DEBUG_V(String("DataToSend: ") + String(DataToSend));
DataToSend = dataBuffer[0].Data[SpiOutputDataByteIndex-1];
SpiOutputDataByteIndex--;
}

return ISR_MoreDataToSend();
} // ISR_GetNextIntensityToSend

//----------------------------------------------------------------------------
void c_OutputGrinch::StartNewFrame()
{
// DEBUG_START;

// build the data frame
uint32_t NumChannelsToProcess = GetNumOutputBufferBytesNeeded();
uint8_t * pInputData = GetBufferAddress();
uint8_t OutputData = 0;
uint8_t OutputDataByteIndex = 0;
uint8_t bitCounter = 0;

while(NumChannelsToProcess)
{
if(bitCounter >= (sizeof(OutputData) * 8))
{
// write the output data
OutputDataByteIndex ++;

// 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[0].Data[OutputDataByteIndex] = OutputData;
pInputData ++;
bitCounter ++;
NumChannelsToProcess--;
}

SpiOutputDataByteIndex = NumberOfGrinchDataBytes;

// DEBUG_END;
} // StartNewFrame

#endif // def SUPPORT_OutputType_GRINCH
77 changes: 77 additions & 0 deletions ESPixelStick/src/output/OutputGrinch.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#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 (NumberOfGrinchChannels); }
uint32_t GetNumOutputBufferChannelsServiced () { return (NumberOfGrinchChannels); }

void StartNewFrame();
inline bool IRAM_ATTR ISR_MoreDataToSend () {return SpiOutputDataByteIndex > 0;}
bool IRAM_ATTR ISR_GetNextIntensityToSend (uint32_t &DataToSend);

protected:

#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;
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
108 changes: 108 additions & 0 deletions ESPixelStick/src/output/OutputGrinchSpi.cpp
Original file line number Diff line number Diff line change
@@ -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);
Spi.SetCsPin(DataStrobe);
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)
Loading

0 comments on commit 4a86c5d

Please sign in to comment.