void applyQuadrantColor(const uint8_t ledIndex, const ledConfig_t *ledConfig, const quadrant_e quadrant, const hsvColor_t *color) { switch (quadrant) { case QUADRANT_NORTH_EAST: if (GET_LED_Y(ledConfig) <= highestYValueForNorth && GET_LED_X(ledConfig) >= lowestXValueForEast) { setLedHsv(ledIndex, color); } return; case QUADRANT_SOUTH_EAST: if (GET_LED_Y(ledConfig) >= lowestYValueForSouth && GET_LED_X(ledConfig) >= lowestXValueForEast) { setLedHsv(ledIndex, color); } return; case QUADRANT_SOUTH_WEST: if (GET_LED_Y(ledConfig) >= lowestYValueForSouth && GET_LED_X(ledConfig) <= highestXValueForWest) { setLedHsv(ledIndex, color); } return; case QUADRANT_NORTH_WEST: if (GET_LED_Y(ledConfig) <= highestYValueForNorth && GET_LED_X(ledConfig) <= highestXValueForWest) { setLedHsv(ledIndex, color); } return; } }
static void applyLedAnimationLayer(bool updateNow, uint32_t *timer) { static uint8_t frameCounter = 0; const int animationFrames = ledGridHeight; if(updateNow) { frameCounter = (frameCounter + 1 < animationFrames) ? frameCounter + 1 : 0; *timer += LED_STRIP_HZ(20); } if (ARMING_FLAG(ARMED)) return; int previousRow = frameCounter > 0 ? frameCounter - 1 : animationFrames - 1; int currentRow = frameCounter; int nextRow = (frameCounter + 1 < animationFrames) ? frameCounter + 1 : 0; for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; if (ledGetY(ledConfig) == previousRow) { setLedHsv(ledIndex, getSC(LED_SCOLOR_ANIMATION)); scaleLedValue(ledIndex, 50); } else if (ledGetY(ledConfig) == currentRow) { setLedHsv(ledIndex, getSC(LED_SCOLOR_ANIMATION)); } else if (ledGetY(ledConfig) == nextRow) { scaleLedValue(ledIndex, 50); } } }
// blink twice, then wait ; either always or just when landing static void applyLedBlinkLayer(bool updateNow, uint32_t *timer) { const uint16_t blinkPattern = 0x8005; // 0b1000000000000101; static uint16_t blinkMask; if (updateNow) { blinkMask = blinkMask >> 1; if (blinkMask <= 1) blinkMask = blinkPattern; *timer += LED_STRIP_HZ(10); } bool ledOn = (blinkMask & 1); // b_b_____... if (!ledOn) { for (int i = 0; i < ledCounts.count; ++i) { const ledConfig_t *ledConfig = &ledConfigs[i]; if (ledGetOverlayBit(ledConfig, LED_OVERLAY_BLINK) || (ledGetOverlayBit(ledConfig, LED_OVERLAY_LANDING_FLASH) && scaledThrottle < 55 && scaledThrottle > 10)) { setLedHsv(i, getSC(LED_SCOLOR_BLINKBACKGROUND)); } } } }
static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer) { static uint8_t rotationPhase; int ledRingIndex = 0; if (updateNow) { rotationPhase = rotationPhase > 0 ? rotationPhase - 1 : ledCounts.ringSeqLen - 1; int scale = scaledThrottle; // ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 10, 100) : 10; *timer += LED_STRIP_HZ(5) * 10 / scale; // 5 - 50Hz update rate } for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; if (ledGetFunction(ledConfig) == LED_FUNCTION_THRUST_RING) { bool applyColor; if (ARMING_FLAG(ARMED)) { applyColor = (ledRingIndex + rotationPhase) % ledCounts.ringSeqLen < ROTATION_SEQUENCE_LED_WIDTH; } else { applyColor = !(ledRingIndex % 2); // alternating pattern } if (applyColor) { const hsvColor_t *ringColor = &masterConfig.colors[ledGetColor(ledConfig)]; setLedHsv(ledIndex, ringColor); } ledRingIndex++; } } }
static void applyLedThrustRingLayer(bool updateNow, timeUs_t *timer) { static uint8_t rotationPhase; int ledRingIndex = 0; if (updateNow) { rotationPhase = rotationPhase > 0 ? rotationPhase - 1 : ledCounts.ringSeqLen - 1; *timer += HZ_TO_US(5 + (45 * scaledThrottle) / 100); // 5 - 50Hz update rate } for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[ledIndex]; if (ledGetFunction(ledConfig) == LED_FUNCTION_THRUST_RING) { bool applyColor; if (ARMING_FLAG(ARMED)) { applyColor = (ledRingIndex + rotationPhase) % ledCounts.ringSeqLen < ROTATION_SEQUENCE_LED_WIDTH; } else { applyColor = !(ledRingIndex % 2); // alternating pattern } if (applyColor) { const hsvColor_t *ringColor = &ledStripConfig()->colors[ledGetColor(ledConfig)]; setLedHsv(ledIndex, ringColor); } ledRingIndex++; } } }
void setStripColors(const hsvColor_t *colors) { uint16_t index; for (index = 0; index < WS2811_LED_STRIP_LENGTH; index++) { setLedHsv(index, colors++); } }
void applyLedModeLayer(void) { const ledConfig_t *ledConfig; uint8_t ledIndex; for (ledIndex = 0; ledIndex < ledCount; ledIndex++) { ledConfig = &ledConfigs[ledIndex]; if (!(ledConfig->flags & LED_FUNCTION_THRUST_RING)) { if (ledConfig->flags & LED_FUNCTION_COLOR) { setLedHsv(ledIndex, &colors[ledConfig->color]); } else { setLedHsv(ledIndex, &hsv_black); } } if (!(ledConfig->flags & LED_FUNCTION_FLIGHT_MODE)) { if (ledConfig->flags & LED_FUNCTION_ARM_STATE) { if (!ARMING_FLAG(ARMED)) { setLedHsv(ledIndex, &hsv_green); } else { setLedHsv(ledIndex, &hsv_blue); } } continue; } applyDirectionalModeColor(ledIndex, ledConfig, &orientationModeColors); if (FLIGHT_MODE(HEADFREE_MODE)) { applyDirectionalModeColor(ledIndex, ledConfig, &headfreeModeColors); #ifdef MAG } else if (FLIGHT_MODE(MAG_MODE)) { applyDirectionalModeColor(ledIndex, ledConfig, &magModeColors); #endif #ifdef BARO } else if (FLIGHT_MODE(BARO_MODE)) { applyDirectionalModeColor(ledIndex, ledConfig, &baroModeColors); #endif } else if (FLIGHT_MODE(HORIZON_MODE)) { applyDirectionalModeColor(ledIndex, ledConfig, &horizonModeColors); } else if (FLIGHT_MODE(ANGLE_MODE)) { applyDirectionalModeColor(ledIndex, ledConfig, &angleModeColors); } } }
static void applyLedHsv(uint32_t mask, const hsvColor_t *color) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; if ((*ledConfig & mask) == mask) setLedHsv(ledIndex, color); } }
void applyLedWarningLayer(uint8_t updateNow) { const ledConfig_t *ledConfig; uint8_t ledIndex; static uint8_t warningFlashCounter = 0; if (updateNow && warningFlashCounter == 0) { warningFlags = WARNING_FLAG_NONE; if (feature(FEATURE_VBAT) && getBatteryState() != BATTERY_OK) { warningFlags |= WARNING_FLAG_LOW_BATTERY; } if (feature(FEATURE_FAILSAFE) && failsafeIsActive()) { warningFlags |= WARNING_FLAG_FAILSAFE; } if (!ARMING_FLAG(ARMED) && !ARMING_FLAG(OK_TO_ARM)) { warningFlags |= WARNING_FLAG_ARMING_DISABLED; } } if (warningFlags || warningFlashCounter > 0) { const hsvColor_t *warningColor = &hsv_black; if ((warningFlashCounter & 1) == 0) { if (warningFlashCounter < 4 && (warningFlags & WARNING_FLAG_ARMING_DISABLED)) { warningColor = &hsv_green; } if (warningFlashCounter >= 4 && warningFlashCounter < 12 && (warningFlags & WARNING_FLAG_LOW_BATTERY)) { warningColor = &hsv_red; } if (warningFlashCounter >= 12 && warningFlashCounter < 16 && (warningFlags & WARNING_FLAG_FAILSAFE)) { warningColor = &hsv_yellow; } } else { if (warningFlashCounter >= 12 && warningFlashCounter < 16 && (warningFlags & WARNING_FLAG_FAILSAFE)) { warningColor = &hsv_blue; } } for (ledIndex = 0; ledIndex < ledCount; ledIndex++) { ledConfig = &ledConfigs[ledIndex]; if (!(ledConfig->flags & LED_FUNCTION_WARNING)) { continue; } setLedHsv(ledIndex, warningColor); } } if (updateNow && (warningFlags || warningFlashCounter)) { warningFlashCounter++; if (warningFlashCounter == 20) { warningFlashCounter = 0; } } }
static void applyLedFixedLayers() { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[ledIndex]; hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND); int fn = ledGetFunction(ledConfig); int hOffset = HSV_HUE_MAX; switch (fn) { case LED_FUNCTION_COLOR: color = ledStripConfig()->colors[ledGetColor(ledConfig)]; break; case LED_FUNCTION_FLIGHT_MODE: for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++) if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) { const hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &ledStripConfig()->modeColors[flightModeToLed[i].ledMode]); if (directionalColor) { color = *directionalColor; } break; // stop on first match } break; case LED_FUNCTION_ARM_STATE: color = ARMING_FLAG(ARMED) ? *getSC(LED_SCOLOR_ARMED) : *getSC(LED_SCOLOR_DISARMED); break; case LED_FUNCTION_BATTERY: color = HSV(RED); hOffset += scaleRange(calculateBatteryPercentage(), 0, 100, -30, 120); break; case LED_FUNCTION_RSSI: color = HSV(RED); hOffset += scaleRange(rssi * 100, 0, 1023, -30, 120); break; default: break; } if (ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) { hOffset += scaledAux; } color.h = (color.h + hOffset) % (HSV_HUE_MAX + 1); setLedHsv(ledIndex, &color); } }
void applyDirectionalModeColor(const uint8_t ledIndex, const ledConfig_t *ledConfig, const modeColorIndexes_t *modeColors) { // apply up/down colors regardless of quadrant. if ((ledConfig->flags & LED_DIRECTION_UP)) { setLedHsv(ledIndex, &colors[modeColors->up]); } if ((ledConfig->flags & LED_DIRECTION_DOWN)) { setLedHsv(ledIndex, &colors[modeColors->down]); } // override with n/e/s/w colors to each n/s e/w half - bail at first match. if ((ledConfig->flags & LED_DIRECTION_WEST) && GET_LED_X(ledConfig) <= highestXValueForWest) { setLedHsv(ledIndex, &colors[modeColors->west]); } if ((ledConfig->flags & LED_DIRECTION_EAST) && GET_LED_X(ledConfig) >= lowestXValueForEast) { setLedHsv(ledIndex, &colors[modeColors->east]); } if ((ledConfig->flags & LED_DIRECTION_NORTH) && GET_LED_Y(ledConfig) <= highestYValueForNorth) { setLedHsv(ledIndex, &colors[modeColors->north]); } if ((ledConfig->flags & LED_DIRECTION_SOUTH) && GET_LED_Y(ledConfig) >= lowestYValueForSouth) { setLedHsv(ledIndex, &colors[modeColors->south]); } }
void applyLedWarningLayer(uint8_t warningState, uint8_t warningFlags) { const ledConfig_t *ledConfig; static uint8_t warningFlashCounter = 0; if (warningState) { warningFlashCounter++; warningFlashCounter = warningFlashCounter % 4; } uint8_t ledIndex; for (ledIndex = 0; ledIndex < ledCount; ledIndex++) { ledConfig = &ledConfigs[ledIndex]; if (!(ledConfig->flags & LED_FUNCTION_WARNING)) { continue; } if (warningState == 0) { if (warningFlashCounter == 0 && warningFlags & WARNING_FLAG_LOW_BATTERY) { setLedHsv(ledIndex, &hsv_red); } if (warningFlashCounter > 1 && warningFlags & WARNING_FLAG_FAILSAFE) { setLedHsv(ledIndex, &hsv_lightBlue); } } else { if (warningFlashCounter == 0 && warningFlags & WARNING_FLAG_LOW_BATTERY) { setLedHsv(ledIndex, &hsv_black); } if (warningFlashCounter > 1 && warningFlags & WARNING_FLAG_FAILSAFE) { setLedHsv(ledIndex, &hsv_limeGreen); } } } }
static void applyLedAnimationLayer(void) { const ledConfig_t *ledConfig; if (ARMING_FLAG(ARMED)) { return; } uint8_t ledIndex; for (ledIndex = 0; ledIndex < ledCount; ledIndex++) { ledConfig = &ledConfigs[ledIndex]; if (GET_LED_Y(ledConfig) == previousRow) { setLedHsv(ledIndex, &white); setLedBrightness(ledIndex, 50); } else if (GET_LED_Y(ledConfig) == currentRow) { setLedHsv(ledIndex, &white); } else if (GET_LED_Y(ledConfig) == nextRow) { setLedBrightness(ledIndex, 50); } } }
void applyLedThrustRingLayer(void) { uint8_t ledIndex; static uint8_t rotationPhase = ROTATION_SEQUENCE_LED_COUNT; bool nextLedOn = false; hsvColor_t ringColor; const ledConfig_t *ledConfig; uint8_t ledRingIndex = 0; for (ledIndex = 0; ledIndex < ledCount; ledIndex++) { ledConfig = &ledConfigs[ledIndex]; if ((ledConfig->flags & LED_FUNCTION_THRUST_RING) == 0) { continue; } bool applyColor = false; if (ARMING_FLAG(ARMED)) { if ((ledRingIndex + rotationPhase) % ROTATION_SEQUENCE_LED_COUNT < ROTATION_SEQUENCE_LED_WIDTH) { applyColor = true; } } else { if (nextLedOn == false) { applyColor = true; } nextLedOn = !nextLedOn; } if (applyColor) { ringColor = colors[ledConfig->color]; } else { ringColor = hsv_black; } setLedHsv(ledIndex, &ringColor); ledRingIndex++; } rotationPhase--; if (rotationPhase == 0) { rotationPhase = ROTATION_SEQUENCE_LED_COUNT; } }
static void applyLedIndicatorLayer(bool updateNow, uint32_t *timer) { static bool flash = 0; if (updateNow) { if (rxIsReceivingSignal()) { // calculate update frequency int scale = MAX(ABS(rcCommand[ROLL]), ABS(rcCommand[PITCH])); // 0 - 500 scale += (50 - INDICATOR_DEADBAND); // start increasing frequency right after deadband *timer += LED_STRIP_HZ(5) * 50 / MAX(50, scale); // 5 - 50Hz update, 2.5 - 25Hz blink flash = !flash; } else { *timer += LED_STRIP_HZ(5); // try again soon } } if (!flash) return; const hsvColor_t *flashColor = &HSV(ORANGE); // TODO - use user color? quadrant_e quadrants = 0; if (rcCommand[ROLL] > INDICATOR_DEADBAND) { quadrants |= QUADRANT_NORTH_EAST | QUADRANT_SOUTH_EAST; } else if (rcCommand[ROLL] < -INDICATOR_DEADBAND) { quadrants |= QUADRANT_NORTH_WEST | QUADRANT_SOUTH_WEST; } if (rcCommand[PITCH] > INDICATOR_DEADBAND) { quadrants |= QUADRANT_NORTH_EAST | QUADRANT_NORTH_WEST; } else if (rcCommand[PITCH] < -INDICATOR_DEADBAND) { quadrants |= QUADRANT_SOUTH_EAST | QUADRANT_SOUTH_WEST; } for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; if (ledGetOverlayBit(ledConfig, LED_OVERLAY_INDICATOR)) { if (getLedQuadrant(ledIndex) & quadrants) setLedHsv(ledIndex, flashColor); } } }
void applyLedThrottleLayer() { const ledConfig_t *ledConfig; hsvColor_t color; uint8_t ledIndex; for (ledIndex = 0; ledIndex < ledCount; ledIndex++) { ledConfig = &ledConfigs[ledIndex]; if (!(ledConfig->flags & LED_FUNCTION_THROTTLE)) { continue; } getLedHsv(ledIndex, &color); int scaled = scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, -60, +60); scaled += HSV_HUE_MAX; color.h = (color.h + scaled) % HSV_HUE_MAX; setLedHsv(ledIndex, &color); } }
static void applyLarsonScannerLayer(bool updateNow, uint32_t *timer) { static larsonParameters_t larsonParameters = { 0, 0, 1 }; if (updateNow) { larsonScannerNextStep(&larsonParameters, 15); *timer += LED_STRIP_HZ(60); } int scannerLedIndex = 0; for (unsigned i = 0; i < ledCounts.count; i++) { const ledConfig_t *ledConfig = &ledConfigs[i]; if (ledGetOverlayBit(ledConfig, LED_OVERLAY_LARSON_SCANNER)) { hsvColor_t ledColor; getLedHsv(i, &ledColor); ledColor.v = brightnessForLarsonIndex(&larsonParameters, scannerLedIndex); setLedHsv(i, &ledColor); scannerLedIndex++; } } }
// blink twice, then wait ; either always or just when landing static void applyLedBlinkLayer(bool updateNow, timeUs_t *timer) { const uint16_t blinkPattern = 0x8005; // 0b1000000000000101; static uint16_t blinkMask; if (updateNow) { blinkMask = blinkMask >> 1; if (blinkMask <= 1) blinkMask = blinkPattern; *timer += HZ_TO_US(10); } bool ledOn = (blinkMask & 1); // b_b_____... if (!ledOn) { for (int i = 0; i < ledCounts.count; ++i) { const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[i]; if (ledGetOverlayBit(ledConfig, LED_OVERLAY_BLINK)) { setLedHsv(i, getSC(LED_SCOLOR_BLINKBACKGROUND)); } } } }
void applyLedThrustRingLayer(void) { const ledConfig_t *ledConfig; hsvColor_t ringColor; uint8_t ledIndex; // initialised to special value instead of using more memory for a flag. static uint8_t rotationSeqLedCount = RING_PATTERN_NOT_CALCULATED; static uint8_t rotationPhase = ROTATION_SEQUENCE_LED_COUNT; bool nextLedOn = false; uint8_t ledRingIndex = 0; for (ledIndex = 0; ledIndex < ledCount; ledIndex++) { ledConfig = &ledConfigs[ledIndex]; if ((ledConfig->flags & LED_FUNCTION_THRUST_RING) == 0) { continue; } bool applyColor = false; if (ARMING_FLAG(ARMED)) { if ((ledRingIndex + rotationPhase) % rotationSeqLedCount < ROTATION_SEQUENCE_LED_WIDTH) { applyColor = true; } } else { if (nextLedOn == false) { applyColor = true; } nextLedOn = !nextLedOn; } if (applyColor) { ringColor = colors[ledConfig->color]; } else { ringColor = hsv_black; } setLedHsv(ledIndex, &ringColor); ledRingIndex++; } uint8_t ledRingLedCount = ledRingIndex; if (rotationSeqLedCount == RING_PATTERN_NOT_CALCULATED) { // update ring pattern according to total number of ring leds found rotationSeqLedCount = ledRingLedCount; // try to split in segments/rings of exactly ROTATION_SEQUENCE_LED_COUNT leds if ((ledRingLedCount % ROTATION_SEQUENCE_LED_COUNT) == 0) { rotationSeqLedCount = ROTATION_SEQUENCE_LED_COUNT; } else { // else split up in equal segments/rings of at most ROTATION_SEQUENCE_LED_COUNT leds while ((rotationSeqLedCount > ROTATION_SEQUENCE_LED_COUNT) && ((rotationSeqLedCount % 2) == 0)) { rotationSeqLedCount >>= 1; } } // trigger start over rotationPhase = 1; }
static void applyLedVtxLayer(bool updateNow, timeUs_t *timer) { static uint16_t frequency = 0; static uint8_t power = 255; static uint8_t pit = 255; static uint8_t showSettings = false; static uint16_t lastCheck = 0; static bool blink = false; const vtxDevice_t *vtxDevice = vtxCommonDevice(); if (!vtxDevice) { return; } uint8_t band = 255, channel = 255; uint16_t check = 0; if (updateNow) { // keep counter running, so it stays in sync with vtx vtxCommonGetBandAndChannel(vtxDevice, &band, &channel); vtxCommonGetPowerIndex(vtxDevice, &power); vtxCommonGetPitMode(vtxDevice, &pit); frequency = vtx58frequencyTable[band - 1][channel - 1]; //subtracting 1 from band and channel so that correct frequency is returned. //might not be correct for tramp but should fix smart audio. // check if last vtx values have changed. check = pit + (power << 1) + (band << 4) + (channel << 8); if (!showSettings && check != lastCheck) { // display settings for 3 seconds. showSettings = 15; } lastCheck = check; // quick way to check if any settings changed. if (showSettings) { showSettings--; } blink = !blink; *timer += HZ_TO_US(5); // check 5 times a second } hsvColor_t color = {0, 0, 0}; if (showSettings) { // show settings uint8_t vtxLedCount = 0; for (int i = 0; i < ledCounts.count && vtxLedCount < 6; ++i) { const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[i]; if (ledGetOverlayBit(ledConfig, LED_OVERLAY_VTX)) { if (vtxLedCount == 0) { color.h = HSV(GREEN).h; color.s = HSV(GREEN).s; color.v = blink ? 15 : 0; // blink received settings } else if (vtxLedCount > 0 && power >= vtxLedCount && !pit) { // show power color.h = HSV(ORANGE).h; color.s = HSV(ORANGE).s; color.v = blink ? 15 : 0; // blink received settings } else { // turn rest off color.h = HSV(BLACK).h; color.s = HSV(BLACK).s; color.v = HSV(BLACK).v; } setLedHsv(i, &color); ++vtxLedCount; } } } else { // show frequency // calculate the VTX color based on frequency int colorIndex = 0; if (frequency <= 5672) { colorIndex = COLOR_WHITE; } else if (frequency <= 5711) { colorIndex = COLOR_RED; } else if (frequency <= 5750) { colorIndex = COLOR_ORANGE; } else if (frequency <= 5789) { colorIndex = COLOR_YELLOW; } else if (frequency <= 5829) { colorIndex = COLOR_GREEN; } else if (frequency <= 5867) { colorIndex = COLOR_BLUE; } else if (frequency <= 5906) { colorIndex = COLOR_DARK_VIOLET; } else { colorIndex = COLOR_DEEP_PINK; } hsvColor_t color = ledStripConfig()->colors[colorIndex]; color.v = pit ? (blink ? 15 : 0) : 255; // blink when in pit mode applyLedHsv(LED_MOV_OVERLAY(LED_FLAG_OVERLAY(LED_OVERLAY_VTX)), &color); } }
static void applyLedFixedLayers(void) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[ledIndex]; hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND); int fn = ledGetFunction(ledConfig); int hOffset = HSV_HUE_MAX + 1; switch (fn) { case LED_FUNCTION_COLOR: color = ledStripConfig()->colors[ledGetColor(ledConfig)]; hsvColor_t nextColor = ledStripConfig()->colors[(ledGetColor(ledConfig) + 1 + LED_CONFIGURABLE_COLOR_COUNT) % LED_CONFIGURABLE_COLOR_COUNT]; hsvColor_t previousColor = ledStripConfig()->colors[(ledGetColor(ledConfig) - 1 + LED_CONFIGURABLE_COLOR_COUNT) % LED_CONFIGURABLE_COLOR_COUNT]; if (ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) { //smooth fade with selected Aux channel of all HSV values from previousColor through color to nextColor int centerPWM = (PWM_RANGE_MIN + PWM_RANGE_MAX) / 2; if (auxInput < centerPWM) { color.h = scaleRange(auxInput, PWM_RANGE_MIN, centerPWM, previousColor.h, color.h); color.s = scaleRange(auxInput, PWM_RANGE_MIN, centerPWM, previousColor.s, color.s); color.v = scaleRange(auxInput, PWM_RANGE_MIN, centerPWM, previousColor.v, color.v); } else { color.h = scaleRange(auxInput, centerPWM, PWM_RANGE_MAX, color.h, nextColor.h); color.s = scaleRange(auxInput, centerPWM, PWM_RANGE_MAX, color.s, nextColor.s); color.v = scaleRange(auxInput, centerPWM, PWM_RANGE_MAX, color.v, nextColor.v); } } break; case LED_FUNCTION_FLIGHT_MODE: for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++) if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) { const hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &ledStripConfig()->modeColors[flightModeToLed[i].ledMode]); if (directionalColor) { color = *directionalColor; } break; // stop on first match } break; case LED_FUNCTION_ARM_STATE: color = ARMING_FLAG(ARMED) ? *getSC(LED_SCOLOR_ARMED) : *getSC(LED_SCOLOR_DISARMED); break; case LED_FUNCTION_BATTERY: color = HSV(RED); hOffset += scaleRange(calculateBatteryPercentageRemaining(), 0, 100, -30, 120); break; case LED_FUNCTION_RSSI: color = HSV(RED); hOffset += scaleRange(getRssi() * 100, 0, 1023, -30, 120); break; default: break; } if ((fn != LED_FUNCTION_COLOR) && ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) { hOffset += scaleRange(auxInput, PWM_RANGE_MIN, PWM_RANGE_MAX, 0, HSV_HUE_MAX + 1); } color.h = (color.h + hOffset) % (HSV_HUE_MAX + 1); setLedHsv(ledIndex, &color); } }
void setStripColor(const hsvColor_t *color) { for (int index = 0; index < WS2811_LED_STRIP_LENGTH; index++) setLedHsv(index, color); }