New led control
This commit is contained in:
56
espmusicmouse/lib/leds/LedAnimation.h
Normal file
56
espmusicmouse/lib/leds/LedAnimation.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "LedControl.h"
|
||||
|
||||
class LedAnimation
|
||||
{
|
||||
public:
|
||||
/// Sets leds in the strip and returns number of milliseconds to wait until it is called again
|
||||
virtual int operator()(LedStrip &leds) = 0;
|
||||
};
|
||||
|
||||
class SweepCircularAnimation : public LedAnimation
|
||||
{
|
||||
public:
|
||||
SweepCircularAnimation(const ColorRGB &color, int delayMs = 100, int numLedsHalfWidth = 3, float brightnessFallOff = 0.8)
|
||||
: color_(color), delayMs_(delayMs), numLedsHalfWidth_(numLedsHalfWidth), brightnessFallOff_(brightnessFallOff), currentCenter_(0)
|
||||
{
|
||||
}
|
||||
|
||||
int operator()(LedStrip &leds) override
|
||||
{
|
||||
for (int i = 0; i < leds.numLeds(); ++i)
|
||||
leds.setColor(i, 0, 0, 0, 0);
|
||||
|
||||
leds.setColor(currentCenter_, color_);
|
||||
|
||||
ColorRGB currColor = color_;
|
||||
for (int i = 1; i <= numLedsHalfWidth_; ++i)
|
||||
{
|
||||
currColor.r = uint8_t(float(currColor.r) * brightnessFallOff_);
|
||||
currColor.g = uint8_t(float(currColor.g) * brightnessFallOff_);
|
||||
currColor.b = uint8_t(float(currColor.b) * brightnessFallOff_);
|
||||
leds.setColor(leds.normalizeLedIdx(currentCenter_ - i), currColor);
|
||||
leds.setColor(leds.normalizeLedIdx(currentCenter_ + i), currColor);
|
||||
}
|
||||
currentCenter_ = leds.normalizeLedIdx(currentCenter_ + 1);
|
||||
return delayMs_;
|
||||
}
|
||||
|
||||
private:
|
||||
// parameters
|
||||
ColorRGB color_;
|
||||
int delayMs_;
|
||||
int numLedsHalfWidth_; // number of leds on to the left and right of center
|
||||
float brightnessFallOff_;
|
||||
|
||||
// state
|
||||
int currentCenter_;
|
||||
};
|
||||
|
||||
// strategy:
|
||||
// use queue to send animation pointers over
|
||||
// task calls animate function and waits for new even in queue with timeout of next due call
|
||||
//
|
||||
|
||||
void setAnimation(LedAnimation *animation)
|
||||
{
|
||||
}
|
||||
@@ -3,6 +3,85 @@
|
||||
#include "esp32_digital_led_lib.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#define HSV_SECTION_6 (0x20)
|
||||
#define HSV_SECTION_3 (0x40)
|
||||
|
||||
static ColorRGB hsv2rgb(const ColorHSV &hsv)
|
||||
{
|
||||
// Convert hue, saturation and brightness ( HSV/HSB ) to RGB
|
||||
// "Dimming" is used on saturation and brightness to make
|
||||
// the output more visually linear.
|
||||
|
||||
// Apply dimming curves
|
||||
uint8_t value = hsv.v;
|
||||
uint8_t saturation = hsv.s;
|
||||
|
||||
// The brightness floor is minimum number that all of
|
||||
// R, G, and B will be set to.
|
||||
uint8_t invsat = 255 - saturation;
|
||||
uint8_t brightness_floor = (value * invsat) / 256;
|
||||
|
||||
// The color amplitude is the maximum amount of R, G, and B
|
||||
// that will be added on top of the brightness_floor to
|
||||
// create the specific hue desired.
|
||||
uint8_t color_amplitude = value - brightness_floor;
|
||||
|
||||
// Figure out which section of the hue wheel we're in,
|
||||
// and how far offset we are withing that section
|
||||
uint8_t section = hsv.h / HSV_SECTION_3; // 0..2
|
||||
uint8_t offset = hsv.h % HSV_SECTION_3; // 0..63
|
||||
|
||||
uint8_t rampup = offset; // 0..63
|
||||
uint8_t rampdown = (HSV_SECTION_3 - 1) - offset; // 63..0
|
||||
|
||||
// We now scale rampup and rampdown to a 0-255 range -- at least
|
||||
// in theory, but here's where architecture-specific decsions
|
||||
// come in to play:
|
||||
// To scale them up to 0-255, we'd want to multiply by 4.
|
||||
// But in the very next step, we multiply the ramps by other
|
||||
// values and then divide the resulting product by 256.
|
||||
// So which is faster?
|
||||
// ((ramp * 4) * othervalue) / 256
|
||||
// or
|
||||
// ((ramp ) * othervalue) / 64
|
||||
// It depends on your processor architecture.
|
||||
// On 8-bit AVR, the "/ 256" is just a one-cycle register move,
|
||||
// but the "/ 64" might be a multicycle shift process. So on AVR
|
||||
// it's faster do multiply the ramp values by four, and then
|
||||
// divide by 256.
|
||||
// On ARM, the "/ 256" and "/ 64" are one cycle each, so it's
|
||||
// faster to NOT multiply the ramp values by four, and just to
|
||||
// divide the resulting product by 64 (instead of 256).
|
||||
// Moral of the story: trust your profiler, not your insticts.
|
||||
|
||||
// Since there's an AVR assembly version elsewhere, we'll
|
||||
// assume what we're on an architecture where any number of
|
||||
// bit shifts has roughly the same cost, and we'll remove the
|
||||
// redundant math at the source level:
|
||||
|
||||
// // scale up to 255 range
|
||||
// //rampup *= 4; // 0..252
|
||||
// //rampdown *= 4; // 0..252
|
||||
|
||||
// compute color-amplitude-scaled-down versions of rampup and rampdown
|
||||
uint8_t rampup_amp_adj = (rampup * color_amplitude) / (256 / 4);
|
||||
uint8_t rampdown_amp_adj = (rampdown * color_amplitude) / (256 / 4);
|
||||
|
||||
// add brightness_floor offset to everything
|
||||
uint8_t rampup_adj_with_floor = rampup_amp_adj + brightness_floor;
|
||||
uint8_t rampdown_adj_with_floor = rampdown_amp_adj + brightness_floor;
|
||||
|
||||
if (section)
|
||||
{
|
||||
if (section == 1)
|
||||
return ColorRGB{brightness_floor, rampdown_adj_with_floor, rampup_adj_with_floor};
|
||||
else
|
||||
return ColorRGB{rampup_adj_with_floor, brightness_floor, rampdown_adj_with_floor};
|
||||
}
|
||||
else
|
||||
return ColorRGB{rampdown_adj_with_floor, rampup_adj_with_floor, brightness_floor};
|
||||
}
|
||||
|
||||
LedStrip::LedStrip(int numLeds, int pin)
|
||||
: numLeds_(numLeds), pin_(pin)
|
||||
{
|
||||
@@ -25,6 +104,15 @@ void LedStrip::clear()
|
||||
digitalLeds_resetPixels(strands, 1);
|
||||
}
|
||||
|
||||
int LedStrip::normalizeLedIdx(int i)
|
||||
{
|
||||
while (i < 0)
|
||||
i += numLeds_;
|
||||
while (i >= numLeds_)
|
||||
i -= numLeds_;
|
||||
return i;
|
||||
}
|
||||
|
||||
void LedStrip::setColor(int led, int r, int g, int b, int w)
|
||||
{
|
||||
strands[0]->pixels[led] = pixelFromRGBW(r, g, b, w);
|
||||
@@ -45,4 +133,14 @@ void LedStrip::setRange(int begin, int end, int r, int g, int b, int w)
|
||||
{
|
||||
for (int i = begin; i < min(end, numLeds_); ++i)
|
||||
setColor(i, r, g, b, w);
|
||||
}
|
||||
|
||||
void LedStrip::setColor(int led, const ColorRGB &color)
|
||||
{
|
||||
setColor(led, color.r, color.g, color.b, 0);
|
||||
}
|
||||
|
||||
void LedStrip::setColor(int led, const ColorHSV &color)
|
||||
{
|
||||
setColor(led, hsv2rgb(color));
|
||||
}
|
||||
@@ -1,5 +1,15 @@
|
||||
#pragma once
|
||||
#include "esp32_digital_led_lib.h"
|
||||
|
||||
struct ColorRGB
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
};
|
||||
|
||||
struct ColorHSV
|
||||
{
|
||||
uint8_t h, s, v;
|
||||
};
|
||||
|
||||
class LedStrip
|
||||
{
|
||||
@@ -9,11 +19,16 @@ public:
|
||||
void begin();
|
||||
|
||||
void setColor(int led, int r, int g, int b, int w);
|
||||
void setColor(int led, const ColorRGB &color);
|
||||
void setColor(int led, const ColorHSV &color);
|
||||
void transmit();
|
||||
void clear();
|
||||
void setAll(int r, int g, int b, int w);
|
||||
void setRange(int begin, int end, int r, int g, int b, int w);
|
||||
int numLeds() const { return numLeds_; }
|
||||
|
||||
int normalizeLedIdx(int i);
|
||||
|
||||
private:
|
||||
strand_t cfg;
|
||||
strand_t *strands[1];
|
||||
|
||||
Reference in New Issue
Block a user