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® | SMART ARM®-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