diff options
author | Sergey Vlasov <vsu@altlinux.ru> | 2021-02-09 00:33:04 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-09 08:33:04 +1100 |
commit | 627ceebef3ed19eceba3642a830ffbf44f4a9e04 (patch) | |
tree | 261ce414affa8c15f4973036153ec770553138ef /drivers/avr/ws2812.c | |
parent | d2f204c1e3ef92d774feded0ba05a145c2d03cf7 (diff) | |
download | qmk_firmware-627ceebef3ed19eceba3642a830ffbf44f4a9e04.tar.gz qmk_firmware-627ceebef3ed19eceba3642a830ffbf44f4a9e04.zip |
ws2812: Fix number of nops for AVR at 8 MHz (#9559)
* ws2812: Fix number of nops for AVR at 8 MHz
When trying to calculate the number of nops for AVR running at 8 MHz,
the value of `w3` is expected to be negative; however, because `F_CPU`
is defined in tmk_core/avr.mk with the `UL` suffix, the preprocessor
performs its calculations using `unsigned long`, getting a very large
positive number instead of the expected negative number; this then
results in generating code with a huge number of nops. Fix the broken
calculations by performing a comparison before subtraction, so that the
unsigned number wraparound does not occur.
The keyboard which triggers the problem is `handwired/promethium`; the
buggy code silently compiles, but the resulting timings would be
completely wrong.
* ws2812: Clean up the code after the 8 MHz fix
Remove old code which was unsuccessfully trying to clamp negative w1, w2
and w3 values to 0, and set w1_nops, w2_nops and w3_nops directly.
Diffstat (limited to 'drivers/avr/ws2812.c')
-rw-r--r-- | drivers/avr/ws2812.c | 38 |
1 files changed, 17 insertions, 21 deletions
diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c index dd2ef8991..77c492cd4 100644 --- a/drivers/avr/ws2812.c +++ b/drivers/avr/ws2812.c | |||
@@ -67,19 +67,27 @@ void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { | |||
67 | #define w_onecycles (((F_CPU / 1000) * w_onepulse + 500000) / 1000000) | 67 | #define w_onecycles (((F_CPU / 1000) * w_onepulse + 500000) / 1000000) |
68 | #define w_totalcycles (((F_CPU / 1000) * w_totalperiod + 500000) / 1000000) | 68 | #define w_totalcycles (((F_CPU / 1000) * w_totalperiod + 500000) / 1000000) |
69 | 69 | ||
70 | // w1 - nops between rising edge and falling edge - low | 70 | // w1_nops - nops between rising edge and falling edge - low |
71 | #define w1 (w_zerocycles - w_fixedlow) | 71 | #if w_zerocycles >= w_fixedlow |
72 | // w2 nops between fe low and fe high | 72 | # define w1_nops (w_zerocycles - w_fixedlow) |
73 | #define w2 (w_onecycles - w_fixedhigh - w1) | ||
74 | // w3 nops to complete loop | ||
75 | #define w3 (w_totalcycles - w_fixedtotal - w1 - w2) | ||
76 | |||
77 | #if w1 > 0 | ||
78 | # define w1_nops w1 | ||
79 | #else | 73 | #else |
80 | # define w1_nops 0 | 74 | # define w1_nops 0 |
81 | #endif | 75 | #endif |
82 | 76 | ||
77 | // w2_nops - nops between fe low and fe high | ||
78 | #if w_onecycles >= (w_fixedhigh + w1_nops) | ||
79 | # define w2_nops (w_onecycles - w_fixedhigh - w1_nops) | ||
80 | #else | ||
81 | # define w2_nops 0 | ||
82 | #endif | ||
83 | |||
84 | // w3_nops - nops to complete loop | ||
85 | #if w_totalcycles >= (w_fixedtotal + w1_nops + w2_nops) | ||
86 | # define w3_nops (w_totalcycles - w_fixedtotal - w1_nops - w2_nops) | ||
87 | #else | ||
88 | # define w3_nops 0 | ||
89 | #endif | ||
90 | |||
83 | // The only critical timing parameter is the minimum pulse length of the "0" | 91 | // The only critical timing parameter is the minimum pulse length of the "0" |
84 | // Warn or throw error if this timing can not be met with current F_CPU settings. | 92 | // Warn or throw error if this timing can not be met with current F_CPU settings. |
85 | #define w_lowtime ((w1_nops + w_fixedlow) * 1000000) / (F_CPU / 1000) | 93 | #define w_lowtime ((w1_nops + w_fixedlow) * 1000000) / (F_CPU / 1000) |
@@ -90,18 +98,6 @@ void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { | |||
90 | # warning "Please consider a higher clockspeed, if possible" | 98 | # warning "Please consider a higher clockspeed, if possible" |
91 | #endif | 99 | #endif |
92 | 100 | ||
93 | #if w2 > 0 | ||
94 | # define w2_nops w2 | ||
95 | #else | ||
96 | # define w2_nops 0 | ||
97 | #endif | ||
98 | |||
99 | #if w3 > 0 | ||
100 | # define w3_nops w3 | ||
101 | #else | ||
102 | # define w3_nops 0 | ||
103 | #endif | ||
104 | |||
105 | #define w_nop1 "nop \n\t" | 101 | #define w_nop1 "nop \n\t" |
106 | #define w_nop2 "rjmp .+0 \n\t" | 102 | #define w_nop2 "rjmp .+0 \n\t" |
107 | #define w_nop4 w_nop2 w_nop2 | 103 | #define w_nop4 w_nop2 w_nop2 |