5 #if defined(PLATFORM_ESP32) && defined(GPIO_PIN_LED_WS2812) && (GPIO_PIN_LED_WS2812 != UNDEF_PIN)
6 #include <NeoPixelBus.h>
7 static constexpr uint16_t PixelCount
= 2;
9 static NeoPixelBus
<NeoGrbFeature
, Neo800KbpsMethod
> strip(PixelCount
, GPIO_PIN_LED_WS2812
);
11 static NeoPixelBus
<NeoRgbFeature
, Neo800KbpsMethod
> strip(PixelCount
, GPIO_PIN_LED_WS2812
);
19 void WS281BsetLED(uint32_t color
)
21 strip
.ClearTo(RgbColor(HtmlColor(color
)));
26 #if defined(PLATFORM_STM32) && (GPIO_PIN_LED_WS2812 != UNDEF_PIN) && (GPIO_PIN_LED_WS2812_FAST != UNDEF_PIN)
27 #include "STM32F3_WS2812B_LED.h"
31 #if defined(GPIO_PIN_LED_WS2812) && (GPIO_PIN_LED_WS2812 != UNDEF_PIN)
34 #include "crsf_protocol.h"
35 #include "POWERMGNT.h"
37 #if defined(TARGET_RX)
38 extern bool InBindingMode
;
39 extern bool connectionHasModelMatch
;
46 uint32_t HsvToRgb(blinkyColor_t
&blinkyColor
)
48 uint8_t region
, remainder
, p
, q
, t
;
50 if (blinkyColor
.s
== 0)
52 return blinkyColor
.v
<< 16 | blinkyColor
.v
<< 8 | blinkyColor
.v
;
55 region
= blinkyColor
.h
/ 43;
56 remainder
= (blinkyColor
.h
- (region
* 43)) * 6;
58 p
= (blinkyColor
.v
* (255 - blinkyColor
.s
)) >> 8;
59 q
= (blinkyColor
.v
* (255 - ((blinkyColor
.s
* remainder
) >> 8))) >> 8;
60 t
= (blinkyColor
.v
* (255 - ((blinkyColor
.s
* (255 - remainder
)) >> 8))) >> 8;
65 return blinkyColor
.v
<< 16 | t
<< 8 | p
;
67 return q
<< 16 | blinkyColor
.v
<< 8 | p
;
69 return p
<< 16 | blinkyColor
.v
<< 8 | t
;
71 return p
<< 16 | q
<< 8 | blinkyColor
.v
;
73 return t
<< 16 | p
<< 8 | blinkyColor
.v
;
75 return blinkyColor
.v
<< 16 | p
<< 8 | q
;
79 void brightnessFadeLED(blinkyColor_t
&blinkyColor
, uint8_t start
, uint8_t end
)
81 static uint8_t lightness
= 0;
82 static int8_t dir
= 1;
84 if (lightness
<= start
)
89 else if (lightness
>= end
)
97 blinkyColor
.v
= lightness
;
98 WS281BsetLED(HsvToRgb(blinkyColor
));
101 void hueFadeLED(blinkyColor_t
&blinkyColor
, uint16_t start
, uint16_t end
, uint8_t lightness
, uint8_t count
)
103 static bool hueMode
= true;
104 static uint16_t hue
= 0;
105 static int8_t dir
= 1;
106 static uint8_t counter
= 0;
111 if (blinkyColor
.v
== 0)
115 WS281BsetLED(HsvToRgb(blinkyColor
));
146 blinkyColor
.h
= hue
% 256;
147 blinkyColor
.v
= lightness
;
148 WS281BsetLED(HsvToRgb(blinkyColor
));
150 if (count
!= 0 && hue
== start
)
153 if (counter
>= count
)
162 uint16_t flashLED(blinkyColor_t
&blinkyColor
, uint8_t onLightness
, uint8_t offLightness
, const uint8_t durations
[], uint8_t durationCounts
)
164 static int counter
= 0;
166 blinkyColor
.v
= counter
% 2 == 0 ? onLightness
: offLightness
;
167 WS281BsetLED(HsvToRgb(blinkyColor
));
168 if (counter
>= durationCounts
)
172 return durations
[counter
++] * 10;
180 constexpr uint8_t LEDSEQ_RADIO_FAILED
[] = { 10, 10 }; // 100ms on, 100ms off (fast blink)
181 constexpr uint8_t LEDSEQ_DISCONNECTED
[] = { 50, 50 }; // 500ms on, 500ms off
182 constexpr uint8_t LEDSEQ_NO_CROSSFIRE
[] = { 10, 100 }; // 1 blink, 1s pause (one blink/s)
183 constexpr uint8_t LEDSEQ_BINDING
[] = { 10, 10, 10, 100 }; // 2x 100ms blink, 1s pause
184 constexpr uint8_t LEDSEQ_MODEL_MISMATCH
[] = { 10, 10, 10, 10, 10, 100 }; // 3x 100ms blink, 1s pause
186 #define NORMAL_UPDATE_INTERVAL 50
188 constexpr uint8_t rate_hue
[RATE_MAX
] =
190 170, // 500/200 hz blue
191 85, // 250/100 hz green
192 21, // 150/50 hz orange
196 static blinkyColor_t blinkyColor
;
198 static int blinkyUpdate() {
199 static constexpr uint8_t hueStepValue
= 1;
200 static constexpr uint8_t lightnessStep
= 5;
202 WS281BsetLED(HsvToRgb(blinkyColor
));
203 if ((int)blinkyColor
.h
+ hueStepValue
> 255) {
204 if ((int)blinkyColor
.v
- lightnessStep
< 0) {
205 blinkyState
= NORMAL
;
206 return NORMAL_UPDATE_INTERVAL
;
208 blinkyColor
.v
-= lightnessStep
;
210 blinkyColor
.h
+= hueStepValue
;
212 return 3000/(256/hueStepValue
);
215 static void initialize()
225 blinkyState
= STARTUP
;
226 #ifdef PLATFORM_ESP32
227 // Only do the blinkies if it was NOT a software reboot
228 if (esp_reset_reason() == ESP_RST_SW
) {
229 blinkyState
= NORMAL
;
230 return NORMAL_UPDATE_INTERVAL
;
233 return DURATION_IMMEDIATELY
;
238 if (blinkyState
== STARTUP
&& connectionState
< FAILURE_STATES
)
240 return blinkyUpdate();
242 #if defined(TARGET_RX)
246 return flashLED(blinkyColor
, 192, 0, LEDSEQ_BINDING
, sizeof(LEDSEQ_BINDING
));
249 switch (connectionState
)
252 #if defined(TARGET_RX)
253 if (!connectionHasModelMatch
)
256 return flashLED(blinkyColor
, 192, 0, LEDSEQ_MODEL_MISMATCH
, sizeof(LEDSEQ_MODEL_MISMATCH
));
259 // Set the color and we're done!
260 blinkyColor
.h
= rate_hue
[ExpressLRS_currAirRate_Modparams
->index
];
261 blinkyColor
.v
= fmap(POWERMGNT::currPower(), 0, PWR_COUNT
-1, 10, 128);
262 WS281BsetLED(HsvToRgb(blinkyColor
));
263 return DURATION_NEVER
;
265 // Set the color and we're done!
266 blinkyColor
.h
= rate_hue
[ExpressLRS_currAirRate_Modparams
->index
];
267 blinkyColor
.v
= fmap(POWERMGNT::currPower(), 0, PWR_COUNT
-1, 10, 50);
268 WS281BsetLED(HsvToRgb(blinkyColor
));
269 return DURATION_NEVER
;
271 #if defined(TARGET_RX)
273 return flashLED(blinkyColor
, 192, 0, LEDSEQ_DISCONNECTED
, sizeof(LEDSEQ_DISCONNECTED
));
275 #if defined(TARGET_TX)
276 blinkyColor
.h
= rate_hue
[ExpressLRS_currAirRate_Modparams
->index
];
277 brightnessFadeLED(blinkyColor
, 0, 64);
278 return NORMAL_UPDATE_INTERVAL
;
281 hueFadeLED(blinkyColor
, 85, 85-30, 128, 2); // Yellow->Green cross-fade
284 hueFadeLED(blinkyColor
, 170, 170+30, 128, 2); // Blue cross-fade
288 return flashLED(blinkyColor
, 192, 0, LEDSEQ_RADIO_FAILED
, sizeof(LEDSEQ_RADIO_FAILED
));
291 return flashLED(blinkyColor
, 192, 0, LEDSEQ_NO_CROSSFIRE
, sizeof(LEDSEQ_NO_CROSSFIRE
));
293 return DURATION_NEVER
;
297 device_t RGB_device
= {
298 .initialize
= initialize
,
306 device_t RGB_device
= {