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
This commit is contained in:
Joel Challis 2020-04-02 20:46:38 +01:00 committed by GitHub
parent 2b427f774a
commit 31fd0cbc1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 17 additions and 35 deletions

View File

@ -20,12 +20,13 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "ws2812.h" #include "ws2812.h"
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> #include <util/delay.h>
#define pinmask(pin) (_BV((pin)&0xF))
/* /*
* Forward declare internal functions * Forward declare internal functions
* *
@ -33,20 +34,21 @@
* The length is the number of bytes to send - three per LED. * The length is the number of bytes to send - three per LED.
*/ */
void ws2812_sendarray(uint8_t *array, uint16_t length); static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi);
void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask);
// Setleds for standard RGB // Setleds for standard RGB
void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) { void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) {
// ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); // wrap up usage of RGB_DI_PIN
ws2812_setleds_pin(ledarray, leds, _BV(RGB_DI_PIN & 0xF)); ws2812_setleds_pin(ledarray, number_of_leds, RGB_DI_PIN);
} }
void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) { void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pin) {
// new universal format (DDR) DDRx_ADDRESS(RGB_DI_PIN) |= pinmask(pin);
_SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask;
ws2812_sendarray_mask((uint8_t *)ledarray, leds * sizeof(LED_TYPE), pinmask); uint8_t masklo = ~(pinmask(pin)) & PORTx_ADDRESS(pin);
uint8_t maskhi = pinmask(pin) | PORTx_ADDRESS(pin);
ws2812_sendarray_mask((uint8_t *)ledarray, number_of_leds * sizeof(LED_TYPE), masklo, maskhi);
#ifdef RGBW #ifdef RGBW
_delay_us(80); _delay_us(80);
@ -55,8 +57,6 @@ void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmas
#endif #endif
} }
void ws2812_sendarray(uint8_t *data, uint16_t datlen) { ws2812_sendarray_mask(data, datlen, _BV(RGB_DI_PIN & 0xF)); }
/* /*
This routine writes an array of bytes with RGB values to the Dataout pin This routine writes an array of bytes with RGB values to the Dataout pin
using the fast 800kHz clockless WS2811/2812 protocol. 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
#define w_nop8 w_nop4 w_nop4 #define w_nop8 w_nop4 w_nop4
#define w_nop16 w_nop8 w_nop8 #define w_nop16 w_nop8 w_nop8
void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi) { static inline void ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t masklo, uint8_t maskhi) {
uint8_t curbyte, ctr, masklo; uint8_t curbyte, ctr, sreg_prev;
uint8_t sreg_prev;
// masklo =~maskhi&ws2812_PORTREG;
// maskhi |= ws2812_PORTREG;
masklo = ~maskhi & _SFR_IO8((RGB_DI_PIN >> 4) + 2);
maskhi |= _SFR_IO8((RGB_DI_PIN >> 4) + 2);
sreg_prev = SREG; sreg_prev = SREG;
cli(); cli();
@ -188,7 +183,7 @@ void inline ws2812_sendarray_mask(uint8_t *data, uint16_t datlen, uint8_t maskhi
" dec %0 \n\t" // '1' [+2] '0' [+2] " dec %0 \n\t" // '1' [+2] '0' [+2]
" brne loop%=\n\t" // '1' [+3] '0' [+4] " brne loop%=\n\t" // '1' [+3] '0' [+4]
: "=&d"(ctr) : "=&d"(ctr)
: "r"(curbyte), "I"(_SFR_IO_ADDR(_SFR_IO8((RGB_DI_PIN >> 4) + 2))), "r"(maskhi), "r"(masklo)); : "r"(curbyte), "I"(_SFR_IO_ADDR(PORTx_ADDRESS(RGB_DI_PIN))), "r"(maskhi), "r"(masklo));
} }
SREG = sreg_prev; SREG = sreg_prev;

View File

@ -29,7 +29,7 @@
* Input: * Input:
* ledarray: An array of GRB data describing the LED colors * ledarray: An array of GRB data describing the LED colors
* number_of_leds: The number of LEDs to write * number_of_leds: The number of LEDs to write
* pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0) * pin (optional): A pin_t definition for the line to drive
* *
* The functions will perform the following actions: * The functions will perform the following actions:
* - Set the data-out pin as output * - Set the data-out pin as output
@ -37,4 +37,4 @@
* - Wait 50us to reset the LEDs * - Wait 50us to reset the LEDs
*/ */
void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds);
void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pinmask); void ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t number_of_leds, uint8_t pin);

View File

@ -27,19 +27,6 @@
extern rgblight_config_t rgblight_config; extern rgblight_config_t rgblight_config;
/*
* Forward declare internal functions
*
* The functions take a byte-array and send to the data output as WS2812 bitstream.
* The length is the number of bytes to send - three per LED.
*/
void ws2812_sendarray(uint8_t *array, uint16_t length);
void ws2812_sendarray_mask(uint8_t *array, uint16_t length, uint8_t pinmask);
void rgblight_set(void) { void rgblight_set(void) {
if (!rgblight_config.enable) { if (!rgblight_config.enable) {
for (uint8_t i = 0; i < RGBLED_NUM; i++) { for (uint8_t i = 0; i < RGBLED_NUM; i++) {