Fix AVR backlight breathing: low brightness limit & exceeding breathing table max index #16770
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In attempting to do simple backlight breathing on Atmega32U4, I ran into two problems:
Description
Investigating the first problem of low backlight limit, it appears that the data pulled from the breathing table was cast to
uint16_t
before being multiplied toICRx
(line 415 of backlight_avr.c). This limits the multiplication result to auint16_t
value, which is then divided by 255. This limits the overall result of the calculation to 257, which is artificially low (sincescale_backlight()
acceptsuint16_t
as input) . In other places like line 289 of backlight_avr.c where a similar calculation is performed, the multiplicand forICRx
is cast to auint32_t
.Casting to
uint32_t
in line 415 (now line 419) has been tested and performs backlight breathing correctly, going all the way up to the assigned brightness level.I notice similar multiplication operations being performed in backlight_chibios.c, line 150, but I have not tested on ARM yet to determine if it is a problem or not. I am not sure, perhaps it is compiler-dependent.
Regarding the problem of backlight briefly turning on between breathing cycles, it appears that the modulo operation performed on line 408 in backlight_avr.c is not ideal because of truncation on the
interval
variable. For example:6 * 120 / 128 = 5.625
, which is then truncated tointerval = 5
.breathing_counter
on line 407 is then limited to6 * 120 = 720
.breathing_counter / interval
can give results as high as720 / 5 = 144
. Then doing a modulo operation onBREATHING_STEPS
of 128 results in progressing 1/8th of the way through a breathing cycle again.It seems much cleaner to skip the modulo operation, and instead just limit index to the maximum valid value for index which is
BREATHING_STEPS - 1
.I checked backlight_chibios.c for the same issue and the problem does not exist there, because a breathing_ISR_frequency of 256 Hz is used instead of 120 Hz. Thus, for 128 steps in the breathing table, the math
period * 256 / 128
will always result in an exact interval. So technically, the% BREATHING_STEPS
modulo operation on line 149 of backlight_chibios.c can be removed, as long as BREATHING_STEPS = 128 (but unlike the changes in this pull request, I haven't tested removal of the chibios modulo on actual hardware)It should be noted that another possible solution for the AVR code might be also adopt a 128 or 256 Hz breathing ISR frequency, but I've not tested that approach given the ominous comment
Only run this ISR at ~120 Hz
on line 399.Types of Changes
Issues Fixed or Closed by This PR
Checklist