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