including light effects from different project

This commit is contained in:
2024-12-15 22:46:44 +01:00
parent e4621f8ad8
commit 6db9bd85a5
20 changed files with 1533 additions and 43 deletions
+4
View File
@@ -0,0 +1,4 @@
idf_component_register(
SRC_DIRS "src"
INCLUDE_DIRS "include"
)
+202
View File
@@ -0,0 +1,202 @@
/**
* @file color.hpp
* @author Gustice
* @brief
*
* @copyright Copyright (c) 2024
*/
#pragma once
#include <cassert>
#include <cstdint>
#include <cstring>
#include <type_traits>
/// No Waveform definition
extern uint8_t const *const noWave;
/**
* @brief Color class
*
* @details Defines color data and common operations with color objects
* \li Supports RGB with overlapping white channel (e.g. SK6812-LED)
* \li Supports Operator overloading with '+' and '*' (Combined operation with MixWith)
* \li Return formatted data stream that can be directly sent to an LED
*/
class Color {
private:
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t white;
public:
struct Rgbw {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t white;
};
struct Rgb {
uint8_t red;
uint8_t green;
uint8_t blue;
};
/// @brief Construct a new Color object
/// @details Default color will be Black \ref _ctBlack
Color(void) {
set(0, 0, 0, 0);
};
/// @brief Copy-Construct a new Color object
Color(const Color & c) {
red = c.red;
green = c.green;
blue = c.blue;
white = c.white;
};
/// @brief Construct a new Color object according to rgb color-channel-values
/// @details This constructor also takes an overlapping white channel
/// @param r Red channel
/// @param g Green channel
/// @param b Blue channel
/// @param w White channel (zero by default if not assigned)
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { set(r, g, b, w); };
/// @brief Set the Color object according to rgb color-channel values
/// @param r Red channel
/// @param g Green channel
/// @param b Blue channel
/// @param w White channel (zero by default if not assigned)
void set(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
red = r;
green = g;
blue = b;
white = w;
}
/// @brief Returns Color as Color_t structure
/// @return Color_t Color
template <typename T>
T getColor(void) const {
if constexpr (std::is_same<T, Rgbw>::value) {
return {red, green, blue, white};
} else if constexpr (std::is_same<T, Rgb>::value) {
return {red, green, blue};
} else {
throw "wrong type";
}
}
uint8_t getRed() { return red; };
uint8_t getGreen() { return green; };
uint8_t getBlue() { return blue; };
uint8_t getWhite() { return white; };
/// @brief Scaling and overlaying with given color.
/// @param c2 Color 2
/// @param k scaling factor
/// @return Overlayed Color
Color mixWith(const Color c2, uint8_t k = 0x7F) {
auto t(c2);
*this = (*this * (UINT8_MAX - k)) + (t * k);
return *this;
}
/// @brief Writes Color as formatted byte stream to location
/// @param color
template <typename T>
void writeByteStreamTo(uint8_t raw[sizeof(T)]) const {
if constexpr (std::is_same<T, Rgbw>::value) {
raw[0] = blue;
raw[1] = green;
raw[2] = red;
raw[3] = white;
} else if constexpr (std::is_same<T, Rgb>::value) {
raw[0] = blue;
raw[1] = green;
raw[2] = red;
} else {
throw "wrong type";
}
}
/// @brief Assign overload
Color operator=(const Color &c2) {
red = c2.red;
green = c2.green;
blue = c2.blue;
white = c2.white;
return *this;
}
/// @brief Checks if both color values are equal
bool operator==(Color const &c2) const {
return ((blue == c2.blue) && (green == c2.green) &&
(red == c2.red) && (white == c2.white));
}
/// @brief Checks if both color values are not equal
bool operator!=(Color const &c2) const {
return ((blue != c2.blue) || (green != c2.green) ||
(red != c2.red) || (white != c2.white));
}
/// @brief Scale color by scaling each color-channel by given factor
/// @param c1 Color
/// @param k Scale-factor uint8_t.Max is full-scale
/// @return Scaled Color
Color operator*(uint8_t k) {
red = (uint8_t)((uint16_t)red * k / 0xFF);
green = (uint8_t)((uint16_t)green * k / 0xFF);
blue = (uint8_t)((uint16_t)blue * k / 0xFF);
white = (uint8_t)((uint16_t)white * k / 0xFF);
return *this;
}
/// @brief Overlaying to colors my adding each color channel value
/// @note Colors channels should not overlap since there is no automatic ratio correction.
/// Use *-Operator first in order to scale each color value a a way that no overflow can occur
/// @param c2 Color 2
/// @return Overlayed Color
Color operator+(Color c2) {
red = red + c2.red;
green = green + c2.green;
blue = blue + c2.blue;
white = white + c2.white;
return *this;
}
};
static_assert(sizeof(Color) == 4 && "Color Type is to big");
/// Null color object
extern const Color *noColor;
/// Used old color agreement (if no color pointer)
extern const Color *oldColor;
/// Black color object constant
extern const Color CBlack;
/// Red color object constant
extern const Color CRed;
/// Green color object constant
extern const Color CGreen;
/// Blue color object constant
extern const Color CBlue;
/// Magenta color object constant
extern const Color CMagenta;
/// Cyan color object constant
extern const Color CCyan;
/// Yellow color object constant
extern const Color CYellow;
/// White color object constant
extern const Color CWhite;
/// Warm white color object constant (with higher red channel value)
extern const Color CWarmWhite;
/// Black color object constant (with higher green channel value)
extern const Color CColdWhite;
/// Black color object constant (with higher blue channel value)
extern const Color CSpookyWhite;
+202
View File
@@ -0,0 +1,202 @@
/**
* @file color.hpp
* @author Gustice
* @brief
*
* @copyright Copyright (c) 2024
*/
#pragma once
#include <cassert>
#include <cstdint>
#include <cstring>
#include <type_traits>
/// No Waveform definition
extern uint8_t const *const noWave;
/**
* @brief Color class
*
* @details Defines color data and common operations with color objects
* \li Supports RGB with overlapping white channel (e.g. SK6812-LED)
* \li Supports Operator overloading with '+' and '*' (Combined operation with MixWith)
* \li Return formatted data stream that can be directly sent to an LED
*/
class Color {
private:
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t white;
public:
struct Rgbw {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t white;
};
struct Rgb {
uint8_t red;
uint8_t green;
uint8_t blue;
};
/// @brief Construct a new Color object
/// @details Default color will be Black \ref _ctBlack
Color(void) {
set(0, 0, 0, 0);
};
/// @brief Copy-Construct a new Color object
Color(const Color & c) {
red = c.red;
green = c.green;
blue = c.blue;
white = c.white;
};
/// @brief Construct a new Color object according to rgb color-channel-values
/// @details This constructor also takes an overlapping white channel
/// @param r Red channel
/// @param g Green channel
/// @param b Blue channel
/// @param w White channel (zero by default if not assigned)
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { set(r, g, b, w); };
/// @brief Set the Color object according to rgb color-channel values
/// @param r Red channel
/// @param g Green channel
/// @param b Blue channel
/// @param w White channel (zero by default if not assigned)
void set(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
red = r;
green = g;
blue = b;
white = w;
}
/// @brief Returns Color as Color_t structure
/// @return Color_t Color
template <typename T>
T getColor(void) const {
if constexpr (std::is_same<T, Rgbw>::value) {
return {red, green, blue, white};
} else if constexpr (std::is_same<T, Rgb>::value) {
return {red, green, blue};
} else {
throw "wrong type";
}
}
uint8_t getRed() { return red; };
uint8_t getGreen() { return green; };
uint8_t getBlue() { return blue; };
uint8_t getWhite() { return white; };
/// @brief Scaling and overlaying with given color.
/// @param c2 Color 2
/// @param k scaling factor
/// @return Overlayed Color
Color mixWith(const Color c2, uint8_t k = 0x7F) {
auto t(c2);
*this = (*this * (UINT8_MAX - k)) + (t * k);
return *this;
}
/// @brief Writes Color as formatted byte stream to location
/// @param color
template <typename T>
void writeByteStreamTo(uint8_t raw[sizeof(T)]) const {
if constexpr (std::is_same<T, Rgbw>::value) {
raw[0] = blue;
raw[1] = green;
raw[2] = red;
raw[3] = white;
} else if constexpr (std::is_same<T, Rgb>::value) {
raw[0] = blue;
raw[1] = green;
raw[2] = red;
} else {
throw "wrong type";
}
}
/// @brief Assign overload
Color operator=(const Color &c2) {
red = c2.red;
green = c2.green;
blue = c2.blue;
white = c2.white;
return *this;
}
/// @brief Checks if both color values are equal
bool operator==(Color const &c2) const {
return ((blue == c2.blue) && (green == c2.green) &&
(red == c2.red) && (white == c2.white));
}
/// @brief Checks if both color values are not equal
bool operator!=(Color const &c2) const {
return ((blue != c2.blue) || (green != c2.green) ||
(red != c2.red) || (white != c2.white));
}
/// @brief Scale color by scaling each color-channel by given factor
/// @param c1 Color
/// @param k Scale-factor uint8_t.Max is full-scale
/// @return Scaled Color
Color operator*(uint8_t k) {
red = (uint8_t)((uint16_t)red * k / 0xFF);
green = (uint8_t)((uint16_t)green * k / 0xFF);
blue = (uint8_t)((uint16_t)blue * k / 0xFF);
white = (uint8_t)((uint16_t)white * k / 0xFF);
return *this;
}
/// @brief Overlaying to colors my adding each color channel value
/// @note Colors channels should not overlap since there is no automatic ratio correction.
/// Use *-Operator first in order to scale each color value a a way that no overflow can occur
/// @param c2 Color 2
/// @return Overlayed Color
Color operator+(Color c2) {
red = red + c2.red;
green = green + c2.green;
blue = blue + c2.blue;
white = white + c2.white;
return *this;
}
};
static_assert(sizeof(Color) == 4 && "Color Type is to big");
/// Null color object
extern const Color *noColor;
/// Used old color agreement (if no color pointer)
extern const Color *oldColor;
/// Black color object constant
extern const Color CBlack;
/// Red color object constant
extern const Color CRed;
/// Green color object constant
extern const Color CGreen;
/// Blue color object constant
extern const Color CBlue;
/// Magenta color object constant
extern const Color CMagenta;
/// Cyan color object constant
extern const Color CCyan;
/// Yellow color object constant
extern const Color CYellow;
/// White color object constant
extern const Color CWhite;
/// Warm white color object constant (with higher red channel value)
extern const Color CWarmWhite;
/// Black color object constant (with higher green channel value)
extern const Color CColdWhite;
/// Black color object constant (with higher blue channel value)
extern const Color CSpookyWhite;
@@ -0,0 +1,60 @@
/**
* @file ExactIndex.h
* @author Gustice
* @brief Index-Class with fix-point arithmetic
*/
#pragma once
#include <algorithm>
#include <cstdint>
/**
* @brief Index-Class with fix-point arithmetic for exact stepping though data-points
* @details Allows stepping through data-points by quotient step-sizes
*/
class ExactIndex {
public:
/// @brief Construct Index-object according to number of data points and steps to be taken
/// @param length
/// @param steps
ExactIndex(unsigned length, uint16_t steps) : Length(std::max(1u, length)), Steps(steps) {
_delta = Length << 8;
_delta = _delta / steps;
_index = unsigned(0u - _delta);
}
/// @brief Get current index-position as floor value to never pass upper bound
uint16_t GetIdx(void) { return ((_index) >> 8); };
/// @brief Move index by quotient step forward
ExactIndex &operator++() {
_index = _index + _delta;
return *this;
}
/// @brief Move index by quotient step backward
ExactIndex &operator--() {
_index = _index - _delta;
return *this;
}
/// @brief Get current index-position as floor value to never pass upper bound
operator int() const { return ((_index) >> 8); }
/// @brief Get size of data set (number of data points)
unsigned GetLength() { return Length; }
/// @brief Get number of steps that are to be taken though data set
uint16_t GetSteps() { return Steps; }
private:
/// @brief Number of data points
unsigned Length;
/// @brief Steps to be taken through data-set
uint16_t Steps;
/// @brief Current index in fixed-point representation
unsigned _index = 0;
/// @brief Step-with in fixed-point representation
unsigned _delta;
};
+95
View File
@@ -0,0 +1,95 @@
/**
* @file Macro.h
* @author Gustice
* @brief Predefined effect macros
*
* @copyright Copyright (c) 2024
*/
#pragma once
#include "Color.hpp"
#include "Waveform.hpp"
#include <cstdint>
#include <vector>
namespace Effect {
/// Collection of process values to maintain processing state machine
struct StepProcessVars {
/// @brief Reference of current color
const Color &pCurentColor;
/// @brief Number of color entries
uint8_t ColorLen;
/// @brief Idle value for intensity
uint8_t IdleIntensity;
/// @brief Full value for intensity
uint8_t FullIntensity;
/// @brief Dynamic range for effects
uint8_t DynamicRange;
/// @brief Index in current waveform
uint16_t waveIdx;
/// @brief Reference to processed waveform
const WaveForm_t *const pWave;
};
/**
* @brief Effect implementation for State-Machine
* @details State-Machine invokes referred effect-implementation during processing
*/
typedef Color (*EffectImplementation)(StepProcessVars &pcsParam);
/**
* @brief Definition of Effect-Macro
*/
struct Macro_t {
/// @brief Effect type
const EffectImplementation pImplementation;
/// @brief Effect duration waveforms will be compressed / stretched to fit the duration
const uint8_t Duration;
/// @brief Next SubEffect
const int8_t Next;
/// @brief waveform reference
const WaveForm_t *pWave = emptyWave;
/// @brief Full-Scale-intensity
const uint8_t FsIntensity;
/// @brief Num of Repeats
const int8_t Repeats;
Macro_t(uint8_t duration, int8_t next, EffectImplementation state, uint8_t intensity,
int8_t repeats = 0)
: pImplementation(state), Duration(duration), Next(next), FsIntensity(intensity),
Repeats(repeats) {}
Macro_t(uint8_t duration, int8_t next, WaveForm_t const *wave, EffectImplementation state,
uint8_t intensity, int8_t repeats = 0)
: pImplementation(state), Duration(duration), Next(next), pWave(wave),
FsIntensity(intensity), Repeats(repeats) {}
private:
/// @brief Null-pointer to represent no change in color
static constexpr Color *pOldColor = nullptr;
/// @brief Null-pointer to represent no actual waveform-representation
static constexpr WaveForm_t *pNoWave = nullptr;
/// @brief Default implemented Waveform with no profile
static const constexpr WaveForm_t *emptyWave = &EmptyWave;
};
using Macro = std::vector<Macro_t>;
/// @brief Dark - Nothing to see here
extern const Macro macDark;
/// @brief Continuous idle
extern const Macro macIdle;
/// @brief Continuous flicker
extern const Macro macStartFlicker;
/// @brief Smooth turn on and then remaining idle
extern const Macro macStartIdle;
/// @brief Smooth turn on to full color
extern const Macro macStartFull;
/// @brief Slow pulse starting from idle intensity. Appears like breathing
extern const Macro macStdPulse;
/// @brief Short pulses starting from idle intensity. Appears nervously.
extern const Macro macNervousPulse;
} // namespace Effect
@@ -0,0 +1,53 @@
/**
* @file EffectProcessor.h
* @author Gustice
* @brief Effect-Processor-Class for processing effect scenarios and switching actions
*
* @copyright Copyright (c) 2024
*/
#pragma once
#include "Color.hpp"
#include "Macro.hpp"
#include "StateMachine.hpp"
#include <array>
#include <cstdint>
namespace Effect {
/**
* @brief EffectProcessor Class
* @details Maintains State-Machines, Processes effect-switching, and invokes generation
* of raw data stream for LEDs.
* \li If effect scenarios are changed a cross-fading is executed
* \li Raw-data-stream for each Color object is generated
*/
class EffectProcessor {
public:
///@brief Constructor
///@param fadeSteps Steps count for cross fade
EffectProcessor(uint8_t const fadeSteps = 8);
/// @brief Set next effect sequence
/// @param sequence reference to sequence that has to be processed next
/// @param sColor Start color. Use noColor to start with default color
/// @param intens Idle intensity for effect. Use NULL to start with default intensity
void setEffect(const Macro &sequence, Color const *sColor = noColor, uint8_t delay = 0, uint8_t intens = gu8_idleIntensity);
/// @brief Execute step of effect processor
/// @return Reference to color result
Color tick(void);
private:
StateMachine::Parameter _parameter;
std::array<StateMachine, 2> _effectMachines;
uint8_t _fadeSteps;
uint8_t _fadingCnt;
StateMachine *_EffPV;
StateMachine *_EffPV_old;
Color crossFadeColors(Color &cNew, Color &cOld, uint8_t k);
EffectProcessor();
};
} // namespace Effect
@@ -0,0 +1,118 @@
/**
* @file EffectStateMachine.h
* @author Gustice
* @brief Effect-State-Machine-Class for processing Effect Macros
* @version 0.6
* @date 2019-10-01
*
* @copyright Copyright (c) 2019
*
*/
#pragma once
#include "Color.hpp"
#include "Macro.hpp"
#include <cstdint>
#include "ExactIndex.hpp"
namespace Effect {
/**
* @brief Effect State Machine Class
* @details Processes Effect macro array Macro entry subsequently
* Processing is executed in following manner:
* \li Index-incrementing each Tick
* \li ticks until duration \ref EffMacro is finished
* \li each tick the index incremented by templateLength/duration
* \li Repeats-processing
* \li Each repeat the tick and the index are set back to start
* \li Switches to next Macro enty
* \li Next entry is given by 'next' index
* \li Color changes can be executed optionally
*/
class StateMachine {
public:
/// @brief Collection of object configuration at startup
struct Parameter {
/// @brief Idle intensity as background color
uint8_t idleIntens;
/// @brief dynamic range as variation around background color
uint8_t dynamicRange;
/// @brief Fade steps for color changes
uint8_t fadeSteps;
/// @brief Count of target LEDs
uint8_t targetCount;
};
///@brief Construct a new Effect State Machine object
///@param templateLength Length of waveforms that are used to display
StateMachine(Parameter &parameter);
///@brief Sets the effect state machine to process given effect macro
///@param sequence reference to sequence
///@param startColor Start color. Use noColor to invoke with default color
///@param initialDelay Number of steps that are waited before effect is started
void setEffect(const Macro &sequence, Color const *startColor = noColor, uint8_t initialDelay = 0);
/// @brief Sets the effect state machine to process given effect macro
/// @param sequence reference to sequence
/// @param startColor Start color. Use noColor to invoke with default color
/// @param intens Idle intensity for effect. Use nullptr to start with default intensity
/// @param delayedStart Number of steps that are waited before effect is started
void setEffect(const Macro &sequence, Color const *startColor, const uint8_t *intens,
const uint8_t delayedStart);
/// @brief Execute step of state machine
/// @details Each tick the tick variable is decremented. After the limit is reached,
/// the current macro line is either repeated or the next macro line is started (with
/// an optional color change).\n
/// @note Tick must be called regularly. For standard light applications all 40 ms seems to be
/// a convenient values.
/// @return Color const* Reference to color result
virtual Color tick(void);
/// Black out lights
static Color UpdateBlank(StepProcessVars &pcsParam);
/// Continuous illumination in idle intensity
static Color UpdateIdle(StepProcessVars &pcsParam);
/// Keep latest state on hold
static Color UpdateFreeze(StepProcessVars &pcsParam);
/// Step through a defined waveform
static Color UpdateWave(StepProcessVars &pcsParam);
/// Step through a defined waveform backwards
static Color UpdateRevWave(StepProcessVars &pcsParam);
/// Show flicker effect with idle intensity as static part with dynamic flicker-range
static Color UpdateFlicker(StepProcessVars &pcsParam);
protected:
/// Collection of process values to maintain processing state machine
struct ProcessValues {
/// Decrementing tick, counting duration
uint8_t tick;
/// Decrementing repeats of current Effect-part
uint8_t repeats;
/// Index to macro element
uint8_t macroIdx;
/// Current index to waveform
uint16_t waveIdx;
/// Index step each tick according to duration and template length.
uint16_t waveStep;
};
/// @brief Concentrated parameter values of instance
Parameter &_params;
Color const * _curentColor;
ProcessValues _prcValues;
void SetIndexes(void);
Macro const *_p_effSeq;
Macro_t const *_p_effMac;
ExactIndex _idx;
// Color& (*apF_Effects)(StateMachine * SM);
typedef Color const *pEffPrc(StateMachine *);
};
} // namespace Effect
@@ -0,0 +1,27 @@
/**
* @file WaveForm.h
* @author Gustice
* @brief C++ encapsulated waveform definition
*/
#pragma once
#include "Waveforms.hpp"
#include <cstdint>
namespace Effect {
/**
* @brief Waveform definition based on c-definitions
*/
struct WaveForm_t {
/// @brief Reference to waveform
const uint8_t *const pWave;
/// @brief Length of waveform
const unsigned Length;
};
/// @brief Empty waveform with defined pointer to meaningless data to avoid problems
extern const WaveForm_t EmptyWave;
} // namespace Effect
@@ -0,0 +1,38 @@
/**
* @file EffectWaveforms.h
* @author Gustice
* @brief Predefined Waveforms that can be put together to a complex Waveform
* @version 0.6
* @date 2019-10-01
*
* @copyright Copyright (c) 2019
*
*/
#pragma once
#include <cstdint>
namespace Effect {
/// Length of all subsequent Template definitions
extern const uint16_t cu16_TemplateLength;
/// Idle intensity for Slopes and Pulses
extern const uint8_t gu8_idleIntensity;
/// Idle intensity for Slopes and Pulses
extern const uint8_t gu8_fullIntensity;
/// Headroom for Effects on top of idle brightness
extern const uint8_t gu8_dynamicRange;
/// Standard cross fade steps
extern const uint8_t gu8_fadeSteps;
/// Starts from idle \ref gu8_idleIntensity and represents a gaussian impulse \ref gu8_fullIntensity
extern const uint8_t gau8_offsetPulse[];
/// Starts at zero and rises to idle intensity \ref gu8_idleIntensity
extern const uint8_t gau8_initSlope[];
/// Starts from idle \ref gu8_idleIntensity and rises up to full intensity \ref gu8_fullIntensity
extern const uint8_t gau8_offsetSlope[];
/// Starts at zero and rises to full intensity \ref gu8_fullIntensity
extern const uint8_t gau8_fullSlope[];
/// Starts at zero and represents a gaussian impulse to full intensity \ref gu8_fullIntensity
extern const uint8_t gau8_fullPulse[];
} // namespace Effect
+27
View File
@@ -0,0 +1,27 @@
/**
* @file color.cpp
* @author Gustice
* @brief Implementation of Color-Class
*
* @copyright Copyright (c) 2024
*/
#include "Color.hpp"
uint8_t const * const noWave = nullptr;
const Color *noColor = nullptr;
const Color *oldColor = nullptr;
const Color CBlack(0x00, 0x00, 0x00, 0x00);
const Color CRed(0xFF, 0x00, 0x00, 0x00);
const Color CGreen(0x00, 0xFF, 0x00, 0x00);
const Color CBlue(0x00, 0x00, 0xFF, 0x00);
const Color CMagenta(0x80, 0x00, 0x80, 0x00);
const Color CCyan(0x00, 0x80, 0x80, 0x00);
const Color CYellow(0x80, 0x80, 0x00, 0x00);
const Color CWhite(0x55, 0x55, 0x55, 0x00);
const Color CWarmWhite(0x7F, 0x4F, 0x4F, 0x00);
const Color CColdWhite(0x4F, 0x4F, 0x7F, 0x00);
const Color CSpookyWhite(0x4F, 0x7F, 0x4F, 0x00);
+71
View File
@@ -0,0 +1,71 @@
/**
* @file EffectMacro.cpp
* @author Gustice
* @brief Predefined Macros
* @version 0.6
* @date 2021-03-23
*
* @copyright Copyright (c) 2021
*/
#include "Macro.hpp"
#include "Color.hpp"
#include "Waveforms.hpp"
#include "StateMachine.hpp"
namespace Effect {
const uint8_t Empty[4] = {0, 0, 0, 0};
const WaveForm_t EmptyWave{Empty, 4};
const WaveForm_t OffsetPulseWave{gau8_offsetPulse, cu16_TemplateLength};
const WaveForm_t InitSlopeWave{gau8_initSlope, cu16_TemplateLength};
const WaveForm_t OffsetSlopeWave{gau8_offsetSlope, cu16_TemplateLength};
const WaveForm_t FullSlopeWave{gau8_fullSlope, cu16_TemplateLength};
const WaveForm_t FullPulseWave{gau8_fullPulse, cu16_TemplateLength};
const Macro macDark = {
{32, 0, StateMachine::UpdateBlank, 0, 0}
};
const Macro macIdle = {
{32, 1, StateMachine::UpdateIdle, 0xFF},
{32, 1, StateMachine::UpdateIdle, 0xFF},
};
const Macro macStartIdle = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateIdle, 0xFF},
};
const Macro macStartFlicker = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateFlicker, 0xFF},
};
const Macro macStartFull = {
{24, 1, &FullSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateIdle, 0xFF},
};
const Macro macStdPulse = {
{32, 1, StateMachine::UpdateIdle, 0},
{32, 2, &OffsetPulseWave, StateMachine::UpdateWave, 0xFF},
{32, 0, StateMachine::UpdateIdle, 0},
};
const Macro macNervousPulse = {
{8, 1, StateMachine::UpdateIdle, 0},
{16, 2, &OffsetPulseWave, StateMachine::UpdateWave, 0xFF},
{8, 0, StateMachine::UpdateIdle, 0},
};
const Macro macStdWipe = {
{32, 1, StateMachine::UpdateIdle, 0},
{32, 2, &OffsetSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 3, StateMachine::UpdateFreeze, 0},
{32, 4, &OffsetSlopeWave, StateMachine::UpdateRevWave, 0xFF},
{32, 1, StateMachine::UpdateFreeze, 0},
};
} // namespace Effect
+58
View File
@@ -0,0 +1,58 @@
/**
* @file Processor.cpp
* @author Gustice
* @brief Implementation of Effect-Processor-Class EffectProcessor.h
* @version 0.6
* @date 2019-10-03
*
* @copyright Copyright (c) 2019
*/
#include "Processor.hpp"
#include "Macro.hpp"
#include "Waveforms.hpp"
#include <algorithm>
#include <math.h>
#include <stdlib.h>
namespace Effect {
EffectProcessor::EffectProcessor(uint8_t const fadeSteps)
: _parameter{0x20, 0x20, 0, 1},
_effectMachines{StateMachine{_parameter}, StateMachine{_parameter}} {
_EffPV = &_effectMachines[0];
_EffPV_old = &_effectMachines[1];
_EffPV->setEffect(macDark, noColor);
_fadeSteps = fadeSteps;
}
void EffectProcessor::setEffect(const Macro &sequence, Color const *sColor, uint8_t delay, uint8_t intens) {
_fadingCnt = _fadeSteps;
std::swap(_EffPV, _EffPV_old);
_EffPV->setEffect(sequence, sColor, &intens, delay);
}
Color EffectProcessor::tick(void) {
uint8_t k;
auto cN = (_EffPV->tick());
if (_fadingCnt > 0) { // always process soft cross dissolve between different macros
_fadingCnt--;
k = (uint16_t)_fadingCnt * 0xFF / _fadeSteps;
auto cO = (_EffPV_old->tick());
cN = crossFadeColors(cN, cO, k);
}
return cN;
}
Color EffectProcessor::crossFadeColors(Color &cNew, Color &cOld, uint8_t k) {
cOld = cOld * k;
cNew = cNew * (0xFF - k);
cNew = cNew + cOld;
return cNew;
}
} // namespace Effect
+117
View File
@@ -0,0 +1,117 @@
/**
* @file StateMachine.cpp
* @author Gustice
* @brief Implementation of Effect-State-Machine-Class EffectStateMachine.h
* @version 0.6
* @date 2019-10-01
*
* @copyright Copyright (c) 2019
*
*/
#include "StateMachine.hpp"
#include "Waveforms.hpp"
#include <math.h>
#include <stdlib.h>
namespace Effect {
/// Optional prequel for delayed start.
/// \li Duration must be != 0
/// \li Next entry will be first entry in given Effect sequence
Macro delayPrequel = {
{1, 0, StateMachine::UpdateBlank, 0, 0}
};
StateMachine::StateMachine(Parameter &parameter)
: _params(parameter), _idx(/*pseudo values*/ 1, 1) {}
void StateMachine::setEffect(const Macro &sequence, Color const *startColor, uint8_t initialDelay) {
setEffect(sequence, startColor, &_params.idleIntens, initialDelay);
}
void StateMachine::setEffect(const Macro &sequence, Color const *startColor, const uint8_t *intens,
const uint8_t delayedStart) {
if (startColor != noColor) {
_curentColor = startColor;
}
if (intens != nullptr) {
_params.idleIntens = *intens;
}
_p_effSeq = &sequence;
if (delayedStart > 0) {
_p_effMac = &delayPrequel[0];
_prcValues.tick = delayedStart;
} else {
_p_effMac = &sequence[0];
_prcValues.tick = _p_effMac->Duration;
}
_prcValues.tick++;
_prcValues.repeats = _p_effMac->Repeats;
_idx = ExactIndex(_p_effMac->pWave->Length, _p_effMac->Duration);
}
Color StateMachine::tick(void) {
// tick-increment
if (--_prcValues.tick == 0) {
// repeats-decrement
if (_prcValues.repeats-- == 0) {
_p_effMac = &(*_p_effSeq)[_p_effMac->Next];
_prcValues.repeats = _p_effMac->Repeats;
}
_prcValues.tick = _p_effMac->Duration;
_idx = ExactIndex(_p_effMac->pWave->Length, _p_effMac->Duration);
}
++_idx;
StepProcessVars pv{
.pCurentColor = *_curentColor,
.ColorLen = _params.targetCount,
.IdleIntensity = _params.idleIntens,
.FullIntensity = _p_effMac->FsIntensity,
.DynamicRange = _params.dynamicRange,
.waveIdx = _idx.GetIdx(),
.pWave = _p_effMac->pWave,
};
return _p_effMac->pImplementation(pv);
}
Color StateMachine::UpdateBlank(StepProcessVars &pcsParam) {
return CBlack;
}
Color StateMachine::UpdateIdle(StepProcessVars &pcsParam) {
auto c = pcsParam.pCurentColor;
return c * pcsParam.IdleIntensity;
}
Color StateMachine::UpdateFreeze(StepProcessVars &pcsParam) {
return pcsParam.pCurentColor;
}
Color StateMachine::UpdateWave(StepProcessVars &pcsParam) {
Color temp = pcsParam.pCurentColor;
temp = temp * ((float)(pcsParam.pWave->pWave[pcsParam.waveIdx]) / 0xFF * pcsParam.FullIntensity);
return temp;
}
Color StateMachine::UpdateRevWave(StepProcessVars &pcsParam) {
unsigned lastIndex = pcsParam.pWave->Length - 1;
Color temp = pcsParam.pCurentColor;
temp = temp * ((float)(pcsParam.pWave->pWave[lastIndex - pcsParam.waveIdx]) / 0xFF *
pcsParam.FullIntensity);
return temp;
}
Color StateMachine::UpdateFlicker(StepProcessVars &pcsParam) {
uint8_t k = rand();
k = pcsParam.IdleIntensity + ((int16_t)k * (pcsParam.DynamicRange) / 0xFF);
auto c = pcsParam.pCurentColor;
c = c * ((float)(k));
return c;
}
} // namespace Effect
+100
View File
@@ -0,0 +1,100 @@
/**
* @file Waveforms.cpp
* @author Gustice
* @brief Implementation of defined Waveforms
* @version 0.6
* @date 2019-10-01
*
* @copyright Copyright (c) 2019
* @note The defined waveforms are generated with a the WaveformGenerator
*/
#include "Waveforms.hpp"
namespace Effect {
const uint16_t cu16_TemplateLength = 128;
const uint8_t gu8_idleIntensity = 0x55;
const uint8_t gu8_fullIntensity = 0xFF;
const uint8_t gu8_dynamicRange = gu8_fullIntensity - gu8_idleIntensity;
const uint8_t gu8_fadeSteps = 10;
// clang-format off
// Offset Pulse: Gaussian pulse from background illumination with full scale intensity
const uint8_t gau8_offsetPulse[cu16_TemplateLength * 2] = {
0x55, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59, 0x5A, 0x5B, 0x5C,
0x5D, 0x5E, 0x5F, 0x61, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6F, 0x71, 0x74, 0x77, 0x7B, 0x7E,
0x81, 0x85, 0x89, 0x8E, 0x92, 0x97, 0x9B, 0xA0, 0xA5, 0xAA, 0xAF, 0xB5, 0xBA, 0xBF, 0xC4, 0xC9,
0xCF, 0xD3, 0xD8, 0xDD, 0xE1, 0xE6, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xF9, 0xFB, 0xFD, 0xFD, 0xFE,
0xFF, 0xFE, 0xFD, 0xFD, 0xFB, 0xF9, 0xF7, 0xF4, 0xF1, 0xED, 0xEA, 0xE6, 0xE1, 0xDD, 0xD8, 0xD3,
0xCF, 0xC9, 0xC4, 0xBF, 0xBA, 0xB5, 0xAF, 0xAA, 0xA5, 0xA0, 0x9B, 0x97, 0x92, 0x8E, 0x89, 0x85,
0x81, 0x7E, 0x7B, 0x77, 0x74, 0x71, 0x6F, 0x6C, 0x6A, 0x68, 0x66, 0x64, 0x62, 0x61, 0x5F, 0x5E,
0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x59, 0x58, 0x58, 0x57, 0x57, 0x57, 0x56, 0x56, 0x56, 0x55, 0x55,
0x55, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59, 0x5A, 0x5B, 0x5C,
0x5D, 0x5E, 0x5F, 0x61, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6F, 0x71, 0x74, 0x77, 0x7B, 0x7E,
0x81, 0x85, 0x89, 0x8E, 0x92, 0x97, 0x9B, 0xA0, 0xA5, 0xAA, 0xAF, 0xB5, 0xBA, 0xBF, 0xC4, 0xC9,
0xCF, 0xD3, 0xD8, 0xDD, 0xE1, 0xE6, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xF9, 0xFB, 0xFD, 0xFD, 0xFE,
0xFF, 0xFE, 0xFD, 0xFD, 0xFB, 0xF9, 0xF7, 0xF4, 0xF1, 0xED, 0xEA, 0xE6, 0xE1, 0xDD, 0xD8, 0xD3,
0xCF, 0xC9, 0xC4, 0xBF, 0xBA, 0xB5, 0xAF, 0xAA, 0xA5, 0xA0, 0x9B, 0x97, 0x92, 0x8E, 0x89, 0x85,
0x81, 0x7E, 0x7B, 0x77, 0x74, 0x71, 0x6F, 0x6C, 0x6A, 0x68, 0x66, 0x64, 0x62, 0x61, 0x5F, 0x5E,
0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x59, 0x58, 0x58, 0x57, 0x57, 0x57, 0x56, 0x56, 0x56, 0x55, 0x55,
};
// Full Pulse: Gaussian pulse from dark to full scale intensity
const uint8_t gau8_fullPulse[cu16_TemplateLength * 2] = {
0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B,
0x0D, 0x0E, 0x10, 0x12, 0x14, 0x17, 0x1A, 0x1D, 0x20, 0x23, 0x27, 0x2B, 0x2F, 0x34, 0x39, 0x3E,
0x43, 0x49, 0x4F, 0x56, 0x5C, 0x63, 0x6A, 0x71, 0x79, 0x80, 0x88, 0x90, 0x98, 0x9F, 0xA7, 0xAF,
0xB7, 0xBE, 0xC5, 0xCC, 0xD3, 0xDA, 0xE0, 0xE5, 0xEA, 0xEF, 0xF3, 0xF6, 0xF9, 0xFC, 0xFD, 0xFE,
0xFF, 0xFE, 0xFD, 0xFC, 0xF9, 0xF6, 0xF3, 0xEF, 0xEA, 0xE5, 0xE0, 0xDA, 0xD3, 0xCC, 0xC5, 0xBE,
0xB7, 0xAF, 0xA7, 0x9F, 0x98, 0x90, 0x88, 0x80, 0x79, 0x71, 0x6A, 0x63, 0x5C, 0x56, 0x4F, 0x49,
0x43, 0x3E, 0x39, 0x34, 0x2F, 0x2B, 0x27, 0x23, 0x20, 0x1D, 0x1A, 0x17, 0x14, 0x12, 0x10, 0x0E,
0x0D, 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x05, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01,
0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B,
0x0D, 0x0E, 0x10, 0x12, 0x14, 0x17, 0x1A, 0x1D, 0x20, 0x23, 0x27, 0x2B, 0x2F, 0x34, 0x39, 0x3E,
0x43, 0x49, 0x4F, 0x56, 0x5C, 0x63, 0x6A, 0x71, 0x79, 0x80, 0x88, 0x90, 0x98, 0x9F, 0xA7, 0xAF,
0xB7, 0xBE, 0xC5, 0xCC, 0xD3, 0xDA, 0xE0, 0xE5, 0xEA, 0xEF, 0xF3, 0xF6, 0xF9, 0xFC, 0xFD, 0xFE,
0xFF, 0xFE, 0xFD, 0xFC, 0xF9, 0xF6, 0xF3, 0xEF, 0xEA, 0xE5, 0xE0, 0xDA, 0xD3, 0xCC, 0xC5, 0xBE,
0xB7, 0xAF, 0xA7, 0x9F, 0x98, 0x90, 0x88, 0x80, 0x79, 0x71, 0x6A, 0x63, 0x5C, 0x56, 0x4F, 0x49,
0x43, 0x3E, 0x39, 0x34, 0x2F, 0x2B, 0x27, 0x23, 0x20, 0x1D, 0x1A, 0x17, 0x14, 0x12, 0x10, 0x0E,
0x0D, 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x05, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01,
};
// Init Slope: Gaussian slope from dark to background brightness
const uint8_t gau8_initSlope[cu16_TemplateLength * 2] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04,
0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x12, 0x13, 0x14, 0x16, 0x17, 0x19, 0x1A, 0x1C, 0x1D, 0x1F, 0x21, 0x22, 0x24, 0x26, 0x27, 0x29,
0x2B, 0x2D, 0x2E, 0x30, 0x32, 0x33, 0x35, 0x37, 0x38, 0x3A, 0x3B, 0x3D, 0x3E, 0x40, 0x41, 0x42,
0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4C, 0x4D, 0x4E, 0x4E, 0x4F, 0x4F, 0x50,
0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x54,
0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55,
};
// Offset Pulse: Gaussian slope from background illumination to full scale brightness
const uint8_t gau8_offsetSlope[cu16_TemplateLength] = {
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x56, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59, 0x5A, 0x5A, 0x5B, 0x5C, 0x5D,
0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66, 0x68, 0x6A, 0x6C, 0x6E, 0x70, 0x72, 0x74, 0x76,
0x79, 0x7B, 0x7E, 0x81, 0x84, 0x87, 0x8A, 0x8D, 0x90, 0x93, 0x97, 0x9A, 0x9D, 0xA1, 0xA4, 0xA8,
0xAB, 0xAF, 0xB2, 0xB6, 0xB9, 0xBC, 0xC0, 0xC3, 0xC6, 0xC9, 0xCC, 0xCF, 0xD2, 0xD5, 0xD8, 0xDA,
0xDD, 0xDF, 0xE1, 0xE3, 0xE5, 0xE7, 0xE9, 0xEB, 0xED, 0xEE, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
0xF6, 0xF7, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF,
};
// Full Slope: Gaussian slope from dark to full scale brightness
const uint8_t gau8_fullSlope[cu16_TemplateLength] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C,
0x0D, 0x0F, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1D, 0x1F, 0x22, 0x25, 0x28, 0x2B, 0x2F, 0x32,
0x36, 0x3A, 0x3E, 0x42, 0x46, 0x4B, 0x50, 0x54, 0x59, 0x5E, 0x63, 0x68, 0x6D, 0x72, 0x77, 0x7C,
0x82, 0x87, 0x8C, 0x91, 0x96, 0x9B, 0xA0, 0xA5, 0xAA, 0xAE, 0xB3, 0xB8, 0xBC, 0xC0, 0xC4, 0xC8,
0xCC, 0xCF, 0xD3, 0xD6, 0xD9, 0xDC, 0xDF, 0xE1, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xEF, 0xF1,
0xF2, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFD,
0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF,
};
}// clang-format on
@@ -0,0 +1,5 @@
idf_component_register(
SRC_DIRS "."
INCLUDE_DIRS "."
REQUIRES cmock utils
)
+15
View File
@@ -0,0 +1,15 @@
/**
* @file testUtils.cpp
* @author Gustice
* @brief Hardware bound unit-tests
*
* @copyright Copyright (c) 2024
*/
#include "testable.h"
#include "unity.h"
#include <limits.h>
TEST_CASE("No relevant test case", "[utils]") {
TEST_ASSERT_EQUAL(0, 0);
}
@@ -0,0 +1 @@
unitTestsFrame()
@@ -0,0 +1,59 @@
/**
* @file TestableUTest.cpp
* @author Gustice
* @brief
*
* @copyright Copyright (c) 2024
*/
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "utils.hpp"
#include "doctest/doctest.h"
#include <iostream>
namespace SingleActiveTests {
class Foo : public SingleActive<Foo> {
public:
int test{};
Foo() : SingleActive() {}
};
template <>
bool Foo::SingleActive<Foo>::active{};
class Bar : public SingleActive<Bar> {
public:
int test{};
Bar() : SingleActive() {}
};
template <>
bool Bar::SingleActive<Bar>::active{};
TEST_CASE("Sweet path") {
{ // first instances
Foo dut;
} // destruction
{ // second instances
Foo dut;
} // destruction
{ // third instance
Foo dut1;
Bar dut2; // First instance of second class
} // destruction
CHECK(true);
}
TEST_CASE("Too many instances") {
{
Foo dut1;
Foo *pDut2;
CHECK_THROWS_WITH(pDut2 = new Foo, "Instance already active");
}
CHECK(true);
}
}
+197 -43
View File
@@ -1,42 +1,12 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
/**
* @file watchMain.cpp
* @author Gustice
* @brief ChaosWatch Application
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
* @copyright Copyright (c) 2024
*/
/* eth2ap (Ethernet to Wi-Fi AP packet forwarding) Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <stdlib.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_eth_driver.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "esp_private/wifi.h"
#include "ethernet_init.h"
#include "esp_netif.h"
#include "esp_eth.h"
// Component header
#include "Task.hpp"
#include "PwmExpanderPca9685.hpp"
#include "StepperDrv8833.hpp"
#include "stepperMotor.hpp"
#include "cliWrapper.hpp"
#include "udpSockets.hpp"
#include "tcpSockets.hpp"
#include "Queue.hpp"
#include "Artnet.h"
#include "watchMain.hpp"
static const char *TAG = "Watch";
static esp_eth_handle_t s_eth_handle = NULL;
@@ -46,12 +16,6 @@ extern "C" { // This switch allows the ROS C-implementation to find this main
void app_main(void);
}
struct Color {
uint8_t r;
uint8_t g;
uint8_t b;
};
struct DeviceState {
int jumps;
int pictogram;
@@ -150,7 +114,7 @@ static void telnetSocketTask(int addrFamily) {
constexpr uint32_t DmxUniverse = 0;
constexpr int DmxChannelCount = 9; //
constexpr int DmxChannelCount = 9;
uint8_t scaledRgbChannel(uint8_t value, float scale) {
return static_cast<uint8_t>(value * scale);
@@ -344,6 +308,30 @@ static void initialize_ethernet(void)
ESP_ERROR_CHECK(esp_eth_start(s_eth_handle));
}
namespace Effect {
extern const WaveForm_t OffsetPulseWave{gau8_offsetPulse, cu16_TemplateLength};
extern const WaveForm_t InitSlopeWave{gau8_initSlope, cu16_TemplateLength};
extern const WaveForm_t OffsetSlopeWave{gau8_offsetSlope, cu16_TemplateLength};
extern const WaveForm_t FullSlopeWave{gau8_fullSlope, cu16_TemplateLength};
extern const WaveForm_t FullPulseWave{gau8_fullPulse, cu16_TemplateLength};
const Macro macDemoStart = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateIdle, 0xFF},
};
const Macro macDemoPulse = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 2, StateMachine::UpdateIdle, 0xFF},
{64, 1, &OffsetPulseWave, StateMachine::UpdateWave, 0xFF},
};
const Macro macDemoFlicker = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateFlicker, 0xFF},
};
}
void LightingTask() {
ESP_LOGI(TAG, "Start Lighting");
@@ -376,6 +364,70 @@ void LightingTask() {
}
fos::Task::delayMs(100);
}
// ESP_LOGI(TAG, "Start Lighting");
// static I2cMaster master(I2C_NUM_0, GPIO_NUM_10, GPIO_NUM_11);
// static PmwExpanderPca9685 pca9685(master);
// PmwExpanderPca9685::GrayValues values;
// AddressableLeRtz ledBar(GPIO_NUM_15, AddressableLeRtz::Type::Rgb, 6);
// std::vector<Color> pictoSpots(6);
// for (auto &&led : pictoSpots) {
// led.set(0, 0, 0);
// }
// auto const &colorSource = activeState.color;
// std::array<Effect::EffectProcessor, 6> processors{
// Effect::EffectProcessor(8),
// Effect::EffectProcessor(8),
// Effect::EffectProcessor(8),
// Effect::EffectProcessor(8),
// Effect::EffectProcessor(8),
// Effect::EffectProcessor(8)};
// processors[0].setEffect(Effect::macDemoStart, &colorSource, 16);
// processors[1].setEffect(Effect::macDemoStart, &colorSource, 32);
// processors[2].setEffect(Effect::macDemoPulse, &colorSource, 48);
// processors[3].setEffect(Effect::macDemoPulse, &colorSource, 64);
// processors[4].setEffect(Effect::macStartFlicker, &colorSource, 80);
// processors[5].setEffect(Effect::macStartIdle, &colorSource, 96);
// int idx = 0;
// values.fill(0);
// while (true) {
// values[0] = activeState.color.getRed() * 257;
// values[1] = activeState.color.getGreen() * 257;
// values[2] = activeState.color.getBlue() * 257;
// pca9685.sendImage(values);
// for (size_t i = 0; i < 600; i++) {
// Task::delayMs(20);
// for (size_t i = 0; i < pictoSpots.size(); i++) {
// pictoSpots[i] = processors[i].tick();
// }
// ledBar.send(pictoSpots);
// }
// processors[1].setEffect(Effect::macDark, &colorSource, 32);
// processors[2].setEffect(Effect::macDark, &colorSource, 48);
// processors[3].setEffect(Effect::macDark, &colorSource, 64);
// processors[4].setEffect(Effect::macDark, &colorSource, 80);
// for (size_t i = 0; i < 50; i++) {
// Task::delayMs(20);
// for (size_t i = 0; i < pictoSpots.size(); i++) {
// pictoSpots[i] = processors[i].tick();
// }
// ledBar.send(pictoSpots);
// }
// processors[1].setEffect(Effect::macDemoStart, &colorSource, 32);
// processors[2].setEffect(Effect::macDemoPulse, &colorSource, 48);
// processors[3].setEffect(Effect::macDemoPulse, &colorSource, 64);
// processors[4].setEffect(Effect::macStartFlicker, &colorSource, 80);
// }
}
void MovementTask() {
@@ -415,6 +467,108 @@ void MovementTask() {
while (true) {
fos::Task::delayMs(100);
}
// ESP_LOGI(TAG, "Start Stepper");
// StepperDriverTb6612::Pins stepperPins{
// LEDC_TIMER_0,
// LEDC_CHANNEL_0,
// GPIO_NUM_23,
// {GPIO_NUM_22, GPIO_NUM_21},
// LEDC_CHANNEL_1,
// GPIO_NUM_20,
// {GPIO_NUM_19, GPIO_NUM_18},
// };
// constexpr int MicroSteps = 32;
// StepperDriverTb6612 stepperDriver(stepperPins, MicroSteps);
// stepperDriver.setPos(0);
// StepperMotor::Config stepperCfg{1.8F, MicroSteps};
// InputPort initSens(GPIO_NUM_3);
// initSens.setLogic(GpioPort::Logic::Inverted);
// StepperMotor stepper(stepperCfg, stepperDriver, initSens);
// ESP_LOGI(TAG, "Find Home");
// stepper.findRef();
// ESP_LOGI(TAG, "Fist Position is %f.2", stepper.getScaledPos() * 6);
// Task::delayMs(1000);
// AddressableLeRtz ledRing(GPIO_NUM_9, AddressableLeRtz::Type::Rgb, 12);
// std::vector<Color> ledStrip(12);
// for (auto &&led : ledStrip) {
// led.set(0, 0, 0);
// }
// uint32_t ledPos = 0;
// ledStrip[0].set(
// activeState.color.getRed(),
// activeState.color.getGreen(),
// activeState.color.getBlue(),
// 0);
// ledRing.send(ledStrip);
// while (true) {
// ESP_LOGD(TAG, "Waiting for command");
// auto cmd = commandQueue.dequeue();
// if (cmd->type == MoveType::Step) {
// if (stepper.isIdle()) {
// auto delta = cmd->deltaPic;
// auto profile = cmd->profile;
// for (auto &&led : ledStrip) {
// led.set(0, 0, 0);
// }
// ledPos = (ledPos + delta) % 6;
// activeState.pictogram = ledPos;
// ledStrip[ledPos * 2].set(
// cmd->color.getRed(),
// cmd->color.getGreen(),
// cmd->color.getBlue(),
// 0);
// ledRing.send(ledStrip);
// MqttClient::publishPosition(ledPos);
// delta = std::min<uint8_t>(delta, 7);
// Syslog::logv(Syslog::Severity::Notice, "Running Stepper by %i steps with prof=%i a=%.2f w=%.2f", delta, profile, activeState.accel, activeState.speed);
// stepper.moveBy(delta * std::numbers::pi / 3,
// profile, activeState.accel, activeState.speed);
// }
// } else if (cmd->type == MoveType::AllPictograms) {
// activeState.pictogram = -1;
// stepper.findRef();
// Task::delayMs(1000);
// for (size_t i = 0; i < 6; i++) {
// for (auto &&led : ledStrip) {
// led.set(0, 0, 0);
// }
// ledStrip[i * 2].set(0, 0, 16);
// ledRing.send(ledStrip);
// stepper.moveBy(std::numbers::pi / 3);
// while (!stepper.isIdle()) {
// Task::delayMs(100);
// }
// ESP_LOGI(TAG, "Position is %f.2", stepper.getScaledPos() * 6);
// }
// } else if (cmd->type == MoveType::Arbitrary) {
// activeState.pictogram = -1;
// ESP_LOGI(TAG, "Full Turn");
// stepper.demoFullTurn();
// Task::delayMs(4000);
// while (true) {
// if (stepper.isIdle()) {
// ESP_LOGI(TAG, "Position is %f.2", stepper.getScaledPos() * 6);
// Task::delayMs(500);
// stepper.createDemoProfile();
// }
// Task::delayMs(20);
// }
// }
// }
}
void IoTest()
+84
View File
@@ -0,0 +1,84 @@
/**
* @file watchMain.hpp
* @author Gustice
*
* @copyright Copyright (c) 2024
*/
#pragma once
#include <string.h>
#include <stdlib.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_eth_driver.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "esp_private/wifi.h"
#include "ethernet_init.h"
#include "esp_netif.h"
#include "esp_eth.h"
// Component header
#include "Task.hpp"
#include "PwmExpanderPca9685.hpp"
#include "StepperDrv8833.hpp"
#include "stepperMotor.hpp"
#include "cliWrapper.hpp"
#include "udpSockets.hpp"
#include "tcpSockets.hpp"
#include "Mutex.hpp"
#include "Queue.hpp"
#include "Semaphore.hpp"
#include "Task.hpp"
#include "Artnet.h"
#include "Processor.hpp"
// #include "esp_chip_info.h"
// #include "esp_flash.h"
// #include "esp_log.h"
// #include "esp_netif.h"
// #include "esp_ota_ops.h"
// #include "esp_partition.h"
// #include "esp_random.h"
// #include "esp_system.h"
// #include "esp_vfs_fat.h"
// #include "esp_vfs_semihost.h"
// #include "esp_wifi.h"
// #include "fileSystem.hpp"
// #include "freertos/FreeRTOS.h"
// #include "freertos/task.h"
// #include "gpTimer.hpp"
// #include "gpioPort.hpp"
// #include "i2cPort.hpp"
// #include "lwip/apps/netbiosns.h"
// #include "mdns.h"
// #include "mqttClient.hpp"
// #include "nlohmann/json.hpp"
// #include "nvsFunctions.hpp"
// #include "pwmExpanderPca9685.hpp"
// #include "pwmPort.hpp"
// #include "rmtPort.hpp"
// #include "sdkconfig.h"
// #include "soc/soc_caps.h"
// #include "stepperMotor.hpp"
// #include "stepperTB6612.hpp"
// #include "stepperDrv8833.hpp"
// #include "string.h"
// #include "systemFunctions.hpp"
// #include "tcpSockets.hpp"
// #include "uartPort.hpp"
// #include "udpSockets.hpp"
// #include "webServer.hpp"
// #include "wifiFunctions.hpp"
// #include <inttypes.h>
// #include <string.h>
// #include <sys/param.h>
// #include <unistd.h>
// #include <cmath>