1 /**
2 * \file
3 *
4 * \brief SAM AC - Analog Comparator Callback Driver
5 *
6 * Copyright (C) 2013-2015 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 AC_CALLBACK_H_INCLUDED
48 #define AC_CALLBACK_H_INCLUDED
49
50 #include <compiler.h>
51 #include <system_interrupt.h>
52 #include "ac.h"
53
54 #ifdef __cplusplus
55 extern "C" {
56 #endif
57
58 #if (AC_INST_NUM > 1) && !defined(__DOXYGEN__)
59 /**
60 * \internal Get the interrupt vector for the given device instance
61 *
62 * \param[in] TC module instance number
63 *
64 * \return Interrupt vector for of the given TC module instance.
65 */
_ac_interrupt_get_interrupt_vector(uint32_t inst_num)66 static enum system_interrupt_vector _ac_interrupt_get_interrupt_vector(
67 uint32_t inst_num)
68 {
69 static uint8_t ac_interrupt_vectors[AC_INST_NUM] =
70 {
71 SYSTEM_INTERRUPT_MODULE_AC,
72 #if (AC_INST_NUM == 2)
73 SYSTEM_INTERRUPT_MODULE_AC1,
74 #endif
75 #if (AC_INST_NUM >= 3)
76 # error This driver is not support more than three AC instances.
77 #endif
78 };
79
80 return ac_interrupt_vectors[inst_num];
81 }
82 #endif /* (AC_INST_NUM > 1) !defined(__DOXYGEN__)*/
83
84 /**
85 * \name Callback Management
86 * {@
87 */
88
89 enum status_code ac_register_callback(
90 struct ac_module *const module,
91 ac_callback_t callback_func,
92 const enum ac_callback callback_type);
93
94 enum status_code ac_unregister_callback(
95 struct ac_module *const module,
96 const enum ac_callback callback_type);
97
98 /**
99 * \brief Enables callback.
100 *
101 * Enables the callback function registered by the \ref
102 * ac_register_callback. The callback function will be called from the
103 * interrupt handler when the conditions for the callback type are
104 * met. This function will also enable the appropriate interrupts.
105 *
106 * \param[in] module Pointer to AC software instance struct
107 * \param[in] callback_type Callback type given by an enum
108 */
ac_enable_callback(struct ac_module * const module,const enum ac_callback callback_type)109 static inline void ac_enable_callback(
110 struct ac_module *const module,
111 const enum ac_callback callback_type)
112 {
113 /* Sanity check arguments */
114 Assert(module);
115
116 /* Set software flag for the callback */
117 module->enable_callback_mask |= (1 << callback_type);
118
119 uint32_t inenset_temp = 0;
120
121 switch (callback_type)
122 {
123 case AC_CALLBACK_COMPARATOR_0:
124 inenset_temp |= AC_INTFLAG_COMP0;
125 break;
126 case AC_CALLBACK_COMPARATOR_1:
127 inenset_temp |= AC_INTFLAG_COMP1;
128 break;
129 case AC_CALLBACK_WINDOW_0:
130 inenset_temp |= AC_INTFLAG_WIN0;
131 break;
132 #if (AC_NUM_CMP > 2)
133 case AC_CALLBACK_COMPARATOR_2:
134 inenset_temp |= AC_INTFLAG_COMP2;
135 break;
136 case AC_CALLBACK_COMPARATOR_3:
137 inenset_temp |= AC_INTFLAG_COMP3;
138 break;
139 # if !(SAMC20)
140 case AC_CALLBACK_WINDOW_1:
141 inenset_temp |= AC_INTFLAG_WIN1;
142 break;
143 # endif
144 #endif
145 default:
146 break;
147 }
148
149 /* Enable the interrupt for the callback */
150 module->hw->INTENSET.reg = inenset_temp;
151
152 #if (AC_INST_NUM == 1)
153 /* Enable interrupts for AC module */
154 system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_AC);
155 #elif (AC_INST_NUM > 1)
156 system_interrupt_enable(_ac_interrupt_get_interrupt_vector(_ac_get_inst_index(module->hw)));
157 #endif /* (AC_INST_NUM > 1) */
158 }
159
160 /**
161 * \brief Disables callback.
162 *
163 * Disables the callback function registered by the \ref
164 * ac_register_callback, and the callback will not be called from the
165 * interrupt routine. The function will also disable the appropriate
166 * interrupts.
167 *
168 * \param[in] module Pointer to AC software instance struct
169 * \param[in] callback_type Callback type given by an enum
170 */
ac_disable_callback(struct ac_module * const module,const enum ac_callback callback_type)171 static inline void ac_disable_callback(
172 struct ac_module *const module,
173 const enum ac_callback callback_type)
174 {
175 /* Sanity check arguments */
176 Assert(module);
177
178 /* Clear software flag for the callback */
179 module->enable_callback_mask &= ~(1 << callback_type);
180
181 uint32_t inenclr_temp = 0;
182
183 switch (callback_type)
184 {
185 case AC_CALLBACK_COMPARATOR_0:
186 inenclr_temp |= AC_INTFLAG_COMP0;
187 break;
188 case AC_CALLBACK_COMPARATOR_1:
189 inenclr_temp |= AC_INTFLAG_COMP1;
190 break;
191 case AC_CALLBACK_WINDOW_0:
192 inenclr_temp |= AC_INTFLAG_WIN0;
193 break;
194 #if (AC_NUM_CMP > 2)
195 case AC_CALLBACK_COMPARATOR_2:
196 inenclr_temp |= AC_INTFLAG_COMP2;
197 break;
198 case AC_CALLBACK_COMPARATOR_3:
199 inenclr_temp |= AC_INTFLAG_COMP3;
200 break;
201 # if !(SAMC20)
202 case AC_CALLBACK_WINDOW_1:
203 inenclr_temp |= AC_INTFLAG_WIN1;
204 break;
205 # endif
206 #endif
207 default:
208 break;
209 }
210
211 /* Disable the interrupt for the callback */
212 module->hw->INTENCLR.reg = inenclr_temp;
213 }
214
215 /**
216 * @}
217 */
218
219 #ifdef __cplusplus
220 }
221 #endif
222
223 #endif /* AC_CALLBACK_H_INCLUDED */
224