2021-11-02 22:47:46 +01:00
#include "ledstrip.h"
// 3rdparty lib includes
// local includes
#include "globals.h"
#include "cpputils.h"
#include "espchrono.h"
#include "ledstripdefines.h"
2021-11-15 20:38:54 +01:00
#include "utils.h"
2021-11-18 15:15:48 +01:00
#include "ota.h"
2021-12-30 03:17:30 +01:00
#include "newsettings.h"
2021-11-02 22:47:46 +01:00
using namespace std :: chrono_literals ;
std :: vector < CRGB > leds ;
uint8_t gHue = 0 ;
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-02-18 01:21:54 +01:00
if ( configs . feature . ledstrip . isEnabled . value )
2022-01-17 13:02:57 +01:00
{
leds . resize ( configs . ledstrip . ledsCount . value );
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-02-18 01:21:54 +01:00
if ( configs . feature . ledstrip . isEnabled . value && ! initialized )
2022-02-14 22:27:50 +01:00
initLedStrip ();
2022-02-18 01:21:54 +01: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-02-18 01:21:54 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
const auto center = ( std :: begin ( leds ) + ( leds . size () / 2 ) + configs . ledstrip . centerOffset . value );
2021-11-02 22:47:46 +01:00
2022-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
std :: fill ( center - configs . ledstrip . bigOffset . value , center - configs . ledstrip . smallOffset . value , color );
2021-11-15 20:38:54 +01:00
}
else
{
2022-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
std :: fill ( center + configs . ledstrip . smallOffset . value , center + configs . ledstrip . bigOffset . value , color );
2021-11-15 20:38:54 +01:00
}
else
{
2022-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
if ( configs . ledstrip . enableFullBlink . value )
2021-11-02 22:47:46 +01:00
{
std :: fill ( std :: begin ( leds ), std :: end ( leds ), color );
}
2022-01-02 22:43:33 +01:00
else if ( ! configs . ledstrip . enableAnimBlink . value )
2021-11-02 22:47:46 +01:00
{
2022-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
if ( have_disabled_beeper == false && ( ! ( 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-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
if ( simplified || configs . ledstrip . enableStVO . value )
2021-11-02 22:47:46 +01:00
{
2022-01-02 22:43:33 +01:00
const auto center = ( std :: begin ( leds ) + ( leds . size () / 2 ) + configs . ledstrip . centerOffset . value );
2021-11-02 22:47:46 +01:00
2022-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
if ( configs . ledstrip . stvoFrontEnable . value )
2021-11-02 22:47:46 +01:00
{
2022-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
if ( configs . ledstrip . enableLedAnimation . value
2021-12-09 08:06:38 +01:00
&& ! simplified
2022-01-02 22:43:33 +01:00
&& ! ( asyncOtaTaskStarted && configs . ledstrip . otaMode . value != OtaAnimationModes :: None )
2021-12-09 08:06:38 +01:00
)
2021-11-02 22:47:46 +01:00
{
2022-01-03 21:00:16 +01:00
switch ( configs . ledstrip . animationType . value )
{
case LedstripAnimation :: DefaultRainbow : showDefaultLedstrip (); break ;
case LedstripAnimation :: BetterRainbow : showBetterRainbow (); break ;
case LedstripAnimation :: SpeedSync : showSpeedSyncAnimation (); break ;
case LedstripAnimation :: CustomColor : showCustomColor (); break ;
default : showDefaultLedstrip ();
}
2021-11-02 22:47:46 +01:00
}
2022-01-02 22:43:33 +01: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-01-02 22:43:33 +01: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-01-02 22:43:33 +01:00
else if ( configs . ledstrip . otaMode . value == OtaAnimationModes :: ColorChangeAll )
2021-11-18 15:15:48 +01:00
{
const uint8_t redChannel = 255 - ( 2.55 * percentage );
const uint8_t greenChannel = 2.55 * percentage ;
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 ;
for ( int i = 0 ; i < numToFill ; i ++ ) {
hsv . hue = huecalc ;
pFirstLED [ i ] = hsv ;
if ( i > invertAtLed ){
huecalc -= deltahue ;
} else {
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-01-02 22:43:33 +01:00
const float hue_per_led = 1. / std :: max ( uint8_t ( 1 ), uint8_t ( configs . ledstrip . animationMultiplier . value ));
2021-11-02 22:47:46 +01:00
const float meter_per_second = avgSpeedKmh / 3.6 ;
2022-01-18 08:44:54 +01: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 ;
}
}
void showCustomColor ()
{
const auto eighth_length = leds . size () / 8 ;
2022-01-02 22:43:33 +01:00
const auto center = ( std :: begin ( leds ) + ( leds . size () / 2 ) + configs . ledstrip . centerOffset . value );
2021-11-02 22:47:46 +01:00
2022-01-17 17:55:45 +01: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-01-17 17:55:45 +01: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-01-17 17:55:45 +01: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-01-17 17:55:45 +01: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-01-17 17:55:45 +01: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-01-17 17:55:45 +01: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-01-17 17:55:45 +01: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
}