rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
WS2812.cpp
Go to the documentation of this file.
1/**
2 * @file WS2812.cpp
3 * @brief WS2812 RGB LED driver
4 *
5 * @date 25.03.2023
6 * @author Benas Brazdziunas
7 */
8
9#include "pch.h"
10
11#if EFI_WS2812
12
13#include "WS2812.h"
14#include "ws2812_conf.h"
15
16
17static WS2812_RGB_t WS2812_LED_BUF[WS2812_LED_N];
18static uint32_t WS2812_TIM_BUF[WS2812_BUFLEN];
19static uint8_t WS2812_BRIGHTNESS = 20;
20
22{
23 palSetPadMode(WS2812_PORT, WS2812_PIN, PAL_MODE_ALTERNATE(1));
24
25 static const PWMConfig ws2812_pwm_config = {
26 .frequency = WS2812_PWM_FREQUENCY,
27 .period = WS2812_PWM_PERIOD,
28 .callback = NULL,
29 .channels = {
30 [0] = {.mode = WS2812_TIM_CH == 0 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED, .callback = NULL}, // Turn on the channel we care about
31 [1] = {.mode = WS2812_TIM_CH == 1 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED, .callback = NULL}, // Turn on the channel we care about
32 [2] = {.mode = WS2812_TIM_CH == 2 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED, .callback = NULL}, // Turn on the channel we care about
33 [3] = {.mode = WS2812_TIM_CH == 3 ? PWM_OUTPUT_ACTIVE_HIGH : PWM_OUTPUT_DISABLED, .callback = NULL}, // Turn on the channel we care about
34 },
35 .cr2 = 0,
36 .bdtr = 0,
37 .dier = TIM_DIER_UDE, // DMA on update event for next period
38 };
39
40 const stm32_dma_stream_t *dma = dmaStreamAlloc(WS2812_DMA_STREAM, 10, NULL, NULL);
41 dmaStreamSetPeripheral(dma, &(WS2812_PWM_DRIVER.tim->CCR[WS2812_TIM_CH]));
42 dmaStreamSetMemory0(dma, WS2812_TIM_BUF);
43 dmaStreamSetTransactionSize(dma, WS2812_BUFLEN);
44 // M2P: Memory 2 Periph; PL: Priority Level
45 dmaStreamSetMode(dma,
46 STM32_DMA_CR_CHSEL(WS2812_DMA_CHANNEL) |
47 STM32_DMA_CR_DIR_M2P |
48 STM32_DMA_CR_PSIZE_WORD |
49 STM32_DMA_CR_MSIZE_WORD |
50 STM32_DMA_CR_MINC |
51 STM32_DMA_CR_CIRC |
52 STM32_DMA_CR_PL(3)
53 );
54
55 dmaStreamEnable(dma);
56 pwmStart(&PWMD1, &ws2812_pwm_config);
57 pwmEnableChannel(&PWMD1, WS2812_TIM_CH, 0); //(WS2812_PWM_PERIOD/2)
58
59 //TEST FUNCTIONALITY
62 setWS2812All((WS2812_RGB_t){255, 0, 0});
63 setWS2812One(19,(WS2812_RGB_t){0, 0, 255});
64 setWS2812One(9,(WS2812_RGB_t){0, 255, 0});
66}
67
68/**
69 * Set one LEDs to 0 (off)
70 */
71void clearWS2812One(uint32_t num)
72{
73 if (num < WS2812_LED_N)
74 {
75 WS2812_LED_BUF[num] = (WS2812_RGB_t){0, 0, 0};
76 }
77 calcBuf();
78}
79
80/**
81 * Set all LEDs to 0 (off)
82 */
84{
85 for (uint16_t num = 0; num < WS2812_LED_N; num++)
86 {
87 WS2812_LED_BUF[num] = (WS2812_RGB_t){0, 0, 0};
88 }
89 calcBuf();
90}
91
92/**
93 * Set one LED (R, G, B values).
94 */
95void setWS2812One(uint32_t num, WS2812_RGB_t rgb_col)
96{
97 if (num < WS2812_LED_N)
98 {
99 WS2812_LED_BUF[num] = rgb_col;
100 }
101 calcBuf();
102}
103
104/**
105 * Set all LEDs (R, G, B values).
106 */
108{
109 for (uint16_t num = 0; num < WS2812_LED_N; num++)
110 {
111 WS2812_LED_BUF[num] = rgb_col;
112 }
113 calcBuf();
114}
115
116/**
117 * Set all LEDs Brightness.
118 */
119void setWS2812Brightness(uint8_t num)
120{
121 num = num >= 100 ? 100 : num;
122 num = num <= 0 ? 0 : num;
123 WS2812_BRIGHTNESS = num;
124 calcBuf();
125}
126
127/**
128 * Calculate Timer DMA buffer
129 */
131{
132 uint32_t pos = 0;
133 // set timings for all LEDs
134 for (uint32_t num = 0; num < WS2812_LED_N; num++)
135 {
136 WS2812_RGB_t led = WS2812_LED_BUF[num];
137 float brightness = WS2812_BRIGHTNESS / 100.0;
138
139 led.red = (uint8_t)(led.red * brightness);
140 led.green = (uint8_t)(led.green * brightness);
141 led.blue = (uint8_t)(led.blue * brightness);
142
143 // Col:Green , Bit:7..0
144 WS2812_TIM_BUF[pos++] = ((led.green & 0x80) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
145 WS2812_TIM_BUF[pos++] = ((led.green & 0x40) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
146 WS2812_TIM_BUF[pos++] = ((led.green & 0x20) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
147 WS2812_TIM_BUF[pos++] = ((led.green & 0x10) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
148 WS2812_TIM_BUF[pos++] = ((led.green & 0x08) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
149 WS2812_TIM_BUF[pos++] = ((led.green & 0x04) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
150 WS2812_TIM_BUF[pos++] = ((led.green & 0x02) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
151 WS2812_TIM_BUF[pos++] = ((led.green & 0x01) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
152
153 // Col:Red , Bit:7..0
154 WS2812_TIM_BUF[pos++] = ((led.red & 0x80) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
155 WS2812_TIM_BUF[pos++] = ((led.red & 0x40) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
156 WS2812_TIM_BUF[pos++] = ((led.red & 0x20) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
157 WS2812_TIM_BUF[pos++] = ((led.red & 0x10) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
158 WS2812_TIM_BUF[pos++] = ((led.red & 0x08) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
159 WS2812_TIM_BUF[pos++] = ((led.red & 0x04) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
160 WS2812_TIM_BUF[pos++] = ((led.red & 0x02) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
161 WS2812_TIM_BUF[pos++] = ((led.red & 0x01) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
162
163 // Col:Blue , Bit:7..0
164 WS2812_TIM_BUF[pos++] = ((led.blue & 0x80) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
165 WS2812_TIM_BUF[pos++] = ((led.blue & 0x40) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
166 WS2812_TIM_BUF[pos++] = ((led.blue & 0x20) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
167 WS2812_TIM_BUF[pos++] = ((led.blue & 0x10) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
168 WS2812_TIM_BUF[pos++] = ((led.blue & 0x08) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
169 WS2812_TIM_BUF[pos++] = ((led.blue & 0x04) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
170 WS2812_TIM_BUF[pos++] = ((led.blue & 0x02) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
171 WS2812_TIM_BUF[pos++] = ((led.blue & 0x01) != 0) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
172 }
173}
174
175#endif /* EFI_WS2812 */
void clearWS2812All()
Definition WS2812.cpp:83
void setWS2812One(uint32_t num, WS2812_RGB_t rgb_col)
Definition WS2812.cpp:95
static uint32_t WS2812_TIM_BUF[WS2812_BUFLEN]
Definition WS2812.cpp:18
static uint8_t WS2812_BRIGHTNESS
Definition WS2812.cpp:19
void clearWS2812One(uint32_t num)
Definition WS2812.cpp:71
void initWS2812()
Definition WS2812.cpp:21
static WS2812_RGB_t WS2812_LED_BUF[WS2812_LED_N]
Definition WS2812.cpp:17
void calcBuf()
Definition WS2812.cpp:130
void setWS2812Brightness(uint8_t num)
Definition WS2812.cpp:119
void setWS2812All(WS2812_RGB_t rgb_col)
Definition WS2812.cpp:107
PWMDriver PWMD1
PWMD1 driver identifier.
Definition hal_pwm_lld.c:49
Type of a PWM driver configuration structure.
uint32_t frequency
Timer clock in Hz.
uint8_t green
Definition WS2812.h:12
uint8_t blue
Definition WS2812.h:13
uint8_t red
Definition WS2812.h:11