diff --git a/src/main/fc/settings.yaml b/src/main/fc/settings.yaml index 4e8affb0221..898c5fa2b4c 100644 --- a/src/main/fc/settings.yaml +++ b/src/main/fc/settings.yaml @@ -4502,3 +4502,20 @@ groups: field: noWayHomeAction table: geozone_rth_no_way_home type: uint8_t + - name: PG_LED_STRIP_CONFIG + type: ledStripConfig_t + headers: ["io/ledstrip.h"] + condition: USE_LED_STRIP + members: + - name: ledstrip_rainbow_sweep_rate + description: "Rainbow overlay sweep rate. Higher values sweep faster. 0 freezes the rainbow." + default_value: 100 + field: ledstrip_rainbow_sweep_rate + min: 0 + max: 255 + - name: ledstrip_rainbow_delta_deg + description: "Hue offset in degrees between adjacent LEDs carrying the rainbow overlay. 0 makes every rainbow LED the same color; larger values spread more of the spectrum across the strip." + default_value: 30 + field: ledstrip_rainbow_delta_deg + min: 0 + max: 359 \ No newline at end of file diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c index 8e8e5771450..16d75288962 100644 --- a/src/main/io/ledstrip.c +++ b/src/main/io/ledstrip.c @@ -154,6 +154,8 @@ void pgResetFn_ledStripConfig(ledStripConfig_t *instance) } memcpy_fn(&instance->modeColors, &defaultModeColors, sizeof(defaultModeColors)); memcpy_fn(&instance->specialColors, &defaultSpecialColors, sizeof(defaultSpecialColors)); + instance->ledstrip_rainbow_sweep_rate = 10; + instance->ledstrip_rainbow_delta_deg = 30; } static int scaledThrottle; @@ -224,7 +226,7 @@ static const hsvColor_t* getSC(ledSpecialColorIds_e index) static const char directionCodes[LED_DIRECTION_COUNT] = { 'N', 'E', 'S', 'W', 'U', 'D' }; static const char baseFunctionCodes[LED_BASEFUNCTION_COUNT] = { 'C', 'F', 'A', 'L', 'S', 'G', 'R', 'H' }; -static const char overlayCodes[LED_OVERLAY_COUNT] = { 'T', 'O', 'B', 'N', 'I', 'W', 'E' }; +static const char overlayCodes[LED_OVERLAY_COUNT] = { 'T', 'O', 'B', 'N', 'I', 'W', 'E', 'V' }; #define CHUNK_BUFFER_SIZE 11 @@ -841,6 +843,41 @@ static void applyLarsonScannerLayer(bool updateNow, timeUs_t *timer) } } +static void applyLedRainbowLayer(bool updateNow, timeUs_t *timer) +{ + static uint16_t accumulator = 0; + static uint8_t stepCount = 0; + + if (updateNow) { + *timer += LED_STRIP_HZ(100); + const uint8_t speed = ledStripConfig()->ledstrip_rainbow_sweep_rate; + if (speed > 0) { + accumulator += speed; + while (accumulator >= 256) { + accumulator -= 256; + if (++stepCount >= 180) { + stepCount = 0; + } + } + } + } + + const uint16_t rainbowHue = (uint16_t)stepCount << 1; + const uint16_t rainbowDelta = ledStripConfig()->ledstrip_rainbow_delta_deg % 360; + + for (unsigned i = 0; i < ledCounts.count; i++) { + const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[i]; + + if (ledGetOverlayBit(ledConfig, LED_OVERLAY_RAINBOW)) { + hsvColor_t ledColor; + ledColor.h = (rainbowHue + (i * rainbowDelta)) % 360; + ledColor.s = 0; + ledColor.v = 255; + setLedHsv(i, &ledColor); + } + } +} + // blink twice, then wait ; either always or just when landing static void applyLedBlinkLayer(bool updateNow, timeUs_t *timer) { @@ -907,6 +944,7 @@ static void applyLedAnimationLayer(bool updateNow, timeUs_t *timer) typedef enum { timBlink = 0, timLarson, + timRainbow, timBattery, timRssi, #ifdef USE_GPS @@ -933,6 +971,7 @@ typedef void applyLayerFn_timed(bool updateNow, timeUs_t *timer); static applyLayerFn_timed* layerTable[timTimerCount] = { [timBlink] = &applyLedBlinkLayer, [timLarson] = &applyLarsonScannerLayer, + [timRainbow] = &applyLedRainbowLayer, [timBattery] = &applyLedBatteryLayer, [timRssi] = &applyLedRssiLayer, #ifdef USE_GPS diff --git a/src/main/io/ledstrip.h b/src/main/io/ledstrip.h index 2aea06cde73..ff3c2fcec44 100644 --- a/src/main/io/ledstrip.h +++ b/src/main/io/ledstrip.h @@ -26,7 +26,7 @@ #define LED_MODE_COUNT 7 #define LED_DIRECTION_COUNT 6 #define LED_BASEFUNCTION_COUNT 8 -#define LED_OVERLAY_COUNT 7 +#define LED_OVERLAY_COUNT 8 #define LED_SPECIAL_COLOR_COUNT 9 #define LED_FUNCTION_OFFSET 8 @@ -122,7 +122,8 @@ typedef enum { LED_OVERLAY_LANDING_FLASH, LED_OVERLAY_INDICATOR, LED_OVERLAY_WARNING, - LED_OVERLAY_STROBE + LED_OVERLAY_STROBE, + LED_OVERLAY_RAINBOW } ledOverlayId_e; typedef struct modeColorIndexes_s { @@ -154,6 +155,8 @@ typedef struct ledStripConfig_s { hsvColor_t colors[LED_CONFIGURABLE_COLOR_COUNT]; modeColorIndexes_t modeColors[LED_MODE_COUNT]; specialColorIndexes_t specialColors; + uint8_t ledstrip_rainbow_sweep_rate; // hue sweep rate for rainbow overlay, 0-255, 0=stopped, 255=fastest + uint16_t ledstrip_rainbow_delta_deg; // hue offset between adjacent rainbow-overlay LEDs, 0-359 degrees } ledStripConfig_t; PG_DECLARE(ledStripConfig_t, ledStripConfig);