1 /**
2  * @file xmc_posif.c
3  * @date 2017-02-25
4  *
5  * @cond
6  **********************************************************************************
7  * XMClib v2.1.24 - XMC Peripheral Driver Library
8  *
9  * Copyright (c) 2015-2019, Infineon Technologies AG
10  * All rights reserved.
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  *   Redistributions of source code must retain the above copyright notice,
16  *   this list of conditions and the following disclaimer.
17  *
18  *   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  *   Neither the name of the copyright holders nor the names of its contributors
23  *   may be used to endorse or promote products derived from this software without
24  *   specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30  * LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * To improve the quality of the software, users are encouraged to share
39  * modifications, enhancements or bug fixes with Infineon Technologies AG
40  * dave@infineon.com).
41  **********************************************************************************
42  *
43  * Change History
44  * --------------
45  *
46  * 2015-02-18:
47  *     - Initial version
48  *
49  * 2015-02-20:
50  *     - Driver description added <BR>
51  *
52  * 2015-04-30:
53  *     - XMC_POSIF_Enable and XMC_POSIF_Disable APIs updated for POSIF1 peripheral check <BR>
54  *
55  * 2015-06-19:
56  *     - Removed GetDriverVersion API <BR>
57  *
58  * 2017-02-25:
59  *     - XMC_POSIF_Enable() and XMC_POSIF_Disable() fixed compilation warnings
60  *
61  * @endcond
62  *
63  */
64 
65 /*********************************************************************************************************************
66  * HEADER FILES
67  ********************************************************************************************************************/
68 #include <xmc_posif.h>
69 
70 /* POSIF is not available on XMC1100 and XMC1200 */
71 #if defined(POSIF0)
72 #include <xmc_scu.h>
73 
74 /*********************************************************************************************************************
75  * MACROS
76  ********************************************************************************************************************/
77 #define XMC_POSIF_PCONF_INSEL_Msk        (0x3fUL << POSIF_PCONF_INSEL0_Pos) /*< Mask for input pins selection */
78 #define XMC_POSIF_INSEL_MAX              (4U) /*< Maximum possible input selector */
79 
80 /*********************************************************************************************************************
81  * LOCAL ROUTINES
82  ********************************************************************************************************************/
83 #ifdef XMC_ASSERT_ENABLE
XMC_POSIF_IsPeripheralValid(const XMC_POSIF_t * const peripheral)84 __STATIC_INLINE bool XMC_POSIF_IsPeripheralValid(const XMC_POSIF_t *const peripheral)
85 {
86   bool tmp;
87 
88   tmp = (peripheral == POSIF0);
89 #if defined(POSIF1)
90   tmp |= (peripheral == POSIF1);
91 #endif
92 
93   return tmp;
94 }
95 #endif
96 /*********************************************************************************************************************
97  * API IMPLEMENTATION
98  ********************************************************************************************************************/
99 
100 /* API to enable the POSIF module */
XMC_POSIF_Enable(XMC_POSIF_t * const peripheral)101 void XMC_POSIF_Enable(XMC_POSIF_t *const peripheral)
102 {
103 #if UC_FAMILY == XMC4
104   XMC_SCU_CLOCK_EnableClock(XMC_SCU_CLOCK_CCU);
105 #endif
106 
107   if (peripheral == POSIF0)
108   {
109 #if defined(CLOCK_GATING_SUPPORTED)
110     XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_POSIF0);
111 #endif
112 #if defined(PERIPHERAL_RESET_SUPPORTED)
113       XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_POSIF0);
114 #endif
115   }
116 #if defined(POSIF1)
117   else if (peripheral == POSIF1)
118   {
119 #if defined(CLOCK_GATING_SUPPORTED)
120       XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_POSIF1);
121 #endif
122 #if defined(PERIPHERAL_RESET_SUPPORTED)
123       XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_POSIF1);
124 #endif
125   }
126 #endif
127   else
128   {
129     XMC_ASSERT("XMC_POSIF_Disable:Invalid module pointer", 0);
130   }
131 }
132 
133 /* API to disable the POSIF module */
XMC_POSIF_Disable(XMC_POSIF_t * const peripheral)134 void XMC_POSIF_Disable(XMC_POSIF_t *const peripheral)
135 {
136   if (peripheral == POSIF0)
137   {
138 #if defined(PERIPHERAL_RESET_SUPPORTED)
139       XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_POSIF0);
140 #endif
141 #if defined(CLOCK_GATING_SUPPORTED)
142       XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_POSIF0);
143 #endif
144   }
145 #if defined(POSIF1)
146   else if (peripheral == POSIF1)
147   {
148 #if defined(PERIPHERAL_RESET_SUPPORTED)
149       XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_POSIF1);
150 #endif
151 #if defined(CLOCK_GATING_SUPPORTED)
152       XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_POSIF1);
153 #endif
154   }
155 #endif
156   else
157   {
158     XMC_ASSERT("XMC_POSIF_Disable:Invalid module pointer", 0);
159   }
160 }
161 
162 /* API to initialize POSIF global resources */
XMC_POSIF_Init(XMC_POSIF_t * const peripheral,const XMC_POSIF_CONFIG_t * const config)163 void XMC_POSIF_Init(XMC_POSIF_t *const peripheral, const XMC_POSIF_CONFIG_t *const config)
164 {
165   XMC_ASSERT("XMC_POSIF_Init:Invalid module pointer", XMC_POSIF_IsPeripheralValid(peripheral));
166   XMC_ASSERT("XMC_POSIF_Init:NULL Pointer", (config != (XMC_POSIF_CONFIG_t *)NULL) );
167 
168   /* Enable the POSIF module */
169   XMC_POSIF_Enable(peripheral);
170 
171   /* Stop POSIF */
172   XMC_POSIF_Stop(peripheral);
173 
174   /* Program the operational mode, input selectors and debounce filter */
175   peripheral->PCONF = config->pconf;
176 }
177 
178 /* API to initialize hall sensor interface */
XMC_POSIF_HSC_Init(XMC_POSIF_t * const peripheral,const XMC_POSIF_HSC_CONFIG_t * const config)179 XMC_POSIF_STATUS_t XMC_POSIF_HSC_Init(XMC_POSIF_t *const peripheral, const XMC_POSIF_HSC_CONFIG_t * const config)
180 {
181   XMC_POSIF_STATUS_t retval;
182 
183   XMC_ASSERT("XMC_POSIF_HSC_Init:Invalid module pointer\n", XMC_POSIF_IsPeripheralValid(peripheral));
184   XMC_ASSERT("XMC_POSIF_HSC_Init:NULL Pointer\n", (config != (XMC_POSIF_HSC_CONFIG_t *)NULL) );
185 
186   if (XMC_POSIF_MODE_HALL_SENSOR == (XMC_POSIF_MODE_t)((peripheral->PCONF) & (uint32_t)POSIF_PCONF_FSEL_Msk) )
187   {
188     peripheral->PCONF |= config->hall_config;
189     retval = XMC_POSIF_STATUS_OK;
190   }
191   else
192   {
193     retval = XMC_POSIF_STATUS_ERROR;
194   }
195   return retval;
196 }
197 
198 /* API to initialize quadrature decoder interface */
XMC_POSIF_QD_Init(XMC_POSIF_t * const peripheral,const XMC_POSIF_QD_CONFIG_t * const config)199 XMC_POSIF_STATUS_t XMC_POSIF_QD_Init(XMC_POSIF_t *const peripheral, const XMC_POSIF_QD_CONFIG_t * const config)
200 {
201   uint8_t reg;
202   XMC_POSIF_STATUS_t retval;
203 
204   XMC_ASSERT("XMC_POSIF_QD_Init:Invalid module pointer", XMC_POSIF_IsPeripheralValid(peripheral));
205   XMC_ASSERT("XMC_POSIF_QD_Init:NULL Pointer", (config != (XMC_POSIF_QD_CONFIG_t *)NULL) );
206 
207   reg = (uint8_t)((peripheral->PCONF) & (uint32_t)POSIF_PCONF_FSEL_Msk);
208   if (((uint32_t)XMC_POSIF_MODE_QD == reg) || ((uint32_t)XMC_POSIF_MODE_MCM_QD == reg))
209   {
210     /* Program the quadrature mode */
211     peripheral->PCONF |= (uint32_t)(config->mode) << POSIF_PCONF_QDCM_Pos;
212     peripheral->QDC = config->qdc;
213     retval = XMC_POSIF_STATUS_OK;
214   }
215   else
216   {
217     retval = XMC_POSIF_STATUS_ERROR;
218   }
219 
220   return retval;
221 }
222 
223 /* API to initialize multi-channel mode.
224  * This is used in Hall mode, standalone multi-channel mode and quadrature with multi-channel mode
225  */
XMC_POSIF_MCM_Init(XMC_POSIF_t * const peripheral,const XMC_POSIF_MCM_CONFIG_t * const config)226 XMC_POSIF_STATUS_t XMC_POSIF_MCM_Init(XMC_POSIF_t *const peripheral, const XMC_POSIF_MCM_CONFIG_t * const config)
227 {
228   XMC_POSIF_STATUS_t retval;
229 
230   XMC_ASSERT("XMC_POSIF_MCM_Init:Invalid module pointer", XMC_POSIF_IsPeripheralValid(peripheral));
231   XMC_ASSERT("XMC_POSIF_MCM_Init:NULL Pointer", (config != (XMC_POSIF_MCM_CONFIG_t *)NULL) );
232 
233   if ((XMC_POSIF_MODE_t)((peripheral->PCONF) & (uint32_t)POSIF_PCONF_FSEL_Msk) != XMC_POSIF_MODE_QD)
234   {
235     peripheral->PCONF |= config->mcm_config;
236     retval = XMC_POSIF_STATUS_OK;
237   }
238   else
239   {
240     retval = XMC_POSIF_STATUS_ERROR;
241   }
242   return retval;
243 }
244 
245 /* API to configure input source */
XMC_POSIF_SelectInputSource(XMC_POSIF_t * const peripheral,const XMC_POSIF_INPUT_PORT_t input0,const XMC_POSIF_INPUT_PORT_t input1,const XMC_POSIF_INPUT_PORT_t input2)246 void XMC_POSIF_SelectInputSource (XMC_POSIF_t *const peripheral, const XMC_POSIF_INPUT_PORT_t input0,
247     const XMC_POSIF_INPUT_PORT_t input1, const XMC_POSIF_INPUT_PORT_t input2)
248 {
249   uint32_t reg;
250   XMC_ASSERT("XMC_POSIF_SelectInputSource:Invalid module pointer", XMC_POSIF_IsPeripheralValid(peripheral));
251   XMC_ASSERT("XMC_POSIF_SelectInputSource:Wrong input port input0", (input0 < XMC_POSIF_INSEL_MAX));
252   XMC_ASSERT("XMC_POSIF_SelectInputSource:Wrong input port input1", (input1 < XMC_POSIF_INSEL_MAX));
253   XMC_ASSERT("XMC_POSIF_SelectInputSource:Wrong input port input2", (input2 < XMC_POSIF_INSEL_MAX));
254 
255   reg = (uint32_t)((((uint32_t)input0 << POSIF_PCONF_INSEL0_Pos) & (uint32_t)POSIF_PCONF_INSEL0_Msk) |
256         (((uint32_t)input1 << POSIF_PCONF_INSEL1_Pos) & (uint32_t)POSIF_PCONF_INSEL1_Msk) |
257         (((uint32_t)input2 << POSIF_PCONF_INSEL2_Pos) & (uint32_t)POSIF_PCONF_INSEL2_Msk));
258   peripheral->PCONF = ((peripheral->PCONF & ~(uint32_t)XMC_POSIF_PCONF_INSEL_Msk) | reg);
259 }
260 
261 /* API to select an interrupt node */
XMC_POSIF_SetInterruptNode(XMC_POSIF_t * const peripheral,const XMC_POSIF_IRQ_EVENT_t event,const XMC_POSIF_SR_ID_t sr)262 void XMC_POSIF_SetInterruptNode(XMC_POSIF_t *const peripheral, const XMC_POSIF_IRQ_EVENT_t event, const XMC_POSIF_SR_ID_t sr)
263 {
264   uint32_t reg;
265 
266   XMC_ASSERT("XMC_POSIF_SetInterruptNode:Invalid module pointer", XMC_POSIF_IsPeripheralValid(peripheral));
267   XMC_ASSERT("XMC_POSIF_SetInterruptNode:Wrong IRQ event", (event <= XMC_POSIF_IRQ_EVENT_PCLK) );
268   XMC_ASSERT("XMC_POSIF_SetInterruptNode:Wrong SR ID", (sr <= XMC_POSIF_SR_ID_1) );
269 
270   reg = peripheral->PFLGE;
271   reg &= ~((uint32_t)1 << ((uint32_t)event + (uint32_t)POSIF_PFLGE_CHESEL_Pos));
272   reg |= (uint32_t)sr << ((uint32_t)event + (uint32_t)POSIF_PFLGE_CHESEL_Pos);
273   peripheral->PFLGE = reg;
274 }
275 #endif /* #if defined(POSIF0) */
276