1 /**
2  * @file xmc_ledts.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 modification,are permitted provided that the
13  * following conditions are met:
14  *
15  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16  * disclaimer.
17  *
18  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19  * disclaimer in the documentation and/or other materials provided with the distribution.
20  *
21  * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22  * products derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33  * Infineon Technologies AG dave@infineon.com).
34  *********************************************************************************************************************
35  *
36  * Change History
37  * --------------
38  *
39  * 2015-02-20:
40  *     - Initial draft <br>
41  *     - New API added: XMC_LEDTS_SetActivePADNo() <br>
42  *
43  * 2015-06-20:
44  *     - Removed version macros and declaration of GetDriverVersion API
45  *
46  * 2017-02-25:
47  *     - XMC_LEDTS_InitGlobal() fixed compilation warnings
48  *
49  * <b>Detailed description of file:</b><br>
50  * APIs for the functional blocks of LEDTS have been defined:<br>
51  * -- GLOBAL (APIs prefixed with LEDTS_GLOBAL_) <br>
52  * -- Clock configuration, Function/Event configuration, Interrupt configuration
53  *
54  * @endcond
55  *
56  */
57 
58 /*********************************************************************************************************************
59  * HEADER FILES
60  ********************************************************************************************************************/
61 #include <xmc_ledts.h>
62 
63 #if defined(LEDTS0)
64 #include "xmc_scu.h"
65 
66 /*********************************************************************************************************************
67  * MACROS
68  ********************************************************************************************************************/
69 #define XMC_LEDTS_CLOCK_NOT_RUNNING 0U
70 
71 /*********************************************************************************************************************
72  * ENUMS
73  ********************************************************************************************************************/
74 
75 /*********************************************************************************************************************
76  * DATA STRUCTURES
77  ********************************************************************************************************************/
78 
79 /*********************************************************************************************************************
80  * GLOBAL DATA
81  ********************************************************************************************************************/
82 
83 /*********************************************************************************************************************
84  * LOCAL/UTILITY ROUTINES
85  ********************************************************************************************************************/
86 
87 /*********************************************************************************************************************
88  * API IMPLEMENTATION
89  ********************************************************************************************************************/
90 
91 /**
92   * Initialization of global register
93   */
XMC_LEDTS_InitGlobal(XMC_LEDTS_t * const ledts,const XMC_LEDTS_GLOBAL_CONFIG_t * config)94 XMC_LEDTS_STATUS_t XMC_LEDTS_InitGlobal(XMC_LEDTS_t *const ledts, const XMC_LEDTS_GLOBAL_CONFIG_t *config)
95 {
96   XMC_ASSERT("XMC_LEDTS_InitGlobal:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
97   XMC_ASSERT("XMC_LEDTS_InitGlobal:Null Pointer", (config != (XMC_LEDTS_GLOBAL_CONFIG_t *)NULL));
98 
99   if (ledts == XMC_LEDTS0)
100   {
101 #if defined(CLOCK_GATING_SUPPORTED)
102       XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_LEDTS0);
103 #endif
104 #if defined(PERIPHERAL_RESET_SUPPORTED)
105       XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_LEDTS0);
106 #endif
107   }
108 #if defined(LEDTS1)
109   else if (ledts == XMC_LEDTS1)
110   {
111 #if defined(CLOCK_GATING_SUPPORTED)
112       XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_LEDTS1);
113 #endif
114 #if defined(PERIPHERAL_RESET_SUPPORTED)
115       XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_LEDTS1);
116 #endif
117   }
118 #endif
119 #if defined(LEDTS2)
120   else if (ledts == XMC_LEDTS2)
121   {
122 #if defined(CLOCK_GATING_SUPPORTED)
123       XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_LEDTS2);
124 #endif
125 #if defined(PERIPHERAL_RESET_SUPPORTED)
126       XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_LEDTS2);
127 #endif
128   }
129 #endif
130   else
131   {
132     XMC_ASSERT("XMC_LEDTS_InitGlobal:Invalid Module Pointer", 0);
133   }
134 
135   if((ledts->GLOBCTL & LEDTS_GLOBCTL_CLK_PS_Msk) != XMC_LEDTS_CLOCK_NOT_RUNNING)
136   {
137     return XMC_LEDTS_STATUS_RUNNING;
138   }
139 
140   ledts->GLOBCTL = config->globctl;
141 
142   return XMC_LEDTS_STATUS_SUCCESS;
143 }
144 
145 /**
146   * Initialization of registers for LED-driving function
147   */
XMC_LEDTS_InitLED(XMC_LEDTS_t * const ledts,const XMC_LEDTS_LED_CONFIG_t * config)148 XMC_LEDTS_STATUS_t XMC_LEDTS_InitLED(XMC_LEDTS_t *const ledts, const XMC_LEDTS_LED_CONFIG_t *config)
149 {
150   XMC_ASSERT("XMC_LEDTS_LED_Init:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
151   XMC_ASSERT("XMC_LEDTS_LED_Init:Null Pointer", (config != (XMC_LEDTS_LED_CONFIG_t *)NULL));
152 
153   if((ledts->GLOBCTL & LEDTS_GLOBCTL_CLK_PS_Msk) != XMC_LEDTS_CLOCK_NOT_RUNNING)
154   {
155     return XMC_LEDTS_STATUS_RUNNING;
156   }
157 
158   ledts->FNCTL &= ~(LEDTS_FNCTL_COLLEV_Msk | LEDTS_FNCTL_NR_LEDCOL_Msk);
159   ledts->FNCTL |= (config->fnctl);
160 
161   /* Enable LED function */
162   ledts->GLOBCTL |= LEDTS_GLOBCTL_LD_EN_Msk;
163 
164   return XMC_LEDTS_STATUS_SUCCESS;
165 }
166 
167 /**
168   * Initialization of registers for basic Touch-Sense control function
169   */
XMC_LEDTS_InitTSBasic(XMC_LEDTS_t * const ledts,const XMC_LEDTS_TS_CONFIG_BASIC_t * config)170 XMC_LEDTS_STATUS_t XMC_LEDTS_InitTSBasic(XMC_LEDTS_t *const ledts, const XMC_LEDTS_TS_CONFIG_BASIC_t *config)
171 {
172   uint32_t reg;
173 
174   XMC_ASSERT("XMC_LEDTS_TS_Basic_Init:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
175   XMC_ASSERT("XMC_LEDTS_TS_Basic_Init:Null Pointer", (config != (XMC_LEDTS_TS_CONFIG_BASIC_t *)NULL));
176 
177   if((ledts->GLOBCTL & LEDTS_GLOBCTL_CLK_PS_Msk) != XMC_LEDTS_CLOCK_NOT_RUNNING)
178   {
179     return XMC_LEDTS_STATUS_RUNNING;
180   }
181 
182   reg = ~(LEDTS_FNCTL_ACCCNT_Msk | LEDTS_FNCTL_TSCCMP_Msk | LEDTS_FNCTL_TSCTRR_Msk | LEDTS_FNCTL_TSCTRSAT_Msk |
183 		 LEDTS_FNCTL_NR_TSIN_Msk);
184   ledts->FNCTL &= (reg);
185   ledts->FNCTL |= (config->fnctl);
186 
187   /* Enable TS function */
188   ledts->GLOBCTL |= LEDTS_GLOBCTL_TS_EN_Msk;
189 
190   return XMC_LEDTS_STATUS_SUCCESS;
191 }
192 
193 /**
194   * Initialization of registers for advanced Touch-Sense control function
195   */
XMC_LEDTS_InitTSAdvanced(XMC_LEDTS_t * const ledts,const XMC_LEDTS_TS_CONFIG_ADVANCED_t * config)196 XMC_LEDTS_STATUS_t XMC_LEDTS_InitTSAdvanced (XMC_LEDTS_t *const ledts, const XMC_LEDTS_TS_CONFIG_ADVANCED_t *config)
197 {
198   uint32_t reg;
199 
200   XMC_ASSERT("XMC_LEDTS_TS_Advanced_Init:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
201   XMC_ASSERT("XMC_LEDTS_TS_Advanced_Init:Null Pointer", (config != (XMC_LEDTS_TS_CONFIG_ADVANCED_t *)NULL));
202 
203   if((ledts->GLOBCTL & LEDTS_GLOBCTL_CLK_PS_Msk) != XMC_LEDTS_CLOCK_NOT_RUNNING)
204   {
205     return XMC_LEDTS_STATUS_RUNNING;
206   }
207 
208   reg = ~(LEDTS_GLOBCTL_MASKVAL_Msk | LEDTS_GLOBCTL_FENVAL_Msk);
209   ledts->GLOBCTL &= (reg);
210   ledts->GLOBCTL |= (config->globctl);
211 
212   reg = ~(LEDTS_FNCTL_PADT_Msk | LEDTS_FNCTL_PADTSW_Msk | LEDTS_FNCTL_EPULL_Msk | LEDTS_FNCTL_TSOEXT_Msk);
213   ledts->FNCTL &= (reg);
214   ledts->FNCTL |= (config->fnctl);
215 
216   return XMC_LEDTS_STATUS_SUCCESS;
217 }
218 
219 /**
220   * Starts LEDTS-counter
221   */
XMC_LEDTS_StartCounter(XMC_LEDTS_t * const ledts,const uint16_t prescaler)222 void XMC_LEDTS_StartCounter(XMC_LEDTS_t *const ledts, const uint16_t prescaler)
223 {
224   XMC_ASSERT("XMC_LEDTS_Start_Counter:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
225 
226   ledts->GLOBCTL |= prescaler<<16U;
227 }
228 
229 /**
230   * Stops LEDTS-counter
231   */
XMC_LEDTS_StopCounter(XMC_LEDTS_t * const ledts)232 void XMC_LEDTS_StopCounter(XMC_LEDTS_t *const ledts)
233 {
234   XMC_ASSERT("XMC_LEDTS_Stop_Counter:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
235 
236   ledts->GLOBCTL &= 0x0000FFFF;
237 }
238 
239 /**
240   * Reads time interrupt flags
241   */
XMC_LEDTS_ReadInterruptFlag(XMC_LEDTS_t * const ledts)242 uint32_t XMC_LEDTS_ReadInterruptFlag(XMC_LEDTS_t *const ledts)
243 {
244   XMC_ASSERT("XMC_LEDTS_ReadInterruptFlag:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
245 
246   return (ledts->EVFR & 0xF);
247 }
248 
249 /**
250   * Set the active pad number
251   */
XMC_LEDTS_SetActivePADNo(XMC_LEDTS_t * const ledts,XMC_LEDTS_NUMBER_TS_INPUT_t pad_num)252 void XMC_LEDTS_SetActivePADNo(XMC_LEDTS_t *const ledts, XMC_LEDTS_NUMBER_TS_INPUT_t pad_num)
253 {
254   uint32_t reg;
255 
256   XMC_ASSERT("XMC_LEDTS_SetActivePADNo:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
257 
258   reg = ledts->FNCTL;
259   reg &= ~(LEDTS_FNCTL_PADT_Msk);
260   reg |= (uint32_t)pad_num;
261   ledts->FNCTL = reg;
262 }
263 
264 /**
265   * Clears interrupt indication flags
266   */
XMC_LEDTS_ClearInterruptFlag(XMC_LEDTS_t * const ledts,uint32_t interrupt_mask)267 void XMC_LEDTS_ClearInterruptFlag(XMC_LEDTS_t *const ledts, uint32_t interrupt_mask)
268 {
269   XMC_ASSERT("XMC_LEDTS_ClearInterruptFlag:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
270 
271   ledts->EVFR = (interrupt_mask << LEDTS_EVFR_CTSF_Pos);
272 }
273 
274 /**
275   * Programming of registers to output pattern on an LED column in LED matrix
276   */
XMC_LEDTS_SetLEDLinePattern(XMC_LEDTS_t * const ledts,XMC_LEDTS_LED_COLUMN_t column,const uint8_t pattern)277 void XMC_LEDTS_SetLEDLinePattern(XMC_LEDTS_t *const ledts, XMC_LEDTS_LED_COLUMN_t column, const uint8_t pattern)
278 {
279   uint32_t reg;
280   uint8_t reg_index = ((uint8_t)column) >> 2;
281   uint8_t bit_shift_count = ((uint8_t)column & 0x03) * 8;
282 
283   XMC_ASSERT("XMC_LEDTS_Set_LED_Line_Pattern:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
284 
285   reg = ledts->LINE[reg_index];
286   reg &= (~(0xff << bit_shift_count));
287   reg |= pattern << bit_shift_count;
288   ledts->LINE[reg_index] = reg;
289 
290 }
291 
292 /**
293   * Programming of registers to adjust brightness of an LED column in LED matrix
294   */
XMC_LEDTS_SetColumnBrightness(XMC_LEDTS_t * const ledts,XMC_LEDTS_LED_COLUMN_t column,const uint8_t brightness)295 void XMC_LEDTS_SetColumnBrightness(XMC_LEDTS_t *const ledts, XMC_LEDTS_LED_COLUMN_t column, const uint8_t brightness)
296 {
297   uint32_t reg;
298   uint8_t reg_index = ((uint8_t)column) >> 2;
299   uint8_t bit_shift_count = ((uint8_t)column & 0x03) * 8;
300 
301   XMC_ASSERT("XMC_LEDTS_Set_Column_Brightness:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
302 
303 	reg = ledts->LDCMP[reg_index];
304 	reg &= (~(0xff << bit_shift_count));
305 	reg |= brightness << bit_shift_count;
306 	ledts->LDCMP[reg_index] = reg;
307 }
308 
309 /**
310   * Programming of registers to set common oscillation window size for touch-sense inputs
311   */
XMC_LEDTS_SetCommonOscillationWindow(XMC_LEDTS_t * const ledts,const uint8_t common_size)312 void XMC_LEDTS_SetCommonOscillationWindow(XMC_LEDTS_t *const ledts, const uint8_t common_size)
313 {
314   uint32_t reg;
315 
316   XMC_ASSERT("XMC_LEDTS_Set_Common_Oscillation_Window:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
317 
318   reg = ledts->LDCMP[1];
319   reg &= ~LEDTS_LDCMP1_CMP_LDA_TSCOM_Msk;
320   reg |= (common_size << LEDTS_LDCMP1_CMP_LDA_TSCOM_Pos);
321   ledts->LDCMP[1] = reg;
322 }
323 
324 /**
325   * Checking the previous active function or LED column status
326   */
XMC_LEDTS_ReadFNCOL(XMC_LEDTS_t * const ledts)327 uint32_t XMC_LEDTS_ReadFNCOL(XMC_LEDTS_t *const ledts)
328 {
329   uint32_t fncol_read;
330 
331   XMC_ASSERT("XMC_LEDTS_Read_FNCOL:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
332 
333   fncol_read = ledts->FNCTL & LEDTS_FNCTL_FNCOL_Msk;
334   fncol_read >>= LEDTS_FNCTL_FNCOL_Pos;
335 
336   return fncol_read;
337 }
338 
339 /**
340   * Set the number of LED column Enabled
341   */
XMC_LEDTS_SetNumOfLEDColumns(XMC_LEDTS_t * const ledts,uint8_t count)342 void XMC_LEDTS_SetNumOfLEDColumns(XMC_LEDTS_t *const ledts, uint8_t count)
343 {
344 
345   XMC_ASSERT("XMC_LEDTS_SetNumOfLEDColumns:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
346 
347   ledts->FNCTL &= ~(LEDTS_FNCTL_NR_LEDCOL_Msk);
348   ledts->FNCTL |= (count << LEDTS_FNCTL_NR_LEDCOL_Pos);
349 }
350 
351 /**
352   * Reading recorded number of oscillation counts
353   */
XMC_LEDTS_ReadTSVAL(XMC_LEDTS_t * const ledts)354 uint16_t XMC_LEDTS_ReadTSVAL(XMC_LEDTS_t *const ledts)
355 {
356   uint16_t no_of_oscillations;
357 
358   XMC_ASSERT("XMC_LEDTS_Read_TSVAL:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
359 
360   no_of_oscillations = (ledts->TSVAL & 0xFFFF);
361 
362   return no_of_oscillations;
363 }
364 
365 /**
366   * Programming of registers to adjust the size of oscillation window
367   */
XMC_LEDTS_SetOscillationWindow(XMC_LEDTS_t * const ledts,XMC_LEDTS_NUMBER_TS_INPUT_t touchpad,const uint8_t size)368 void XMC_LEDTS_SetOscillationWindow(XMC_LEDTS_t *const ledts, XMC_LEDTS_NUMBER_TS_INPUT_t touchpad, const uint8_t size)
369 {
370   uint32_t reg;
371   uint8_t reg_index = ((uint8_t)touchpad) >> 2;
372   uint8_t bit_shift_count = ((uint8_t)touchpad & 0x03) * 8;
373 
374   XMC_ASSERT("XMC_LEDTS_Set_Oscillation_Window:Wrong Module Pointer", XMC_LEDTS_CHECK_KERNEL_PTR(ledts));
375 
376 	reg = ledts->TSCMP[reg_index];
377 	reg &= (~(0xff << bit_shift_count));
378 	reg |= size << bit_shift_count;
379 	ledts->TSCMP[reg_index] = reg;
380 }
381 
382 #endif /* LEDTS0 */
383 
384