2021-11-02 22:47:46 +01:00
#include "ledstrip.h"
// 3rdparty lib includes
2022-03-26 20:17:27 +01:00
#include <cpputils.h>
#include <espchrono.h>
2022-04-19 09:12:40 +02:00
#include <math.h>
2021-11-02 22:47:46 +01:00
// local includes
#include "globals.h"
#include "ledstripdefines.h"
2021-12-30 03:17:30 +01:00
#include "newsettings.h"
2022-03-26 20:17:27 +01:00
#include "ota.h"
2022-04-01 15:41:18 +02:00
#include "time_bobbycar.h"
2022-03-26 20:17:27 +01:00
#include "utils.h"
2021-11-02 22:47:46 +01:00
using namespace std :: chrono_literals ;
std :: vector < CRGB > leds ;
uint8_t gHue = 0 ;
2022-04-18 16:39:47 +02:00
float gLedPosition = 0 ; // yes, this is intendet as a float value! Do NOT change!
2021-11-02 22:47:46 +01:00
2021-12-07 02:53:43 +01:00
uint16_t blinkAnimation = LEDSTRIP_OVERWRITE_NONE ;
2021-11-02 22:47:46 +01:00
2022-02-14 22:27:50 +01:00
namespace {
bool initialized { false };
} // namespace
2021-11-02 22:47:46 +01:00
void initLedStrip ()
{
2022-04-29 22:40:49 +02:00
if ( configs . feature . ledstrip . isEnabled . value ())
2022-01-17 13:02:57 +01:00
{
2022-04-29 22:40:49 +02:00
leds . resize ( configs . ledstrip . ledsCount . value ());
2022-01-17 13:02:57 +01:00
FastLED . addLeds < NEOPIXEL , PINS_LEDSTRIP > ( &* std :: begin ( leds ), leds . size ())
. setCorrection ( TypicalSMD5050 );
2022-02-14 22:27:50 +01:00
initialized = true ;
2022-01-17 13:02:57 +01:00
}
2021-11-02 22:47:46 +01:00
}
void updateLedStrip ()
{
2022-04-29 22:40:49 +02:00
if ( configs . feature . ledstrip . isEnabled . value () && ! initialized )
2022-02-14 22:27:50 +01:00
initLedStrip ();
2022-04-29 22:40:49 +02:00
else if ( ! configs . feature . ledstrip . isEnabled . value () && initialized )
2022-02-14 22:27:50 +01:00
{
std :: fill ( std :: begin ( leds ), std :: end ( leds ), CRGB :: Black );
FastLED . show ();
initialized = false ;
return ;
}
2022-04-29 22:40:49 +02:00
else if ( ! configs . feature . ledstrip . isEnabled . value ())
2022-02-14 22:27:50 +01:00
return ;
2022-01-17 13:02:57 +01:00
2021-11-02 22:47:46 +01:00
EVERY_N_MILLISECONDS ( 20 ) { gHue ++ ; }
static bool have_disabled_beeper = false ;
2022-04-29 22:40:49 +02:00
const bool enAnim = configs . ledstrip . enableAnimBlink . value ();
2021-11-02 22:47:46 +01:00
if ( cpputils :: is_in ( blinkAnimation , LEDSTRIP_OVERWRITE_BLINKLEFT , LEDSTRIP_OVERWRITE_BLINKRIGHT , LEDSTRIP_OVERWRITE_BLINKBOTH ))
{
std :: fill ( std :: begin ( leds ), std :: end ( leds ), CRGB { 0 , 0 , 0 });
2021-12-29 06:39:31 +01:00
if ( espchrono :: utc_clock :: now (). time_since_epoch () % 750 ms < 375 ms || enAnim )
2021-11-02 22:47:46 +01:00
{
2022-04-29 22:40:49 +02:00
const auto anim_to_fill = time_to_percent ( 750 ms , 500 ms , 100 ms , configs . ledstrip . enableFullBlink . value () ? ( leds . size () / 2 ) : configs . ledstrip . bigOffset . value () - configs . ledstrip . smallOffset . value (), configs . ledstrip . enableFullBlink . value ());
if ( configs . ledstrip . enableBeepWhenBlink . value ())
2021-11-02 22:47:46 +01:00
{
2021-12-29 06:39:31 +01:00
if ( espchrono :: utc_clock :: now (). time_since_epoch () % 750 ms < 375 ms )
2021-11-15 20:38:54 +01:00
for ( Controller & controller : controllers )
controller . command . buzzer . freq = 3 ;
else
for ( Controller & controller : controllers )
controller . command . buzzer . freq = 0 ;
2021-11-02 22:47:46 +01:00
}
2021-11-15 20:38:54 +01:00
auto color = CRGB { 255 , 200 , 0 };
2022-04-29 22:40:49 +02:00
const auto center = ( std :: begin ( leds ) + ( leds . size () / 2 ) + configs . ledstrip . centerOffset . value ());
2021-11-02 22:47:46 +01:00
2022-04-29 22:40:49 +02:00
if ( configs . ledstrip . enableFullBlink . value ())
2021-11-02 22:47:46 +01:00
{
2021-11-15 20:38:54 +01:00
// Full
if ( BLINK_LEFT_EXPR )
{
// Blink left
if ( ! enAnim )
{
std :: fill ( std :: begin ( leds ), center , color );
}
else
{
std :: fill ( std :: begin ( leds ) + anim_to_fill , center , color );
}
}
if ( BLINK_RIGHT_EXPR )
{
// Blink right
if ( ! enAnim )
{
std :: fill ( center , std :: end ( leds ), color );
}
else
{
std :: fill ( center , std :: end ( leds ) - anim_to_fill , color );
}
}
2021-11-02 22:47:46 +01:00
}
2021-11-15 20:38:54 +01:00
else
2021-11-02 22:47:46 +01:00
{
2021-11-15 20:38:54 +01:00
// Only in the back
if ( BLINK_LEFT_EXPR )
{
// Blink left
if ( ! enAnim )
{
2022-04-29 22:40:49 +02:00
std :: fill ( center - configs . ledstrip . bigOffset . value (), center - configs . ledstrip . smallOffset . value (), color );
2021-11-15 20:38:54 +01:00
}
else
{
2022-04-29 22:40:49 +02:00
std :: fill ( center - configs . ledstrip . smallOffset . value () - anim_to_fill , center - configs . ledstrip . smallOffset . value (), color );
2021-11-15 20:38:54 +01:00
}
}
if ( BLINK_RIGHT_EXPR )
{
// Blink right
if ( ! enAnim )
{
2022-04-29 22:40:49 +02:00
std :: fill ( center + configs . ledstrip . smallOffset . value (), center + configs . ledstrip . bigOffset . value (), color );
2021-11-15 20:38:54 +01:00
}
else
{
2022-04-29 22:40:49 +02:00
std :: fill ( center + configs . ledstrip . smallOffset . value (), center + configs . ledstrip . smallOffset . value () + anim_to_fill , color );
2021-11-15 20:38:54 +01:00
}
}
2021-11-02 22:47:46 +01:00
}
} else {
2022-04-29 22:40:49 +02:00
if ( configs . ledstrip . enableBeepWhenBlink . value ())
2021-11-02 22:47:46 +01:00
{
for ( Controller & controller : controllers )
controller . command . buzzer . freq = 0 ;
}
}
}
else
{
2022-04-29 22:40:49 +02:00
if ( configs . ledstrip . enableBrakeLights . value ())
2021-11-02 22:47:46 +01:00
{
float avgPwm {};
for ( const Controller & controller : controllers )
{
avgPwm +=
controller . command . left . pwm * ( controller . invertLeft ? - 1 : 1 ) +
controller . command . right . pwm * ( controller . invertRight ? - 1 : 1 );
}
avgPwm /= 4 ;
if ( avgPwm < - 1.f )
{
auto color = avgSpeedKmh < - 0.1f ? CRGB { 255 , 255 , 255 } : CRGB { 255 , 0 , 0 };
2022-04-29 22:40:49 +02:00
const auto center = ( std :: begin ( leds ) + ( leds . size () / 2 ) + configs . ledstrip . centerOffset . value ());
2021-11-02 22:47:46 +01:00
std :: fill ( std :: begin ( leds ), std :: end ( leds ), CRGB { 0 , 0 , 0 });
2022-04-29 22:40:49 +02:00
if ( configs . ledstrip . enableFullBlink . value ())
2021-11-02 22:47:46 +01:00
{
std :: fill ( std :: begin ( leds ), std :: end ( leds ), color );
}
2022-04-29 22:40:49 +02:00
else if ( ! configs . ledstrip . enableAnimBlink . value ())
2021-11-02 22:47:46 +01:00
{
2022-04-29 22:40:49 +02:00
std :: fill ( center - configs . ledstrip . bigOffset . value () - 2 , center - configs . ledstrip . smallOffset . value () + 2 , color );
std :: fill ( center + configs . ledstrip . smallOffset . value () - 2 , center + configs . ledstrip . bigOffset . value () + 2 , color );
2021-11-02 22:47:46 +01:00
}
}
else
{
showAnimation ();
}
}
else
{
showAnimation ();
}
}
2022-04-29 22:40:49 +02:00
if ( ! have_disabled_beeper && ( ! ( cpputils :: is_in ( blinkAnimation , LEDSTRIP_OVERWRITE_BLINKLEFT , LEDSTRIP_OVERWRITE_BLINKRIGHT , LEDSTRIP_OVERWRITE_BLINKBOTH )) || ! configs . ledstrip . enableBeepWhenBlink . value ()))
2021-11-02 22:47:46 +01:00
{
for ( Controller & controller : controllers )
controller . command . buzzer . freq = 0 ;
have_disabled_beeper = true ;
}
2022-04-29 22:40:49 +02:00
else if (( cpputils :: is_in ( blinkAnimation , LEDSTRIP_OVERWRITE_BLINKLEFT , LEDSTRIP_OVERWRITE_BLINKRIGHT , LEDSTRIP_OVERWRITE_BLINKBOTH )) && configs . ledstrip . enableBeepWhenBlink . value ()) have_disabled_beeper = false ;
2021-11-02 22:47:46 +01:00
2022-03-26 20:17:27 +01:00
const auto automaticLight = activateAutomaticFrontLight ();
2022-04-29 22:40:49 +02:00
if ( simplified || configs . ledstrip . enableStVO . value () || automaticLight )
2021-11-02 22:47:46 +01:00
{
2022-04-29 22:40:49 +02:00
const auto center = ( std :: begin ( leds ) + ( leds . size () / 2 ) + configs . ledstrip . centerOffset . value ());
2021-11-02 22:47:46 +01:00
2022-04-29 22:40:49 +02:00
if ( ! ( blinkAnimation == LEDSTRIP_OVERWRITE_BLINKLEFT || blinkAnimation == LEDSTRIP_OVERWRITE_BLINKBOTH ) || ! ( espchrono :: utc_clock :: now (). time_since_epoch () % 750 ms < 375 ms ) || configs . ledstrip . enableFullBlink . value ()) // Condition for right
2021-11-02 22:47:46 +01:00
{
2022-04-29 22:40:49 +02:00
std :: fill ( center - configs . ledstrip . bigOffset . value (), center - configs . ledstrip . smallOffset . value (), CRGB { 0 , 0 , 0 });
std :: fill ( center - configs . ledstrip . bigOffset . value () - 1U , center - configs . ledstrip . smallOffset . value () - 1U , CRGB { 255 , 0 , 0 }); // Right
2021-11-02 22:47:46 +01:00
}
2022-04-29 22:40:49 +02:00
if ( ! ( blinkAnimation == LEDSTRIP_OVERWRITE_BLINKRIGHT || blinkAnimation == LEDSTRIP_OVERWRITE_BLINKBOTH ) || ! ( espchrono :: utc_clock :: now (). time_since_epoch () % 750 ms < 375 ms ) || configs . ledstrip . enableFullBlink . value ()) // Condition for left
2021-11-02 22:47:46 +01:00
{
2022-04-29 22:40:49 +02:00
std :: fill ( center + configs . ledstrip . smallOffset . value (), center + configs . ledstrip . bigOffset . value (), CRGB { 0 , 0 , 0 });
std :: fill ( center + configs . ledstrip . smallOffset . value () + 1U , center + configs . ledstrip . bigOffset . value () + 1U , CRGB { 255 , 0 , 0 }); // Left
2021-11-02 22:47:46 +01:00
}
2022-04-29 22:40:49 +02:00
if ( configs . ledstrip . stvoFrontEnable . value () || automaticLight )
2021-11-02 22:47:46 +01:00
{
2022-04-29 22:40:49 +02:00
std :: fill ( std :: begin ( leds ) + configs . ledstrip . stvoFrontOffset . value (), std :: begin ( leds ) + configs . ledstrip . stvoFrontOffset . value () + configs . ledstrip . stvoFrontLength . value (), CRGB { 255 , 255 , 255 });
std :: fill ( std :: end ( leds ) - configs . ledstrip . stvoFrontOffset . value () - configs . ledstrip . stvoFrontLength . value (), std :: end ( leds ) - configs . ledstrip . stvoFrontOffset . value (), CRGB { 255 , 255 , 255 });
2021-11-02 22:47:46 +01:00
}
}
2022-04-29 22:40:49 +02:00
FastLED . setMaxPowerInVoltsAndMilliamps ( 5 , configs . ledstrip . maxMilliamps . value ());
FastLED . setBrightness ( configs . ledstrip . brightness . value ());
2021-11-02 22:47:46 +01:00
FastLED . show ();
}
void showAnimation ()
{
2022-04-29 22:40:49 +02:00
if ( configs . ledstrip . enableLedAnimation . value ()
&& ! ( asyncOtaTaskStarted && configs . ledstrip . otaMode . value () != OtaAnimationModes :: None )
2021-12-09 08:06:38 +01:00
)
2021-11-02 22:47:46 +01:00
{
2022-04-29 22:40:49 +02:00
switch ( configs . ledstrip . animationType . value ())
2022-01-03 21:00:16 +01:00
{
case LedstripAnimation :: DefaultRainbow : showDefaultLedstrip (); break ;
case LedstripAnimation :: BetterRainbow : showBetterRainbow (); break ;
case LedstripAnimation :: SpeedSync : showSpeedSyncAnimation (); break ;
case LedstripAnimation :: CustomColor : showCustomColor (); break ;
2022-04-18 13:29:35 +02:00
case LedstripAnimation :: SnakeAnimation : showSnakeAnimation (); break ;
2022-04-22 22:54:29 +02:00
case LedstripAnimation :: GasOMeter : showGasOMeterAnimation (); break ;
2022-06-12 02:58:39 +02:00
case LedstripAnimation :: Pride : showPrideAnimation (); break ;
2022-01-03 21:00:16 +01:00
default : showDefaultLedstrip ();
}
2021-11-02 22:47:46 +01:00
}
2022-04-29 22:40:49 +02:00
else if ( asyncOtaTaskStarted && configs . ledstrip . otaMode . value () != OtaAnimationModes :: None )
2021-11-18 15:15:48 +01:00
{
// show ota animation
showOtaAnimation ();
}
2021-11-02 22:47:46 +01:00
else
{
std :: fill ( std :: begin ( leds ), std :: end ( leds ), CRGB { 0 , 0 , 0 });
}
}
2021-11-18 15:15:48 +01:00
void showOtaAnimation ()
{
std :: fill ( std :: begin ( leds ), std :: end ( leds ), CRGB { 0 , 0 , 0 });
const auto leds_count = leds . size ();
float percentage = 0 ;
const auto progress = asyncOta -> progress ();
if ( const auto totalSize = asyncOta -> totalSize (); totalSize && * totalSize > 0 )
{
percentage = ( float ( progress ) / * totalSize * 100 );
2022-04-29 22:40:49 +02:00
if ( configs . ledstrip . otaMode . value () == OtaAnimationModes :: GreenProgressBar )
2021-11-18 15:15:48 +01:00
{
2021-12-08 02:24:24 +01:00
int numLeds = ( leds_count * percentage ) / 100 ;
2021-11-18 15:15:48 +01:00
if ( numLeds >= leds_count )
{
numLeds = leds_count - 1 ;
}
std :: fill ( std :: begin ( leds ), std :: begin ( leds ) + numLeds , CRGB { 0 , 255 , 0 });
}
2022-04-29 22:40:49 +02:00
else if ( configs . ledstrip . otaMode . value () == OtaAnimationModes :: ColorChangeAll )
2021-11-18 15:15:48 +01:00
{
2022-06-12 17:51:31 +02:00
const uint8_t redChannel = 255 - ( 2.55f * percentage );
const uint8_t greenChannel = 2.55f * percentage ;
2021-11-18 15:15:48 +01:00
std :: fill ( std :: begin ( leds ), std :: end ( leds ), CRGB { redChannel , greenChannel , 0 });
}
}
}
2021-11-02 22:47:46 +01:00
void showBetterRainbow ()
{
fill_rainbow ( &* std :: begin ( leds ), leds . size (), gHue );
}
void fill_rainbow_invert_at ( struct CRGB * pFirstLED , int numToFill , int invertAtLed ,
uint8_t initialhue ,
float deltahue )
{
float huecalc = initialhue ;
CHSV hsv ;
hsv . hue = initialhue ;
hsv . val = 255 ;
hsv . sat = 240 ;
2022-04-18 15:04:05 +02:00
for ( int i = 0 ; i < numToFill ; i ++ ) {
2021-11-02 22:47:46 +01:00
hsv . hue = huecalc ;
pFirstLED [ i ] = hsv ;
2022-04-18 15:04:05 +02:00
if ( i > invertAtLed )
{
2021-11-02 22:47:46 +01:00
huecalc -= deltahue ;
2022-04-18 15:04:05 +02:00
}
else
{
2021-11-02 22:47:46 +01:00
huecalc += deltahue ;
}
}
}
void showSpeedSyncAnimation ()
{
static auto last_interval = espchrono :: millis_clock :: now ();
2022-02-06 19:10:18 +01:00
const auto difference_ms = espchrono :: ago ( last_interval ) / 1 ms ;
2021-11-02 22:47:46 +01:00
static float hue_result = 0 ;
2022-06-12 17:51:31 +02:00
const float hue_per_led = 1.f / std :: max ( uint8_t ( 1 ), uint8_t ( configs . ledstrip . animationMultiplier . value ()));
const float meter_per_second = avgSpeedKmh / 3.6f ;
2022-04-29 22:40:49 +02:00
const float leds_per_second = meter_per_second * configs . ledstrip . leds_per_meter . value ();
2021-11-02 22:47:46 +01:00
const float hue_per_second = leds_per_second * hue_per_led ;
hue_result += hue_per_second * difference_ms / 1000.f ;
fill_rainbow_invert_at ( &* std :: begin ( leds ), leds . size (), leds . size () / 2 , hue_result , - hue_per_led );
last_interval = espchrono :: millis_clock :: now ();
}
void showDefaultLedstrip ()
{
fadeToBlackBy ( &* std :: begin ( leds ), leds . size (), 20 );
uint8_t dothue = 0 ;
for ( int i = 0 ; i < 8 ; i ++ )
{
leds [ beatsin16 ( i + 7 , 0 , leds . size ())] |= CHSV ( dothue , 200 , 255 );
dothue += 32 ;
}
}
2022-04-18 13:29:35 +02:00
void showSnakeAnimation ()
{
2022-06-12 17:51:31 +02:00
const float leds_per_cycle = ( 1.f / std :: max < int16_t > ( 1 , configs . ledstrip . animationMultiplier . value ())) * ( avgSpeedKmh + 1 ); // yes, this is intended as a float value! Do NOT change!
2022-04-18 14:18:17 +02:00
fadeToBlackBy ( &* std :: begin ( leds ), leds . size (), floor ( 20 * leds_per_cycle ));
2022-04-18 15:04:05 +02:00
if ( gLedPosition >= leds . size ())
{
gLedPosition = 0 ;
}
if ( gHue == 255 ) {
gHue = 0 ;
}
for ( int16_t i = floor ( gLedPosition ); i < floor ( gLedPosition + leds_per_cycle ); i ++ )
{
2022-04-18 14:18:17 +02:00
leds [ i ] |= CHSV ( gHue , 255 , 255 );
2022-06-12 17:51:31 +02:00
uint8_t snake_2_pos = floorf ( leds . size () / 2.f ) + i ;
2022-04-18 15:04:05 +02:00
if ( snake_2_pos > leds . size ())
{
snake_2_pos -= leds . size ();
}
2022-04-18 14:18:17 +02:00
leds [ snake_2_pos ] |= CHSV ( gHue , 255 , 255 );
}
2022-04-18 15:04:05 +02:00
2022-04-18 14:18:17 +02:00
gLedPosition += leds_per_cycle ;
2022-04-18 13:29:35 +02:00
gHue += 5 ;
}
2022-04-22 22:54:29 +02:00
void showGasOMeterAnimation ()
2022-04-18 13:29:35 +02:00
{
2022-04-19 09:12:40 +02:00
if ( const auto avgVoltage = controllers . getAvgVoltage (); avgVoltage )
2022-04-22 22:54:29 +02:00
{
auto watt = sumCurrent * * avgVoltage ;
auto w_per_kmh = watt / std :: abs ( avgSpeedKmh );
CRGB color = 0 ;
if ( isinf ( w_per_kmh ) || isnan ( w_per_kmh ))
2022-04-19 09:12:40 +02:00
{
2022-04-22 22:54:29 +02:00
color = 0 ;
2022-04-19 09:12:40 +02:00
}
2022-04-22 22:54:29 +02:00
else if ( w_per_kmh <= - 40 )
{
color = CRGB ( 255 , 0 , 255 );
}
else if ( w_per_kmh < - 20 )
{
2022-06-12 17:51:31 +02:00
color = CRGB ( 255 , 0 , cpputils :: mapValueClamped < float > ( w_per_kmh , - 40 , - 20 , 255.f , 0.f ));
2022-04-22 22:54:29 +02:00
}
else if ( w_per_kmh < 0 )
{
2022-06-12 17:51:31 +02:00
color = CRGB ( 255 , cpputils :: mapValueClamped < float > ( w_per_kmh , - 20 , 0 , 0.f , 255.f ), 0 );
2022-04-22 22:54:29 +02:00
}
else if ( w_per_kmh < 20 )
{
2022-06-12 17:51:31 +02:00
color = CRGB ( cpputils :: mapValueClamped < float > ( w_per_kmh , 0 , 20 , 255.f , 0.f ), 255 , 0 );
2022-04-22 22:54:29 +02:00
}
else if ( w_per_kmh < 40 )
{
2022-06-12 17:51:31 +02:00
color = CRGB ( 0 , cpputils :: mapValueClamped < float > ( w_per_kmh , 20 , 40 , 255.f , 0.f ), cpputils :: mapValueClamped < float > ( w_per_kmh , 20 , 40 , 0.f , 255.f ));
2022-04-22 22:54:29 +02:00
}
else
{
color = CRGB ( 0 , 0 , 255 );
}
std :: fill ( std :: begin ( leds ), std :: end ( leds ), color );
}
2022-04-18 13:29:35 +02:00
}
2021-11-02 22:47:46 +01:00
void showCustomColor ()
{
const auto eighth_length = leds . size () / 8 ;
2022-04-29 22:40:49 +02:00
const auto center = ( std :: begin ( leds ) + ( leds . size () / 2 ) + configs . ledstrip . centerOffset . value ());
2021-11-02 22:47:46 +01:00
2022-04-29 22:40:49 +02:00
std :: fill ( std :: begin ( leds ), std :: end ( leds ), configs . ledstrip . custom_color [ int ( Bobbycar_Side :: FRONT )]. value ()); // Front
std :: fill ( center - ( eighth_length / 2 ), center + ( eighth_length / 2 ), configs . ledstrip . custom_color [ int ( Bobbycar_Side :: BACK )]. value ()); // Back
2021-11-02 22:47:46 +01:00
#ifdef LEDSTRIP_WRONG_DIRECTION
2022-04-29 22:54:25 +02:00
std :: fill ( center + ( eighth_length / 2 ), center + ( eighth_length / 2 ) + eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: BACK_LEFT )]. value ()); // Back Left
std :: fill ( center - ( eighth_length / 2 ) - eighth_length , center - ( eighth_length / 2 ), configs . ledstrip . custom_color [ int ( Bobbycar_Side :: BACK_RIGHT )]. value ()); // Back Right
2021-11-02 22:47:46 +01:00
#else
2022-04-29 22:40:49 +02:00
std :: fill ( center + ( eighth_length / 2 ), center + ( eighth_length / 2 ) + eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: BACK_RIGHT )]. value ()); // Back Right
std :: fill ( center - ( eighth_length / 2 ) - eighth_length , center - ( eighth_length / 2 ), configs . ledstrip . custom_color [ int ( Bobbycar_Side :: BACK_LEFT )]. value ()); // Back Left
2021-11-02 22:47:46 +01:00
#endif
#ifdef LEDSTRIP_WRONG_DIRECTION
2022-04-29 22:54:25 +02:00
std :: fill ( center + ( eighth_length / 2 ) + eighth_length , center + ( eighth_length / 2 ) + eighth_length + eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: LEFT )]. value ()); // Left
std :: fill ( center - ( eighth_length / 2 ) - eighth_length - eighth_length , center - ( eighth_length / 2 ) - eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: RIGHT )]. value ()); // Right
2021-11-02 22:47:46 +01:00
#else
2022-04-29 22:40:49 +02:00
std :: fill ( center + ( eighth_length / 2 ) + eighth_length , center + ( eighth_length / 2 ) + eighth_length + eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: RIGHT )]. value ()); // Right
std :: fill ( center - ( eighth_length / 2 ) - eighth_length - eighth_length , center - ( eighth_length / 2 ) - eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: LEFT )]. value ()); // Left
2021-11-02 22:47:46 +01:00
#endif
#ifdef LEDSTRIP_WRONG_DIRECTION
2022-04-29 22:54:25 +02:00
std :: fill ( center + ( eighth_length / 2 ) + eighth_length + eighth_length , center + ( eighth_length / 2 ) + eighth_length + eighth_length + eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: FRONT_LEFT )]. value ()); // Front Left
std :: fill ( center - ( eighth_length / 2 ) - eighth_length - eighth_length - eighth_length , center - ( eighth_length / 2 ) - eighth_length - eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: FRONT_RIGHT )]. value ()); // Front Right
2021-11-02 22:47:46 +01:00
#else
2022-04-29 22:40:49 +02:00
std :: fill ( center + ( eighth_length / 2 ) + eighth_length + eighth_length , center + ( eighth_length / 2 ) + eighth_length + eighth_length + eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: FRONT_RIGHT )]. value ()); // Front Right
std :: fill ( center - ( eighth_length / 2 ) - eighth_length - eighth_length - eighth_length , center - ( eighth_length / 2 ) - eighth_length - eighth_length , configs . ledstrip . custom_color [ int ( Bobbycar_Side :: FRONT_LEFT )]. value ()); // Front Left
2021-11-02 22:47:46 +01:00
#endif
}
2022-03-26 20:17:27 +01:00
2022-06-12 02:58:39 +02:00
void showPrideAnimation ()
{
const auto ledstrip_length = leds . size ();
static uint16_t sPseudotime { 0 };
static espchrono :: millis_clock :: time_point sLastMillis {};
static uint16_t sHue16 { 0 };
const uint8_t sat8 = beatsin88 ( 87 , 220 , 250 );
const uint8_t brightdepth = beatsin88 ( 341 , 96 , 224 );
const uint16_t brightnessthetainc16 = beatsin88 ( 203 , ( 25 * 256 ), ( 40 * 256 ));
const uint8_t msmultiplier = beatsin88 ( 147 , 23 , 60 );
uint16_t hue16 = sHue16 ; //gHue * 256;
uint16_t hueinc16 = beatsin88 ( 113 , 1 , 3000 );
const auto deltams = espchrono :: ago ( sLastMillis ). count () / 1000 ;
sLastMillis = espchrono :: millis_clock :: now ();
sPseudotime += deltams * msmultiplier ;
sHue16 += deltams * beatsin88 ( 400 , 5 , 9 );
uint16_t brightnesstheta16 = sPseudotime ;
for ( uint16_t i = 0 ; i < ledstrip_length ; i ++ ) {
hue16 += hueinc16 ;
const uint8_t hue8 = hue16 / 256 ;
brightnesstheta16 += brightnessthetainc16 ;
const uint16_t b16 = sin16 ( brightnesstheta16 ) + 32768 ;
const uint16_t bri16 = ( uint32_t )(( uint32_t ) b16 * ( uint32_t ) b16 ) / 65536 ;
uint8_t bri8 = ( uint32_t )((( uint32_t ) bri16 ) * brightdepth ) / 65536 ;
bri8 += ( 255 - brightdepth );
const CRGB newcolor = CHSV ( hue8 , sat8 , bri8 );
const uint16_t pixelnumber = ( ledstrip_length - 1 ) - i ;
nblend ( leds [ pixelnumber ], newcolor , 64 );
}
}
2022-03-26 20:19:06 +01:00
[[nodiscard]] bool activateAutomaticFrontLight ()
2022-03-26 20:17:27 +01:00
{
2022-04-01 15:41:18 +02:00
using namespace std :: chrono_literals ;
2022-04-29 22:40:49 +02:00
if ( ! configs . ledstrip . automaticLight . value ())
2022-03-26 20:17:27 +01:00
return false ;
const auto today = toDateTime ( espchrono :: utc_clock :: now ());
2022-04-01 15:41:18 +02:00
if ( static_cast < int > ( today . date . year ()) < 2000 )
2022-04-17 13:32:45 +02:00
return true ;
2022-04-01 15:41:18 +02:00
if ( ! sunrise_dt || ( * sunrise_dt ). date . day () != today . date . day ())
{
sunrise_dt = today ;
calculate_sun ();
}
const int currentTimeInMinutes = today . hour * 60 + today . minute ;
return ( currentTimeInMinutes <= sunrise || currentTimeInMinutes >= sunset );
2022-03-26 20:17:27 +01:00
}