Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Grinch support #779

Merged
merged 9 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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