1 /**
2  * \file
3  *
4  * \brief SAM Sigma-Delta Analog-to-Digital Converter (SDADC) Driver
5  *
6  * Copyright (C) 2015-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 
47 #ifndef SDADC_H_INCLUDED
48 #define SDADC_H_INCLUDED
49 
50 /**
51  * \defgroup asfdoc_sam0_sdadc_group SAM Sigma-Delta Analog-to-Digital Converter (SDADC) Driver
52  *
53  * This driver for Atmel&reg; | SMART ARM&reg;-based microcontrollers provides an interface for the configuration
54  * and management of the device's SDADC functionality.
55  *
56  * The following peripheral is used by this module:
57  *  - SDADC (Sigma-Delta Analog-to-Digital Converter)
58  *
59  * The following devices can use this module:
60  *  - Atmel | SMART SAM C21
61  *
62  * The outline of this documentation is as follows:
63  *  - \ref asfdoc_sam0_sdadc_prerequisites
64  *  - \ref asfdoc_sam0_sdadc_module_overview
65  *  - \ref asfdoc_sam0_sdadc_special_considerations
66  *  - \ref asfdoc_sam0_sdadc_extra_info
67  *  - \ref asfdoc_sam0_sdadc_examples
68  *  - \ref asfdoc_sam0_sdadc_api_overview
69  *
70  *
71  * \section asfdoc_sam0_sdadc_prerequisites Prerequisites
72  *
73  * There are no prerequisites for this module.
74  *
75  *
76  * \section asfdoc_sam0_sdadc_module_overview Module Overview
77  *
78  * The Sigma-Delta Analog-to-Digital Converter (SDADC) converts analog signals to
79  * digital values. The sigma-delta architecture of the SDADC implies a filtering
80  * and a decimation of the bitstream at the output of the SDADC. The input selection
81  * is up to three input analog channels.
82  *
83  * The SDADC provides up to 16-bit resolution at about 1000 samples per second (1KSPS)
84  * and sized 24 bits signed result to handle filtering and gain correction without overflow.
85  * The SDADC measurements can be started by either application software or an incoming
86  * event from another peripheral in the device.
87  *
88  * The conversion is performed on a full range between 0V and the reference voltage.
89  * Both internal and external reference voltages can be selected. The reference range
90  * must be set to match the voltage of the reference used. Analog inputs between
91  * these voltages convert to values based on a linear conversion.
92  *
93  *
94  * \subsection asfdoc_sam0_sdadc_module_overview_clock Sample Clock
95  * A generic clock (GCLK_SDADC) is required to generate the CLK_SDADC to the SDADC
96  * module. The SDADC features a prescaler, which enables conversion at lower clock
97  * rates than the input Generic Clock to the SDADC module.
98  *
99  * The SDADC data sampling frequency (CLK_SDADC_FS) in the SDADC module is the
100  * CLK_SDADC/4, the reduction comes from the phase generator between the prescaler
101  * and the SDADC.
102  *
103  * OSR is the Over Sampling Ratio, which can be modified to change the output data
104  * rate. The conversion time depends on the selected OSR and the sampling frequency
105  * of the SDADC.
106  * The conversion time can be described with:
107  * \f[
108  * t_{SAMPLE} = \frac {22 + 3 \times OSR} {CLK \_ SDADC \_ FS}
109  * \f]
110  * -# Initialization of the SDADC (22 sigma-delta samples).
111  * -# Filling of the decimation filter (3*OSR sigma-delta samples).
112  *
113  * \subsection asfdoc_sam0_sdadc_module_overview_offset_corr Gain and Offset Correction
114  * A specific offset, gain, and shift can be applied to each source of the SDADC
115  * by performing the following operation:
116  * \f[
117  * Data = (Data_{0} + OFFSET) \times \frac {GAIN}{2^{SHIFT}}
118  * \f]
119  *
120  *
121  * \subsection asfdoc_sam0_sdadc_module_overview_window_monitor Window Monitor
122  * The SDADC module window monitor function can be used to automatically compare
123  * the conversion result against a predefined pair of upper and lower
124  * threshold values.
125  *
126  *
127  * \subsection asfdoc_sam0_sdadc_module_overview_events Events
128  * Event generation and event actions are configurable in the SDADC.
129  *
130  * The SDADC has two actions that can be triggered upon event reception:
131  * \li Start conversion
132  * \li Conversion flush
133  *
134  * The SDADC can generate two kinds of events:
135  * \li Window monitor
136  * \li Result ready
137  *
138  * If the event actions are enabled in the configuration, any incoming event
139  * will trigger the action.
140  *
141  * If the window monitor event is enabled, an event will be generated
142  * when the configured window condition is detected.
143  *
144  * If the result ready event is enabled, an event will be generated when a
145  * conversion is completed.
146  *
147  *
148  * \section asfdoc_sam0_sdadc_special_considerations Special Considerations
149  *
150  * There are no special considerations for this module.
151  *
152  *
153  * \section asfdoc_sam0_sdadc_extra_info Extra Information
154  *
155  * For extra information see \ref asfdoc_sam0_sdadc_extra. This includes:
156  *  - \ref asfdoc_sam0_sdadc_extra_acronyms
157  *  - \ref asfdoc_sam0_sdadc_extra_dependencies
158  *  - \ref asfdoc_sam0_sdadc_extra_errata
159  *  - \ref asfdoc_sam0_sdadc_extra_history
160  *
161  *
162  * \section asfdoc_sam0_sdadc_examples Examples
163  *
164  * For a list of examples related to this driver, see
165  * \ref asfdoc_sam0_sdadc_exqsg.
166  *
167  *
168  * \section asfdoc_sam0_sdadc_api_overview API Overview
169  * @{
170  */
171 #ifdef __cplusplus
172 extern "C" {
173 #endif
174 
175 #include <compiler.h>
176 #include <system.h>
177 
178 #if SDADC_CALLBACK_MODE == true
179 #  include <system_interrupt.h>
180 
181 #if !defined(__DOXYGEN__)
182 extern struct sdadc_module *_sdadc_instances[SDADC_INST_NUM];
183 #endif
184 
185 /** Forward definition of the device instance. */
186 struct sdadc_module;
187 
188 /** Type of the callback functions. */
189 typedef void (*sdadc_callback_t)(const struct sdadc_module *const module);
190 
191 /**
192  * \brief SDADC Callback enum.
193  *
194  * Callback types for SDADC callback driver.
195  *
196  */
197 enum sdadc_callback {
198 	/** Callback for buffer received */
199 	SDADC_CALLBACK_READ_BUFFER,
200 	/** Callback when window is hit */
201 	SDADC_CALLBACK_WINDOW,
202 	/** Callback for error */
203 	SDADC_CALLBACK_ERROR,
204 #  if !defined(__DOXYGEN__)
205 	/** Number of available callbacks */
206 	SDADC_CALLBACK_N,
207 #  endif
208 };
209 
210 #endif
211 
212 /**
213  * \name Module Status Flags
214  *
215  * SDADC status flags, returned by \ref sdadc_get_status() and cleared by
216  * \ref sdadc_clear_status().
217  *
218  * @{
219  */
220 
221 /** SDADC result ready. */
222 #define SDADC_STATUS_RESULT_READY  (1UL << 0)
223 /** SDADC result overwritten before read. */
224 #define SDADC_STATUS_OVERRUN       (1UL << 1)
225 /** Window monitor match. */
226 #define SDADC_STATUS_WINDOW        (1UL << 2)
227 
228 /** @} */
229 
230 /**
231  * \brief SDADC reference voltage enum.
232  *
233  * Enum for the possible reference voltages for the SDADC.
234  *
235  */
236 enum sdadc_reference_select {
237 	/** Internal Bandgap Reference */
238 	SDADC_REFERENCE_INTREF = SDADC_REFCTRL_REFSEL(0),
239 	/** External reference B */
240 	SDADC_REFERENCE_AREFB  = SDADC_REFCTRL_REFSEL(1),
241 	/** DACOUT */
242 	SDADC_REFERENCE_DACOUT = SDADC_REFCTRL_REFSEL(2),
243 	/** VDDANA */
244 	SDADC_REFERENCE_INTVCC = SDADC_REFCTRL_REFSEL(3),
245 };
246 
247 /**
248  * \brief SDADC reference range enum.
249  *
250  * Enum for the matched voltage range of the SDADC reference used.
251  *
252  */
253 enum sdadc_reference_range {
254 	/** Vref < 1.4V */
255 	SDADC_REFRANGE_0 = SDADC_REFCTRL_REFRANGE(0),
256 	/** 1.4V < Vref < 2.4V */
257 	SDADC_REFRANGE_1 = SDADC_REFCTRL_REFRANGE(1),
258 	/** 2.4V < Vref < 3.6V */
259 	SDADC_REFRANGE_2 = SDADC_REFCTRL_REFRANGE(2),
260 	/** Vref > 3.6V */
261 	SDADC_REFRANGE_3 = SDADC_REFCTRL_REFRANGE(3),
262 };
263 
264 /**
265  * \brief SDADC over sampling ratio enum.
266  *
267  * Enum for the over sampling ratio, which change the output data rate.
268  *
269  */
270 enum sdadc_over_sampling_ratio {
271 	/** SDADC over Sampling Ratio is 64 */
272 	SDADC_OVER_SAMPLING_RATIO64    = SDADC_CTRLB_OSR(0),
273 	/** SDADC over Sampling Ratio is 128 */
274 	SDADC_OVER_SAMPLING_RATIO128   = SDADC_CTRLB_OSR(1),
275 	/** SDADC over Sampling Ratio is 256 */
276 	SDADC_OVER_SAMPLING_RATIO256   = SDADC_CTRLB_OSR(2),
277 	/** SDADC over Sampling Ratio is 512 */
278 	SDADC_OVER_SAMPLING_RATIO512   = SDADC_CTRLB_OSR(3),
279 	/** SDADC over Sampling Ratio is 1024 */
280 	SDADC_OVER_SAMPLING_RATIO1024  = SDADC_CTRLB_OSR(4),
281 };
282 
283 /**
284  * \brief SDADC window monitor mode enum.
285  *
286  * Enum for the possible window monitor modes for the SDADC.
287  *
288  */
289 enum sdadc_window_mode {
290 	/** No window mode */
291 	SDADC_WINDOW_MODE_DISABLE          = SDADC_WINCTRL_WINMODE(0),
292 	/** RESULT > WINLT */
293 	SDADC_WINDOW_MODE_ABOVE            = SDADC_WINCTRL_WINMODE(1),
294 	/** RESULT < WINUT */
295 	SDADC_WINDOW_MODE_BELOW            = SDADC_WINCTRL_WINMODE(2),
296 	/** WINLT < RESULT < WINUT */
297 	SDADC_WINDOW_MODE_INSIDE           = SDADC_WINCTRL_WINMODE(3),
298 	/** !(WINLT < RESULT < WINUT) */
299 	SDADC_WINDOW_MODE_OUTSIDE          = SDADC_WINCTRL_WINMODE(4),
300 };
301 
302 /**
303  * \brief SDADC event action enum.
304  *
305  * Enum for the possible actions to take on an incoming event.
306  *
307  */
308 enum sdadc_event_action {
309 	/** Event action disabled */
310 	SDADC_EVENT_ACTION_DISABLED         = 0,
311 	/** Flush SDADC and start conversion */
312 	SDADC_EVENT_ACTION_FLUSH_START_CONV = SDADC_EVCTRL_FLUSHEI,
313 	/** Start conversion */
314 	SDADC_EVENT_ACTION_START_CONV       = SDADC_EVCTRL_STARTEI,
315 };
316 
317 /**
318  * \brief SDADC MUX input selection enum.
319  *
320  * Enum for the possible MUX input selections for the SDADC.
321  *
322  */
323 enum sdadc_mux_input {
324 	/** Select SDADC AINN0 and AINP0 pins */
325 	SDADC_MUX_INPUT_AIN0    = SDADC_INPUTCTRL_MUXSEL_AIN0,
326 	/** Select SDADC AINN1 and AINP1 pins */
327 	SDADC_MUX_INPUT_AIN1    = SDADC_INPUTCTRL_MUXSEL_AIN1,
328 	/** Select SDADC AINN2 and AINP2 pins */
329 	SDADC_MUX_INPUT_AIN2    = SDADC_INPUTCTRL_MUXSEL_AIN2,
330 };
331 
332 #if SDADC_CALLBACK_MODE == true
333 /**
334  * Enum for the possible SDADC interrupt flags.
335  */
336 enum sdadc_interrupt_flag {
337 	/** SDADC result ready */
338 	SDADC_INTERRUPT_RESULT_READY = SDADC_INTFLAG_RESRDY,
339 	/** SDADC result overwritten before read */
340 	SDADC_INTERRUPT_OVERRUN      = SDADC_INTFLAG_OVERRUN,
341 	/** Window monitor match */
342 	SDADC_INTERRUPT_WINDOW       = SDADC_INTFLAG_WINMON,
343 };
344 #endif
345 
346 /**
347  * \brief Reference configuration structure.
348  *
349  * Reference configuration structure.
350  */
351 struct sdadc_reference {
352 	/** Reference voltage selection */
353 	enum sdadc_reference_select ref_sel;
354 	/** Reference voltage range */
355 	enum sdadc_reference_select ref_range;
356 	/** Reference buffer turning switch */
357 	bool on_ref_buffer;
358 };
359 
360 /**
361  * \brief Window monitor configuration structure.
362  *
363  * Window monitor configuration structure.
364  */
365 struct sdadc_window_config {
366 	/** Selected window mode */
367 	enum sdadc_window_mode window_mode;
368 	/** Lower window value */
369 	int32_t window_lower_value;
370 	/** Upper window value */
371 	int32_t window_upper_value;
372 };
373 
374 /**
375  * \brief SDADC event enable/disable structure.
376  *
377  * Event flags for the SDADC module. This is used to enable and
378  * disable events via \ref sdadc_enable_events() and \ref sdadc_disable_events().
379  */
380 struct sdadc_events {
381 	/** Enable event generation on conversion done */
382 	bool generate_event_on_conversion_done;
383 	/** Enable event generation on window monitor */
384 	bool generate_event_on_window_monitor;
385 };
386 
387 /**
388  * \brief SDADC correction configuration structure.
389  *
390  * Offset, gain, and shift correction configuration structure.
391  * Part of the \ref sdadc_config struct will be initialized by
392  * \ref sdadc_get_config_defaults.
393  */
394 struct sdadc_correction_config {
395 	/** Offset correction */
396 	int32_t offset_correction;
397 	/** Gain correction */
398 	uint16_t gain_correction;
399 	/** Shift correction */
400 	uint8_t shift_correction;
401 };
402 
403 /**
404  * \brief SDADC configuration structure.
405  *
406  * Configuration structure for an SDADC instance. This structure should be
407  * initialized by the \ref sdadc_get_config_defaults()
408  * function before being modified by the user application.
409  */
410 struct sdadc_config {
411 	/** GCLK generator used to clock the peripheral */
412 	enum gclk_generator clock_source;
413 	/** Voltage reference */
414 	struct sdadc_reference reference;
415 	/** Over sampling ratio */
416 	enum sdadc_over_sampling_ratio osr;
417 	/** Clock prescaler */
418 	uint8_t clock_prescaler;
419 	/** Skip Count */
420 	uint8_t skip_count;
421 	/** MUX input */
422 	enum sdadc_mux_input mux_input;
423 	/** Enables free running mode if true */
424 	bool freerunning;
425 	/** Enables SDADC in standby sleep mode if true */
426 	bool run_in_standby;
427 	/** Enables SDADC depend on other peripheral if true */
428 	bool on_command;
429 	/** Enables positive input in the sequence if true */
430 	bool seq_enable[3];
431 	/** Window monitor configuration structure */
432 	struct sdadc_window_config window;
433 	/** Gain and offset correction configuration structure */
434 	struct sdadc_correction_config correction;
435 	/** Event action to take on incoming event */
436 	enum sdadc_event_action event_action;
437 };
438 
439 /**
440  * \brief SDADC software device instance structure.
441  *
442  * SDADC software instance structure, used to retain software state information
443  * of an associated hardware module instance.
444  *
445  * \note The fields of this structure should not be altered by the user
446  *       application; they are reserved for module-internal use only.
447  */
448 struct sdadc_module {
449 #if !defined(__DOXYGEN__)
450 	/** Pointer to SDADC hardware module */
451 	Sdadc *hw;
452 	/** Keep reference configuration so we know when enable is called */
453 	struct sdadc_reference reference;
454 #  if SDADC_CALLBACK_MODE == true
455 	/** Array to store callback functions */
456 	sdadc_callback_t callback[SDADC_CALLBACK_N];
457 	/** Pointer to buffer used for SDADC results */
458 	volatile int32_t *job_buffer;
459 	/** Remaining number of conversions in current job */
460 	volatile uint16_t remaining_conversions;
461 	/** Bit mask for callbacks registered */
462 	uint8_t registered_callback_mask;
463 	/** Bit mask for callbacks enabled */
464 	uint8_t enabled_callback_mask;
465 	/** Holds the status of the ongoing or last conversion job */
466 	volatile enum status_code job_status;
467 	/** If software triggering is needed */
468 	bool software_trigger;
469 #  endif
470 #endif
471 };
472 
473 /**
474  * \name Driver Initialization and Configuration
475  * @{
476  */
477 enum status_code sdadc_init(
478 		struct sdadc_module *const module_inst,
479 		Sdadc *hw,
480 		struct sdadc_config *config);
481 
482 /**
483  * \brief Initializes an SDADC configuration structure to defaults.
484  *
485  * Initializes a given SDADC configuration struct to a set of known default
486  * values. This function should be called on any new instance of the
487  * configuration struct before being modified by the user application.
488  *
489  * The default configuration is as follows:
490  *  \li GCLK generator 0 (GCLK main) clock source
491  *  \li Positive reference 1
492  *  \li Div 2 clock prescaler
493  *  \li Over Sampling Ratio is 64
494  *  \li Skip 0 samples
495  *  \li MUX input on SDADC AIN1
496  *  \li All events (input and generation) disabled
497  *  \li Free running disabled
498  *  \li Run in standby disabled
499  *  \li On command disabled
500  *  \li Disable all positive input in sequence
501  *  \li Window monitor disabled
502  *  \li No gain/offset/shift correction
503  *
504  * \param[out] config  Pointer to configuration struct to initialize to
505  *                     default values
506  */
sdadc_get_config_defaults(struct sdadc_config * const config)507 static inline void sdadc_get_config_defaults(struct sdadc_config *const config)
508 {
509 	Assert(config);
510 	config->clock_source                  = GCLK_GENERATOR_0;
511 	config->reference.ref_sel             = SDADC_REFERENCE_INTREF;
512 	config->reference.ref_range           = SDADC_REFRANGE_0;
513 	config->reference.on_ref_buffer       = false;
514 	config->clock_prescaler               = 2;
515 	config->osr                           = SDADC_OVER_SAMPLING_RATIO64;
516 	config->skip_count                    = 2;
517 	config->mux_input                     = SDADC_MUX_INPUT_AIN1;
518 	config->event_action                  = SDADC_EVENT_ACTION_DISABLED;
519 	config->freerunning                   = false;
520 	config->run_in_standby                = false;
521 	config->on_command                    = false;
522 	config->seq_enable[0]                 = false;
523 	config->seq_enable[1]                 = false;
524 	config->seq_enable[2]                 = false;
525 	config->window.window_mode            = SDADC_WINDOW_MODE_DISABLE;
526 	config->window.window_upper_value     = 0;
527 	config->window.window_lower_value     = 0;
528 	config->correction.gain_correction    = 1;
529 	config->correction.offset_correction  = SDADC_OFFSETCORR_RESETVALUE;
530 	config->correction.shift_correction   = SDADC_SHIFTCORR_RESETVALUE;
531 }
532 
533 /** @} */
534 
535 /**
536  * \name Status Management
537  * @{
538  */
539 
540 /**
541  * \brief Retrieves the current module status.
542  *
543  * Retrieves the status of the module, giving overall state information.
544  *
545  * \param[in] module_inst  Pointer to the SDADC software instance struct
546  *
547  * \return Bitmask of \c SDADC_STATUS_* flags.
548  *
549  * \retval SDADC_STATUS_RESULT_READY  SDADC result is ready to be read
550  * \retval SDADC_STATUS_WINDOW        SDADC has detected a value inside the set
551  *                                  window range
552  * \retval SDADC_STATUS_OVERRUN       SDADC result has overrun
553  */
sdadc_get_status(struct sdadc_module * const module_inst)554 static inline uint32_t sdadc_get_status(
555 		struct sdadc_module *const module_inst)
556 {
557 	/* Sanity check arguments */
558 	Assert(module_inst);
559 	Assert(module_inst->hw);
560 
561 	Sdadc *const sdadc_module = module_inst->hw;
562 
563 	uint32_t int_flags = sdadc_module->INTFLAG.reg;
564 
565 	uint32_t status_flags = 0;
566 
567 	/* Check for SDADC Result Ready */
568 	if (int_flags & SDADC_INTFLAG_RESRDY) {
569 		status_flags |= SDADC_STATUS_RESULT_READY;
570 	}
571 
572 	/* Check for SDADC Window Match */
573 	if (int_flags & SDADC_INTFLAG_WINMON) {
574 		status_flags |= SDADC_STATUS_WINDOW;
575 	}
576 
577 	/* Check for SDADC Overrun */
578 	if (int_flags & SDADC_INTFLAG_OVERRUN) {
579 		status_flags |= SDADC_STATUS_OVERRUN;
580 	}
581 
582 	return status_flags;
583 }
584 
585 /**
586  * \brief Clears a module status flag.
587  *
588  * Clears the given status flag of the module.
589  *
590  * \param[in] module_inst   Pointer to the SDADC software instance struct
591  * \param[in] status_flags  Bitmask of \c SDADC_STATUS_* flags to clear
592  */
sdadc_clear_status(struct sdadc_module * const module_inst,const uint32_t status_flags)593 static inline void sdadc_clear_status(
594 		struct sdadc_module *const module_inst,
595 		const uint32_t status_flags)
596 {
597 	/* Sanity check arguments */
598 	Assert(module_inst);
599 	Assert(module_inst->hw);
600 
601 	Sdadc *const sdadc_module = module_inst->hw;
602 
603 	uint32_t int_flags = 0;
604 
605 	/* Check for SDADC Result Ready */
606 	if (status_flags & SDADC_STATUS_RESULT_READY) {
607 		int_flags |= SDADC_INTFLAG_RESRDY;
608 	}
609 
610 	/* Check for SDADC Window Match */
611 	if (status_flags & SDADC_STATUS_WINDOW) {
612 		int_flags |= SDADC_INTFLAG_WINMON;
613 	}
614 
615 	/* Check for SDADC Overrun */
616 	if (status_flags & SDADC_STATUS_OVERRUN) {
617 		int_flags |= SDADC_INTFLAG_OVERRUN;
618 	}
619 
620 	/* Clear interrupt flag */
621 	sdadc_module->INTFLAG.reg = int_flags;
622 }
623 
624 /**
625  * \brief Get a module sequence flag.
626  *
627  * Get the given status flag of the module.
628  *
629  * \param[in]   module_inst   Pointer to the SDADC software instance struct
630  * \param[out]  seq_state     Identifies the last conversion done in the sequence
631  *
632  * \return Status of the SDADC sequence conversion.
633  *
634  * \retval true  When the sequence start
635  * \retval false When the last conversion in a sequence is done
636  */
sdadc_get_sequence_status(struct sdadc_module * const module_inst,uint8_t * seq_state)637 static inline bool sdadc_get_sequence_status(
638 		struct sdadc_module *const module_inst,
639 		uint8_t* seq_state)
640 {
641 	/* Sanity check arguments */
642 	Assert(module_inst);
643 	Assert(module_inst->hw);
644 
645 	Sdadc *const sdadc_module = module_inst->hw;
646 
647 	/* Get SDADC result */
648 	*seq_state = sdadc_module->SEQSTATUS.reg & SDADC_SEQSTATUS_SEQSTATE_Msk;
649 
650 	return ((sdadc_module->SEQSTATUS.bit.SEQBUSY == 1) ? true : false);
651 }
652 /** @} */
653 
654 /**
655  * \name Enable, Disable, and Reset SDADC Module, Start Conversion and Read Result
656  * @{
657  */
658 
659 /**
660  * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
661  *
662  * Checks to see if the underlying hardware peripheral module(s) are currently
663  * synchronizing across multiple clock domains to the hardware bus. This
664  * function can be used to delay further operations on a module until such time
665  * that it is ready, to prevent blocking delays for synchronization in the
666  * user application.
667  *
668  * \param[in] module_inst  Pointer to the SDADC software instance struct
669  *
670  * \return Synchronization status of the underlying hardware module(s).
671  *
672  * \retval true  If the module synchronization is ongoing
673  * \retval false If the module has completed synchronization
674  */
sdadc_is_syncing(struct sdadc_module * const module_inst)675 static inline bool sdadc_is_syncing(
676 	struct sdadc_module *const module_inst)
677 {
678 	/* Sanity check arguments */
679 	Assert(module_inst);
680 
681 	Sdadc *const sdadc_module = module_inst->hw;
682 
683 	if (sdadc_module->SYNCBUSY.reg) {
684 		return true;
685 	}
686 
687 	return false;
688 }
689 
690 /**
691  * \brief Enables the SDADC module.
692  *
693  * Enables an SDADC module that has previously been configured. If any internal reference
694  * is selected it will be enabled.
695  *
696  * \param[in] module_inst  Pointer to the SDADC software instance struct
697  */
sdadc_enable(struct sdadc_module * const module_inst)698 static inline enum status_code sdadc_enable(
699 		struct sdadc_module *const module_inst)
700 {
701 	Assert(module_inst);
702 	Assert(module_inst->hw);
703 
704 	Sdadc *const sdadc_module = module_inst->hw;
705 
706 	while (sdadc_is_syncing(module_inst)) {
707 		/* Wait for synchronization */
708 	}
709 
710 #if SDADC_CALLBACK_MODE == true
711 	system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_SDADC);
712 #endif
713 
714 	sdadc_module->CTRLA.reg |= SDADC_CTRLA_ENABLE;
715 	return STATUS_OK;
716 }
717 
718 /**
719  * \brief Disables the SDADC module.
720  *
721  * Disables an SDADC module that was previously enabled.
722  *
723  * \param[in] module_inst Pointer to the SDADC software instance struct
724  */
sdadc_disable(struct sdadc_module * const module_inst)725 static inline enum status_code sdadc_disable(
726 		struct sdadc_module *const module_inst)
727 {
728 	Assert(module_inst);
729 	Assert(module_inst->hw);
730 
731 	Sdadc *const sdadc_module = module_inst->hw;
732 
733 #if SDADC_CALLBACK_MODE == true
734 	system_interrupt_disable(SYSTEM_INTERRUPT_MODULE_SDADC);
735 #endif
736 
737 	while (sdadc_is_syncing(module_inst)) {
738 		/* Wait for synchronization */
739 	}
740 
741 	/* Disbale interrupt */
742 	sdadc_module->INTENCLR.reg = SDADC_INTENCLR_MASK;
743 	/* Clear interrupt flag */
744 	sdadc_module->INTFLAG.reg = SDADC_INTFLAG_MASK;
745 
746 	sdadc_module->CTRLA.reg &= ~SDADC_CTRLA_ENABLE;
747 	return STATUS_OK;
748 }
749 
750 /**
751  * \brief Resets the SDADC module.
752  *
753  * Resets an SDADC module, clearing all module state, and registers to their
754  * default values.
755  *
756  * \param[in] module_inst  Pointer to the SDADC software instance struct
757  */
sdadc_reset(struct sdadc_module * const module_inst)758 static inline enum status_code sdadc_reset(
759 		struct sdadc_module *const module_inst)
760 {
761 	/* Sanity check arguments */
762 	Assert(module_inst);
763 	Assert(module_inst->hw);
764 
765 	Sdadc *const sdadc_module = module_inst->hw;
766 
767 	/* Disable to make sure the pipeline is flushed before reset */
768 	sdadc_disable(module_inst);
769 
770 	while (sdadc_is_syncing(module_inst)) {
771 		/* Wait for synchronization */
772 	}
773 
774 	/* Software reset the module */
775 	sdadc_module->CTRLA.reg |= SDADC_CTRLA_SWRST;
776 	return STATUS_OK;
777 }
778 
779 
780 /**
781  * \brief Enables an SDADC event input or output.
782  *
783  *  Enables one or more input or output events to or from the SDADC module. See
784  *  \ref sdadc_events for a list of events this module supports.
785  *
786  *  \note Events cannot be altered while the module is enabled.
787  *
788  *  \param[in] module_inst  Software instance for the SDADC peripheral
789  *  \param[in] events       Struct containing flags of events to enable
790  */
sdadc_enable_events(struct sdadc_module * const module_inst,struct sdadc_events * const events)791 static inline void sdadc_enable_events(
792 		struct sdadc_module *const module_inst,
793 		struct sdadc_events *const events)
794 {
795 	/* Sanity check arguments */
796 	Assert(module_inst);
797 	Assert(module_inst->hw);
798 	Assert(events);
799 
800 	Sdadc *const sdadc_module = module_inst->hw;
801 
802 	uint32_t event_mask = 0;
803 
804 	/* Configure Window Monitor event */
805 	if (events->generate_event_on_window_monitor) {
806 		event_mask |= SDADC_EVCTRL_WINMONEO;
807 	}
808 
809 	/* Configure Result Ready event */
810 	if (events->generate_event_on_conversion_done) {
811 		event_mask |= SDADC_EVCTRL_RESRDYEO;
812 	}
813 
814 	sdadc_module->EVCTRL.reg |= event_mask;
815 }
816 
817 /**
818  * \brief Disables an SDADC event input or output.
819  *
820  *  Disables one or more input or output events to or from the SDADC module. See
821  *  \ref sdadc_events for a list of events this module supports.
822  *
823  *  \note Events cannot be altered while the module is enabled.
824  *
825  *  \param[in] module_inst  Software instance for the SDADC peripheral
826  *  \param[in] events       Struct containing flags of events to disable
827  */
sdadc_disable_events(struct sdadc_module * const module_inst,struct sdadc_events * const events)828 static inline void sdadc_disable_events(
829 		struct sdadc_module *const module_inst,
830 		struct sdadc_events *const events)
831 {
832 	/* Sanity check arguments */
833 	Assert(module_inst);
834 	Assert(module_inst->hw);
835 	Assert(events);
836 
837 	Sdadc *const sdadc_module = module_inst->hw;
838 
839 	uint32_t event_mask = 0;
840 
841 	/* Configure Window Monitor event */
842 	if (events->generate_event_on_window_monitor) {
843 		event_mask |= SDADC_EVCTRL_WINMONEO;
844 	}
845 
846 	/* Configure Result Ready event */
847 	if (events->generate_event_on_conversion_done) {
848 		event_mask |= SDADC_EVCTRL_RESRDYEO;
849 	}
850 
851 	sdadc_module->EVCTRL.reg &= ~event_mask;
852 }
853 
854 /**
855  * \brief Starts an SDADC conversion.
856  *
857  * Starts a new SDADC conversion.
858  *
859  * \param[in] module_inst  Pointer to the SDADC software instance struct
860  */
sdadc_start_conversion(struct sdadc_module * const module_inst)861 static inline void sdadc_start_conversion(
862 		struct sdadc_module *const module_inst)
863 {
864 	Assert(module_inst);
865 	Assert(module_inst->hw);
866 
867 	Sdadc *const sdadc_module = module_inst->hw;
868 
869 	while (sdadc_is_syncing(module_inst)) {
870 		/* Wait for synchronization */
871 	}
872 
873 	sdadc_module->SWTRIG.reg |= SDADC_SWTRIG_START;
874 }
875 
876 /**
877  * \brief Reads the SDADC result.
878  *
879  * Reads the result from an SDADC conversion that was previously started.
880  *
881  * \param[in]  module_inst  Pointer to the SDADC software instance struct
882  * \param[out] result       Pointer to store the result value in
883  *
884  * \return Status of the SDADC read request.
885  * \retval STATUS_OK           The result was retrieved successfully
886  * \retval STATUS_BUSY         A conversion result was not ready
887  * \retval STATUS_ERR_OVERFLOW The result register has been overwritten by the
888  *                             SDADC module before the result was read by the software
889  */
sdadc_read(struct sdadc_module * const module_inst,int32_t * result)890 static inline enum status_code sdadc_read(
891 		struct sdadc_module *const module_inst,
892 		int32_t *result)
893 {
894 	Assert(module_inst);
895 	Assert(module_inst->hw);
896 	Assert(result);
897 
898 	if (!(sdadc_get_status(module_inst) & SDADC_STATUS_RESULT_READY)) {
899 		/* Result not ready */
900 		return STATUS_BUSY;
901 	}
902 
903 	Sdadc *const sdadc_module = module_inst->hw;
904 
905 	/* Get SDADC result */
906 	*result = ((int32_t)(sdadc_module->RESULT.reg << 8)) >> 8;
907 
908 	/* Reset ready flag */
909 	sdadc_clear_status(module_inst, SDADC_STATUS_RESULT_READY);
910 
911 	if (sdadc_get_status(module_inst) & SDADC_STATUS_OVERRUN) {
912 		sdadc_clear_status(module_inst, SDADC_STATUS_OVERRUN);
913 		return STATUS_ERR_OVERFLOW;
914 	}
915 
916 	return STATUS_OK;
917 }
918 
919 /** @} */
920 
921 /**
922  * \name Runtime Changes of SDADC Module
923  * @{
924  */
925 
926 /**
927  * \brief Flushes the SDADC pipeline.
928  *
929  * Flushes the pipeline and restart the SDADC clock on the next peripheral clock
930  * edge. All conversions in progress will be lost. When flush is complete, the
931  * module will resume where it left off.
932  *
933  * \param[in] module_inst  Pointer to the SDADC software instance struct
934  */
sdadc_flush(struct sdadc_module * const module_inst)935 static inline void sdadc_flush(
936 		struct sdadc_module *const module_inst)
937 {
938 	Assert(module_inst);
939 	Assert(module_inst->hw);
940 
941 	Sdadc *const sdadc_module = module_inst->hw;
942 
943 	while (sdadc_is_syncing(module_inst)) {
944 		/* Wait for synchronization */
945 	}
946 
947 	sdadc_module->SWTRIG.reg |= SDADC_SWTRIG_FLUSH;
948 }
949 
950 /**
951  * \brief Sets the SDADC window mode.
952  *
953  * Sets the SDADC window mode to a given mode and value range.
954  *
955  * \param[in] module_inst         Pointer to the SDADC software instance struct
956  * \param[in] window_mode         Window monitor mode to set
957  * \param[in] window_lower_value  Lower window monitor threshold value
958  * \param[in] window_upper_value  Upper window monitor threshold value
959   */
sdadc_set_window_mode(struct sdadc_module * const module_inst,const enum sdadc_window_mode window_mode,const int16_t window_lower_value,const int16_t window_upper_value)960 static inline void sdadc_set_window_mode(
961 		struct sdadc_module *const module_inst,
962 		const enum sdadc_window_mode window_mode,
963 		const int16_t window_lower_value,
964 		const int16_t window_upper_value)
965 {
966 	/* Sanity check arguments */
967 	Assert(module_inst);
968 	Assert(module_inst->hw);
969 
970 	Sdadc *const sdadc_module = module_inst->hw;
971 
972 	while (sdadc_is_syncing(module_inst)) {
973 		/* Wait for synchronization */
974 	}
975 
976 	/* Set window mode */
977 	sdadc_module->WINCTRL.reg = window_mode << SDADC_WINCTRL_WINMODE_Pos;
978 
979 	while (sdadc_is_syncing(module_inst)) {
980 		/* Wait for synchronization */
981 	}
982 
983 	/* Set lower window monitor threshold value */
984 	sdadc_module->WINLT.reg = window_lower_value << SDADC_WINLT_WINLT_Pos;
985 
986 	while (sdadc_is_syncing(module_inst)) {
987 		/* Wait for synchronization */
988 	}
989 
990 	/* Set upper window monitor threshold value */
991 	sdadc_module->WINUT.reg = window_upper_value << SDADC_WINUT_WINUT_Pos;
992 }
993 
994 /**
995  * \brief Sets MUX SDADC input pin.
996  *
997  * Sets the MUX SDADC input pin selection.
998  *
999  * \param[in] module_inst     Pointer to the SDADC software instance struct
1000  * \param[in] mux_input       MUX input pin
1001  */
sdadc_set_mux_input(struct sdadc_module * const module_inst,const enum sdadc_mux_input mux_input)1002 static inline void sdadc_set_mux_input(
1003 		struct sdadc_module *const module_inst,
1004 		const enum sdadc_mux_input mux_input)
1005 {
1006 	/* Sanity check arguments */
1007 	Assert(module_inst);
1008 	Assert(module_inst->hw);
1009 
1010 	Sdadc *const sdadc_module = module_inst->hw;
1011 
1012 	while (sdadc_is_syncing(module_inst)) {
1013 		/* Wait for synchronization */
1014 	}
1015 
1016 	/* Set mux input pin */
1017 	sdadc_module->INPUTCTRL.reg =
1018 			(sdadc_module->INPUTCTRL.reg & ~SDADC_INPUTCTRL_MUXSEL_Msk) | mux_input;
1019 }
1020 
1021 
1022 /** @} */
1023 
1024 #if SDADC_CALLBACK_MODE == true
1025 /**
1026  * \name Enable and Disable Interrupts
1027  * @{
1028  */
1029 
1030 /**
1031  * \brief Enable interrupt.
1032  *
1033  * Enable the given interrupt request from the SDADC module.
1034  *
1035  * \param[in] module_inst Pointer to the SDADC software instance struct
1036  * \param[in] interrupt Interrupt to enable
1037  */
sdadc_enable_interrupt(struct sdadc_module * const module_inst,enum sdadc_interrupt_flag interrupt)1038 static inline void sdadc_enable_interrupt(struct sdadc_module *const module_inst,
1039 		enum sdadc_interrupt_flag interrupt)
1040 {
1041 	/* Sanity check arguments */
1042 	Assert(module_inst);
1043 	Assert(module_inst->hw);
1044 
1045 	Sdadc *const sdadc_module = module_inst->hw;
1046 	/* Enable interrupt */
1047 	sdadc_module->INTENSET.reg = interrupt;
1048 }
1049 
1050 /**
1051  * \brief Disable interrupt.
1052  *
1053  * Disable the given interrupt request from the SDADC module.
1054  *
1055  * \param[in] module_inst Pointer to the SDADC software instance struct
1056  * \param[in] interrupt Interrupt to disable
1057  */
sdadc_disable_interrupt(struct sdadc_module * const module_inst,enum sdadc_interrupt_flag interrupt)1058 static inline void sdadc_disable_interrupt(struct sdadc_module *const module_inst,
1059 		enum sdadc_interrupt_flag interrupt)
1060 {
1061 	/* Sanity check arguments */
1062 	Assert(module_inst);
1063 	Assert(module_inst->hw);
1064 
1065 	Sdadc *const sdadc_module = module_inst->hw;
1066 	/* Enable interrupt */
1067 	sdadc_module->INTENCLR.reg = interrupt;
1068 }
1069 
1070 /** @} */
1071 #endif /* SDADC_CALLBACK_MODE == true */
1072 
1073 #ifdef __cplusplus
1074 }
1075 #endif
1076 
1077 /** @} */
1078 
1079 /**
1080  * \page asfdoc_sam0_sdadc_extra Extra Information for SDADC Driver
1081  *
1082  * \section asfdoc_sam0_sdadc_extra_acronyms Acronyms
1083  * Below is a table listing the acronyms used in this module, along with their
1084  * intended meanings.
1085  *
1086  * <table>
1087  *	<tr>
1088  *		<th>Acronym</th>
1089  *		<th>Description</th>
1090  *	</tr>
1091  *  <tr>
1092  *		<td>SDADC</td>
1093  *		<td>Sigma-Delta Analog-to-Digital Converter</td>
1094  *	</tr>
1095  *  <tr>
1096  *		<td>OSR</td>
1097  *		<td>Over Sampling Ratio</td>
1098  *	</tr>
1099  * </table>
1100  *
1101  *
1102  * \section asfdoc_sam0_sdadc_extra_dependencies Dependencies
1103  * This driver has no dependencies.
1104  *
1105  *
1106  * \section asfdoc_sam0_sdadc_extra_errata Errata
1107  * There are no errata related to this driver.
1108  *
1109  *
1110  * \section asfdoc_sam0_sdadc_extra_history Module History
1111  * An overview of the module history is presented in the table below, with
1112  * details on the enhancements and fixes made to the module since its first
1113  * release. The current version of this corresponds to the newest version in
1114  * the table.
1115  *
1116  * <table>
1117  *	<tr>
1118  *		<th>Changelog</th>
1119  *	</tr>
1120   *	<tr>
1121  *		<td>Initial Release</td>
1122  *	</tr>
1123  * </table>
1124  */
1125 
1126 /**
1127  * \page asfdoc_sam0_sdadc_exqsg Examples for SDADC Driver
1128  *
1129  * This is a list of the available Quick Start guides (QSGs) and example
1130  * applications for \ref asfdoc_sam0_sdadc_group. QSGs are simple examples with
1131  * step-by-step instructions to configure and use this driver in a selection of
1132  * use cases. Note that a QSG can be compiled as a standalone application or be
1133  * added to the user application.
1134  *
1135  *  - \subpage asfdoc_sam0_sdadc_basic_use_case
1136  * \if SDADC_CALLBACK_MODE
1137  *  - \subpage asfdoc_sam0_sdadc_basic_use_case_callback
1138  * \endif
1139  *
1140  * \page asfdoc_sam0_sdadc_document_revision_history Document Revision History
1141  *
1142  * <table>
1143  *	<tr>
1144  *		<th>Doc. Rev.</td>
1145  *		<th>Date</td>
1146  *		<th>Comments</td>
1147  *	</tr>
1148  *	<tr>
1149  *		<td>42496A</td>
1150  *		<td>09/2015</td>
1151  *		<td>Initial document release</td>
1152  *	</tr>
1153  * </table>
1154  */
1155 
1156 #endif /* SDADC_H_INCLUDED */
1157 
1158