ARM WS2812 SPI config (baudrate and circular buffer) (#12216)

* initial commit

* include circular buffer command

* add endif

* circular buffer mode

* remove untrue comment

* revamp and add documentation

* do not allow WS2812_SPI_SYNC & CIRCULAR_BUFFER
This commit is contained in:
Xelus22 2021-03-19 08:29:18 +00:00 committed by GitHub
parent f2715a0593
commit 6f7466b6dd
Failed to generate hash of commit
2 changed files with 59 additions and 4 deletions

View file

@ -32,6 +32,37 @@
# endif
#endif
// Define SPI config speed
// baudrate should target 3.2MHz
// F072 fpclk = 48MHz
// 48/16 = 3Mhz
#if WS2812_SPI_DIVISOR == 2
# define WS2812_SPI_DIVISOR (0)
#elif WS2812_SPI_DIVISOR == 4
# define WS2812_SPI_DIVISOR (SPI_CR1_BR_0)
#elif WS2812_SPI_DIVISOR == 8
# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1)
#elif WS2812_SPI_DIVISOR == 16 //same as default
# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0)
#elif WS2812_SPI_DIVISOR == 32
# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2)
#elif WS2812_SPI_DIVISOR == 64
# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_0)
#elif WS2812_SPI_DIVISOR == 128
# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1)
#elif WS2812_SPI_DIVISOR == 256
# define WS2812_SPI_DIVISOR (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0)
#else
# define WS2812_SPI_DIVISOR (SPI_CR1_BR_1 | SPI_CR1_BR_0) //default
#endif
// Use SPI circular buffer
#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER
# define WS2812_SPI_BUFFER_MODE 1 //circular buffer
#else
# define WS2812_SPI_BUFFER_MODE 0 //normal buffer
#endif
#define BYTES_FOR_LED_BYTE 4
#define NB_COLORS 3
#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS)
@ -82,13 +113,16 @@ void ws2812_init(void) {
// TODO: more dynamic baudrate
static const SPIConfig spicfg = {
0, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN),
SPI_CR1_BR_1 | SPI_CR1_BR_0 // baudrate : fpclk / 8 => 1tick is 0.32us (2.25 MHz)
WS2812_SPI_BUFFER_MODE, NULL, PAL_PORT(RGB_DI_PIN), PAL_PAD(RGB_DI_PIN),
WS2812_SPI_DIVISOR
};
spiAcquireBus(&WS2812_SPI); /* Acquire ownership of the bus. */
spiStart(&WS2812_SPI, &spicfg); /* Setup transfer parameters. */
spiSelect(&WS2812_SPI); /* Slave Select assertion. */
#ifdef WS2812_SPI_USE_CIRCULAR_BUFFER
spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf);
#endif
}
void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
@ -104,9 +138,11 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
// Send async - each led takes ~0.03ms, 50 leds ~1.5ms, animations flushing faster than send will cause issues.
// Instead spiSend can be used to send synchronously (or the thread logic can be added back).
#ifdef WS2812_SPI_SYNC
#ifndef WS2812_SPI_USE_CIRCULAR_BUFFER
# ifdef WS2812_SPI_SYNC
spiSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf);
#else
# else
spiStartSend(&WS2812_SPI, sizeof(txbuf) / sizeof(txbuf[0]), txbuf);
# endif
#endif
}