-
-
Notifications
You must be signed in to change notification settings - Fork 39.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Core] PWM Backlight for RP2040 #17706
Conversation
c38247f
to
cd4baea
Compare
|
||
/* PWM Low Level driver specific fields */ | ||
#ifndef pwm_lld_driver_fields | ||
# define pwm_lld_driver_fields , 0, 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can decide to rely on the default zero initialization for static structs and just drop this platform-dependent part?
The current initializer does not match the STM32 version of PWMConfig
anyway (there are 3 extra fields there now — cr2
, bdtr
, dier
), so we already rely on dier
being implicitly initialized to 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is the best option in this case I guess. Done that.
@@ -100,7 +109,7 @@ void backlight_set(uint8_t level) { | |||
} else { | |||
// Turn backlight on | |||
uint32_t duty = (uint32_t)(cie_lightness(rescale_limit_val(0xFFFF * (uint32_t)level / BACKLIGHT_LEVELS))); | |||
pwmEnableChannel(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, duty)); | |||
pwmEnableChannel(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_COUNTER_FREQUENCY, duty)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 0xFFFF
should not be changed — it is actually the maximum possible value of duty
, which does not depend on the underlying PWM timer frequency.
PWM_FRACTION_TO_WIDTH(pwmp, denominator, numerator)
actually calculates pwmp->period * numerator / denominator
, which is the pulse width that would give the numerator/denominator
duty fraction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, I didn't fully understand the code here.
@@ -150,7 +159,7 @@ void breathing_callback(PWMDriver *pwmp) { | |||
uint32_t duty = cie_lightness(rescale_limit_val(scale_backlight(breathing_table[index] * 256))); | |||
|
|||
chSysLockFromISR(); | |||
pwmEnableChannelI(pwmp, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, duty)); | |||
pwmEnableChannelI(pwmp, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_COUNTER_FREQUENCY, duty)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 0xFFFF
should also remain as it is for the same reason as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
#ifndef BACKLIGHT_PWM_COUNTER_FREQUENCY | ||
# define BACKLIGHT_PWM_COUNTER_FREQUENCY 0xFFFF | ||
#endif | ||
|
||
#ifndef BACKLIGHT_PWM_PERIOD | ||
# define BACKLIGHT_PWM_PERIOD 256 | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making this tunable is a great feature by itself (256 Hz PWM lighting looks like crap, even the shittiest old WS2812B use ≈400 Hz, and that looks bad too). The only concern is that exposing the tunable parameters this way may not be the most understandable one, but restrictions of the actual hardware are mostly on these values, so maybe such tunables would be acceptable. (The AVR driver currently has only the BACKLIGHT_CUSTOM_RESOLUTION
tunable that controls the PWM output frequency indirectly.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Previously the advance of backlight steps was done in the PWM channel wrap callback, which of course would either slow down or speed up depending on the chosen PWM period. This is now done using a virtual timer which runs at ~256Hz so in line with the old cone and decouples the advance from the PWM settings.
platforms/chibios/chibios_config.h
Outdated
@@ -28,6 +28,11 @@ | |||
# define USE_GPIOV1 | |||
# define PAL_OUTPUT_TYPE_OPENDRAIN _Static_assert(0, "RP2040 has no Open Drain GPIO configuration, setting this is not possible"); | |||
|
|||
# define BACKLIGHT_PAL_MODE (PAL_MODE_ALTERNATE_PWM | PAL_RP_PAD_DRIVE12 | PAL_RP_GPIO_OE) | |||
# define BACKLIGHT_PWM_COUNTER_FREQUENCY 490196 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe write this as 125000000/255
instead of using a strange number of unknown origin?
Although the datasheet says that dividing by 256 should be supported too, so this might be 125000000/256
= 488281
(with the 0.25
remainder truncated). Or maybe just use 1000000
, which should be obtainable precisely even if someone decides to run the chip on another frequency than the maximum 125 MHz, and would give a slightly better brightness resolution (3906 steps at 256 Hz output frequency instead of 1914).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I changed it to use the suggested 1000000
value.
77bf97f
to
3f13520
Compare
@sigprof That is some great feedback, I have incorporated your suggestions and will answer tomorrow in greater detail. |
4ffd3b9
to
5355630
Compare
05234bd
to
b43f0f3
Compare
ee15630
to
2723475
Compare
chSysUnlockFromISR(); | ||
} | ||
|
||
// TODO: integrate generic pulse solution | ||
void breathing_pulse(void) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code that was here was here was mostly intentional, avoiding previous race conditions. This was mostly on the list of things to remove so im not keen on its reintroduction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean removing the backlight pulse feature as is? I can revert it if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reverted this to the blocking wait.
|
||
#define RP2040_PWM_CHANNEL_A 1 | ||
#define RP2040_PWM_CHANNEL_B 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably shouldnt exist in pin defs, as its not coupled to GPIO
#define RP2040_PWM_CHANNEL_A 1 | |
#define RP2040_PWM_CHANNEL_B 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The channels are coupled to the GPIOs every pin can only be one at a time, but yes it could probably live in chibios_config.h
for the time being?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After revisiting this I still think that _pin_defs.h
while not optimal is the better option over e.g. chibios_config.h
2723475
to
5fb5d63
Compare
5fb5d63
to
9d5fb48
Compare
* Decouple PWM frequency from breathing mechanism by using a virtual timer with 256Hz interrupt frequency * Make PWM frequency configurable * Drive by correct PAL mode for STM32F4xx onekeys
9d5fb48
to
20ca1e0
Compare
Tested this on RP2040 and STM32F401 Blackpill - also applied a fix to use the correct alternate function. Therefore I'm merging. |
Description
256Hz interrupt frequency
Implement non-blocking backlight pulserevertedTypes of Changes
Issues Fixed or Closed by This PR
Checklist