Skip to content

Give the gamma correction 0 for 0, a test and its source - #81

Merged
AndreasBur merged 1 commit into
masterfrom
gamma-correction-dark-at-zero
Oct 27, 2026
Merged

AndreasBur merged 1 commit into
masterfrom
gamma-correction-dark-at-zero

Conversation

@theAndreas

Copy link
Copy Markdown
Collaborator

The gamma correction is the exponential curve from the "Sparsamere Implementierung" section of Diskussion:LED-Fading. It stores 16 values for the top doubling and gets every lower doubling by shifting. The background is the article itself, LED-Fading.

What changed

  • 0 maps to 0. The source's author points out that the exponential never reaches zero and recommends answering a setting of 0 with 0. That recommendation did not come over with the code, so 0 became 1. It is now answered as a separate case rather than by subtracting 1 from every result, because subtracting would also turn 255 into 254.
  • Documentation. The header now explains what the curve is and links to both pages. It explains why 128 steps = 16 values × 8 bits, which a static_assert now enforces; before, numberOfBits() happened to return 8. It also notes what to know before changing the curve:
    • the coarse bottom end is a limit of 8-bit output, not of the code;
    • the dark middle (half the setting gives about 6 %) comes from the base of 256 that the shift trick fixes, while the article suggests a base of 10 to 100.
  • Clean-up. Variable names now say what the values are (the old exponent holds the mantissa), and the empty sections are gone. memcpy_P stays, because that is how the firmware core reads flash everywhere.

What does not change

What reaches the strip stays the same today. DisplayColor::dimmColor deliberately keeps every channel at 1 or above, and a test enforces that, with or without the correction. A setting of 0 therefore still gives the faintest light. After this change, the correction passes on the same 0 that an uncorrected setting does, and the stage after it decides what that means.

Measured

  • testGammaCorrectionCurve() checks both ends, that the curve never falls, and one value from each end of the shift range. Made to fail on purpose: against the old header, exactly the 0 check fails and every other check passes. The curve itself is unchanged.
  • AVR flash: 48 116 → 48 140 bytes (+24), for the 0 check at its two call sites.
  • Built: simulator with ctest, AVR, ESP32, RP2350, and both host-test suites. tools/documented-sizes.py passes for all three firmwares, and clang-tidy is clean on all four builds.

Whether the middle of the range should be brighter (a flatter base) can only be judged on the real strip, so this PR leaves it alone.

The curve is the one from the "Sparsamere Implementierung" section of
https://www.mikrocontroller.net/articles/Diskussion:LED-Fading - 16
stored values for the top doubling, every lower one a shift. Its author
notes that the exponential never reaches zero and recommends answering
a setting of 0 with 0; that part did not come over, so a setting of 0
became 1. It is answered apart now rather than by subtracting 1 from
every result, which would have taken 255 down to 254 as well.

What reaches the strip does not change today: DisplayColor keeps every
channel at 1 at the bottom on purpose, with and without the correction.
The correction now hands on the same 0 an uncorrected setting does and
leaves that decision to the stage that makes it.

The header now says what the curve is and where it comes from, with
both links; why 128 steps, 16 values and 8 bits have to agree, which a
static_assert holds instead of a numberOfBits() that only happened to
be 8; and what to know before changing it - the coarse bottom, which is
8 bits and not the code, and the dark middle, which is the base of 256
the shift trick fixes.

testGammaCorrectionCurve() checks both ends, that the curve never
falls, and a value from each end of the shift range. Run against the
old header, exactly the 0 check fails and the rest pass - the curve
itself is unchanged.

AVR flash 48116 -> 48140 bytes for the check at its two call sites.
Built: simulator with ctest, AVR, ESP32, RP2350, both host suites;
clang-tidy clean on all four builds.
@AndreasBur
AndreasBur merged commit 8f1dacd into master Oct 27, 2026
10 of 11 checks passed
@theAndreas
theAndreas deleted the gamma-correction-dark-at-zero branch October 27, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants