160 lines
4.6 KiB
C++
160 lines
4.6 KiB
C++
#include "led.h"
|
|||
|
|
|
||
|
|
// system includes
|
||
|
|
#include <array>
|
||
|
|
|
||
|
|
// esp-idf includes
|
||
|
|
#include <driver/ledc.h>
|
||
|
|
|
||
|
|
// Arduino includes
|
||
|
|
#include <Arduino.h>
|
||
|
|
|
||
|
|
// 3rdparty lib includes
|
||
|
|
#include <FastLED.h>
|
||
|
|
#include <espchrono.h>
|
||
|
|
|
||
|
|
#define LEDC_CHANNEL_0 0
|
||
|
|
#define LEDC_CHANNEL_1 0
|
||
|
|
#define LEDC_CHANNEL_2 0
|
||
|
|
#define LEDC_TIMER_13_BIT 13
|
||
|
|
#define LEDC_BASE_FREQ 5000
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
std::array<CRGB, 5> leds;
|
||
|
|
|
||
|
|
CRGBPalette16 currentPalette;
|
||
|
|
TBlendType currentBlending;
|
||
|
|
|
||
|
|
extern CRGBPalette16 myRedWhiteBluePalette;
|
||
|
|
extern const TProgmemPalette16 myRedWhiteBluePalette_p;
|
||
|
|
|
||
|
|
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255);
|
||
|
|
}
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax)
|
||
|
|
{
|
||
|
|
// calculate duty, 8191 from 2 ^ 13 - 1
|
||
|
|
uint32_t duty = (8191 / valueMax) * min(value, valueMax);
|
||
|
|
|
||
|
|
// write duty to LEDC
|
||
|
|
ledcWrite(channel, duty);
|
||
|
|
}
|
||
|
|
|
||
|
|
void FillLEDsFromPaletteColors( uint8_t colorIndex)
|
||
|
|
{
|
||
|
|
uint8_t brightness = 255;
|
||
|
|
|
||
|
|
for( int i = 0; i < leds.size(); ++i) {
|
||
|
|
leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
|
||
|
|
colorIndex += 3;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void SetupTotallyRandomPalette()
|
||
|
|
{
|
||
|
|
for( int i = 0; i < 16; ++i) {
|
||
|
|
currentPalette[i] = CHSV( random8(), 255, random8());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void SetupBlackAndWhiteStripedPalette()
|
||
|
|
{
|
||
|
|
// 'black out' all 16 palette entries...
|
||
|
|
fill_solid( currentPalette, 16, CRGB::Black);
|
||
|
|
// and set every fourth one to white.
|
||
|
|
currentPalette[0] = CRGB::White;
|
||
|
|
currentPalette[4] = CRGB::White;
|
||
|
|
currentPalette[8] = CRGB::White;
|
||
|
|
currentPalette[12] = CRGB::White;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void SetupPurpleAndGreenPalette()
|
||
|
|
{
|
||
|
|
CRGB purple = CHSV( HUE_PURPLE, 255, 255);
|
||
|
|
CRGB green = CHSV( HUE_GREEN, 255, 255);
|
||
|
|
CRGB black = CRGB::Black;
|
||
|
|
|
||
|
|
currentPalette = CRGBPalette16(
|
||
|
|
green, green, black, black,
|
||
|
|
purple, purple, black, black,
|
||
|
|
green, green, black, black,
|
||
|
|
purple, purple, black, black );
|
||
|
|
}
|
||
|
|
|
||
|
|
const TProgmemPalette16 myRedWhiteBluePalette_p =
|
||
|
|
{
|
||
|
|
CRGB::Red,
|
||
|
|
CRGB::Gray, // 'white' is too bright compared to red and blue
|
||
|
|
CRGB::Blue,
|
||
|
|
CRGB::Black,
|
||
|
|
|
||
|
|
CRGB::Red,
|
||
|
|
CRGB::Gray,
|
||
|
|
CRGB::Blue,
|
||
|
|
CRGB::Black,
|
||
|
|
|
||
|
|
CRGB::Red,
|
||
|
|
CRGB::Red,
|
||
|
|
CRGB::Gray,
|
||
|
|
CRGB::Gray,
|
||
|
|
CRGB::Blue,
|
||
|
|
CRGB::Blue,
|
||
|
|
CRGB::Black,
|
||
|
|
CRGB::Black
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
void ChangePalettePeriodically()
|
||
|
|
{
|
||
|
|
constexpr auto millis = []() -> unsigned int { return espchrono::millis_clock::now().time_since_epoch().count(); };
|
||
|
|
|
||
|
|
uint8_t secondHand = (millis() / 1000) % 60;
|
||
|
|
static uint8_t lastSecond = 99;
|
||
|
|
|
||
|
|
if( lastSecond != secondHand) {
|
||
|
|
lastSecond = secondHand;
|
||
|
|
if( secondHand == 0) { currentPalette = RainbowColors_p; currentBlending = LINEARBLEND; }
|
||
|
|
if( secondHand == 10) { currentPalette = RainbowStripeColors_p; currentBlending = NOBLEND; }
|
||
|
|
if( secondHand == 15) { currentPalette = RainbowStripeColors_p; currentBlending = LINEARBLEND; }
|
||
|
|
if( secondHand == 20) { SetupPurpleAndGreenPalette(); currentBlending = LINEARBLEND; }
|
||
|
|
if( secondHand == 25) { SetupTotallyRandomPalette(); currentBlending = LINEARBLEND; }
|
||
|
|
if( secondHand == 30) { SetupBlackAndWhiteStripedPalette(); currentBlending = NOBLEND; }
|
||
|
|
if( secondHand == 35) { SetupBlackAndWhiteStripedPalette(); currentBlending = LINEARBLEND; }
|
||
|
|
if( secondHand == 40) { currentPalette = CloudColors_p; currentBlending = LINEARBLEND; }
|
||
|
|
if( secondHand == 45) { currentPalette = PartyColors_p; currentBlending = LINEARBLEND; }
|
||
|
|
if( secondHand == 50) { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND; }
|
||
|
|
if( secondHand == 55) { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void led_setup()
|
||
|
|
{
|
||
|
|
currentPalette = RainbowColors_p;
|
||
|
|
currentBlending = LINEARBLEND;
|
||
|
|
|
||
|
|
ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
|
||
|
|
ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
|
||
|
|
ledcSetup(LEDC_CHANNEL_2, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
|
||
|
|
ledcAttachPin(27, LEDC_CHANNEL_0);
|
||
|
|
ledcAttachPin(33, LEDC_CHANNEL_1);
|
||
|
|
ledcAttachPin(32, LEDC_CHANNEL_2);
|
||
|
|
}
|
||
|
|
|
||
|
|
void led_update()
|
||
|
|
{
|
||
|
|
ChangePalettePeriodically();
|
||
|
|
|
||
|
|
static uint8_t startIndex = 0;
|
||
|
|
startIndex = startIndex + 1; /* motion speed */
|
||
|
|
|
||
|
|
FillLEDsFromPaletteColors( startIndex);
|
||
|
|
|
||
|
|
ledcAnalogWrite(LEDC_CHANNEL_0, leds[0].red);
|
||
|
|
ledcAnalogWrite(LEDC_CHANNEL_1, leds[0].green);
|
||
|
|
ledcAnalogWrite(LEDC_CHANNEL_2, leds[0].blue);
|
||
|
|
}
|