aboutsummaryrefslogtreecommitdiff
path: root/drivers/avr/ws2812.c
diff options
context:
space:
mode:
authorJoel Challis <git@zvecr.com>2020-04-02 20:46:38 +0100
committerGitHub <noreply@github.com>2020-04-02 20:46:38 +0100
commit31fd0cbc1ca35ce023fbbc3553a04aa480dc2187 (patch)
treeb561d6508598fe03073f85adb395d0a2498b5901 /drivers/avr/ws2812.c
parent2b427f774a6665819306cf716d79355db3f7d169 (diff)
downloadqmk_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.c35
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
36void ws2812_sendarray(uint8_t *array, uint16_t length); 37static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi);
37void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask);
38 38
39// Setleds for standard RGB 39// Setleds for standard RGB
40void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { 40void 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
45void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) { 45void 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
58void 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
121void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi) { 121static 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;