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