Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_dac.c
1 #include <bc_dac.h>
2 #include <bc_scheduler.h>
3 #include <bc_system.h>
4 #include <stm32l0xx.h>
5 
6 // Approximate voltage to code constant
7 #define _BC_DAC_VOLTAGE_TO_CODE_CONSTANT 19961
8 
9 typedef struct
10 {
11  bool is_initialized;
12  bool is_in_progress;
13  void (*event_handler)(bc_dac_channel_t, bc_dac_event_t, void *);
14  void *event_param;
15 
16  struct
17  {
18  uint8_t *u8;
19  uint16_t *u16;
20 
21  } dac_register;
22 
23  bc_dma_channel_t dma_channel;
24  bc_dma_channel_config_t dma_config;
25 
26  TIM_TypeDef *tim;
27  bc_dac_sample_rate_t sample_rate;
28 
30 
31 static struct
32 {
33  bc_dac_channel_setup_t channel[2];
34 
35 } _bc_dac;
36 
37 static const bc_dac_channel_setup_t _bc_dac_channel_0_setup_default;
38 
39 static const bc_dac_channel_setup_t _bc_dac_channel_1_setup_default;
40 
41 static void _bc_dac_dma_handler(bc_dma_channel_t channel, bc_dma_event_t event, void *event_param);
42 
44 {
45  if (_bc_dac.channel[channel].is_initialized)
46  {
47  return;
48  }
49 
50  RCC->APB1ENR |= RCC_APB1ENR_DACEN;
51 
52  // Errata workaround
53  RCC->AHBENR;
54 
55  if (channel == BC_DAC_DAC0)
56  {
57  _bc_dac.channel[BC_DAC_DAC0] = _bc_dac_channel_0_setup_default;
58 
59  // Enable DAC channel 0
60  DAC->CR |= DAC_CR_EN1;
61  }
62  else if (channel == BC_DAC_DAC1)
63  {
64  _bc_dac.channel[BC_DAC_DAC1] = _bc_dac_channel_1_setup_default;
65 
66  // Enable DAC channel 1
67  DAC->CR |= DAC_CR_EN2;
68  }
69 
70  _bc_dac.channel[channel].is_initialized = true;
71 }
72 
74 {
75  if (!_bc_dac.channel[channel].is_initialized)
76  {
77  return;
78  }
79 
80  if (_bc_dac.channel[channel].is_in_progress)
81  {
82  bc_dac_async_stop(channel);
83  }
84 
85  if (channel == BC_DAC_DAC0)
86  {
87  // Disable DAC channel 0
88  DAC->CR &= ~DAC_CR_EN1_Msk;
89  }
90  else if (channel == BC_DAC_DAC1)
91  {
92  // Disable DAC channel 1
93  DAC->CR &= ~DAC_CR_EN2_Msk;
94  }
95 
96  _bc_dac.channel[channel].is_initialized = false;
97 
98  if (!_bc_dac.channel[BC_DAC_DAC0].is_initialized && !_bc_dac.channel[BC_DAC_DAC1].is_initialized)
99  {
100  RCC->APB1ENR &= ~RCC_APB1ENR_DACEN;
101  }
102 }
103 
104 void bc_dac_set_output(bc_dac_channel_t channel, const void *raw, bc_dac_format_t format)
105 {
106  if (_bc_dac.channel[channel].is_in_progress)
107  {
108  return;
109  }
110 
111  uint16_t *dac_value = _bc_dac.channel[channel].dac_register.u16;
112 
113  switch (format)
114  {
115  case BC_DAC_FORMAT_8_BIT:
116  {
117  *_bc_dac.channel[channel].dac_register.u8 = *(uint8_t *) raw;
118  break;
119  }
121  {
122  *dac_value = *(uint16_t *) raw;
123  break;
124  }
126  {
127  *dac_value = *(float *) raw * _BC_DAC_VOLTAGE_TO_CODE_CONSTANT;
128  break;
129  }
130  default:
131  {
132  return;
133  }
134  }
135 }
136 
137 void bc_dac_set_event_handler(bc_dac_channel_t channel, void (*event_handler)(bc_dac_channel_t, bc_dac_event_t, void *), void *event_param)
138 {
139  _bc_dac.channel[channel].event_handler = event_handler;
140  _bc_dac.channel[channel].event_param = event_param;
141 }
142 
144 {
145  if (_bc_dac.channel[channel].is_in_progress)
146  {
147  return false;
148  }
149 
150  bc_dma_channel_config_t *dac_dma_config = &_bc_dac.channel[channel].dma_config;
151 
152  // Set peripheral address according to data size
153  if (config->data_size == BC_DAC_DATA_SIZE_8)
154  {
155  dac_dma_config->address_peripheral = _bc_dac.channel[channel].dac_register.u8;
156  }
157  else if (config->data_size == BC_DAC_DATA_SIZE_16)
158  {
159  dac_dma_config->address_peripheral = _bc_dac.channel[channel].dac_register.u16;
160  }
161 
162  // Set data-size
163  if (config->data_size == BC_DAC_DATA_SIZE_8)
164  {
165  dac_dma_config->data_size_memory = BC_DMA_SIZE_1;
166  }
167  else if (config->data_size == BC_DAC_DATA_SIZE_16)
168  {
169  dac_dma_config->data_size_memory = BC_DMA_SIZE_2;
170  }
171 
172  // Set DMA channel mode
173  if (config->mode == BC_DAC_MODE_SINGLE)
174  {
175  dac_dma_config->mode = BC_DMA_MODE_STANDARD;
176  }
177  else if (config->mode == BC_DAC_MODE_CIRCULAR)
178  {
179  dac_dma_config->mode = BC_DMA_MODE_CIRCULAR;
180  }
181 
182  dac_dma_config->length = config->length;
183 
184  dac_dma_config->address_memory = config->buffer;
185 
186  _bc_dac.channel[channel].sample_rate = config->sample_rate;
187 
188  return true;
189 }
190 
192 {
193  bc_dac_channel_setup_t *dac_channel_setup = &_bc_dac.channel[channel];
194 
195  if (dac_channel_setup->is_in_progress)
196  {
197  return false;
198  }
199 
200  bc_system_pll_enable();
201 
202  if (channel == BC_DAC_DAC0)
203  {
204  DAC->CR &= ~(DAC_CR_TSEL1_Msk);
205 
206  // DMA transfer with timer 6 TRGO event as a trigger
207  DAC->CR |= DAC_CR_DMAEN1 | DAC_CR_TEN1;
208 
209  // Enable time-base timer clock
210  RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;
211  }
212  else if (channel == BC_DAC_DAC1)
213  {
214  DAC->CR &= ~(DAC_CR_TSEL2_Msk);
215 
216  // DMA transfer with timer 7 TRGO event as a trigger
217  DAC->CR |= DAC_CR_DMAEN2 | DAC_CR_TEN2 | DAC_CR_TSEL2_0 | DAC_CR_TSEL2_2 | DAC_CR_WAVE1_0;
218 
219  // Enable time-base timer clock
220  RCC->APB1ENR |= RCC_APB1ENR_TIM7EN;
221  }
222 
223  // Errata workaround
224  RCC->AHBENR;
225 
226  TIM_TypeDef *tim = _bc_dac.channel[channel].tim;
227 
228  // Set prescaler - Tout 0.5us
229  tim->PSC = 16 - 1;
230 
231  // Configure auto-reload register according to desired sample rate (125us or 62.5us)
232  if (dac_channel_setup->sample_rate == BC_DAC_SAMPLE_RATE_8K)
233  {
234  tim->ARR = 250 - 1;
235  }
236  else if (dac_channel_setup->sample_rate == BC_DAC_SAMPLE_RATE_16K)
237  {
238  tim->ARR = 125 - 1;
239  }
240 
241  // Enable update event generation
242  tim->EGR = TIM_EGR_UG;
243 
244  // Set the update event as a trigger output (TRGO)
245  tim->CR2 = TIM_CR2_MMS_1;
246 
247  bc_dma_init();
248 
249  // Update DMA channel with image of DAC DMA channel
250  bc_dma_channel_config(dac_channel_setup->dma_channel, &dac_channel_setup->dma_config);
251 
252  bc_dma_set_event_handler(dac_channel_setup->dma_channel, _bc_dac_dma_handler, (void *)channel);
253 
254  bc_dma_channel_run(dac_channel_setup->dma_channel);
255 
256  // Start timer
257  tim->CR1 |= TIM_CR1_CEN;
258 
259  dac_channel_setup->is_in_progress = true;
260 
261  return true;
262 }
263 
265 {
266  bc_dac_channel_setup_t *dac_channel_setup = &_bc_dac.channel[channel];
267 
268  if (!dac_channel_setup->is_in_progress)
269  {
270  return;
271  }
272 
273  // Stop timer
274  dac_channel_setup->tim->CR1 &= ~TIM_CR1_CEN;
275 
276  bc_dma_channel_stop(dac_channel_setup->dma_channel);
277 
278  if (channel == BC_DAC_DAC0)
279  {
280  DAC->CR &= ~(DAC_CR_DMAEN1_Msk | DAC_CR_TEN1_Msk | DAC_CR_TSEL1_Msk);
281 
282  // Disable time-base timer clock
283  RCC->APB1ENR &= ~RCC_APB1ENR_TIM6EN;
284  }
285  else if (channel == BC_DAC_DAC1)
286  {
287  DAC->CR &= ~(DAC_CR_DMAEN2_Msk | DAC_CR_TEN2_Msk | DAC_CR_TSEL2_Msk);
288 
289  // Disable time-base timer clock
290  RCC->APB1ENR &= ~RCC_APB1ENR_TIM7EN;
291  }
292 
293  dac_channel_setup->is_in_progress = false;
294 
295  bc_system_pll_disable();
296 }
297 
298 static void _bc_dac_dma_handler(bc_dma_channel_t channel, bc_dma_event_t event, void *event_param)
299 {
300  (void) channel;
301 
302  bc_dac_channel_t dac_channel = (bc_dac_channel_t) event_param;
303  bc_dac_channel_setup_t *dac_channel_setup = &_bc_dac.channel[dac_channel];
304 
305  if (event == BC_DMA_EVENT_HALF_DONE)
306  {
307  if (dac_channel_setup->event_handler != NULL)
308  {
309  dac_channel_setup->event_handler(dac_channel, BC_DAC_EVENT_HALF_DONE, dac_channel_setup->event_param);
310  }
311  }
312  else if (event == BC_DMA_EVENT_DONE)
313  {
314  if (dac_channel_setup->event_handler != NULL)
315  {
316  dac_channel_setup->event_handler(dac_channel, BC_DAC_EVENT_DONE, dac_channel_setup->event_param);
317  }
318 
319  if (dac_channel_setup->dma_config.mode != BC_DMA_MODE_CIRCULAR)
320  {
321  bc_dac_async_stop(dac_channel);
322  }
323  }
324  else if (event == BC_DMA_EVENT_ERROR)
325  {
326  // TODO Do something
327  }
328 }
329 
330 static const bc_dac_channel_setup_t _bc_dac_channel_0_setup_default =
331 {
332  .is_initialized = false,
333  .is_in_progress = false,
334  .event_handler = NULL,
335  .event_param = NULL,
336 
337  .dac_register =
338  {
339  .u8 = (void *)&DAC->DHR8R1,
340  .u16 = (void *)&DAC->DHR12L1
341  },
342 
343  .dma_channel = BC_DMA_CHANNEL_2,
344 
345  .dma_config =
346  {
347  .request = BC_DMA_REQUEST_9,
348  .direction = BC_DMA_DIRECTION_TO_PERIPHERAL,
349  .data_size_peripheral = BC_DMA_SIZE_2,
350  .priority = BC_DMA_PRIORITY_LOW
351  },
352  .tim = TIM6,
353  .sample_rate = BC_DAC_SAMPLE_RATE_8K
354 };
355 
356 static const bc_dac_channel_setup_t _bc_dac_channel_1_setup_default =
357 {
358  .is_initialized = false,
359  .is_in_progress = false,
360  .event_handler = NULL,
361  .event_param = NULL,
362 
363  .dac_register =
364  {
365  .u8 = (void *)&DAC->DHR8R2,
366  .u16 = (void *)&DAC->DHR12L2
367  },
368 
369  .dma_channel = BC_DMA_CHANNEL_4,
370  {
371  .request = BC_DMA_REQUEST_15,
372  .direction = BC_DMA_DIRECTION_TO_PERIPHERAL,
373  .data_size_peripheral = BC_DMA_SIZE_2,
374  .priority = BC_DMA_PRIORITY_LOW
375  },
376  .tim = TIM7,
377  .sample_rate = BC_DAC_SAMPLE_RATE_8K
378 };
size_t length
DMA channel data length.
Definition: bc_dma.h:180
DAC channel DAC1.
Definition: bc_dac.h:19
DMA channel configuration.
Definition: bc_dma.h:165
Raw value format is 16-bit.
Definition: bc_dac.h:31
void bc_dac_set_output(bc_dac_channel_t channel, const void *raw, bc_dac_format_t format)
Set DAC channel output as raw value.
Definition: bc_dac.c:104
Raw value format is float.
Definition: bc_dac.h:34
void bc_dac_set_event_handler(bc_dac_channel_t channel, void(*event_handler)(bc_dac_channel_t, bc_dac_event_t, void *), void *event_param)
Set callback function.
Definition: bc_dac.c:137
void bc_dac_init(bc_dac_channel_t channel)
Initialize DAC channel.
Definition: bc_dac.c:43
DMA channel 4.
Definition: bc_dma.h:24
bc_dma_event_t
DMA channel event.
Definition: bc_dma.h:132
Data size is 16b.
Definition: bc_dac.h:58
bc_dma_channel_t
DMA channels.
Definition: bc_dma.h:12
DMA channel data size 2B.
Definition: bc_dma.h:111
bc_dac_channel_t
DAC channel.
Definition: bc_dac.h:13
bc_dac_sample_rate_t
Sample rate.
Definition: bc_dac.h:40
Event is done.
Definition: bc_dac.h:79
DMA channel priority is low.
Definition: bc_dma.h:150
void * address_peripheral
Peripheral address.
Definition: bc_dma.h:189
Event is done.
Definition: bc_dac.h:82
void bc_dma_set_event_handler(bc_dma_channel_t channel, void(*event_handler)(bc_dma_channel_t, bc_dma_event_t, void *), void *event_param)
Set callback function.
Definition: bc_dma.c:173
void * address_memory
RAM memory address.
Definition: bc_dma.h:186
Data sample-rate is 16kHz.
Definition: bc_dac.h:46
bc_dac_format_t
Raw value format.
Definition: bc_dac.h:25
DMA channel mode circular.
Definition: bc_dma.h:126
void bc_dma_init(void)
Initialize DMA.
Definition: bc_dma.c:56
Data size is 8b.
Definition: bc_dac.h:55
void bc_dac_deinit(bc_dac_channel_t channel)
Deitialize DAC channel.
Definition: bc_dac.c:73
void bc_dma_channel_run(bc_dma_channel_t channel)
Start DMA channel.
Definition: bc_dma.c:179
DMA channel direction from RAM to peripheral.
Definition: bc_dma.h:96
DMA channel event half done.
Definition: bc_dma.h:138
DMA channel 2.
Definition: bc_dma.h:18
Raw value format is 8-bit.
Definition: bc_dac.h:28
Data sample-rate is 8kHz.
Definition: bc_dac.h:43
void bc_dac_async_stop(bc_dac_channel_t channel)
Stop asynchronous DAC channel operation.
Definition: bc_dac.c:264
bool bc_dac_async_run(bc_dac_channel_t channel)
Start asynchronous DAC channel operation.
Definition: bc_dac.c:191
bc_dma_mode_t mode
DMA channel mode.
Definition: bc_dma.h:183
DMA channel data size 1B.
Definition: bc_dma.h:108
void bc_dma_channel_stop(bc_dma_channel_t channel)
Stop DMA channel.
Definition: bc_dma.c:184
DMA request 9.
Definition: bc_dma.h:69
DMA channel mode standard.
Definition: bc_dma.h:123
bc_dac_event_t
DAC channel event.
Definition: bc_dac.h:76
void bc_dma_channel_config(bc_dma_channel_t channel, bc_dma_channel_config_t *config)
Configure DMA channel.
Definition: bc_dma.c:95
bool bc_dac_async_config(bc_dac_channel_t channel, bc_dac_config_t *config)
Configure image of DAC DMA channel.
Definition: bc_dac.c:143
Mode circular (repeate playing buffer)
Definition: bc_dac.h:70
DAC channel DAC0.
Definition: bc_dac.h:16
DAC channel event.
Definition: bc_dac.h:88
DMA channel event error.
Definition: bc_dma.h:135
bc_dma_size_t data_size_memory
DMA channel memory data size.
Definition: bc_dma.h:174
Mode single.
Definition: bc_dac.h:67
DMA request 15.
Definition: bc_dma.h:87
DMA channel event done.
Definition: bc_dma.h:141