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:
		
							parent
							
								
									f2715a0593
								
							
						
					
					
						commit
						6f7466b6dd
					
				
					 2 changed files with 59 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -77,6 +77,25 @@ Configure the hardware via your config.h:
 | 
			
		|||
 | 
			
		||||
You must also turn on the SPI feature in your halconf.h and mcuconf.h
 | 
			
		||||
 | 
			
		||||
#### Circular Buffer Mode
 | 
			
		||||
Some boards may flicker while in the normal buffer mode. To fix this issue, circular buffer mode may be used to rectify the issue. 
 | 
			
		||||
 | 
			
		||||
By default, the circular buffer mode is disabled.
 | 
			
		||||
 | 
			
		||||
To enable this alternative buffer mode, place this into your `config.h` file:
 | 
			
		||||
```c
 | 
			
		||||
#define WS2812_SPI_USE_CIRCULAR_BUFFER
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Setting baudrate with divisor
 | 
			
		||||
To adjust the baudrate at which the SPI peripheral is configured, users will need to derive the target baudrate from the clock tree provided by STM32CubeMX.
 | 
			
		||||
 | 
			
		||||
Only divisors of 2, 4, 8, 16, 32, 64, 128 and 256 are supported by hardware.
 | 
			
		||||
 | 
			
		||||
|Define              |Default|Description                          |
 | 
			
		||||
|--------------------|-------|-------------------------------------|
 | 
			
		||||
|`WS2812_SPI_DIVISOR`|`16`   |SPI source clock peripheral divisor  |
 | 
			
		||||
 | 
			
		||||
#### Testing Notes
 | 
			
		||||
 | 
			
		||||
While not an exhaustive list, the following table provides the scenarios that have been partially validated:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue