/* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /** library to drive a WS2812B LED chain (code) * @file led_ws2812b.c * @author King Kévin * @date 2016 * @note peripherals used: SPI @ref led_ws2812b_spi, timer @ref led_ws2812b_timer, DMA @ref led_ws2812b_dma */ /* standard libraries */ #include // standard integer types #include // general utilities /* STM32 (including CM3) libraries */ #include // real-time control clock library #include // general purpose input output library #include // SPI library #include // timer library #include // DMA library #include // interrupt handler #include // Cortex M3 utilities #include "led_ws2812b.h" // LED WS2812B library API #include "global.h" // common methods /** bit template to encode one byte to be shifted out by SPI to the WS2812B LEDs * @details For each WS2812B bit which needs to be transfered we require to transfer 3 SPI bits. * The first SPI bit is the high start of the WS2812B bit frame. * The second SPI bit determines if the WS2812B bit is a 0 or 1. * The third SPI bit is the last part of the WS2812B bit frame, which is always low. * The binary pattern is 0b100100100100100100100100 */ #define LED_WS2812B_SPI_TEMPLATE 0x924924 uint8_t led_ws2812b_data[LED_WS2812B_LEDS*3*3+40*3/8+1] = {0}; /**< data encoded to be shifted out by SPI for the WS2812B, plus the 50us reset (~40 data bits) */ static volatile bool transmit_flag = false; /**< flag set in software when transmission started, clear by interrupt when transmission completed */ void led_ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue) { // verify the led exists if (led>=LED_WS2812B_LEDS) { return; } // wait for transmission to complete before changing the color while (transmit_flag) { __WFI(); } 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>16); led_ws2812b_data[i*3+1] = (uint8_t)(LED_WS2812B_SPI_TEMPLATE>>8); led_ws2812b_data[i*3+2] = (uint8_t)(LED_WS2812B_SPI_TEMPLATE>>0); } // fill remaining with with 0 to encode the reset code for (uint16_t i=LED_WS2812B_LEDS*3*3; i