94 lines
2.3 KiB
C++
94 lines
2.3 KiB
C++
#pragma once
|
|
|
|
#include "effects/Common.h"
|
|
#include "helpers/ColorRGBW.h"
|
|
#include "helpers/BellCurve.h"
|
|
|
|
struct EffectCircularConfig
|
|
{
|
|
float speed; // in degrees per second
|
|
float width; // width in degrees
|
|
ColorRGBW color;
|
|
};
|
|
|
|
template <typename TLedStrip>
|
|
class EffectCircular
|
|
{
|
|
public:
|
|
static constexpr auto NUM_LEDS = numLeds<TLedStrip>();
|
|
static constexpr int DELAY_MS = 10;
|
|
using ConfigType = EffectCircularConfig;
|
|
|
|
EffectCircular(const EffectCircularConfig &cfg, TLedStrip &ledStrip)
|
|
: config_(cfg),
|
|
ledStrip_(ledStrip),
|
|
currentPosition_(0),
|
|
widthInLeds_((numLeds(ledStrip) * cfg.width / 360)),
|
|
invWidth_(1.0f / widthInLeds_)
|
|
{
|
|
}
|
|
|
|
static constexpr int normalizeIdx(int idx)
|
|
{
|
|
return (idx < 0) ? (idx + NUM_LEDS) : (idx >= NUM_LEDS ? idx - NUM_LEDS : idx);
|
|
}
|
|
|
|
int operator()()
|
|
{
|
|
int startLed = int(currentPosition_);
|
|
float distDown = currentPosition_ - float(startLed);
|
|
float distUp = 1.f - distDown;
|
|
|
|
clear(ledStrip_);
|
|
// center
|
|
setLedRGBW(ledStrip_, normalizeIdx(startLed),
|
|
config_.color * bellCurveApproximation(distDown, invWidth_));
|
|
|
|
// down
|
|
for (int i = 1; i < widthInLeds_ / 2 + 1; ++i)
|
|
{
|
|
setLedRGBW(ledStrip_, normalizeIdx(startLed - i),
|
|
config_.color * bellCurveApproximation(distDown + i, invWidth_));
|
|
}
|
|
|
|
// up
|
|
for (int i = 1; i < widthInLeds_ / 2 + 1; ++i)
|
|
{
|
|
setLedRGBW(ledStrip_, normalizeIdx(startLed + i),
|
|
config_.color * bellCurveApproximation(distUp + i - 1, invWidth_));
|
|
}
|
|
|
|
currentPosition_ += config_.speed / 1000 / 360 * NUM_LEDS * DELAY_MS;
|
|
if (currentPosition_ > NUM_LEDS)
|
|
currentPosition_ -= NUM_LEDS;
|
|
|
|
//Serial.printf("Current pos %f led %d width %d\n", currentPosition_, normalizeIdx(startLed), widthInLeds_ / 2 + 1);
|
|
return DELAY_MS;
|
|
}
|
|
|
|
private:
|
|
EffectCircularConfig config_;
|
|
TLedStrip &ledStrip_;
|
|
float currentPosition_; // between 0 and num leds
|
|
int widthInLeds_;
|
|
float invWidth_;
|
|
};
|
|
|
|
// Traits
|
|
template <>
|
|
struct EffectIdToConfig<EffectId::CIRCULAR>
|
|
{
|
|
using type = EffectCircularConfig;
|
|
};
|
|
|
|
template <>
|
|
struct EffectConfigToId<EffectCircularConfig>
|
|
{
|
|
static constexpr auto id = EffectId::CIRCULAR;
|
|
};
|
|
|
|
template <typename TLedStrip>
|
|
struct EffectIdToClass<EffectId::CIRCULAR, TLedStrip>
|
|
{
|
|
using type = EffectCircular<TLedStrip>;
|
|
}; |