diff --git a/lib/led_ws2812b.c b/lib/led_ws2812b.c index 8bcd658..25bf2ac 100644 --- a/lib/led_ws2812b.c +++ b/lib/led_ws2812b.c @@ -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)