1 /**
2 * \file
3 *
4 * \brief SAM Analog Comparator Driver
5 *
6 * Copyright (c) 2012-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 #ifndef AC_H_INCLUDED
47 #define AC_H_INCLUDED
48
49 /**
50 * \defgroup asfdoc_sam0_ac_group SAM Analog Comparator (AC) Driver
51 *
52 * This driver for Atmel® | SMART ARM®-based microcontrollers
53 * provides an interface for the configuration
54 * and management of the device's Analog Comparator functionality, for the
55 * comparison of analog voltages against a known reference voltage to determine
56 * its relative level. The following driver API modes are covered by this
57 * manual:
58 * - Polled APIs
59 * \if AC_CALLBACK_MODE
60 * - Callback APIs
61 * \endif
62 *
63 * The following peripherals are used by this module:
64 * - AC (Analog Comparator)
65 *
66 * The following devices can use this module:
67 * - Atmel | SMART SAM D20/D21
68 * - Atmel | SMART SAM R21
69 * - Atmel | SMART SAM D10/D11
70 * - Atmel | SMART SAM L21/L22
71 * - Atmel | SMART SAM DA1
72 * - Atmel | SMART SAM C20/C21
73 * - Atmel | SMART SAM HA1
74 *
75 * The outline of this documentation is as follows:
76 * - \ref asfdoc_sam0_ac_prerequisites
77 * - \ref asfdoc_sam0_ac_module_overview
78 * - \ref asfdoc_sam0_ac_special_considerations
79 * - \ref asfdoc_sam0_ac_extra_info
80 * - \ref asfdoc_sam0_ac_examples
81 * - \ref asfdoc_sam0_ac_api_overview
82 *
83 *
84 * \section asfdoc_sam0_ac_prerequisites Prerequisites
85 *
86 * There are no prerequisites for this module.
87 *
88 *
89 * \section asfdoc_sam0_ac_module_overview Module Overview
90 *
91 * The Analog Comparator module provides an interface for the comparison of one
92 * or more analog voltage inputs (sourced from external or internal inputs)
93 * against a known reference voltage, to determine if the unknown voltage is
94 * higher or lower than the reference. Additionally, window functions are
95 * provided so that two comparators can be connected together to determine if
96 * an input is below, inside, above, or outside the two reference points of the
97 * window.
98 *
99 * Each comparator requires two analog input voltages, a positive and negative
100 * channel input. The result of the comparison is a binary \c true if the
101 * comparator's positive channel input is higher than the comparator's negative
102 * input channel, and \c false if otherwise.
103 *
104 *
105 * \subsection asfdoc_sam0_ac_module_features Driver Feature Macro Definition
106 * <table>
107 * <tr>
108 * <th>Driver Feature Macro</th>
109 * <th>Supported devices</th>
110 * </tr>
111 * <tr>
112 * <td>FEATURE_AC_HYSTERESIS_LEVEL</td>
113 * <td>SAM L21/L22/C20/C21</td>
114 * </tr>
115 * <tr>
116 * <td>FEATURE_AC_SYNCBUSY_SCHEME_VERSION_2</td>
117 * <td>SAM L21/L22/C20/C21</td>
118 * </tr>
119 * <tr>
120 * <td>FEATURE_AC_RUN_IN_STANDY_EACH_COMPARATOR</td>
121 * <td>SAM L21/L22/C20/C21</td>
122 * </tr>
123 * <tr>
124 * <td>FEATURE_AC_RUN_IN_STANDY_PAIR_COMPARATOR</td>
125 * <td>SAM D20/L22/D21/D10/D11/R21/DA1/HA1</td>
126 * </tr>
127 * </table>
128 * \note The specific features are only available in the driver when the
129 * selected device supports those features.
130 *
131 * \subsection asfdoc_sam0_ac_module_overview_pairs Window Comparators and Comparator Pairs
132 * Each comparator module contains one or more comparator pairs, a set of two
133 * distinct comparators which can be used independently or linked together for
134 * Window Comparator mode. In this latter mode, the two comparator units in a
135 * comparator pair are linked together to allow the module to detect if an input
136 * voltage is below, inside, above, or outside a window set by the upper and
137 * lower threshold voltages set by the two comparators. If not required, window
138 * comparison mode can be turned off and the two comparator units can be
139 * configured and used separately.
140 *
141 * \subsection asfdoc_sam0_ac_module_overview_pos_neg_mux Positive and Negative Input MUXes
142 * Each comparator unit requires two input voltages, a positive and a negative
143 * channel (note that these names refer to the logical operation that the unit
144 * performs, and both voltages should be above GND), which are then compared with
145 * one another. Both the positive and the negative channel inputs are connected to
146 * a pair of multiplexers (MUXes), which allows one of several possible inputs to be
147 * selected for each comparator channel.
148 *
149 * The exact channels available for each comparator differ for the positive and
150 * the negative inputs, but the same MUX choices are available for all comparator
151 * units (i.e. all positive MUXes are identical, all negative MUXes are
152 * identical). This allows the user application to select which voltages are
153 * compared to one another.
154 *
155 * When used in window mode, both comparators in the window pair should have
156 * their positive channel input MUXes configured to the same input channel, with
157 * the negative channel input MUXes used to set the lower and upper window
158 * bounds.
159 *
160 * \subsection asfdoc_sam0_ac_module_overview_output_filtering Output Filtering
161 * The output of each comparator unit can either be used directly with no
162 * filtering (giving a lower latency signal, with potentially more noise around
163 * the comparison threshold) or be passed through a multiple stage
164 * digital majority filter. Several filter lengths are available, with the
165 * longer stages producing a more stable result, at the expense of a higher
166 * latency.
167 *
168 * When output filtering is used in single shot mode, a single trigger of the
169 * comparator will automatically perform the required number of samples to
170 * produce a correctly filtered result.
171 *
172 * \subsection asfdoc_sam0_ac_module_overview_input_hysteresis Input Hysteresis
173 * To prevent unwanted noise around the threshold where the comparator unit's
174 * positive and negative input channels are close in voltage to one another, an
175 * optional hysteresis can be used to widen the point at which the output result
176 * flips. This mode will prevent a change in the comparison output unless the
177 * inputs cross one another beyond the hysteresis gap introduces by this mode.
178 *
179 * \subsection asfdoc_sam0_ac_module_overview_sampling Single Shot and Continuous Sampling Modes
180 * Comparators can be configured to run in either Single Shot or Continuous
181 * sampling modes; when in Single Shot mode, the comparator will only perform a
182 * comparison (and any resulting filtering, see
183 * \ref asfdoc_sam0_ac_module_overview_output_filtering) when triggered via a
184 * software or event trigger. This mode improves the power efficiency of the
185 * system by only performing comparisons when actually required by the
186 * application.
187 *
188 * For systems requiring a lower latency or more frequent comparisons,
189 * continuous mode will place the comparator into continuous sampling mode,
190 * which increases the module's power consumption, but decreases the latency
191 * between each comparison result by automatically performing a comparison on
192 * every cycle of the module's clock.
193 *
194 * \subsection asfdoc_sam0_ac_module_overview_events Events
195 * Each comparator unit is capable of being triggered by both software and
196 * hardware triggers. Hardware input events allow for other peripherals to
197 * automatically trigger a comparison on demand - for example, a timer output
198 * event could be used to trigger comparisons at a desired regular interval.
199 *
200 * The module's output events can similarly be used to trigger other hardware
201 * modules each time a new comparison result is available. This scheme allows
202 * for reduced levels of CPU usage in an application and lowers the overall
203 * system response latency by directly triggering hardware peripherals from one
204 * another without requiring software intervention.
205 *
206 * \note The connection of events between modules requires the use of the
207 * \ref asfdoc_sam0_events_group "SAM Event System Driver (EVENTS)"
208 * to route output event of one module to the input event of another.
209 * For more information on event routing, refer to the event driver
210 * documentation.
211 *
212 * \subsection asfdoc_sam0_ac_module_overview_physical Physical Connection
213 * Physically, the modules are interconnected within the device as shown in
214 * \ref asfdoc_sam0_ac_module_int_connections "the diagram below".
215 *
216 * \anchor asfdoc_sam0_ac_module_int_connections
217 * \dot
218 * digraph overview {
219 * rankdir = LR;
220 * splines = false;
221 *
222 * pos_src1_1 [label="GPIO Pins", shape=none, height=0];
223 * neg_src1_1 [label="GPIO Pins", shape=none, height=0];
224 * neg_src1_2 [label="Internal DAC", shape=none, height=0];
225 * neg_src1_3 [label="Internal Refs", shape=none, height=0];
226 * pos_src2_1 [label="GPIO Pins", shape=none, height=0];
227 * neg_src2_1 [label="GPIO Pins", shape=none, height=0];
228 * neg_src2_2 [label="Internal DAC", shape=none, height=0];
229 * neg_src2_3 [label="Internal Refs", shape=none, height=0];
230 * res_out1 [label="", style=invisible];
231 * res_out2 [label="", style=invisible];
232 * res_window [label="", style=invisible];
233 *
234 * mux_pos1 [label="", shape=polygon, sides=4, distortion=0.6, orientation=90, style=filled, fillcolor=black, height=0.9, width=0.2];
235 * mux_neg1 [label="", shape=polygon, sides=4, distortion=0.6, orientation=90, style=filled, fillcolor=black, height=0.9, width=0.2];
236 * mux_neg2 [label="", shape=polygon, sides=4, distortion=0.6, orientation=90, style=filled, fillcolor=black, height=0.9, width=0.2];
237 * mux_pos2 [label="", shape=polygon, sides=4, distortion=0.6, orientation=90, style=filled, fillcolor=black, height=0.9, width=0.2];
238 * ac1 [label="AC 1", shape=triangle, orientation=-90, style=filled, fillcolor=darkolivegreen1, height=1, width=1];
239 * ac2 [label="AC 2", shape=triangle, orientation=-90, style=filled, fillcolor=darkolivegreen1, height=1, width=1];
240 *
241 * window_comp [label="Window\nLogic", shape=rectangle style=filled fillcolor=lightgray];
242 *
243 * edge [dir="forward"];
244 *
245 * pos_src1_1:e -> mux_pos1:w;
246 * mux_pos1:e -> ac1:nw [label="+"];
247 * neg_src1_1:e -> mux_neg1:nw;
248 * neg_src1_2:e -> mux_neg1:w;
249 * neg_src1_3:e -> mux_neg1:sw;
250 * mux_neg1:e -> ac1:sw [label="-"];
251 * ac1:e -> res_out1 [label="Comparator 1 Result"];
252 *
253 * pos_src2_1:e -> mux_pos2:w;
254 * mux_pos2:e -> ac2:sw [label="+"];
255 * neg_src2_1:e -> mux_neg2:nw;
256 * neg_src2_2:e -> mux_neg2:w;
257 * neg_src2_3:e -> mux_neg2:sw;
258 * mux_neg2:e -> ac2:nw [label="-"];
259 * ac2:e -> res_out2 [label="Comparator 2 Result"];
260 *
261 * ac1:e -> window_comp:nw;
262 * ac2:e -> window_comp:sw;
263 * window_comp:e -> res_window:w [label="Window Result"];
264 *
265 * {rank=same; pos_src1_1 neg_src1_1 neg_src1_2 neg_src1_3 pos_src2_1 neg_src2_1 neg_src2_2 neg_src2_3 }
266 * {rank=same; mux_pos1 mux_neg1 mux_pos2 mux_neg2 }
267 * {rank=same; ac1 ac2 }
268 * {rank=same; res_out1 res_out2 res_window }
269 * }
270 * \enddot
271 *
272 *
273 * \section asfdoc_sam0_ac_special_considerations Special Considerations
274 *
275 * The number of comparator pairs (and, thus, window comparators) within a
276 * single hardware instance of the Analog Comparator module is device-specific.
277 * Some devices will contain a single comparator pair, while others may have two
278 * pairs; refer to your device specific datasheet for details.
279 *
280 *
281 * \section asfdoc_sam0_ac_extra_info Extra Information
282 *
283 * For extra information, see \ref asfdoc_sam0_ac_extra. This includes:
284 * - \ref asfdoc_sam0_ac_extra_acronyms
285 * - \ref asfdoc_sam0_ac_extra_dependencies
286 * - \ref asfdoc_sam0_ac_extra_errata
287 * - \ref asfdoc_sam0_ac_extra_history
288 *
289 *
290 * \section asfdoc_sam0_ac_examples Examples
291 *
292 * For a list of examples related to this driver, see
293 * \ref asfdoc_sam0_ac_exqsg.
294 *
295 *
296 * \section asfdoc_sam0_ac_api_overview API Overview
297 * @{
298 */
299
300 #include <compiler.h>
301 #include <clock.h>
302
303 #ifdef __cplusplus
304 extern "C" {
305 #endif
306
307 /**
308 * \name Driver Feature Definition
309 * Define AC driver feature set according to different device family.
310 * @{
311 */
312 #if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || (SAMR30) || defined(__DOXYGEN__)
313 /** Setting of hysteresis level */
314 # define FEATURE_AC_HYSTERESIS_LEVEL
315 /** SYNCBUSY scheme version 2 */
316 # define FEATURE_AC_SYNCBUSY_SCHEME_VERSION_2
317 #endif
318
319 #if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || (SAMR30) || defined(__DOXYGEN__)
320 /** Run in standby feature for each comparator */
321 # define FEATURE_AC_RUN_IN_STANDY_EACH_COMPARATOR
322 #else
323 /** Run in standby feature for comparator pair */
324 # define FEATURE_AC_RUN_IN_STANDY_PAIR_COMPARATOR
325 #endif
326 /* @} */
327
328 #if !defined(__DOXYGEN__)
329 /* Forward declaration of struct */
330 struct ac_module;
331
332 extern struct ac_module *_ac_instance[AC_INST_NUM];
333 #endif
334
335
336 /**
337 * \name AC Window Channel Status Flags
338 *
339 * AC window channel status flags, returned by \ref ac_win_get_status().
340 *
341 * @{
342 */
343
344 /** Unknown output state; the comparator window channel was not ready. */
345 #define AC_WIN_STATUS_UNKNOWN (1UL << 0)
346 /** Window Comparator's input voltage is above the window */
347 #define AC_WIN_STATUS_ABOVE (1UL << 1)
348 /** Window Comparator's input voltage is inside the window */
349 #define AC_WIN_STATUS_INSIDE (1UL << 2)
350 /** Window Comparator's input voltage is below the window */
351 #define AC_WIN_STATUS_BELOW (1UL << 3)
352 /**
353 * This state reflects the window interrupt flag. When the interrupt flag
354 * should be set is configured in \ref ac_win_set_config(). This state needs
355 * to be cleared by the of \ref ac_win_clear_status().
356 */
357 #define AC_WIN_STATUS_INTERRUPT_SET (1UL << 4)
358 /** @} */
359
360 /**
361 * \name AC Channel Status Flags
362 *
363 * AC channel status flags, returned by \ref ac_chan_get_status().
364 *
365 * @{
366 */
367
368 /** Unknown output state; the comparator channel was not ready. */
369 #define AC_CHAN_STATUS_UNKNOWN (1UL << 0)
370 /** Comparator's negative input pin is higher in voltage than the positive
371 * input pin. */
372 #define AC_CHAN_STATUS_NEG_ABOVE_POS (1UL << 1)
373 /** Comparator's positive input pin is higher in voltage than the negative
374 * input pin. */
375 #define AC_CHAN_STATUS_POS_ABOVE_NEG (1UL << 2)
376 /**
377 * This state reflects the channel interrupt flag. When the interrupt flag
378 * should be set is configured in ac_chan_set_config(). This state needs
379 * to be cleared by the of ac_chan_clear_status().
380 */
381 #define AC_CHAN_STATUS_INTERRUPT_SET (1UL << 3)
382 /** @} */
383
384 /** Type definition for a AC module callback function. */
385 typedef void (*ac_callback_t)(struct ac_module *const module_inst);
386
387 /** Enum for possible callback types for the AC module. */
388 enum ac_callback {
389 /** Callback for comparator 0 */
390 AC_CALLBACK_COMPARATOR_0 = 0,
391 /** Callback for comparator 1 */
392 AC_CALLBACK_COMPARATOR_1 = 1,
393 /** Callback for window 0 */
394 AC_CALLBACK_WINDOW_0 = 4,
395 #if (AC_NUM_CMP > 2)
396 /** Callback for comparator 2 */
397 AC_CALLBACK_COMPARATOR_2 = 2,
398 /** Callback for comparator 3 */
399 AC_CALLBACK_COMPARATOR_3 = 3,
400 /** Callback for window 1 */
401 AC_CALLBACK_WINDOW_1 = 5,
402 /** Number of available callbacks */
403 #endif /* (AC_NUM_CMP == 2) */
404 #if !defined(__DOXYGEN__)
405 AC_CALLBACK_N,
406 #endif /* !defined(__DOXYGEN__) */
407 };
408
409 #ifdef FEATURE_AC_HYSTERESIS_LEVEL
410 /** Enum for possible hysteresis level types for AC module. */
411 enum ac_hysteresis_level {
412 /** Hysteresis level of 50mV */
413 AC_HYSTERESIS_LEVEL_50 = 0,
414 /** Hysteresis level of 70mV */
415 AC_HYSTERESIS_LEVEL_70,
416 /** Hysteresis level of 90mV */
417 AC_HYSTERESIS_LEVEL_90,
418 /** Hysteresis level of 110mV */
419 AC_HYSTERESIS_LEVEL_110
420 };
421 #endif
422
423 /**
424 * \brief AC comparator channel selection enum.
425 *
426 * Enum for the possible comparator channels.
427 */
428 enum ac_chan_channel {
429 /** Comparator channel 0 (Pair 0, Comparator 0) */
430 AC_CHAN_CHANNEL_0 = 0,
431 /** Comparator channel 1 (Pair 0, Comparator 1) */
432 AC_CHAN_CHANNEL_1 = 1,
433 #if defined(__DOXYGEN__) || (AC_NUM_CMP > 2)
434 /** Comparator channel 2 (Pair 1, Comparator 0) */
435 AC_CHAN_CHANNEL_2 = 2,
436 /** Comparator channel 3 (Pair 1, Comparator 1) */
437 AC_CHAN_CHANNEL_3 = 3,
438 #endif
439 };
440
441 /**
442 * \brief AC channel input sampling mode configuration enum.
443 *
444 * Enum for the possible channel sampling modes of an Analog Comparator channel.
445 */
446 enum ac_chan_sample_mode {
447 /** Continuous sampling mode; when the channel is enabled the comparator
448 * output is available for reading at any time */
449 AC_CHAN_MODE_CONTINUOUS = 0,
450 /** Single shot mode; when used the comparator channel must be triggered to
451 * perform a comparison before reading the result */
452 AC_CHAN_MODE_SINGLE_SHOT = AC_COMPCTRL_SINGLE,
453 };
454
455 /**
456 * \brief AC channel positive comparator pin input configuration enum.
457 *
458 * Enum for the possible channel positive pin input of an Analog Comparator
459 * channel.
460 */
461 enum ac_chan_pos_mux {
462 /** Positive comparator input is connected to physical AC input pin 0 */
463 AC_CHAN_POS_MUX_PIN0 = AC_COMPCTRL_MUXPOS_PIN0,
464 /** Positive comparator input is connected to physical AC input pin 1 */
465 AC_CHAN_POS_MUX_PIN1 = AC_COMPCTRL_MUXPOS_PIN1,
466 /** Positive comparator input is connected to physical AC input pin 2 */
467 AC_CHAN_POS_MUX_PIN2 = AC_COMPCTRL_MUXPOS_PIN2,
468 /** Positive comparator input is connected to physical AC input pin 3 */
469 AC_CHAN_POS_MUX_PIN3 = AC_COMPCTRL_MUXPOS_PIN3,
470 };
471
472 /**
473 * \brief AC channel negative comparator pin input configuration enum.
474 *
475 * Enum for the possible channel negative pin input of an Analog Comparator
476 * channel.
477 */
478 enum ac_chan_neg_mux {
479 /** Negative comparator input is connected to physical AC input pin 0 */
480 AC_CHAN_NEG_MUX_PIN0 = AC_COMPCTRL_MUXNEG_PIN0,
481 /** Negative comparator input is connected to physical AC input pin 1 */
482 AC_CHAN_NEG_MUX_PIN1 = AC_COMPCTRL_MUXNEG_PIN1,
483 /** Negative comparator input is connected to physical AC input pin 2 */
484 AC_CHAN_NEG_MUX_PIN2 = AC_COMPCTRL_MUXNEG_PIN2,
485 /** Negative comparator input is connected to physical AC input pin 3 */
486 AC_CHAN_NEG_MUX_PIN3 = AC_COMPCTRL_MUXNEG_PIN3,
487 /** Negative comparator input is connected to the internal ground plane */
488 AC_CHAN_NEG_MUX_GND = AC_COMPCTRL_MUXNEG_GND,
489 /** Negative comparator input is connected to the channel's internal V<SUB>CC</SUB>
490 * plane voltage scalar */
491 AC_CHAN_NEG_MUX_SCALED_VCC = AC_COMPCTRL_MUXNEG_VSCALE,
492 /** Negative comparator input is connected to the internal band gap voltage
493 * reference */
494 AC_CHAN_NEG_MUX_BANDGAP = AC_COMPCTRL_MUXNEG_BANDGAP,
495 #if !(SAML22)
496 /**
497 * For SAM D20/D21/D10/D11/R21/DA1/HA1:
498 * Negative comparator input is connected to the channel's internal DAC
499 * channel 0 output.
500 * For SAM L21/C20/C21:
501 * Negative comparator input is connected to the channel's internal DAC
502 * channel 0 output for Comparator 0 or OPAMP output for Comparator 1.
503 */
504 AC_CHAN_NEG_MUX_DAC0 = AC_COMPCTRL_MUXNEG_DAC,
505 #endif
506 };
507
508 /**
509 * \brief AC channel output filtering configuration enum.
510 *
511 * Enum for the possible channel output filtering configurations of an Analog
512 * Comparator channel.
513 */
514 enum ac_chan_filter {
515 /** No output filtering is performed on the comparator channel */
516 AC_CHAN_FILTER_NONE = AC_COMPCTRL_FLEN_OFF,
517 /** Comparator channel output is passed through a Majority-of-Three
518 * filter */
519 AC_CHAN_FILTER_MAJORITY_3 = AC_COMPCTRL_FLEN_MAJ3,
520 /** Comparator channel output is passed through a Majority-of-Five
521 * filter */
522 AC_CHAN_FILTER_MAJORITY_5 = AC_COMPCTRL_FLEN_MAJ5,
523 };
524
525 /**
526 * \brief AC channel GPIO output routing configuration enum.
527 *
528 * Enum for the possible channel GPIO output routing configurations of an Analog
529 * Comparator channel.
530 */
531 enum ac_chan_output {
532 /** Comparator channel output is not routed to a physical GPIO pin, and is
533 * used internally only */
534 AC_CHAN_OUTPUT_INTERNAL = AC_COMPCTRL_OUT_OFF,
535 /** Comparator channel output is routed to its matching physical GPIO pin,
536 * via an asynchronous path */
537 AC_CHAN_OUTPUT_ASYNCRONOUS = AC_COMPCTRL_OUT_ASYNC,
538 /** Comparator channel output is routed to its matching physical GPIO pin,
539 * via a synchronous path */
540 AC_CHAN_OUTPUT_SYNCHRONOUS = AC_COMPCTRL_OUT_SYNC,
541 };
542
543 /**
544 * \brief AC window channel selection enum.
545 *
546 * Enum for the possible window comparator channels.
547 */
548 enum ac_win_channel {
549 /** Window channel 0 (Pair 0, Comparators 0 and 1) */
550 AC_WIN_CHANNEL_0 = 0,
551 #if defined(__DOXYGEN__) || (AC_PAIRS > 1)
552 /** Window channel 1 (Pair 1, Comparators 2 and 3) */
553 AC_WIN_CHANNEL_1 = 1,
554 #endif
555 };
556
557 /**
558 * \brief Channel interrupt selection enum.
559 *
560 * This enum is used to select when a channel interrupt should occur.
561 */
562 enum ac_chan_interrupt_selection {
563 /** An interrupt will be generated when the comparator level is passed */
564 AC_CHAN_INTERRUPT_SELECTION_TOGGLE = AC_COMPCTRL_INTSEL_TOGGLE,
565 /** An interrupt will be generated when the measurement goes above the
566 * compare level
567 */
568 AC_CHAN_INTERRUPT_SELECTION_RISING = AC_COMPCTRL_INTSEL_RISING,
569 /** An interrupt will be generated when the measurement goes below the
570 * compare level
571 */
572 AC_CHAN_INTERRUPT_SELECTION_FALLING = AC_COMPCTRL_INTSEL_FALLING,
573 /**
574 * An interrupt will be generated when a new measurement is complete.
575 * Interrupts will only be generated in single shot mode. This state needs
576 * to be cleared by the use of ac_chan_cleare_status()
577 */
578 AC_CHAN_INTERRUPT_SELECTION_END_OF_COMPARE = AC_COMPCTRL_INTSEL_EOC,
579 };
580
581 /**
582 * \brief Window interrupt selection enum.
583 *
584 * This enum is used to select when a window interrupt should occur.
585 */
586 enum ac_win_interrupt_selection {
587 /** Interrupt is generated when the compare value goes above the window */
588 AC_WIN_INTERRUPT_SELECTION_ABOVE = AC_WINCTRL_WINTSEL0_ABOVE,
589 /** Interrupt is generated when the compare value goes inside the window */
590 AC_WIN_INTERRUPT_SELECTION_INSIDE = AC_WINCTRL_WINTSEL0_INSIDE,
591 /** Interrupt is generated when the compare value goes below the window */
592 AC_WIN_INTERRUPT_SELECTION_BELOW = AC_WINCTRL_WINTSEL0_BELOW,
593 /** Interrupt is generated when the compare value goes outside the window */
594 AC_WIN_INTERRUPT_SELECTION_OUTSIDE = AC_WINCTRL_WINTSEL0_OUTSIDE,
595 };
596
597 /**
598 * \brief AC software device instance structure.
599 *
600 * AC software instance structure, used to retain software state information
601 * of an associated hardware module instance.
602 *
603 * \note The fields of this structure should not be altered by the user
604 * application; they are reserved for module-internal use only.
605 */
606 struct ac_module {
607 #if !defined(__DOXYGEN__)
608 /** Hardware module pointer of the associated Analog Comparator peripheral. */
609 Ac *hw;
610 # if AC_CALLBACK_MODE == true
611 /** Array of callbacks */
612 ac_callback_t callback[AC_CALLBACK_N];
613 /** Bit mask for callbacks registered */
614 uint8_t register_callback_mask;
615 /** Bit mask for callbacks enabled */
616 uint8_t enable_callback_mask;
617 # endif
618 #endif
619 };
620
621 /**
622 * \brief AC event enable/disable structure.
623 *
624 * Event flags for the Analog Comparator module. This is used to enable and
625 * disable events via \ref ac_enable_events() and \ref ac_disable_events().
626 */
627 struct ac_events {
628 /** If \c true, an event will be generated when a comparator window state
629 * changes */
630 bool generate_event_on_window[AC_PAIRS];
631
632 /** If \c true, an event will be generated when a comparator state
633 * changes */
634 bool generate_event_on_state[AC_NUM_CMP];
635
636 /** If \c true, a comparator will be sampled each time an event is
637 * received */
638 bool on_event_sample[AC_NUM_CMP];
639 };
640
641 /**
642 * \brief Analog Comparator module configuration structure.
643 *
644 * Configuration structure for a comparator channel, to configure the input and
645 * output settings of the comparator.
646 */
647 struct ac_config {
648 #ifdef FEATURE_AC_RUN_IN_STANDY_PAIR_COMPARATOR
649 /** If \c true, the comparator pairs will continue to sample during sleep
650 * mode when triggered */
651 bool run_in_standby[AC_PAIRS];
652 #endif
653
654 #if (SAMD) || (SAMHA1) || (SAMR21)
655 /** Digital source generator for AC GCLK */
656 enum gclk_generator dig_source_generator;
657 /** Analog source generator for AC GCLK */
658 enum gclk_generator ana_source_generator;
659 #else
660 /** Source generator for AC GCLK */
661 enum gclk_generator source_generator;
662 #endif
663 };
664
665 /**
666 * \brief Analog Comparator Comparator channel configuration structure.
667 *
668 * Configuration structure for a comparator channel, to configure the input and
669 * output settings of the comparator.
670 */
671 struct ac_chan_config {
672 /** Sampling mode of the comparator channel */
673 enum ac_chan_sample_mode sample_mode;
674 /** Filtering mode for the comparator output, when the comparator is used
675 * in a supported mode */
676 enum ac_chan_filter filter;
677 /** When \c true, hysteresis mode is enabled on the comparator inputs */
678 bool enable_hysteresis;
679 #ifdef FEATURE_AC_RUN_IN_STANDY_EACH_COMPARATOR
680 /** If \c true, the comparator will continue to sample during sleep
681 * mode when triggered */
682 bool run_in_standby;
683 #endif
684 #ifdef FEATURE_AC_HYSTERESIS_LEVEL
685 /** Hysteresis level of the comparator channel */
686 enum ac_hysteresis_level hysteresis_level;
687 #endif
688 /** Output mode of the comparator, whether it should be available for
689 * internal use, or asynchronously/synchronously linked to a
690 * general-purpose input/output (GPIO) pin */
691 enum ac_chan_output output_mode;
692 /** Input multiplexer selection for the comparator's positive input pin */
693 enum ac_chan_pos_mux positive_input;
694 /** Input multiplexer selection for the comparator's negative input pin.
695 * Any internal reference source, such as a bandgap reference voltage or
696 * the DAC, must be configured and enabled prior to its use as a
697 * comparator input.*/
698 enum ac_chan_neg_mux negative_input;
699 /** Scaled VCC voltage division factor for the channel, when a comparator
700 * pin is connected to the V<SUB>CC</SUB> voltage scalar input. The formular is:
701 * Vscale = Vdd * vcc_scale_factor / 64.
702 * If the V<SUB>CC</SUB> voltage scalar is not selected as a comparator
703 * channel pin's input, this value will be ignored. */
704 uint8_t vcc_scale_factor;
705 /** Interrupt criteria for the comparator channel, to select the condition
706 * that will trigger a callback */
707 enum ac_chan_interrupt_selection interrupt_selection;
708 };
709
710 /**
711 * \brief Analog Comparator Window configuration structure.
712 */
713 struct ac_win_config {
714 /** Interrupt criteria for the comparator window channel, to select the
715 * condition that will trigger a callback */
716 enum ac_win_interrupt_selection interrupt_selection;
717 };
718
719 /**
720 * \name Configuration and Initialization
721 * @{
722 */
723
724 enum status_code ac_reset(
725 struct ac_module *const module_inst);
726
727 enum status_code ac_init(
728 struct ac_module *const module_inst,
729 Ac *const hw,
730 struct ac_config *const config);
731
732 #if (AC_INST_NUM > 1) && !defined(__DOXYGEN__)
733 /**
734 * \internal Find the index of given AC module instance.
735 *
736 * \param[in] AC module instance pointer.
737 *
738 * \return Index of the given AC module instance.
739 */
_ac_get_inst_index(Ac * const hw)740 static uint8_t _ac_get_inst_index(
741 Ac *const hw)
742 {
743 /* List of available AC modules. */
744 static Ac *const ac_modules[AC_INST_NUM] = AC_INSTS;
745
746 /* Find index for AC instance. */
747 for (uint32_t i = 0; i < AC_INST_NUM; i++) {
748 if (hw == ac_modules[i]) {
749 return i;
750 }
751 }
752
753 /* Invalid data given. */
754 Assert(false);
755 return 0;
756 }
757 #endif /* (AC_INST_NUM > 1) && !defined(__DOXYGEN__) */
758
759 /**
760 * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
761 *
762 * Checks to see if the underlying hardware peripheral module(s) are currently
763 * synchronizing across multiple clock domains to the hardware bus. This
764 * function can be used to delay further operations on a module until such time
765 * that it is ready, to prevent blocking delays for synchronization in the
766 * user application.
767 *
768 * \param[in] module_inst Pointer to the AC software instance struct
769 *
770 * \return Synchronization status of the underlying hardware module(s).
771 *
772 * \retval false If the module has completed synchronization
773 * \retval ture If the module synchronization is ongoing
774 */
ac_is_syncing(struct ac_module * const module_inst)775 static inline bool ac_is_syncing(
776 struct ac_module *const module_inst)
777 {
778 /* Sanity check arguments */
779 Assert(module_inst);
780
781 Ac *const ac_module = module_inst->hw;
782
783 #ifdef FEATURE_AC_SYNCBUSY_SCHEME_VERSION_2
784 if (ac_module->SYNCBUSY.reg & AC_SYNCBUSY_MASK) {
785 return true;
786 }
787
788 return false;
789 #else
790 if (ac_module->STATUSB.reg & AC_STATUSB_SYNCBUSY) {
791 return true;
792 }
793
794 return false;
795 #endif
796 }
797
798 /**
799 * \brief Initializes all members of an Analog Comparator configuration
800 * structure to safe defaults.
801 *
802 * Initializes all members of a given Analog Comparator configuration
803 * structure to safe known default values. This function should be called on
804 * all new instances of these configuration structures before being modified
805 * by the user application.
806 *
807 * The default configuration is as follows:
808 * \li All comparator pairs disabled during sleep mode (if has this feature)
809 * \li Generator 0 is the default GCLK generator
810 *
811 * \param[out] config Configuration structure to initialize to default values
812 */
ac_get_config_defaults(struct ac_config * const config)813 static inline void ac_get_config_defaults(
814 struct ac_config *const config)
815 {
816 /* Sanity check arguments */
817 Assert(config);
818 #ifdef FEATURE_AC_RUN_IN_STANDY_PAIR_COMPARATOR
819 /* Default configuration values */
820 for (uint32_t i = 0; i < AC_PAIRS; i++) {
821 config->run_in_standby[i] = false;
822 }
823 #endif
824 #if (SAMD) || (SAMHA1) || (SAMR21)
825 config->dig_source_generator = GCLK_GENERATOR_0;
826 config->ana_source_generator = GCLK_GENERATOR_3;
827 #else
828 config->source_generator = GCLK_GENERATOR_0;
829 #endif
830 }
831
832 /**
833 * \brief Enables an Analog Comparator that was previously configured.
834 *
835 * Enables an Analog Comparator that was previously configured via a
836 * call to \ref ac_init().
837 *
838 * \param[in] module_inst Software instance for the Analog Comparator peripheral
839 */
ac_enable(struct ac_module * const module_inst)840 static inline void ac_enable(
841 struct ac_module *const module_inst)
842 {
843 /* Sanity check arguments */
844 Assert(module_inst);
845 Assert(module_inst->hw);
846
847 Ac *const ac_module = module_inst->hw;
848
849 while (ac_is_syncing(module_inst)) {
850 /* Wait until synchronization is complete */
851 }
852
853 /* Write the new comparator module control configuration */
854 ac_module->CTRLA.reg |= AC_CTRLA_ENABLE;
855 }
856
857 /**
858 * \brief Disables an Analog Comparator that was previously enabled.
859 *
860 * Disables an Analog Comparator that was previously started via a call to
861 * \ref ac_enable().
862 *
863 * \param[in] module_inst Software instance for the Analog Comparator peripheral
864 */
ac_disable(struct ac_module * const module_inst)865 static inline void ac_disable(
866 struct ac_module *const module_inst)
867 {
868 /* Sanity check arguments */
869 Assert(module_inst);
870 Assert(module_inst->hw);
871
872 Ac *const ac_module = module_inst->hw;
873
874 while (ac_is_syncing(module_inst)) {
875 /* Wait until synchronization is complete */
876 }
877
878 /* Disbale interrupt */
879 ac_module->INTENCLR.reg = AC_INTENCLR_MASK;
880 /* Clear interrupt flag */
881 ac_module->INTFLAG.reg = AC_INTFLAG_MASK;
882
883 /* Write the new comparator module control configuration */
884 ac_module->CTRLA.reg &= ~AC_CTRLA_ENABLE;
885 }
886
887 /**
888 * \brief Enables an Analog Comparator event input or output.
889 *
890 * Enables one or more input or output events to or from the Analog Comparator
891 * module. See \ref ac_events for a list of events this module
892 * supports.
893 *
894 * \note Events cannot be altered while the module is enabled.
895 *
896 * \param[in] module_inst Software instance for the Analog Comparator peripheral
897 * \param[in] events Struct containing flags of events to enable
898 */
ac_enable_events(struct ac_module * const module_inst,struct ac_events * const events)899 static inline void ac_enable_events(
900 struct ac_module *const module_inst,
901 struct ac_events *const events)
902 {
903 /* Sanity check arguments */
904 Assert(module_inst);
905 Assert(module_inst->hw);
906 Assert(events);
907
908 Ac *const ac_module = module_inst->hw;
909
910 uint32_t event_mask = 0;
911
912 /* Configure window output events for each comparator pair */
913 for (uint8_t i = 0; i < AC_PAIRS; i++) {
914 if (events->generate_event_on_window[i] == true) {
915 event_mask |= (AC_EVCTRL_WINEO0 << i);
916 }
917 }
918
919 /* Configure sample input/output events for each comparator */
920 for (uint8_t i = 0; i < AC_NUM_CMP; i++) {
921 if (events->on_event_sample[i] == true) {
922 event_mask |= (AC_EVCTRL_COMPEI0 << i);
923 }
924
925 if (events->generate_event_on_state[i] == true) {
926 event_mask |= (AC_EVCTRL_COMPEO0 << i);
927 }
928 }
929
930 ac_module->EVCTRL.reg |= event_mask;
931 }
932
933 /**
934 * \brief Disables an Analog Comparator event input or output.
935 *
936 * Disables one or more input or output events to or from the Analog Comparator
937 * module. See \ref ac_events for a list of events this module
938 * supports.
939 *
940 * \note Events cannot be altered while the module is enabled.
941 *
942 * \param[in] module_inst Software instance for the Analog Comparator peripheral
943 * \param[in] events Struct containing flags of events to disable
944 */
ac_disable_events(struct ac_module * const module_inst,struct ac_events * const events)945 static inline void ac_disable_events(
946 struct ac_module *const module_inst,
947 struct ac_events *const events)
948 {
949 /* Sanity check arguments */
950 Assert(module_inst);
951 Assert(module_inst->hw);
952 Assert(events);
953
954 Ac *const ac_module = module_inst->hw;
955
956 uint32_t event_mask = 0;
957
958 /* Configure window output events for each comparator pair */
959 for (uint8_t i = 0; i < AC_PAIRS; i++) {
960 if (events->generate_event_on_window[i] == true) {
961 event_mask |= (AC_EVCTRL_WINEO0 << i);
962 }
963 }
964
965 /* Configure sample input/output events for each comparator */
966 for (uint8_t i = 0; i < AC_NUM_CMP; i++) {
967 if (events->on_event_sample[i] == true) {
968 event_mask |= (AC_EVCTRL_COMPEI0 << i);
969 }
970
971 if (events->generate_event_on_state[i] == true) {
972 event_mask |= (AC_EVCTRL_COMPEO0 << i);
973 }
974 }
975
976 ac_module->EVCTRL.reg &= ~event_mask;
977 }
978
979 /** @} */
980
981
982 /**
983 * \name Channel Configuration and Initialization
984 * @{
985 */
986
987 /**
988 * \brief Initializes all members of an Analog Comparator channel configuration
989 * structure to safe defaults.
990 *
991 * Initializes all members of an Analog Comparator channel configuration
992 * structure to safe defaults. This function should be called on all new
993 * instances of these configuration structures before being modified by the
994 * user application.
995 *
996 * The default configuration is as follows:
997 * \li Continuous sampling mode
998 * \li Majority of five sample output filter
999 * \li Comparator disabled during sleep mode (if has this feature)
1000 * \li Hysteresis enabled on the input pins
1001 * \li Hysteresis level of 50mV if having this feature
1002 * \li Internal comparator output mode
1003 * \li Comparator pin multiplexer 0 selected as the positive input
1004 * \li Scaled V<SUB>CC</SUB> voltage selected as the negative input
1005 * \li V<SUB>CC</SUB> voltage scaler set for a division factor of two
1006 * \li Channel interrupt set to occur when the compare threshold is passed
1007 *
1008 * \param[out] config Channel configuration structure to initialize to
1009 * default values
1010 */
ac_chan_get_config_defaults(struct ac_chan_config * const config)1011 static inline void ac_chan_get_config_defaults(
1012 struct ac_chan_config *const config)
1013 {
1014 /* Sanity check arguments */
1015 Assert(config);
1016
1017 /* Default configuration values */
1018 config->sample_mode = AC_CHAN_MODE_CONTINUOUS;
1019 config->filter = AC_CHAN_FILTER_MAJORITY_5;
1020 config->enable_hysteresis = true;
1021 #ifdef FEATURE_AC_RUN_IN_STANDY_EACH_COMPARATOR
1022 config->run_in_standby = false;
1023 #endif
1024 #ifdef FEATURE_AC_HYSTERESIS_LEVEL
1025 config->hysteresis_level = AC_HYSTERESIS_LEVEL_50;
1026 #endif
1027 config->output_mode = AC_CHAN_OUTPUT_INTERNAL;
1028 config->positive_input = AC_CHAN_POS_MUX_PIN0;
1029 config->negative_input = AC_CHAN_NEG_MUX_SCALED_VCC;
1030 config->vcc_scale_factor = 32;
1031 config->interrupt_selection = AC_CHAN_INTERRUPT_SELECTION_TOGGLE;
1032 }
1033
1034 enum status_code ac_chan_set_config(
1035 struct ac_module *const module_inst,
1036 const enum ac_chan_channel channel,
1037 struct ac_chan_config *const config);
1038
1039 /**
1040 * \brief Enables an Analog Comparator channel that was previously configured.
1041 *
1042 * Enables an Analog Comparator channel that was previously
1043 * configured via a call to \ref ac_chan_set_config().
1044 *
1045 * \param[in] module_inst Software instance for the Analog Comparator peripheral
1046 * \param[in] channel Comparator channel to enable
1047 */
ac_chan_enable(struct ac_module * const module_inst,const enum ac_chan_channel channel)1048 static inline void ac_chan_enable(
1049 struct ac_module *const module_inst,
1050 const enum ac_chan_channel channel)
1051 {
1052 /* Sanity check arguments */
1053 Assert(module_inst);
1054 Assert(module_inst->hw);
1055
1056 Ac *const ac_module = module_inst->hw;
1057
1058 while (ac_is_syncing(module_inst)) {
1059 /* Wait until synchronization is complete */
1060 }
1061
1062 /* Write the new comparator module control configuration */
1063 ac_module->COMPCTRL[(uint8_t)channel].reg |= AC_COMPCTRL_ENABLE;
1064 }
1065
1066 /**
1067 * \brief Disables an Analog Comparator channel that was previously enabled.
1068 *
1069 * Stops an Analog Comparator channel that was previously started via a call to
1070 * \ref ac_chan_enable().
1071 *
1072 * \param[in] module_inst Software instance for the Analog Comparator peripheral
1073 * \param[in] channel Comparator channel to disable
1074 */
ac_chan_disable(struct ac_module * const module_inst,const enum ac_chan_channel channel)1075 static inline void ac_chan_disable(
1076 struct ac_module *const module_inst,
1077 const enum ac_chan_channel channel)
1078 {
1079 /* Sanity check arguments */
1080 Assert(module_inst);
1081 Assert(module_inst->hw);
1082
1083 Ac *const ac_module = module_inst->hw;
1084
1085 while (ac_is_syncing(module_inst)) {
1086 /* Wait until synchronization is complete */
1087 }
1088
1089 /* Write the new comparator module control configuration */
1090 ac_module->COMPCTRL[(uint8_t)channel].reg &= ~AC_COMPCTRL_ENABLE;
1091 }
1092
1093 /** @} */
1094
1095
1096 /**
1097 * \name Channel Control
1098 * @{
1099 */
1100
1101 /**
1102 * \brief Triggers a comparison on a comparator that is configured in single shot mode.
1103 *
1104 * Triggers a single conversion on a comparator configured to compare on demand
1105 * (single shot mode) rather than continuously.
1106 *
1107 * \param[in] module_inst Software instance for the Analog Comparator peripheral
1108 * \param[in] channel Comparator channel to trigger
1109 */
ac_chan_trigger_single_shot(struct ac_module * const module_inst,const enum ac_chan_channel channel)1110 static inline void ac_chan_trigger_single_shot(
1111 struct ac_module *const module_inst,
1112 const enum ac_chan_channel channel)
1113 {
1114 /* Sanity check arguments */
1115 Assert(module_inst);
1116 Assert(module_inst->hw);
1117
1118 Ac *const ac_module = module_inst->hw;
1119
1120 /* Write the new comparator module control configuration */
1121 ac_module->CTRLB.reg |= (AC_CTRLB_START0 << (uint8_t)channel);
1122 }
1123
1124 /**
1125 * \brief Determines if a given comparator channel is ready for comparisons.
1126 *
1127 * Checks a comparator channel to see if the comparator is currently ready to
1128 * begin comparisons.
1129 *
1130 * \param[in] module_inst Software instance for the Analog Comparator peripheral
1131 * \param[in] channel Comparator channel to test
1132 *
1133 * \return Comparator channel readiness state.
1134 */
ac_chan_is_ready(struct ac_module * const module_inst,const enum ac_chan_channel channel)1135 static inline bool ac_chan_is_ready(
1136 struct ac_module *const module_inst,
1137 const enum ac_chan_channel channel)
1138 {
1139 /* Sanity check arguments */
1140 Assert(module_inst);
1141 Assert(module_inst->hw);
1142
1143 Ac *const ac_module = module_inst->hw;
1144
1145 return (ac_module->STATUSB.reg & (AC_STATUSB_READY0 << (uint8_t)channel));
1146 }
1147
1148 /**
1149 * \brief Determines the output state of a comparator channel.
1150 *
1151 * Retrieves the last comparison value (after filtering) of a given comparator.
1152 * If the comparator was not ready at the time of the check, the comparison
1153 * result will be indicated as being unknown.
1154 *
1155 * \param[in] module_inst Software instance for the Analog Comparator peripheral
1156 * \param[in] channel Comparator channel to test
1157 *
1158 * \return Bit mask of comparator channel status flags.
1159 */
ac_chan_get_status(struct ac_module * const module_inst,const enum ac_chan_channel channel)1160 static inline uint8_t ac_chan_get_status(
1161 struct ac_module *const module_inst,
1162 const enum ac_chan_channel channel)
1163 {
1164 /* Sanity check arguments */
1165 Assert(module_inst);
1166 Assert(module_inst->hw);
1167
1168 Ac *const ac_module = module_inst->hw;
1169
1170 uint8_t status_mask = 0;
1171
1172 if (ac_module->INTFLAG.reg & (1 << channel)) {
1173 status_mask = AC_CHAN_STATUS_INTERRUPT_SET;
1174 }
1175
1176 if (ac_chan_is_ready(module_inst, channel) == false) {
1177 status_mask |= AC_CHAN_STATUS_UNKNOWN;
1178 return status_mask;
1179 }
1180
1181 if (ac_module->STATUSA.reg & (AC_STATUSA_STATE0 << (uint8_t)channel)) {
1182 status_mask |= AC_CHAN_STATUS_POS_ABOVE_NEG;
1183 } else {
1184 status_mask |= AC_CHAN_STATUS_NEG_ABOVE_POS;
1185 }
1186 return status_mask;
1187 }
1188
1189 /**
1190 * \brief Clears an interrupt status flag.
1191 *
1192 * This function is used to clear the AC_CHAN_STATUS_INTERRUPT_SET flag
1193 * it will clear the flag for the channel indicated by the channel argument.
1194 *
1195 * \param[in] module_inst Software instance for the Analog Comparator peripheral
1196 * \param[in] channel Comparator channel to clear
1197 */
ac_chan_clear_status(struct ac_module * const module_inst,const enum ac_chan_channel channel)1198 static inline void ac_chan_clear_status(
1199 struct ac_module *const module_inst,
1200 const enum ac_chan_channel channel)
1201 {
1202 Assert(module_inst);
1203 Assert(module_inst->hw);
1204
1205 module_inst->hw->INTFLAG.reg = (1 << channel);
1206 }
1207 /** @} */
1208
1209
1210 /**
1211 * \name Window Mode Configuration and Initialization
1212 * @{
1213 */
1214
1215 /**
1216 * \brief Initializes an Analog Comparator window configuration structure to defaults.
1217 *
1218 * Initializes a given Analog Comparator channel configuration structure to a
1219 * set of known default values. This function should be called if window interrupts
1220 * are needed and before ac_win_set_config().
1221 *
1222 * The default configuration is as follows:
1223 * \li Channel interrupt set to occur when the measurement is above the window
1224 *
1225 * \param[out] config Window configuration structure to initialize to
1226 * default values
1227 */
ac_win_get_config_defaults(struct ac_win_config * const config)1228 static inline void ac_win_get_config_defaults(
1229 struct ac_win_config *const config)
1230 {
1231 /* Sanity check arguments */
1232 Assert(config);
1233
1234 /* Default configuration values */
1235 config->interrupt_selection = AC_WIN_INTERRUPT_SELECTION_ABOVE;
1236 }
1237
1238 enum status_code ac_win_set_config(
1239 struct ac_module *const module_inst,
1240 enum ac_win_channel const win_channel,
1241 struct ac_win_config *const config);
1242
1243 enum status_code ac_win_enable(
1244 struct ac_module *const module_inst,
1245 const enum ac_win_channel win_channel);
1246
1247 void ac_win_disable(
1248 struct ac_module *const module_inst,
1249 const enum ac_win_channel win_channel);
1250
1251 /** @} */
1252
1253
1254 /**
1255 * \name Window Mode Control
1256 * @{
1257 */
1258
1259 /**
1260 * \brief Determines if a given Window Comparator is ready for comparisons.
1261 *
1262 * Checks a Window Comparator to see if the both comparators used for window
1263 * detection is currently ready to begin comparisons.
1264 *
1265 * \param[in] module_inst Software instance for the Analog Comparator peripheral
1266 * \param[in] win_channel Window Comparator channel to test
1267 *
1268 * \return Window Comparator channel readiness state.
1269 */
ac_win_is_ready(struct ac_module * const module_inst,const enum ac_win_channel win_channel)1270 static inline bool ac_win_is_ready(
1271 struct ac_module *const module_inst,
1272 const enum ac_win_channel win_channel)
1273 {
1274 /* Sanity check arguments */
1275 Assert(module_inst);
1276 Assert(module_inst->hw);
1277
1278 /* Convert a window channel index to the individual comparator channels */
1279 enum ac_chan_channel win_pair_comp0 =
1280 (enum ac_chan_channel)((uint8_t)win_channel * 2);
1281 enum ac_chan_channel win_pair_comp1 =
1282 (enum ac_chan_channel)(((uint8_t)win_channel * 2) + 1);
1283
1284 /* Check if the two comparators used in the window are ready */
1285 bool win_pair_comp0_ready = ac_chan_is_ready(module_inst, win_pair_comp0);
1286 bool win_pair_comp1_ready = ac_chan_is_ready(module_inst, win_pair_comp1);
1287
1288 /* If one or both window comparators not ready, return failure */
1289 if ((win_pair_comp0_ready == false) || (win_pair_comp1_ready == false)) {
1290 return false;
1291 }
1292
1293 return true;
1294 }
1295
1296 uint8_t ac_win_get_status(
1297 struct ac_module *const module_inst,
1298 const enum ac_win_channel win_channel);
1299
1300 /**
1301 * \brief Clears an interrupt status flag.
1302 *
1303 * This function is used to clear the AC_WIN_STATUS_INTERRUPT_SET flag
1304 * it will clear the flag for the channel indicated by the win_channel argument.
1305 *
1306 * \param[in] module_inst Software instance for the Analog Comparator peripheral
1307 * \param[in] win_channel Window channel to clear
1308 */
ac_win_clear_status(struct ac_module * const module_inst,const enum ac_win_channel win_channel)1309 static inline void ac_win_clear_status(
1310 struct ac_module *const module_inst,
1311 const enum ac_win_channel win_channel)
1312 {
1313 Assert(module_inst);
1314 Assert(module_inst->hw);
1315
1316 module_inst->hw->INTFLAG.reg = (1 << (win_channel + AC_INTFLAG_WIN0_Pos));
1317 }
1318 /** @} */
1319
1320 #ifdef __cplusplus
1321 }
1322 #endif
1323
1324 /** @} */
1325
1326
1327 /**
1328 * \page asfdoc_sam0_ac_extra Extra Information for AC Driver
1329 *
1330 * \section asfdoc_sam0_ac_extra_acronyms Acronyms
1331 * Below is a table listing the acronyms used in this module, along with their
1332 * intended meanings.
1333 *
1334 * <table>
1335 * <tr>
1336 * <th>Acronym</th>
1337 * <th>Description</th>
1338 * </tr>
1339 * <tr>
1340 * <td>AC</td>
1341 * <td>Analog Comparator</td>
1342 * </tr>
1343 * <tr>
1344 * <td>DAC</td>
1345 * <td>Digital-to-Analog Converter</td>
1346 * </tr>
1347 * <tr>
1348 * <td>MUX</td>
1349 * <td>Multiplexer</td>
1350 * </tr>
1351 * </table>
1352 *
1353 *
1354 * \section asfdoc_sam0_ac_extra_dependencies Dependencies
1355 * This driver has the following dependencies:
1356 *
1357 * - \ref asfdoc_sam0_system_pinmux_group "System Pin Multiplexer Driver"
1358 *
1359 *
1360 * \section asfdoc_sam0_ac_extra_errata Errata
1361 * There are no errata related to this driver.
1362 *
1363 *
1364 * \section asfdoc_sam0_ac_extra_history Module History
1365 * An overview of the module history is presented in the table below, with
1366 * details on the enhancements and fixes made to the module since its first
1367 * release. The current version of this corresponds to the newest version in
1368 * the table.
1369 *
1370 * <table>
1371 * <tr>
1372 * <th>Changelog</th>
1373 * </tr>
1374 * <tr>
1375 * <td>Initial Release</td>
1376 * </tr>
1377 * </table>
1378 */
1379
1380 /**
1381 * \page asfdoc_sam0_ac_exqsg Examples for AC Driver
1382 *
1383 * This is a list of the available Quick Start guides (QSGs) and example
1384 * applications for \ref asfdoc_sam0_ac_group. QSGs are simple examples with
1385 * step-by-step instructions to configure and use this driver in a selection of
1386 * use cases. Note that a QSG can be compiled as a standalone application or be
1387 * added to the user application.
1388 *
1389 * - \subpage asfdoc_sam0_ac_basic_use_case
1390 * \if AC_CALLBACK_MODE
1391 * - \subpage asfdoc_sam0_ac_callback_use_case
1392 * \endif
1393 *
1394 * \page asfdoc_sam0_ac_document_revision_history Document Revision History
1395 *
1396 * <table>
1397 * <tr>
1398 * <th>Doc. Rev.</th>
1399 * <th>Date</th>
1400 * <th>Comments</th>
1401 * </tr>
1402 * <tr>
1403 * <td>42106F</td>
1404 * <td>12/2015</td>
1405 * <td>Fixed typos and legal disclaimer</td>
1406 * </tr>
1407 * <tr>
1408 * <td>42106E</td>
1409 * <td>08/2015</td>
1410 * <td>Added support for SAM L21, SAM C20/C21, and SAM DA1</td>
1411 * </tr>
1412 * <tr>
1413 * <td>42106D</td>
1414 * <td>12/2014</td>
1415 * <td>Added support for SAM R21 and SAM D10/D11</td>
1416 * </tr>
1417 * <tr>
1418 * <td>42106C</td>
1419 * <td>01/2014</td>
1420 * <td>Added support for SAM D21</td>
1421 * </tr>
1422 * <tr>
1423 * <td>42106B</td>
1424 * <td>06/2013</td>
1425 * <td>Added additional documentation on the event system. Corrected
1426 * documentation typos.</td>
1427 * </tr>
1428 * <tr>
1429 * <td>42106A</td>
1430 * <td>06/2013</td>
1431 * <td>Initial release</td>
1432 * </tr>
1433 * </table>
1434 */
1435
1436 #endif
1437