musicmouse/espmusicmouse/lib/ledtl/effects/Circular.h

90 lines
2.1 KiB
C++

#pragma once
#include "effects/Common.h"
#include "helpers/ColorRGBW.h"
#include "helpers/BellCurve.h"
#pragma pack(push, 1)
struct EffectCircularConfig
{
float speed; // in degrees per second
float width; // width in degrees
ColorRGBW color;
};
#pragma pack(pop)
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_)
{
}
int operator()()
{
int startLed = int(currentPosition_);
float distDown = currentPosition_ - float(startLed);
float distUp = 1.f - distDown;
clear(ledStrip_);
// center
setLedRGBW(ledStrip_, startLed,
config_.color * bellCurveApproximation(distDown, invWidth_));
// down
for (int i = 1; i < widthInLeds_ / 2 + 1; ++i)
{
setLedRGBW(ledStrip_, startLed - i,
config_.color * bellCurveApproximation(distDown + i, invWidth_));
}
// up
for (int i = 1; i < widthInLeds_ / 2 + 1; ++i)
{
setLedRGBW(ledStrip_, 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;
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>;
};