Paparazzi UAS  v5.15_devel-164-g81d4ceb
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
light_ws2812_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 Xavier Paris <xavier.paris@enac.fr>
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
29 /****************************************************************************************
30 https://github.com/joewa/WS2812-LED-Driver_ChibiOS/
31 ****************************************************************************************/
32 
33 #include <hal.h>
36 
37 #define WS2812_SERVO_HZ 800000
38 #define WS2812_PWM_FREQUENCY (STM32_SYSCLK/2)
39 
40 #define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY/(1000000000/350))
41 #define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY/(1000000000/800))
42 
43 #define WS2812_RESET_BIT_N (50)
44 #define WS2812_COLOR_BIT_N (WS2812_NB_LEDS * 24)
45 #define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N)
46 
47 // Use driver 1 by default
48 #ifndef WS2812_CFG_DEF
49 #define WS2812_CFG_DEF WS2812D1_CFG_DEF
50 #endif
51 
52 #define WS2812_DMA_IRQ_PRIORITY 6
53 
57 typedef struct {
62  PWMDriver *pwmp;
63 } WS2812Config;
64 
65 // Config from board conf
67 
71 typedef struct {
74  PWMConfig pwm_conf;
77 } WS2812Driver;
78 
79 // Driver
81 
83 {
84  uint32_t i;
85  for (i = 0; i < WS2812_COLOR_BIT_N; i++) {
86  WS2812D.buf[i] = WS2812_DUTYCYCLE_0;
87  }
88  for (i = 0; i < WS2812_RESET_BIT_N; i++) {
89  WS2812D.buf[i + WS2812_COLOR_BIT_N] = 0;
90  }
91 
92  WS2812D.config = &WS2812CFG;
93 
94  WS2812D.dma_conf = (DMAConfig) {
95  .stream = WS2812CFG.dma_stream,
96  .channel = WS2812CFG.dma_channel,
97  .dma_priority = WS2812CFG.dma_priority,
98  .irq_priority = WS2812_DMA_IRQ_PRIORITY,
99  .direction = DMA_DIR_M2P,
100  .psize = 4,
101  .msize = 4,
102  .inc_peripheral_addr = false,
103  .inc_memory_addr = true,
104  .circular = true,
105  .error_cb = NULL,
106  .end_cb = NULL,
107  .pburst = 0,
108  .mburst = 0,
109  .fifo = 0
110  };
111 
112  WS2812D.pwm_conf = (PWMConfig) {
113  .frequency = WS2812_PWM_FREQUENCY,
115  .callback = NULL,
116  .channels = {
117  {
118  .mode = PWM_OUTPUT_DISABLED,
119  .callback = NULL
120  },
121  {
122  .mode = PWM_OUTPUT_DISABLED,
123  .callback = NULL
124  },
125  {
126  .mode = PWM_OUTPUT_DISABLED,
127  .callback = NULL
128  },
129  {
130  .mode = PWM_OUTPUT_DISABLED,
131  .callback = NULL
132  },
133  },
134  .cr2 = 0,
135  .dier = STM32_TIM_DIER_UDE
136  };
137 
138  dmaObjectInit(&WS2812D.dmap);
139  dmaStart(&WS2812D.dmap, &WS2812D.dma_conf);
140  dmaStartTransfert(&WS2812D.dmap, &(WS2812D.config->pwmp->tim->CCR[WS2812D.config->pwm_channel]), &WS2812D.buf, WS2812_BIT_N);
141 
142  WS2812D.pwm_conf.channels[WS2812D.config->pwm_channel].mode = PWM_OUTPUT_ACTIVE_HIGH;
143  pwmStart(WS2812D.config->pwmp, &WS2812D.pwm_conf);
144  pwmEnableChannel(WS2812D.config->pwmp, WS2812D.config->pwm_channel, 0);
145 }
146 
147 #define WS2812_BIT(led, byte, bit) (24*(led) + 8*(byte) + (7 - (bit)))
148 #define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 1, (bit))
149 #define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 0, (bit))
150 #define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit))
151 
153 {
154  uint32_t bit;
155  if (led_number < WS2812_NB_LEDS) {
156  for (bit = 0; bit < 8; bit++) {
157  WS2812D.buf[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
158  WS2812D.buf[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
159  WS2812D.buf[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
160  }
161  }
162 }
#define WS2812_CFG_DEF
STM32 DMA subsystem driver header.
#define WS2812_BIT_N
bool dmaStart(DMADriver *dmap, const DMAConfig *cfg)
Configures and activates the DMA peripheral.
Definition: hal_stm32_dma.c:85
static WS2812Driver WS2812D
#define WS2812_RED_BIT(led, bit)
DMAConfig dma_conf
uint32_t stream
stream associated with transaction
uint8_t dma_priority
static WS2812Config WS2812CFG
Configuration structure.
void light_ws2812_arch_set(uint32_t led_number, uint8_t r, uint8_t g, uint8_t b)
set color RGB color of one led
#define WS2812_DUTYCYCLE_1
DMA stream configuration structure.
PWMDriver * pwmp
#define WS2812_BLUE_BIT(led, bit)
Driver structure.
const WS2812Config * config
unsigned long uint32_t
Definition: types.h:18
#define WS2812_SERVO_HZ
#define WS2812_GREEN_BIT(led, bit)
ws2812 driver based on ChibiOS
#define WS2812_NB_LEDS
Number of LEDs.
MEMORY to PERIPHERAL.
Definition: hal_stm32_dma.h:84
#define WS2812_DUTYCYCLE_0
bool dmaStartTransfert(DMADriver *dmap, volatile void *periphp, void *mem0p, const size_t size)
Starts a DMA transaction.
unsigned char uint8_t
Definition: types.h:14
#define WS2812_PWM_FREQUENCY
void dmaObjectInit(DMADriver *dmap)
Definition: hal_stm32_dma.c:53
uint32_t buf[WS2812_BIT_N+1]
#define WS2812_COLOR_BIT_N
PWMConfig pwm_conf
uint32_t dma_stream
#define WS2812_RESET_BIT_N
void light_ws2812_arch_init(void)
Structure representing a DMA driver.
#define WS2812_DMA_IRQ_PRIORITY