led_ws2812b: improve set LED speed

This commit is contained in:
King Kévin 2020-03-09 09:43:39 +01:00
parent cfbe9234b1
commit 9b9751e79d
1 changed files with 25 additions and 11 deletions

View File

@ -60,20 +60,34 @@ void led_ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue)
return;
}
const uint8_t colors[] = {green, red, blue}; // color order for the WS2812B
const uint8_t pattern_bit[] = {0x02, 0x10, 0x80, 0x04, 0x20, 0x01, 0x08, 0x40}; // which bit to change in the pattern
const uint8_t pattern_byte[] = {2, 2, 2, 1, 1, 0, 0, 0}; // in which byte in the pattern to write the pattern bit
for (uint8_t color = 0; color < LENGTH(colors); color++) { // colors are encoded similarly
// fill the middle bit (fixed is faster than calculating it)
for (uint8_t bit = 0; bit < 8; bit++) { // bit from the color to set/clear
if (colors[color] & (1 << bit)) { // setting bit
led_ws2812b_data[led * 3 * 3 + color * 3 + pattern_byte[bit]] |= pattern_bit[bit]; // setting bit is pattern
} else { // clear bit
led_ws2812b_data[led * 3 * 3 + color * 3 + pattern_byte[bit]] &= ~pattern_bit[bit]; // clearing bit is pattern
}
// convert RGB bit to SPI bit (each bit is encoded in 3 bits)
uint32_t red_spi = LED_WS2812B_SPI_TEMPLATE, green_spi = LED_WS2812B_SPI_TEMPLATE, blue_spi = LED_WS2812B_SPI_TEMPLATE;
uint32_t bit_spi = 0x2; // the bit to set in the SPI stream
for (uint8_t bit = 0; bit < 8; bit++) { // bit from the color to set/clear
const uint8_t byte_bit = (1 << bit); // which bit to check
if (red & byte_bit) {
red_spi |= bit_spi;
}
if (green & byte_bit) {
green_spi |= bit_spi;
}
if (blue & byte_bit) {
blue_spi |= bit_spi;
}
bit_spi <<= 3; // go to next SPI bit
}
// set calculated pattern in stream (GRB)
// we don't stop the DMA, instead we set LSB to MSB for gradient transition
led_ws2812b_data[led * 3 * 3 + 0 + 2] = (green_spi >> 0);
led_ws2812b_data[led * 3 * 3 + 3 + 2] = (red_spi >> 0);
led_ws2812b_data[led * 3 * 3 + 6 + 2] = (blue_spi >> 0);
led_ws2812b_data[led * 3 * 3 + 0 + 1] = (green_spi >> 8);
led_ws2812b_data[led * 3 * 3 + 3 + 1] = (red_spi >> 8);
led_ws2812b_data[led * 3 * 3 + 6 + 1] = (blue_spi >> 8);
led_ws2812b_data[led * 3 * 3 + 0 + 0] = (green_spi >> 16);
led_ws2812b_data[led * 3 * 3 + 3 + 0] = (red_spi >> 16);
led_ws2812b_data[led * 3 * 3 + 6 + 0] = (blue_spi >> 16);
}
void led_ws2812b_setup(void)