Skip to content

Commit 580011d

Browse files
zvecrthorstenweber83
authored andcommitted
Fix AVR ws2812 when ADDRESS_BASE is non zero (qmk#8646)
* Fix AVR ws2812 when ADDRESS_BASE is non zero * fix port * remove unused function defs
1 parent e2048ec commit 580011d

File tree

3 files changed

+17
-35
lines changed

3 files changed

+17
-35
lines changed

drivers/avr/ws2812.c

+15-20
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,35 @@
2020
* You should have received a copy of the GNU General Public License
2121
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2222
*/
23-
2423
#include "ws2812.h"
2524
#include <avr/interrupt.h>
2625
#include <avr/io.h>
2726
#include <util/delay.h>
2827

28+
#define pinmask(pin) (_BV((pin)&0xF))
29+
2930
/*
3031
* Forward declare internal functions
3132
*
3233
* The functions take a byte-array and send to the data output as WS2812 bitstream.
3334
* The length is the number of bytes to send - three per LED.
3435
*/
3536

36-
void ws2812_sendarray(uint8_t *array, uint16_t length);
37-
void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask);
37+
static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi);
3838

3939
// Setleds for standard RGB
40-
void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
41-
// ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
42-
ws2812_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF));
40+
void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) {
41+
// wrap up usage of RGB_DI_PIN
42+
ws2812_setleds_pin(ledarray, number_of_leds, RGB_DI_PIN);
4343
}
4444

45-
void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) {
46-
// new universal format (DDR)
47-
_SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask;
45+
void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pin) {
46+
DDRx_ADDRESS(RGB_DI_PIN) |= pinmask(pin);
4847

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);
5052

5153
#ifdef RGBW
5254
_delay_us(80);
@@ -55,8 +57,6 @@ void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmas
5557
#endif
5658
}
5759

58-
void ws2812_sendarray(uint8_t *data, uint16_t datlen) { ws2812_sendarray_mask(data, datlen, _BV(RGB_DI_PIN & 0xF)); }
59-
6060
/*
6161
This routine writes an array of bytes with RGB values to the Dataout pin
6262
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
118118
#define w_nop8 w_nop4 w_nop4
119119
#define w_nop16 w_nop8 w_nop8
120120

121-
void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi) {
122-
uint8_t curbyte, ctr, masklo;
123-
uint8_t sreg_prev;
121+
static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi) {
122+
uint8_t curbyte, ctr, sreg_prev;
124123

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);
129124
sreg_prev = SREG;
130125
cli();
131126

@@ -188,7 +183,7 @@ void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi
188183
" dec %0 \n\t" // '1' [+2] '0' [+2]
189184
" brne loop%=\n\t" // '1' [+3] '0' [+4]
190185
: "=&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));
192187
}
193188

194189
SREG = sreg_prev;

drivers/avr/ws2812.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929
* Input:
3030
* ledarray: An array of GRB data describing the LED colors
3131
* number_of_leds: The number of LEDs to write
32-
* pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0)
32+
* pin (optional): A pin_t definition for the line to drive
3333
*
3434
* The functions will perform the following actions:
3535
* - Set the data-out pin as output
3636
* - Send out the LED data
3737
* - Wait 50us to reset the LEDs
3838
*/
3939
void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds);
40-
void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask);
40+
void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pin);

keyboards/ergodox_ez/led_i2c.c

-13
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,6 @@
2727

2828
extern rgblight_config_t rgblight_config;
2929

30-
/*
31-
* Forward declare internal functions
32-
*
33-
* The functions take a byte-array and send to the data output as WS2812 bitstream.
34-
* The length is the number of bytes to send - three per LED.
35-
*/
36-
37-
void ws2812_sendarray(uint8_t *array, uint16_t length);
38-
void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask);
39-
40-
41-
42-
4330
void rgblight_set(void) {
4431
if (!rgblight_config.enable) {
4532
for (uint8_t i = 0; i < RGBLED_NUM; i++) {

0 commit comments

Comments
 (0)