]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/AtmelFiles/libboard_sama5d3x-ek/source/tsd_tsadc.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS / Demo / CORTEX_A5_SAMA5D3x_Xplained_IAR / AtmelFiles / libboard_sama5d3x-ek / source / tsd_tsadc.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2013, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29  \r
30 /** \file */\r
31 \r
32 /*----------------------------------------------------------------------------\r
33  *         Headers\r
34  *----------------------------------------------------------------------------*/\r
35 \r
36 #include <board.h>\r
37 \r
38 #include <string.h>\r
39 \r
40 #ifdef REG_ADC_TSMR\r
41 /** \addtogroup tsd_module\r
42  *@{\r
43  */\r
44 \r
45 /*----------------------------------------------------------------------------\r
46  *         Local definitions\r
47  *----------------------------------------------------------------------------*/\r
48 \r
49 /** SWAP X & Y */\r
50 #define TS_XY_SWAP\r
51 \r
52 /** Status that used for touchscreen */\r
53 #define TS_STATUSES ( ADC_ISR_PENS | ADC_ISR_PEN | ADC_ISR_NOPEN \\r
54                     | ADC_ISR_XRDY | ADC_ISR_YRDY | ADC_ISR_PRDY )\r
55 \r
56 /*----------------------------------------------------------------------------\r
57  *         Local types\r
58  *----------------------------------------------------------------------------*/\r
59 \r
60 /** X value is ready */\r
61 #define TS_X_RDY        (1 << 0)\r
62 /** Y value is ready */\r
63 #define TS_Y_RDY        (1 << 1)\r
64 /** Pressure value is ready */\r
65 #define TS_P_RDY        (1 << 2)\r
66 /** Pen status */\r
67 #define TS_PEN_STAT     (1 << 7)\r
68 /** All data is ready (X,Y & P) */\r
69 #define TS_DATA_RDY     (TS_X_RDY|TS_Y_RDY|TS_P_RDY)\r
70 \r
71 /*----------------------------------------------------------------------------\r
72  *         Local variables\r
73  *----------------------------------------------------------------------------*/\r
74 \r
75 /** Raw register value */\r
76 static uint32_t dwRaw[3];\r
77 /** Touchscreen data sampling results */\r
78 static uint32_t dwTsData[3];\r
79 /** Last Touchscreen sampling results */\r
80 static uint32_t dwLastTsData[3];\r
81 /** Touchscreen data ready */\r
82 static uint8_t  bTsFlags = 0;\r
83 \r
84 /*----------------------------------------------------------------------------\r
85  *         External functions\r
86  *----------------------------------------------------------------------------*/\r
87 \r
88 extern uint32_t TSD_GetRaw(uint32_t i);\r
89 \r
90 /**\r
91  * Return raw register value.\r
92  */\r
93 uint32_t TSD_GetRaw(uint32_t i)\r
94 {\r
95     return dwRaw[i];\r
96 }\r
97 \r
98 /*----------------------------------------------------------------------------\r
99  *        Local definitions\r
100  *----------------------------------------------------------------------------*/\r
101 \r
102 /**\r
103  * Interrupt handler for the TouchScreen.\r
104  * Handles pen press, pen move and pen release events\r
105  * by invoking three callback functions.\r
106  */\r
107 void TSD_Handler(uint32_t dwAdcStatus)\r
108 {\r
109     Adc *pAdc = ADC;\r
110 \r
111     uint32_t status;\r
112 \r
113     /* TSADC status */\r
114     status  = dwAdcStatus;\r
115     status &= /*ADC_GetItMask(pAdc) &*/ TS_STATUSES;\r
116     if (status == 0)    return;\r
117 \r
118     /* Pen released */\r
119     if (status & ADC_ISR_NOPEN)\r
120     {\r
121         if ((bTsFlags & TS_PEN_STAT) == 0)\r
122         {\r
123             /* Register last data */\r
124             memcpy(dwLastTsData, dwTsData, sizeof(dwTsData));\r
125             /* Invoke PenReleased callback */\r
126             if (TSDCom_IsCalibrationOk())\r
127                 TSD_PenReleased(dwTsData[0], dwTsData[1]);\r
128         }\r
129         bTsFlags = 0;\r
130         /* Stop periodic trigger & enable pen */\r
131         ADC_SetTsAverage(pAdc, ADC_TSMR_TSAV_NO_FILTER);\r
132         ADC_SetTsDebounce(pAdc, BOARD_TOUCHSCREEN_DEBOUNCE);\r
133         ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_PEN_TRIG);\r
134         /* Disable pen release detect */\r
135         ADC_DisableIt(pAdc, ADC_IDR_NOPEN);\r
136         /* Enable pen press detect */\r
137         ADC_EnableIt(pAdc, ADC_IER_PEN);\r
138     }\r
139     /* Pen pressed */\r
140     else if (status & ADC_ISR_PEN)\r
141     {\r
142         bTsFlags |= TS_PEN_STAT;\r
143         /* Configure for peripdic trigger */\r
144         ADC_SetTsAverage(pAdc, ADC_TSMR_TSAV_AVG8CONV);\r
145         ADC_SetTsDebounce(pAdc, 300);         /* 300ns */\r
146         ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_PERIOD_TRIG);\r
147         /* Disable pen press detect */\r
148         ADC_DisableIt(pAdc, ADC_IDR_PEN);\r
149         /* Enable pen release detect */\r
150         ADC_EnableIt(pAdc, ADC_IER_NOPEN|ADC_IER_XRDY|ADC_IER_YRDY|ADC_IER_PRDY);\r
151     }\r
152     else if (status & ADC_ISR_PENS)\r
153     {\r
154         /* X */\r
155         if (status & ADC_ISR_XRDY)\r
156         {\r
157             bTsFlags |= TS_X_RDY;\r
158         }\r
159         /* Y */\r
160         if (status & ADC_ISR_YRDY)\r
161         {\r
162             bTsFlags |= TS_Y_RDY;\r
163         }\r
164         /* P: (X/1024)*[(Z2/Z1)-1] */\r
165         if (status & ADC_ISR_PRDY)\r
166         {\r
167             bTsFlags |= TS_P_RDY;\r
168         }\r
169     }\r
170     /* X,Y,P are ready */\r
171     if ((bTsFlags & TS_DATA_RDY) == TS_DATA_RDY)\r
172     {\r
173         uint32_t xpos, z2, z1;\r
174         bTsFlags &= ~TS_DATA_RDY;\r
175 \r
176         /* Get X,Y */\r
177         TSD_GetRawMeasurement(dwRaw);\r
178 \r
179         /* Interprate X,Y */\r
180         TSDCom_InterpolateMeasurement(dwRaw, dwTsData);\r
181 \r
182         /* Get P: Rp = Rxp*(Xpos/1024)*[(Z2/Z1)-1] */\r
183         dwRaw[2] = ADC_GetTsPressure(pAdc);\r
184         #ifdef TS_XY_SWAP\r
185         xpos = (dwRaw[1]);\r
186         #else\r
187         xpos = (dwRaw[0]);\r
188         #endif\r
189         xpos = (xpos & ADC_XPOSR_XPOS_Msk) >> ADC_XPOSR_XPOS_Pos;\r
190         z2 = (dwRaw[2] & ADC_PRESSR_Z2_Msk) >> ADC_PRESSR_Z2_Pos;\r
191         z1 = (dwRaw[2] & ADC_PRESSR_Z1_Msk) >> ADC_PRESSR_Z1_Pos;\r
192         dwTsData[2] = (xpos) * (z2 - z1) / z1;\r
193 \r
194         /* PenPress */\r
195         if (bTsFlags & TS_PEN_STAT)\r
196         {\r
197             bTsFlags &= ~TS_PEN_STAT;\r
198             /* Invoke PenPress callback */\r
199             if (TSDCom_IsCalibrationOk())\r
200                 TSD_PenPressed(dwTsData[0], dwTsData[1], dwTsData[2]);\r
201         }\r
202         /* Periodic if data change invoke callback */\r
203         if (dwTsData[0] != dwLastTsData[0]\r
204             ||   dwTsData[1] != dwLastTsData[1]\r
205             ||   dwTsData[2] != dwLastTsData[2] )\r
206         {\r
207             /* Register last data */\r
208             memcpy(dwLastTsData, dwTsData, sizeof(dwTsData));\r
209             /* Invoke PenMoved callback */\r
210             if (TSDCom_IsCalibrationOk())\r
211                 TSD_PenMoved(dwTsData[0], dwTsData[1], dwTsData[2]);\r
212         }\r
213         \r
214     }\r
215 }\r
216 \r
217 /*----------------------------------------------------------------------------\r
218  *         Global functions\r
219  *----------------------------------------------------------------------------*/\r
220 \r
221 /**\r
222  * Reads and store a touchscreen measurement in the provided array.\r
223  * The value stored are:\r
224  *  - data[0] = XPOS * 1024 / XSCALE\r
225  *  - data[1] = YPOS * 1024 / YSCALE\r
226  * \param pData  Array where the measurements will be stored\r
227  */\r
228 void TSD_GetRawMeasurement(uint32_t *pData)\r
229 {\r
230     Adc *pAdc = ADC;\r
231     uint32_t xr, yr;\r
232     #ifdef TS_XY_SWAP\r
233     yr = ADC_GetTsXPosition(pAdc);\r
234     xr = ADC_GetTsYPosition(pAdc);\r
235     #else\r
236     xr = ADC_GetTsXPosition(pAdc);\r
237     yr = ADC_GetTsYPosition(pAdc);\r
238     #endif\r
239     pData[0]  = ((xr & ADC_XPOSR_XPOS_Msk) >> ADC_XPOSR_XPOS_Pos) * 1024 * 4;\r
240     pData[0] /= ((xr & ADC_XPOSR_XSCALE_Msk) >> ADC_XPOSR_XSCALE_Pos);\r
241     pData[1]  = ((yr & ADC_YPOSR_YPOS_Msk) >> ADC_YPOSR_YPOS_Pos) * 1024 * 4;\r
242     pData[1] /= ((yr & ADC_YPOSR_YSCALE_Msk) >> ADC_YPOSR_YSCALE_Pos);\r
243 }\r
244 \r
245 /**\r
246  * Wait pen pressed\r
247  */\r
248 void TSD_WaitPenPressed(void)\r
249 {\r
250     Adc *pAdc = ADC;\r
251     uint8_t bFlags = 0;\r
252     uint32_t dwStatus;\r
253     /* Wait for touch & end of conversion */\r
254     while (1)\r
255     {\r
256         dwStatus = ADC_GetStatus(pAdc);\r
257         if (dwStatus & ADC_ISR_PEN) bFlags |= 8;\r
258         if (dwStatus & ADC_ISR_XRDY)bFlags |= 1;\r
259         if (dwStatus & ADC_ISR_YRDY)bFlags |= 2;\r
260         if (dwStatus & ADC_ISR_PRDY)bFlags |= 4;\r
261         if (bFlags == 0xF) break;\r
262     }\r
263 }\r
264 \r
265 /**\r
266  * Wait pen released\r
267  */\r
268 void TSD_WaitPenReleased(void)\r
269 {\r
270     Adc *pAdc = ADC;\r
271 \r
272     /* Wait for contact loss */\r
273     while((ADC_GetStatus(pAdc) & ADC_ISR_NOPEN) == 0);\r
274 }\r
275 \r
276 /**\r
277  * Initializes the touchscreen driver and starts the calibration process. When\r
278  * finished, the touchscreen is operational.\r
279  * The configuration is taken from the board.h of the device being compiled.\r
280  * Important: the LCD driver must have been initialized prior to calling this\r
281  * function.\r
282  */\r
283 void TSD_Initialize(void)\r
284 {\r
285     Adc *pAdc = ADC;\r
286 \r
287     bTsFlags = 0;\r
288 \r
289     /* Configuration */\r
290     PMC_EnablePeripheral(ID_ADC);\r
291 \r
292     ADC_SetClock(pAdc, BOARD_TOUCHSCREEN_ADCCLK, BOARD_MCK);\r
293     ADC_SetStartupTime(pAdc, BOARD_TOUCHSCREEN_STARTUP);\r
294     ADC_SetTrackingTime(pAdc, BOARD_TOUCHSCREEN_SHTIM);\r
295 \r
296     ADC_SetTriggerPeriod(pAdc, 20000000); /*  20ms */\r
297 \r
298     ADC_SetTsMode(pAdc, ADC_TSMR_TSMODE_4_WIRE);\r
299     ADC_SetTsAverage(pAdc, ADC_TSMR_TSAV_NO_FILTER);\r
300 \r
301     ADC_SetTsPenDetect(pAdc, 1);\r
302     ADC_SetTsDebounce(pAdc, BOARD_TOUCHSCREEN_DEBOUNCE);\r
303 \r
304     pAdc->ADC_MR &= ~(3<<28);\r
305     pAdc->ADC_ACR = 0x102;    \r
306 }\r
307 \r
308 /**\r
309  * Enable/Disable TSD capturing\r
310  */\r
311 void TSD_Enable(uint8_t bEnDis)\r
312 {\r
313     Adc *pAdc = ADC;\r
314     if (bEnDis)\r
315     {\r
316         ADC_SetTsAverage(pAdc, ADC_TSMR_TSAV_NO_FILTER);\r
317         ADC_TsCalibration(pAdc);\r
318         ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_PEN_TRIG);\r
319         ADC_EnableIt(pAdc, ADC_IER_PEN);\r
320     }\r
321     else\r
322     {\r
323         ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_NO_TRIGGER);\r
324         ADC_DisableIt(pAdc, TS_STATUSES);\r
325         ADC_GetStatus(pAdc);\r
326         ADC_GetTsXPosition(pAdc);\r
327         ADC_GetTsYPosition(pAdc);\r
328         ADC_GetTsPressure(pAdc);\r
329     }\r
330 }\r
331 \r
332 /**\r
333  * Do touchscreen calibration\r
334  * \param pLcdBuffer  LCD buffer to use for displaying the calibration info.\r
335  * \return 1 if calibration is Ok, 0 else\r
336  */\r
337 uint8_t TSD_Calibrate(void)\r
338 {\r
339     Adc *pAdc = ADC;\r
340     uint8_t ret = 0;\r
341 \r
342     /* Calibration is done only once */\r
343     if(TSDCom_IsCalibrationOk())    return 1;\r
344 \r
345     /* Disable touch */\r
346     TSD_Enable(0);\r
347 \r
348     /* Enable capturing */\r
349     ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_PEN_TRIG);\r
350 \r
351     /* Do calibration */\r
352     ret = TSDCom_Calibrate();\r
353 \r
354     /* Configure interrupt generation\r
355        Do it only if the calibration is Ok. */\r
356     //TSD_Enable(ret);\r
357 \r
358     return ret;\r
359 }\r
360 \r
361 /**\r
362  * Reset/stop the touchscreen\r
363  */\r
364 void TSD_DeInitialize(void)\r
365 {\r
366     Adc *pAdc = ADC;\r
367     /* Disable TS related interrupts */\r
368     ADC_DisableIt(pAdc, TS_STATUSES);\r
369     /* Disable Trigger */\r
370     ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_NO_TRIGGER);\r
371     /* Disable TS mode */\r
372     ADC_SetTsMode(pAdc, ADC_TSMR_TSMODE_NONE);\r
373     bTsFlags = 0;\r
374 }\r
375 \r
376 /**@}*/\r
377 #endif /* #ifdef REG_ADC_TSMR */\r
378 \r