From 744d9eb7a31d6ca0c45285b8418d308c2b6b66e0 Mon Sep 17 00:00:00 2001 From: Bruce Luckcuck Date: Sun, 20 Jan 2019 18:10:23 -0500 Subject: [PATCH] Refactor ledstrip profiles to fix excessive cpu load Previous logic bypassed optimizations and updated the ws2811 on every task execution - leading to and average of 92us task execution time. Restored the previous optimizations and additionally optimized the new "RACE" and "BEACON" modes so that they only update the led's when there's an actual state change. Task time for these modes is now in the 2-4us range for F405. For the normal "STATUS" profile the performance has been restored to previous optimized levels and typical configurations will generally have task times in the 8-14us range. Revised the LEDLOW disable mode to function all the time and disable the ledstrip completely. Previously if visual beeper was enabled that would override the disable and the ledstrip would display whatever would be otherwise displayed but only during the duration of the beep. The resulted to a very inconsistent behavior depending on the user's settings. Added visual beeper support to the new "RACE" and "BEACON" profile modes. General cleanup and refactoring. --- src/main/cms/cms_menu_ledstrip.c | 25 +++------- src/main/io/ledstrip.c | 85 +++++++++++++++++++++----------- 2 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/main/cms/cms_menu_ledstrip.c b/src/main/cms/cms_menu_ledstrip.c index ea46add59..bdb963525 100644 --- a/src/main/cms/cms_menu_ledstrip.c +++ b/src/main/cms/cms_menu_ledstrip.c @@ -45,7 +45,6 @@ #ifdef USE_LED_STRIP -static bool featureRead = false; static uint8_t cmsx_FeatureLedstrip; static uint8_t cmsx_LedProfile; static uint8_t cmsx_RaceColor; @@ -59,34 +58,26 @@ const char * const ledProfileNames[LED_PROFILE_COUNT] = { static long cmsx_Ledstrip_OnEnter(void) { - if (!featureRead) { - cmsx_FeatureLedstrip = featureIsEnabled(FEATURE_LED_STRIP) ? 1 : 0; - featureRead = true; - } - -#ifdef USE_LED_STRIP + cmsx_FeatureLedstrip = featureIsEnabled(FEATURE_LED_STRIP) ? 1 : 0; cmsx_LedProfile = getLedProfile(); cmsx_RaceColor = getLedRaceColor(); -#endif + return 0; } static long cmsx_Ledstrip_OnExit(const OSD_Entry *self) { UNUSED(self); - if (featureRead) { - if (cmsx_FeatureLedstrip) - featureEnable(FEATURE_LED_STRIP); - else { - ledStripDisable(); - featureDisable(FEATURE_LED_STRIP); - } + + if (cmsx_FeatureLedstrip) { + featureEnable(FEATURE_LED_STRIP); + } else { + ledStripDisable(); + featureDisable(FEATURE_LED_STRIP); } -#ifdef USE_LED_STRIP setLedProfile(cmsx_LedProfile); setLedRaceColor(cmsx_RaceColor); -#endif return 0; } diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c index 36c754578..910a328c5 100644 --- a/src/main/io/ledstrip.c +++ b/src/main/io/ledstrip.c @@ -85,7 +85,10 @@ const modeColorIndexes_t *modeColors; specialColorIndexes_t specialColors; static bool ledStripInitialised = false; -static volatile bool ledStripEnabled = true; +static bool ledStripEnabled = false; +static uint8_t previousBeaconColorIndex = COLOR_BLACK; +static uint8_t previousRaceColorIndex = COLOR_BLACK; +static timeUs_t raceColorUpdateTimeUs = 0; void ledStripDisable(void); @@ -95,6 +98,9 @@ void ledStripDisable(void); #define BEACON_FLASH_PERIOD_MS 1000 // 1000ms #define BEACON_FLASH_ON_TIME 100 // 100ms +#define RACE_COLOR_UPDATE_INTERVAL_US 1e6 // normally updates when color changes but this is a 1 second forced update + +#define VISUAL_BEEPER_COLOR COLOR_ORANGE #if LED_MAX_STRIP_LENGTH > WS2811_LED_STRIP_LENGTH # error "Led strip length must match driver" @@ -174,8 +180,6 @@ void pgResetFn_ledStripConfig(ledStripConfig_t *ledStripConfig) #endif } -static int scaledThrottle; -static int auxInput; #ifdef USE_LED_STRIP_STATUS_MODE static void updateLedRingCounts(void); #endif @@ -455,6 +459,7 @@ static void applyLedFixedLayers(void) 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 + const int auxInput = rcData[ledStripConfig()->ledstrip_aux_channel]; int centerPWM = (PWM_RANGE_MIN + PWM_RANGE_MAX) / 2; if (auxInput < centerPWM) { color.h = scaleRange(auxInput, PWM_RANGE_MIN, centerPWM, previousColor.h, color.h); @@ -500,6 +505,7 @@ static void applyLedFixedLayers(void) } if ((fn != LED_FUNCTION_COLOR) && ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) { + const int auxInput = rcData[ledStripConfig()->ledstrip_aux_channel]; hOffset += scaleRange(auxInput, PWM_RANGE_MIN, PWM_RANGE_MAX, 0, HSV_HUE_MAX + 1); } @@ -576,7 +582,7 @@ static void applyLedWarningLayer(bool updateNow, timeUs_t *timer) } } else { if (isBeeperOn()) { - warningColor = &HSV(ORANGE); + warningColor = &hsv[VISUAL_BEEPER_COLOR]; } } @@ -856,6 +862,7 @@ static void applyLedThrustRingLayer(bool updateNow, timeUs_t *timer) if (updateNow) { rotationPhase = rotationPhase > 0 ? rotationPhase - 1 : ledCounts.ringSeqLen - 1; + const int scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, 100) : 0; *timer += HZ_TO_US(5 + (45 * scaledThrottle) / 100); // 5 - 50Hz update rate } @@ -1039,7 +1046,7 @@ void updateRequiredOverlay(void) disabledTimerMask |= !isOverlayTypeUsed(LED_OVERLAY_INDICATOR) << timIndicator; } -static void applyStatusProfile(uint32_t now) { +static void applyStatusProfile(timeUs_t now) { // apply all layers; triggered timed functions has to update timers // test all led timers, setting corresponding bits @@ -1067,16 +1074,41 @@ static void applyStatusProfile(uint32_t now) { bool updateNow = timActive & (1 << timId); (*layerTable[timId])(updateNow, timer); } + ws2811UpdateStrip((ledStripFormatRGB_e) ledStripConfig()->ledstrip_grb_rgb); } #endif -static void applyBeaconProfile(void) { - - bool ledsBlink = millis() % (BEACON_FLASH_PERIOD_MS) < BEACON_FLASH_ON_TIME; - if (ledsBlink) { - setStripColor(&HSV(WHITE)); +static uint8_t selectVisualBeeperColor(uint8_t colorIndex) +{ + if (ledStripConfig()->ledstrip_visual_beeper && isBeeperOn()) { + return VISUAL_BEEPER_COLOR; } else { - setStripColor(&HSV(BLACK)); + return colorIndex; + } +} + +static void applyBeaconProfile(void) +{ + const bool beaconState = millis() % (BEACON_FLASH_PERIOD_MS) < BEACON_FLASH_ON_TIME; + uint8_t colorIndex = (beaconState) ? COLOR_WHITE : COLOR_BLACK; + colorIndex = selectVisualBeeperColor(colorIndex); + + if (colorIndex != previousBeaconColorIndex) { + previousBeaconColorIndex = colorIndex; + setStripColor(&hsv[colorIndex]); + ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb); + } +} + +static void applyRaceProfile(timeUs_t currentTimeUs) +{ + uint8_t colorIndex = selectVisualBeeperColor(ledStripConfig()->ledRaceColor); + // refresh the color if it changes or at least every 1 second + if ((colorIndex != previousRaceColorIndex) || (currentTimeUs >= raceColorUpdateTimeUs)) { + setStripColor(&hsv[colorIndex]); + ws2811UpdateStrip((ledStripFormatRGB_e) ledStripConfig()->ledstrip_grb_rgb); + previousRaceColorIndex = colorIndex; + raceColorUpdateTimeUs = currentTimeUs + RACE_COLOR_UPDATE_INTERVAL_US; } } @@ -1086,17 +1118,17 @@ void ledStripUpdate(timeUs_t currentTimeUs) UNUSED(currentTimeUs); #endif - if (!(ledStripInitialised && isWS2811LedStripReady())) { + if (!featureIsEnabled(FEATURE_LED_STRIP) || !ledStripInitialised || !isWS2811LedStripReady()) { return; } - if (((true == ledStripEnabled) - || (ledStripConfig()->ledstrip_visual_beeper && isBeeperOn())) - && !IS_RC_MODE_ACTIVE(BOXLEDLOW)) { - - scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, 100) : 0; - auxInput = rcData[ledStripConfig()->ledstrip_aux_channel]; - + if (ledStripEnabled && IS_RC_MODE_ACTIVE(BOXLEDLOW)) { + ledStripDisable(); + } else if (!IS_RC_MODE_ACTIVE(BOXLEDLOW)) { + ledStripEnabled = true; + } + + if (ledStripEnabled) { switch (ledStripConfig()->ledstrip_profile) { #ifdef USE_LED_STRIP_STATUS_MODE case LED_PROFILE_STATUS: { @@ -1105,7 +1137,7 @@ void ledStripUpdate(timeUs_t currentTimeUs) } #endif case LED_PROFILE_RACE: { - setStripColor(&hsv[ledStripConfig()->ledRaceColor]); + applyRaceProfile(currentTimeUs); break; } case LED_PROFILE_BEACON: { @@ -1115,12 +1147,6 @@ void ledStripUpdate(timeUs_t currentTimeUs) default: break; } - ws2811UpdateStrip((ledStripFormatRGB_e) ledStripConfig()->ledstrip_grb_rgb); - } - else - { - setStripColor(&HSV(BLACK)); - ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb); } } @@ -1218,9 +1244,12 @@ void ledStripEnable(void) void ledStripDisable(void) { ledStripEnabled = false; + previousRaceColorIndex = COLOR_BLACK; + previousBeaconColorIndex = COLOR_BLACK; setStripColor(&HSV(BLACK)); - - ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb); + if (ledStripInitialised) { + ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb); + } }