1 /**
2 * \file
3 *
4 * \brief SAM Peripheral Digital-to-Analog Converter Driver
5 *
6 * Copyright (C) 2014-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46 #include "dac.h"
47 #include <system.h>
48 #include <pinmux.h>
49
50 /**
51 * \internal Writes a DAC configuration to the hardware module.
52 *
53 * Writes out a given configuration to the hardware module.
54 *
55 * \param[out] module_inst Pointer to the DAC software instance struct
56 * \param[in] config Pointer to the configuration struct
57 *
58 */
_dac_set_config(struct dac_module * const module_inst,struct dac_config * const config)59 static void _dac_set_config(
60 struct dac_module *const module_inst,
61 struct dac_config *const config)
62 {
63 /* Sanity check arguments */
64 Assert(module_inst);
65 Assert(config);
66 Assert(module_inst->hw);
67
68 Dac *const dac_module = module_inst->hw;
69
70 /* Set selected DAC start on event to be disable when enabling the module */
71 module_inst->start_on_event[DAC_CHANNEL_0] = false;
72 module_inst->start_on_event[DAC_CHANNEL_1] = false;
73
74 uint32_t new_ctrlb = 0;
75
76 /* Enable DAC in differential mode if configured */
77 if (config->differential_mode) {
78 new_ctrlb |= DAC_CTRLB_DIFF;
79 }
80
81 /* Set reference voltage */
82 new_ctrlb |= config->reference;
83
84 /* Apply the new configuration to the hardware module */
85 dac_module->CTRLB.reg = new_ctrlb;
86 }
87
88 /**
89 * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
90 *
91 * Checks to see if the underlying hardware peripheral module(s) are currently
92 * synchronizing across multiple clock domains to the hardware bus. This
93 * function can be used to delay further operations on a module until such time
94 * that it is ready, to prevent blocking delays for synchronization in the
95 * user application.
96 *
97 * \param[in] dev_inst Pointer to the DAC software instance struct
98 *
99 * \return Synchronization status of the underlying hardware module(s).
100 *
101 * \retval true If the module synchronization is ongoing
102 * \retval false If the module has completed synchronization
103 */
dac_is_syncing(struct dac_module * const dev_inst)104 bool dac_is_syncing(
105 struct dac_module *const dev_inst)
106 {
107 /* Sanity check arguments */
108 Assert(dev_inst);
109
110 Dac *const dac_module = dev_inst->hw;
111
112 if (dac_module->SYNCBUSY.reg) {
113 return true;
114 }
115
116 return false;
117 }
118
119 /**
120 * \brief Initializes a DAC configuration structure to defaults.
121 *
122 * Initializes a given DAC configuration structure to a set of
123 * known default values. This function should be called on any new
124 * instance of the configuration structures before being modified by the
125 * user application.
126 *
127 * The default configuration is as follows:
128 * \li 1V from internal bandgap reference
129 * \li Drive the DAC output to the VOUT pin
130 * \li Right adjust data
131 * \li GCLK generator 0 (GCLK main) clock source
132 * \li The output buffer is disabled when the chip enters STANDBY sleep
133 * mode
134 *
135 * \param[out] config Configuration structure to initialize to default values
136 */
dac_get_config_defaults(struct dac_config * const config)137 void dac_get_config_defaults(
138 struct dac_config *const config)
139 {
140 /* Sanity check arguments */
141 Assert(config);
142
143 /* Default configuration values */
144 config->differential_mode = false;
145 config->reference = DAC_REFERENCE_INTREF;
146 config->clock_source = GCLK_GENERATOR_0;
147 }
148
149 /**
150 * \brief Initialize the DAC device struct.
151 *
152 * Use this function to initialize the Digital to Analog Converter. Resets the
153 * underlying hardware module and configures it.
154 *
155 * \note The DAC channel must be configured separately.
156 *
157 * \param[out] module_inst Pointer to the DAC software instance struct
158 * \param[in] module Pointer to the DAC module instance
159 * \param[in] config Pointer to the config struct, created by the user
160 * application
161 *
162 * \return Status of initialization.
163 * \retval STATUS_OK Module initiated correctly
164 * \retval STATUS_ERR_DENIED If module is enabled
165 * \retval STATUS_BUSY If module is busy resetting
166 */
dac_init(struct dac_module * const module_inst,Dac * const module,struct dac_config * const config)167 enum status_code dac_init(
168 struct dac_module *const module_inst,
169 Dac *const module,
170 struct dac_config *const config)
171 {
172 /* Sanity check arguments */
173 Assert(module_inst);
174 Assert(module);
175 Assert(config);
176
177 /* Initialize device instance */
178 module_inst->hw = module;
179
180 /* Turn on the digital interface clock */
181 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, MCLK_APBCMASK_DAC);
182
183 /* Check if module is enabled. */
184 if (module->CTRLA.reg & DAC_CTRLA_ENABLE) {
185 return STATUS_ERR_DENIED;
186 }
187
188 /* Check if reset is in progress. */
189 if (module->CTRLA.reg & DAC_CTRLA_SWRST) {
190 return STATUS_BUSY;
191 }
192
193 /* Configure GCLK channel and enable clock */
194 struct system_gclk_chan_config gclk_chan_conf;
195 system_gclk_chan_get_config_defaults(&gclk_chan_conf);
196 gclk_chan_conf.source_generator = config->clock_source;
197 system_gclk_chan_set_config(DAC_GCLK_ID, &gclk_chan_conf);
198 system_gclk_chan_enable(DAC_GCLK_ID);
199
200 /* Write configuration to module */
201 _dac_set_config(module_inst, config);
202
203 /* Store reference selection for later use */
204 module_inst->reference = config->reference;
205
206 #if DAC_CALLBACK_MODE == true
207 for (uint8_t i = 0; i < DAC_CHANNEL_N; i++) {
208 for (uint8_t j = 0; j < DAC_CALLBACK_N; j++) {
209 module_inst->callback[i][j] = NULL;
210 }
211 };
212
213 _dac_instances[0] = module_inst;
214 #endif
215
216 return STATUS_OK;
217 }
218
219 /**
220 * \brief Resets the DAC module.
221 *
222 * This function will reset the DAC module to its power on default values and
223 * disable it.
224 *
225 * \param[in] module_inst Pointer to the DAC software instance struct
226 */
dac_reset(struct dac_module * const module_inst)227 void dac_reset(
228 struct dac_module *const module_inst)
229 {
230 /* Sanity check arguments */
231 Assert(module_inst);
232 Assert(module_inst->hw);
233
234 Dac *const dac_module = module_inst->hw;
235
236 while (dac_is_syncing(module_inst)) {
237 /* Wait until the synchronization is complete */
238 }
239
240 /* Software reset the module */
241 dac_module->CTRLA.reg |= DAC_CTRLA_SWRST;
242 }
243
244 /**
245 * \brief Enable the DAC module.
246 *
247 * Enables the DAC interface and the selected output. If any internal reference
248 * is selected it will be enabled.
249 *
250 * \param[in] module_inst Pointer to the DAC software instance struct
251 *
252 */
dac_enable(struct dac_module * const module_inst)253 void dac_enable(
254 struct dac_module *const module_inst)
255 {
256 /* Sanity check arguments */
257 Assert(module_inst);
258 Assert(module_inst->hw);
259
260 Dac *const dac_module = module_inst->hw;
261
262 while (dac_is_syncing(module_inst)) {
263 /* Wait until the synchronization is complete */
264 }
265
266 /* Enable the module */
267 dac_module->CTRLA.reg |= DAC_CTRLA_ENABLE;
268
269 /* Enable internal bandgap reference if selected in the configuration */
270 if (module_inst->reference == DAC_REFERENCE_INTREF) {
271 system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_OUTPUT);
272 }
273
274 if(dac_module->DACCTRL[DAC_CHANNEL_0].reg & DAC_DACCTRL_ENABLE) {
275 while(! (dac_module->STATUS.reg & DAC_STATUS_READY(DAC_CHANNEL_0 + 1))) {
276 };
277 } else if(dac_module->DACCTRL[DAC_CHANNEL_1].reg & DAC_DACCTRL_ENABLE) {
278 while(! (dac_module->STATUS.reg & DAC_STATUS_READY(DAC_CHANNEL_1 + 1))) {
279 };
280 }
281 }
282
283 /**
284 * \brief Disable the DAC module.
285 *
286 * Disables the DAC interface and the output buffer.
287 *
288 * \param[in] module_inst Pointer to the DAC software instance struct
289 *
290 */
dac_disable(struct dac_module * const module_inst)291 void dac_disable(
292 struct dac_module *const module_inst)
293 {
294 /* Sanity check arguments */
295 Assert(module_inst);
296 Assert(module_inst->hw);
297
298 Dac *const dac_module = module_inst->hw;
299
300 while (dac_is_syncing(module_inst)) {
301 /* Wait until the synchronization is complete */
302 }
303
304 /* Disbale interrupt */
305 dac_module->INTENCLR.reg = DAC_INTENCLR_MASK;
306 /* Clear interrupt flag */
307 dac_module->INTFLAG.reg = DAC_INTFLAG_MASK;
308
309 /* Disable DAC */
310 dac_module->CTRLA.reg &= ~DAC_CTRLA_ENABLE;
311 }
312
313 /**
314 * \brief Enables a DAC event input or output.
315 *
316 * Enables one or more input or output events to or from the DAC module. See
317 * \ref dac_events "Struct dac_events" for a list of events this module supports.
318 *
319 * \note Events cannot be altered while the module is enabled.
320 *
321 * \param[in] module_inst Software instance for the DAC peripheral
322 * \param[in] events Struct containing flags of events to enable
323 */
dac_enable_events(struct dac_module * const module_inst,struct dac_events * const events)324 void dac_enable_events(
325 struct dac_module *const module_inst,
326 struct dac_events *const events)
327 {
328 /* Sanity check arguments */
329 Assert(module_inst);
330 Assert(module_inst->hw);
331 Assert(events);
332
333 Dac *const dac_module = module_inst->hw;
334
335 uint32_t event_mask = 0;
336
337 /* Configure Enable Inversion of input event */
338 if (events->generate_event_on_chan0_falling_edge) {
339 event_mask |= DAC_EVCTRL_INVEI0;
340 }
341
342 /* Configure Enable Inversion of input event */
343 if (events->generate_event_on_chan1_falling_edge) {
344 event_mask |= DAC_EVCTRL_INVEI1;
345 }
346
347 /* Configure Buffer Empty event */
348 if (events->generate_event_on_chan0_buffer_empty) {
349 event_mask |= DAC_EVCTRL_EMPTYEO0;
350 }
351
352 /* Configure Buffer Empty event */
353 if (events->generate_event_on_chan1_buffer_empty) {
354 event_mask |= DAC_EVCTRL_EMPTYEO1;
355 }
356
357 /* Configure Conversion Start event */
358 if (events->on_event_chan0_start_conversion) {
359 event_mask |= DAC_EVCTRL_STARTEI0;
360 module_inst->start_on_event[DAC_CHANNEL_0] = true;
361 }
362
363 /* Configure Conversion Start event */
364 if (events->on_event_chan1_start_conversion) {
365 event_mask |= DAC_EVCTRL_STARTEI1;
366 module_inst->start_on_event[DAC_CHANNEL_1] = true;
367 }
368
369 dac_module->EVCTRL.reg |= event_mask;
370 }
371
372 /**
373 * \brief Disables a DAC event input or output.
374 *
375 * Disables one or more input or output events to or from the DAC module. See
376 * \ref dac_events "Struct dac_events" for a list of events this module supports.
377 *
378 * \note Events cannot be altered while the module is enabled.
379 *
380 * \param[in] module_inst Software instance for the DAC peripheral
381 * \param[in] events Struct containing flags of events to disable
382 */
dac_disable_events(struct dac_module * const module_inst,struct dac_events * const events)383 void dac_disable_events(
384 struct dac_module *const module_inst,
385 struct dac_events *const events)
386 {
387 /* Sanity check arguments */
388 Assert(module_inst);
389 Assert(module_inst->hw);
390 Assert(events);
391
392 Dac *const dac_module = module_inst->hw;
393
394 uint32_t event_mask = 0;
395
396 /* Configure Buffer Empty event */
397 if (events->on_event_chan0_start_conversion) {
398 event_mask |= DAC_EVCTRL_EMPTYEO0;
399 }
400
401 /* Configure Buffer Empty event */
402 if (events->on_event_chan1_start_conversion) {
403 event_mask |= DAC_EVCTRL_EMPTYEO1;
404 }
405
406 /* Configure Conversion Start event */
407 if (events->generate_event_on_chan0_buffer_empty) {
408 event_mask |= DAC_EVCTRL_STARTEI0;
409 module_inst->start_on_event[DAC_CHANNEL_0] = false;
410 }
411
412 /* Configure Conversion Start event */
413 if (events->generate_event_on_chan0_buffer_empty) {
414 event_mask |= DAC_EVCTRL_STARTEI1;
415 module_inst->start_on_event[DAC_CHANNEL_1] = false;
416 }
417
418 dac_module->EVCTRL.reg &= ~event_mask;
419 }
420
dac_chan_get_config_defaults(struct dac_chan_config * const config)421 void dac_chan_get_config_defaults(
422 struct dac_chan_config *const config)
423 {
424 /* Sanity check arguments */
425 Assert(config);
426
427 /* Dac channel default configuration values */
428 config->left_adjust = false;
429 config->current = DAC_CURRENT_12M;
430 config->run_in_standby = false;
431 config->dither_mode = false;
432 config->refresh_period = 2;
433 }
434
435
436 /**
437 * \brief Writes a DAC channel configuration to the hardware module.
438 *
439 * Writes out a given channel configuration to the hardware module.
440 *
441 * \note The DAC device instance structure must be initialized before calling
442 * this function.
443 *
444 * \param[in] module_inst Pointer to the DAC software instance struct
445 * \param[in] channel Channel to configure
446 * \param[in] config Pointer to the configuration struct
447 *
448 */
dac_chan_set_config(struct dac_module * const module_inst,const enum dac_channel channel,struct dac_chan_config * const config)449 void dac_chan_set_config(
450 struct dac_module *const module_inst,
451 const enum dac_channel channel,
452 struct dac_chan_config *const config)
453 {
454 /* Sanity check arguments */
455 Assert(module_inst);
456 Assert(module_inst->hw);
457 Assert(config);
458
459 /* MUX the DAC VOUT pin */
460 struct system_pinmux_config pin_conf;
461 system_pinmux_get_config_defaults(&pin_conf);
462
463 pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
464 pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
465
466 if(channel == DAC_CHANNEL_0) {
467 /* Set up the DAC VOUT0 pin */
468 pin_conf.mux_position = MUX_PA02B_DAC_VOUT0;
469 system_pinmux_pin_set_config(PIN_PA02B_DAC_VOUT0, &pin_conf);
470 }
471 else if(channel == DAC_CHANNEL_1) {
472 /* Set up the DAC VOUT1 pin */
473 pin_conf.mux_position = MUX_PA05B_DAC_VOUT1;
474 system_pinmux_pin_set_config(PIN_PA05B_DAC_VOUT1, &pin_conf);
475 }
476
477 Dac *const dac_module = module_inst->hw;
478
479 uint32_t new_dacctrl = 0;
480
481 /* Left adjust data if configured */
482 if (config->left_adjust) {
483 new_dacctrl |= DAC_DACCTRL_LEFTADJ;
484 }
485
486 /* Set current control */
487 new_dacctrl |= config->current;
488
489 /* Enable DAC in standby sleep mode if configured */
490 if (config->run_in_standby) {
491 new_dacctrl |= DAC_DACCTRL_RUNSTDBY;
492 }
493
494 /* Voltage pump disable if configured */
495 if (config->dither_mode) {
496 new_dacctrl |= DAC_DACCTRL_DITHER;
497 }
498
499 new_dacctrl |= DAC_DACCTRL_REFRESH(config->refresh_period);
500
501 /* Apply the new configuration to the hardware module */
502 dac_module->DACCTRL[channel].reg = new_dacctrl;
503 }
504
505 /**
506 * \brief Enable a DAC channel.
507 *
508 * Enables the selected DAC channel.
509 *
510 * \param[in] module_inst Pointer to the DAC software instance struct
511 * \param[in] channel Channel to enable
512 *
513 */
dac_chan_enable(struct dac_module * const module_inst,enum dac_channel channel)514 void dac_chan_enable(
515 struct dac_module *const module_inst,
516 enum dac_channel channel)
517 {
518 /* Sanity check arguments */
519 Assert(module_inst);
520 Assert(module_inst->hw);
521
522 Dac *const dac_module = module_inst->hw;
523
524 /* Enable the module */
525 dac_module->DACCTRL[channel].reg |= DAC_DACCTRL_ENABLE;
526 }
527
528 /**
529 * \brief Disable a DAC channel.
530 *
531 * Disables the selected DAC channel.
532 *
533 * \param[in] module_inst Pointer to the DAC software instance struct
534 * \param[in] channel Channel to disable
535 *
536 */
dac_chan_disable(struct dac_module * const module_inst,enum dac_channel channel)537 void dac_chan_disable(
538 struct dac_module *const module_inst,
539 enum dac_channel channel)
540 {
541 /* Sanity check arguments */
542 Assert(module_inst);
543 Assert(module_inst->hw);
544
545 Dac *const dac_module = module_inst->hw;
546
547 /* Enable the module */
548 dac_module->DACCTRL[channel].reg &= ~DAC_DACCTRL_ENABLE;
549
550 }
551
552 /**
553 * \brief Write to the DAC.
554 *
555 * This function writes to the DATA or DATABUF register.
556 * If the conversion is not event-triggered, the data will be written to
557 * the DATA register and the conversion will start.
558 * If the conversion is event-triggered, the data will be written to DATABUF
559 * and transferred to the DATA register and converted when a Start Conversion
560 * Event is issued.
561 * Conversion data must be right or left adjusted according to configuration
562 * settings.
563 * \note To be event triggered, the enable_start_on_event must be
564 * enabled in the configuration.
565 *
566 * \param[in] module_inst Pointer to the DAC software device struct
567 * \param[in] channel DAC channel to write to
568 * \param[in] data Conversion data
569 *
570 * \return Status of the operation.
571 * \retval STATUS_OK If the data was written
572 */
dac_chan_write(struct dac_module * const module_inst,enum dac_channel channel,const uint16_t data)573 enum status_code dac_chan_write(
574 struct dac_module *const module_inst,
575 enum dac_channel channel,
576 const uint16_t data)
577 {
578 /* Sanity check arguments */
579 Assert(module_inst);
580 Assert(module_inst->hw);
581
582 Dac *const dac_module = module_inst->hw;
583
584 while (dac_is_syncing(module_inst)) {
585 /* Wait until the synchronization is complete */
586 }
587
588 if (module_inst->start_on_event[channel]) {
589 /* Write the new value to the buffered DAC data register */
590 dac_module->DATABUF[channel].reg = data;
591 } else {
592 /* Write the new value to the DAC data register */
593 dac_module->DATA[channel].reg = data;
594 }
595
596 return STATUS_OK;
597 }
598
599 /**
600 * \brief Write to the DAC.
601 *
602 * This function converts a specific number of digital data.
603 * The conversion should be event-triggered, the data will be written to DATABUF
604 * and transferred to the DATA register and converted when a Start Conversion
605 * Event is issued.
606 * Conversion data must be right or left adjusted according to configuration
607 * settings.
608 * \note To be event triggered, the enable_start_on_event must be
609 * enabled in the configuration.
610 *
611 * \param[in] module_inst Pointer to the DAC software device struct
612 * \param[in] channel DAC channel to write to
613 * \param[in] buffer Pointer to the digital data write buffer to be converted
614 * \param[in] length Length of the write buffer
615 *
616 * \return Status of the operation.
617 * \retval STATUS_OK If the data was written or no data conversion required
618 * \retval STATUS_ERR_UNSUPPORTED_DEV The DAC is not configured as using event trigger
619 * \retval STATUS_BUSY The DAC is busy and can not do the conversion
620 */
dac_chan_write_buffer_wait(struct dac_module * const module_inst,enum dac_channel channel,uint16_t * buffer,uint32_t length)621 enum status_code dac_chan_write_buffer_wait(
622 struct dac_module *const module_inst,
623 enum dac_channel channel,
624 uint16_t *buffer,
625 uint32_t length)
626 {
627 /* Sanity check arguments */
628 Assert(module_inst);
629 Assert(module_inst->hw);
630
631 Dac *const dac_module = module_inst->hw;
632
633 while (dac_is_syncing(module_inst)) {
634 /* Wait until the synchronization is complete */
635 }
636
637 /* Zero length request */
638 if (length == 0) {
639 /* No data to be converted */
640 return STATUS_OK;
641 }
642
643 #if DAC_CALLBACK_MODE == true
644 /* Check if busy */
645 if (module_inst->job_status[channel] == STATUS_BUSY) {
646 return STATUS_BUSY;
647 }
648 #endif
649
650 /* Only support event triggered conversion */
651 if (module_inst->start_on_event[channel] == false) {
652 return STATUS_ERR_UNSUPPORTED_DEV;
653 }
654
655 /* Blocks while buffer is being transferred */
656 while (length--) {
657 /* Convert one data */
658 dac_chan_write(module_inst, channel, buffer[length]);
659
660 /* Wait until Transmit is complete or timeout */
661 for (uint32_t i = 0; i <= DAC_TIMEOUT; i++) {
662 if(channel == DAC_CHANNEL_0) {
663 if (dac_module->INTFLAG.reg & DAC_INTFLAG_EMPTY0) {
664 break;
665 } else if (i == DAC_TIMEOUT) {
666 return STATUS_ERR_TIMEOUT;
667 }
668 } else if(channel == DAC_CHANNEL_1) {
669 if (dac_module->INTFLAG.reg & DAC_INTFLAG_EMPTY1) {
670 break;
671 } else if (i == DAC_TIMEOUT) {
672 return STATUS_ERR_TIMEOUT;
673 }
674 }
675 }
676 }
677
678 return STATUS_OK;
679 }
680
681 /**
682 * \brief Retrieves the status of DAC channel end of conversion.
683 *
684 * Checks if the conversion is completed or not and returns boolean flag
685 * of status.
686 *
687 * \param[in] module_inst Pointer to the DAC software instance struct
688 * \param[in] channel Channel to disable
689 *
690 * \retval true Conversion is complete, VOUT is stable
691 * \retval false No conversion completed since last load of DATA
692 */
dac_chan_is_end_of_conversion(struct dac_module * const module_inst,enum dac_channel channel)693 bool dac_chan_is_end_of_conversion(
694 struct dac_module *const module_inst,
695 enum dac_channel channel)
696 {
697 /* Sanity check arguments */
698 Assert(module_inst);
699 Assert(module_inst->hw);
700
701 Dac *const dac_module = module_inst->hw;
702
703 if(dac_module->STATUS.reg & DAC_STATUS_EOC(channel + 1)) {
704 return true;
705 } else {
706 return false;
707 }
708 }
709
710 /**
711 * \brief Retrieves the current module status.
712 *
713 * Checks the status of the module and returns it as a bitmask of status
714 * flags.
715 *
716 * \param[in] module_inst Pointer to the DAC software device struct
717 *
718 * \return Bitmask of status flags.
719 *
720 * \retval DAC_STATUS_CHANNEL_0_EMPTY Data has been transferred from DATABUF
721 * to DATA by a start conversion event
722 * and DATABUF is ready for new data
723 * \retval DAC_STATUS_CHANNEL_0_UNDERRUN A start conversion event has occurred
724 * when DATABUF is empty
725 *
726 */
dac_get_status(struct dac_module * const module_inst)727 uint32_t dac_get_status(
728 struct dac_module *const module_inst)
729 {
730 /* Sanity check arguments */
731 Assert(module_inst);
732 Assert(module_inst->hw);
733
734 Dac *const dac_module = module_inst->hw;
735
736 uint8_t intflags = dac_module->INTFLAG.reg;
737 uint32_t status_flags = 0;
738
739 if (intflags & DAC_INTFLAG_EMPTY0) {
740 status_flags |= DAC_STATUS_CHANNEL_0_EMPTY;
741 }
742
743 if (intflags & DAC_INTFLAG_EMPTY1) {
744 status_flags |= DAC_STATUS_CHANNEL_1_EMPTY;
745 }
746
747 if (intflags & DAC_INTFLAG_UNDERRUN0) {
748 status_flags |= DAC_STATUS_CHANNEL_0_UNDERRUN;
749 }
750
751 if (intflags & DAC_INTFLAG_UNDERRUN1) {
752 status_flags |= DAC_STATUS_CHANNEL_1_UNDERRUN;
753 }
754
755 return status_flags;
756 }
757
758 /**
759 * \brief Clears a module status flag.
760 *
761 * Clears the given status flag of the module.
762 *
763 * \param[in] module_inst Pointer to the DAC software device struct
764 * \param[in] status_flags Bit mask of status flags to clear
765 *
766 */
dac_clear_status(struct dac_module * const module_inst,uint32_t status_flags)767 void dac_clear_status(
768 struct dac_module *const module_inst,
769 uint32_t status_flags)
770 {
771 /* Sanity check arguments */
772 Assert(module_inst);
773 Assert(module_inst->hw);
774
775 Dac *const dac_module = module_inst->hw;
776
777 uint32_t intflags = 0;
778
779 if (status_flags & DAC_STATUS_CHANNEL_0_EMPTY) {
780 intflags |= DAC_INTFLAG_EMPTY0;
781 }
782
783 if (status_flags & DAC_STATUS_CHANNEL_1_EMPTY) {
784 intflags |= DAC_INTFLAG_EMPTY1;
785 }
786
787 if (status_flags & DAC_STATUS_CHANNEL_0_UNDERRUN) {
788 intflags |= DAC_INTFLAG_UNDERRUN0;
789 }
790
791 if (status_flags & DAC_STATUS_CHANNEL_1_UNDERRUN) {
792 intflags |= DAC_INTFLAG_UNDERRUN1;
793 }
794
795 dac_module->INTFLAG.reg = intflags;
796 }
797