38 #ifdef SYSTEMMOD_RGBLED_SUPPORT
39 #include "rgbledsettings.h"
40 #include "stabilizationdesired.h"
41 #include "manualcontrolcommand.h"
44 static void rgb_to_hsv_f(
const float *rgb,
float *hsv)
52 float min_val, max_val, delta;
66 delta = max_val - min_val;
80 delta = max_val - min_val;
96 delta = max_val - min_val;
104 delta = max_val - min_val;
112 if (delta <= 0.00001
f) {
120 h = (h / delta) + sector;
122 hsv[0] = h * (1.0f / 6.0f);
123 hsv[1] = delta / max_val;
127 static void hsv_to_rgb_f(
const float *hsv,
float *rgb)
129 float h = hsv[0], s = hsv[1], v = hsv[2];
149 q = v * ( 1 - s *
f );
150 t = v * ( 1 - s * ( 1 -
f ) );
187 static uint8_t float_to_q8(
float f) {
196 return 255 * f + 0.5f;
199 static inline uint8_t linear_interp_u16(uint8_t val_a, uint8_t val_b,
202 uint32_t tmp = ((uint32_t) val_a) * (65535-fraction);
203 tmp += ((uint32_t) val_b) * fraction;
210 static void interp_in_hsv(
bool backwards,
const uint8_t *rgb_start,
211 const uint8_t *rgb_end, uint8_t *rgb_out, uint16_t fraction) {
212 float fraction_f = fraction / 65535.0f;
214 if (fraction_f > 1.0f) {
221 rgbf[0] = rgb_start[0] / 255.0f;
222 rgbf[1] = rgb_start[1] / 255.0f;
223 rgbf[2] = rgb_start[2] / 255.0f;
225 float hsv_start[3], hsv_end[3], hsv_now[3];
227 rgb_to_hsv_f(rgbf, hsv_start);
229 rgbf[0] = rgb_end[0] / 255.0f;
230 rgbf[1] = rgb_end[1] / 255.0f;
231 rgbf[2] = rgb_end[2] / 255.0f;
233 rgb_to_hsv_f(rgbf, hsv_end);
236 if (hsv_start[0] > hsv_end[0]) {
239 hsv_start[0] += 1.0f;
243 hsv_now[0] = hsv_start[0] * (1.0f - fraction_f) +
244 hsv_end[0] * (fraction_f);
245 hsv_now[1] = hsv_start[1] * (1.0f - fraction_f) +
246 hsv_end[1] * (fraction_f);
247 hsv_now[2] = hsv_start[2] * (1.0f - fraction_f) +
248 hsv_end[2] * (fraction_f);
250 if (hsv_now[0] >= 1.0f) {
254 hsv_to_rgb_f(hsv_now, rgbf);
256 rgb_out[0] = float_to_q8(rgbf[0]);
257 rgb_out[1] = float_to_q8(rgbf[1]);
258 rgb_out[2] = float_to_q8(rgbf[2]);
261 static inline uint16_t float_to_u16(
float in)
265 }
else if (in <= 0) {
272 static uint16_t accessory_desired_get_u16(
int idx)
278 if (idx >= MANUALCONTROLCOMMAND_ACCESSORY_NUMELEM) {
282 float accessories[MANUALCONTROLCOMMAND_ACCESSORY_NUMELEM];
284 ManualControlCommandAccessoryGet(accessories);
286 return float_to_u16(accessories[idx]);
289 static uint16_t sinusodialize(uint16_t fraction) {
292 if (s > 4095)
return 65535;
293 if (s < -4096)
return 0;
295 return (s + 4096) * 8;
299 uint8_t blink_prio,
bool is_armed,
bool force_dim) {
304 if (num_leds == 0)
return;
306 RGBLEDSettingsData rgbSettings;
307 RGBLEDSettingsGet(&rgbSettings);
309 uint8_t range_color[3];
311 uint16_t fraction = 0;
316 RGBLEDSettingsRangeColorBlendSourceOptions blend_source =
317 rgbSettings.RangeColorBlendSource;
318 RGBLEDSettingsRangeColorBlendModeOptions blend_mode =
319 rgbSettings.RangeColorBlendMode;
321 #ifdef PIOS_INCLUDE_USB
322 if (rgbSettings.DimWhenUSB == RGBLEDSETTINGS_DIMWHENUSB_TRUE) {
330 blend_source = rgbSettings.RangeColorBlendUnarmedSource;
334 switch (blend_source) {
335 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_ALWAYSUSEBASECOLOR:
338 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_TIMEHALFSECONDPERIOD:
340 fraction = (tmpui32 % 500) * 65535 / 500;
341 if (blend_mode == RGBLEDSETTINGS_RANGECOLORBLENDMODE_SAWTOOTH) {
343 blend_mode = RGBLEDSETTINGS_RANGECOLORBLENDMODE_SINE;
347 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_TIMESECONDPERIOD:
349 fraction = (tmpui32 % 1000) * 65535 / 1000;
350 if (blend_mode == RGBLEDSETTINGS_RANGECOLORBLENDMODE_SAWTOOTH) {
352 blend_mode = RGBLEDSETTINGS_RANGECOLORBLENDMODE_SINE;
356 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_TIME2SECONDPERIOD:
358 fraction = (tmpui32 % 2000) * 65535 / 2000;
359 if (blend_mode == RGBLEDSETTINGS_RANGECOLORBLENDMODE_SAWTOOTH) {
361 blend_mode = RGBLEDSETTINGS_RANGECOLORBLENDMODE_SINE;
365 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_TIME4SECONDPERIOD:
367 fraction = (tmpui32 % 4000) * 65535 / 4000;
368 if (blend_mode == RGBLEDSETTINGS_RANGECOLORBLENDMODE_SAWTOOTH) {
370 blend_mode = RGBLEDSETTINGS_RANGECOLORBLENDMODE_SINE;
374 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_THROTTLE:
375 StabilizationDesiredThrustGet(&tmp_float);
376 fraction = float_to_u16(fabsf(tmp_float));
379 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_ACCESSORY0:
380 fraction = accessory_desired_get_u16(0);
383 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_ACCESSORY1:
384 fraction = accessory_desired_get_u16(1);
387 case RGBLEDSETTINGS_RANGECOLORBLENDSOURCE_ACCESSORY2:
388 fraction = accessory_desired_get_u16(2);
392 switch (blend_mode) {
394 case RGBLEDSETTINGS_RANGECOLORBLENDMODE_SAWTOOTH:
397 case RGBLEDSETTINGS_RANGECOLORBLENDMODE_SINE:
398 fraction = sinusodialize(fraction);
401 case RGBLEDSETTINGS_RANGECOLORBLENDMODE_TRIANGLE:
402 if (fraction >= 32768) {
404 fraction = 65535 - fraction * 2;
409 case RGBLEDSETTINGS_RANGECOLORBLENDMODE_SQUARE:
410 if (fraction > 32768) {
418 switch (rgbSettings.RangeColorBlendType) {
420 case RGBLEDSETTINGS_RANGECOLORBLENDTYPE_LINEARRGBFADE:
421 range_color[0] = linear_interp_u16(
422 rgbSettings.RangeBaseColor[0],
423 rgbSettings.RangeEndColor[0],
425 range_color[1] = linear_interp_u16(
426 rgbSettings.RangeBaseColor[1],
427 rgbSettings.RangeEndColor[1],
429 range_color[2] = linear_interp_u16(
430 rgbSettings.RangeBaseColor[2],
431 rgbSettings.RangeEndColor[2],
433 case RGBLEDSETTINGS_RANGECOLORBLENDTYPE_LINEARINHSV:
434 interp_in_hsv(
false, rgbSettings.RangeBaseColor,
435 rgbSettings.RangeEndColor,
439 case RGBLEDSETTINGS_RANGECOLORBLENDTYPE_LINEARINHSVBACKWARDSHUE:
440 interp_in_hsv(
true, rgbSettings.RangeBaseColor,
441 rgbSettings.RangeEndColor,
447 uint8_t alarm_color[3] = { 0, 0, 0 };
449 if (led_override && led_override_active) {
452 if (blink_prio >= SYSTEMALARMS_ALARM_CRITICAL) {
453 alarm_color[0] = 255;
456 }
else if (blink_prio >= SYSTEMALARMS_ALARM_WARNING) {
457 alarm_color[0] = 255;
458 alarm_color[1] = 200;
462 alarm_color[1] = 200;
468 range_color[0] = (range_color[0] + 2) / 3;
469 range_color[1] = (range_color[1] + 2) / 3;
470 range_color[2] = (range_color[2] + 2) / 3;
471 alarm_color[0] = (alarm_color[0] + 2) / 3;
472 alarm_color[1] = (alarm_color[1] + 2) / 3;
473 alarm_color[2] = (alarm_color[2] + 2) / 3;
474 rgbSettings.DefaultColor[0] = (rgbSettings.DefaultColor[0] + 2) / 3;
475 rgbSettings.DefaultColor[1] = (rgbSettings.DefaultColor[1] + 2) / 3;
476 rgbSettings.DefaultColor[2] = (rgbSettings.DefaultColor[2] + 2) / 3;
479 for (
int i = 0; i < num_leds; i++) {
481 if ((i >= rgbSettings.AnnunciateRangeBegin) &&
482 (i <= rgbSettings.AnnunciateRangeEnd)) {
492 if ((i >= rgbSettings.RangeBegin) &&
493 (i <= rgbSettings.RangeEnd)) {
495 range_color[0], range_color[1],
501 rgbSettings.DefaultColor[0],
502 rgbSettings.DefaultColor[1],
503 rgbSettings.DefaultColor[2]);
506 #ifdef SYSTEMMOD_RGBLED_VIDEO_HACK
volatile bool video_active
uint32_t PIOS_Thread_Systime(void)
int PIOS_WS2811_get_num_leds(ws2811_dev_t dev)
Find out how many LEDs are configured on an interface.
static int16_t sin_approx(int32_t x)
Fast approximation of sine; 3rd order taylor expansion. Based on http://www.coranac.com/2009/07/sines/.
void systemmod_process_rgb_leds(bool led_override, bool led_override_active, uint8_t blink_prio, bool is_armed, bool force_dim)
void PIOS_WS2811_set(ws2811_dev_t dev, int idx, uint8_t r, uint8_t g, uint8_t b)
Set a given LED to a color value.
Includes PiOS and core architecture components.
void PIOS_WS2811_trigger_update(ws2811_dev_t dev)
Trigger an update of the LED strand.
bool PIOS_USB_CableConnected(uintptr_t id)