FastLED 3.10.8
Loading...
Searching...
No Matches

◆ brightness_within_budget()

static fl::u8 brightness_within_budget ( fl::u32 fixed_mW,
fl::u32 controllable_mW,
fl::u8 target_brightness,
fl::u32 max_power_mW )
static

Definition at line 408 of file power_mgt.cpp.hpp.

410 {
411 const fl::u32 requested_mW =
412 fixed_mW + scale_power_for_brightness(controllable_mW, target_brightness);
413 if (requested_mW <= max_power_mW) {
414 return target_brightness;
415 }
416 if (controllable_mW == 0 || max_power_mW <= fixed_mW) {
417 // Nothing left to scale, or the baseline alone is already over the
418 // budget. Either way no brightness meets it, and returning here is
419 // also what keeps the subtraction below from underflowing and the
420 // division from dividing by zero on an all-dark strip.
421 return 0;
422 }
423 // The ratio is taken over the whole 0-255 scaled range, because
424 // `controllable_mW` is the demand at *full* brightness. Scaling it by the
425 // requested brightness first would answer "what fraction of the request
426 // fits", which is smaller than "what brightness fits" by exactly that
427 // fraction -- and the step-down below only ever decreases, so it cannot
428 // recover it. The cap is where the request comes back in.
429 //
430 // The cap cannot actually fire from here: the caller only reaches this
431 // branch when the request is already over budget, which is the same
432 // inequality. It is kept because that argument runs through
433 // `map_power_value`'s rounding, and a helper that clamps to its own
434 // argument is cheaper than depending on that.
435 const fl::u32 headroom_mW = max_power_mW - fixed_mW;
436 const fl::u8 target_scaled = map_power_value(target_brightness);
437 fl::u32 allowed_scaled = power_ratio_of_255(headroom_mW, controllable_mW);
438 if (allowed_scaled > target_scaled) {
439 allowed_scaled = target_scaled;
440 }
441 const fl::u32 recommended_scaled = static_cast<fl::u32>(allowed_scaled);
442 fl::u8 recommended = unmap_power_value(static_cast<fl::u8>(recommended_scaled));
443
444 // Then check the answer instead of trusting the division. Inverting the
445 // ratio in scaled space is off by the rounding of whichever `scale32by8`
446 // the platform compiled -- the FASTLED_SCALE8_FIXED form computes
447 // `i * (s + 1) >> 8`, so the closed form lands about `controllable/256`
448 // over the budget, which was 176 mW of a 5000 mW budget on the default
449 // model. Demand is monotone in brightness, so stepping down until it fits
450 // is exact whatever the rounding, and terminates: 0 always fits here,
451 // because the branch above already returned for a budget under baseline.
452 while (recommended > 0 &&
453 fixed_mW + scale_power_for_brightness(controllable_mW, recommended) >
454 max_power_mW) {
455 --recommended;
456 }
457 return recommended;
458}
fl::u32 scale_power_for_brightness(fl::u32 total_mW, fl::u8 brightness) FL_NO_EXCEPT
Applies the configured power-scaling response to a total power value.
fl::u32 power_ratio_of_255(fl::u32 num, fl::u32 den) FL_NO_EXCEPT
min(255, floor(255 * num / den)) for den > 0, computed in 32-bit arithmetic.
unsigned char u8
Definition stdint.h:131
static fl::u8 map_power_value(fl::u8 brightness) FL_NO_EXCEPT
static fl::u8 unmap_power_value(fl::u8 scaled_brightness) FL_NO_EXCEPT

References FL_NO_EXCEPT, map_power_value(), power_ratio_of_255(), scale_power_for_brightness(), and unmap_power_value().

Referenced by calculate_max_brightness_for_power_mW(), and calculate_max_brightness_for_power_mW().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: