diff options
author | Joel Challis <git@zvecr.com> | 2020-04-02 20:46:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-02 20:46:38 +0100 |
commit | 31fd0cbc1ca35ce023fbbc3553a04aa480dc2187 (patch) | |
tree | b561d6508598fe03073f85adb395d0a2498b5901 /drivers/avr/ws2812.c | |
parent | 2b427f774a6665819306cf716d79355db3f7d169 (diff) | |
download | qmk_firmware-31fd0cbc1ca35ce023fbbc3553a04aa480dc2187.tar.gz qmk_firmware-31fd0cbc1ca35ce023fbbc3553a04aa480dc2187.zip |
Fix AVR ws2812 when ADDRESS_BASE is non zero (#8646)
* Fix AVR ws2812 when ADDRESS_BASE is non zero
* fix port
* remove unused function defs
Diffstat (limited to 'drivers/avr/ws2812.c')
-rw-r--r-- | drivers/avr/ws2812.c | 35 |
1 files changed, 15 insertions, 20 deletions
diff --git a/drivers/avr/ws2812.c b/drivers/avr/ws2812.c index 82d985c20..5c3d72dcb 100644 --- a/drivers/avr/ws2812.c +++ b/drivers/avr/ws2812.c | |||
@@ -20,12 +20,13 @@ | |||
20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | */ | 22 | */ |
23 | |||
24 | #include "ws2812.h" | 23 | #include "ws2812.h" |
25 | #include <avr/interrupt.h> | 24 | #include <avr/interrupt.h> |
26 | #include <avr/io.h> | 25 | #include <avr/io.h> |
27 | #include <util/delay.h> | 26 | #include <util/delay.h> |
28 | 27 | ||
28 | #define pinmask(pin) (_BV((pin)&0xF)) | ||
29 | |||
29 | /* | 30 | /* |
30 | * Forward declare internal functions | 31 | * Forward declare internal functions |
31 | * | 32 | * |
@@ -33,20 +34,21 @@ | |||
33 | * The length is the number of bytes to send - three per LED. | 34 | * The length is the number of bytes to send - three per LED. |
34 | */ | 35 | */ |
35 | 36 | ||
36 | void ws2812_sendarray(uint8_t *array, uint16_t length); | 37 | static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi); |
37 | void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask); | ||
38 | 38 | ||
39 | // Setleds for standard RGB | 39 | // Setleds for standard RGB |
40 | void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { | 40 | void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { |
41 | // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); | 41 | // wrap up usage of RGB_DI_PIN |
42 | ws2812_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF)); | 42 | ws2812_setleds_pin(ledarray, number_of_leds, RGB_DI_PIN); |
43 | } | 43 | } |
44 | 44 | ||
45 | void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) { | 45 | void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pin) { |
46 | // new universal format (DDR) | 46 | DDRx_ADDRESS(RGB_DI_PIN) |= pinmask(pin); |
47 | _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask; | ||
48 | 47 | ||
49 | ws2812_sendarray_mask((uint8_t *)ledarray, leds * sizeof(LED_TYPE), pinmask); | 48 | uint8_t masklo = ~(pinmask(pin)) & PORTx_ADDRESS(pin); |
49 | uint8_t maskhi = pinmask(pin) | PORTx_ADDRESS(pin); | ||
50 | |||
51 | ws2812_sendarray_mask((uint8_t *)ledarray, number_of_leds * sizeof(LED_TYPE), masklo, maskhi); | ||
50 | 52 | ||
51 | #ifdef RGBW | 53 | #ifdef RGBW |
52 | _delay_us(80); | 54 | _delay_us(80); |
@@ -55,8 +57,6 @@ void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmas | |||
55 | #endif | 57 | #endif |
56 | } | 58 | } |
57 | 59 | ||
58 | void ws2812_sendarray(uint8_t *data, uint16_t datlen) { ws2812_sendarray_mask(data, datlen, _BV(RGB_DI_PIN & 0xF)); } | ||
59 | |||
60 | /* | 60 | /* |
61 | This routine writes an array of bytes with RGB values to the Dataout pin | 61 | This routine writes an array of bytes with RGB values to the Dataout pin |
62 | using the fast 800kHz clockless WS2811/2812 protocol. | 62 | using the fast 800kHz clockless WS2811/2812 protocol. |
@@ -118,14 +118,9 @@ void ws2812_sendarray(uint8_t *data, uint16_t datlen) { ws2812_sendarray_mask(da | |||
118 | #define w_nop8 w_nop4 w_nop4 | 118 | #define w_nop8 w_nop4 w_nop4 |
119 | #define w_nop16 w_nop8 w_nop8 | 119 | #define w_nop16 w_nop8 w_nop8 |
120 | 120 | ||
121 | void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi) { | 121 | static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi) { |
122 | uint8_t curbyte, ctr, masklo; | 122 | uint8_t curbyte, ctr, sreg_prev; |
123 | uint8_t sreg_prev; | ||
124 | 123 | ||
125 | // masklo =~maskhi&ws2812_PORTREG; | ||
126 | // maskhi |= ws2812_PORTREG; | ||
127 | masklo = ~maskhi & _SFR_IO8((RGB_DI_PIN >> 4) + 2); | ||
128 | maskhi |= _SFR_IO8((RGB_DI_PIN >> 4) + 2); | ||
129 | sreg_prev = SREG; | 124 | sreg_prev = SREG; |
130 | cli(); | 125 | cli(); |
131 | 126 | ||
@@ -188,7 +183,7 @@ void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi | |||
188 | " dec %0 \n\t" // '1' [+2] '0' [+2] | 183 | " dec %0 \n\t" // '1' [+2] '0' [+2] |
189 | " brne loop%=\n\t" // '1' [+3] '0' [+4] | 184 | " brne loop%=\n\t" // '1' [+3] '0' [+4] |
190 | : "=&d"(ctr) | 185 | : "=&d"(ctr) |
191 | : "r"(curbyte), "I"(_SFR_IO_ADDR(_SFR_IO8((RGB_DI_PIN >> 4) + 2))), "r"(maskhi), "r"(masklo)); | 186 | : "r"(curbyte), "I"(_SFR_IO_ADDR(PORTx_ADDRESS(RGB_DI_PIN))), "r"(maskhi), "r"(masklo)); |
192 | } | 187 | } |
193 | 188 | ||
194 | SREG = sreg_prev; | 189 | SREG = sreg_prev; |