1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2011, Atmel Corporation
\r
6 * All rights reserved.
\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
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\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
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
32 /*----------------------------------------------------------------------------
\r
34 *----------------------------------------------------------------------------*/
\r
41 /** \addtogroup tsd_module
\r
45 /*----------------------------------------------------------------------------
\r
47 *----------------------------------------------------------------------------*/
\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
56 /*----------------------------------------------------------------------------
\r
58 *----------------------------------------------------------------------------*/
\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
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
71 /*----------------------------------------------------------------------------
\r
73 *----------------------------------------------------------------------------*/
\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
84 /*----------------------------------------------------------------------------
\r
85 * External functions
\r
86 *----------------------------------------------------------------------------*/
\r
88 extern uint32_t TSD_GetRaw(uint32_t i);
\r
91 * Return raw register value.
\r
93 uint32_t TSD_GetRaw(uint32_t i)
\r
98 /*----------------------------------------------------------------------------
\r
100 *----------------------------------------------------------------------------*/
\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
107 void TSD_Handler(uint32_t dwAdcStatus)
\r
114 status = dwAdcStatus;
\r
115 status &= /*ADC_GetItMask(pAdc) &*/ TS_STATUSES;
\r
116 if (status == 0) return;
\r
119 if (status & ADC_ISR_NOPEN)
\r
121 if ((bTsFlags & TS_PEN_STAT) == 0)
\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
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
140 else if (status & ADC_ISR_PEN)
\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
152 else if (status & ADC_ISR_PENS)
\r
155 if (status & ADC_ISR_XRDY)
\r
157 bTsFlags |= TS_X_RDY;
\r
160 if (status & ADC_ISR_YRDY)
\r
162 bTsFlags |= TS_Y_RDY;
\r
164 /* P: (X/1024)*[(Z2/Z1)-1] */
\r
165 if (status & ADC_ISR_PRDY)
\r
167 bTsFlags |= TS_P_RDY;
\r
170 /* X,Y,P are ready */
\r
171 if ((bTsFlags & TS_DATA_RDY) == TS_DATA_RDY)
\r
173 uint32_t xpos, z2, z1;
\r
174 bTsFlags &= ~TS_DATA_RDY;
\r
177 TSD_GetRawMeasurement(dwRaw);
\r
179 /* Interprate X,Y */
\r
180 TSDCom_InterpolateMeasurement(dwRaw, dwTsData);
\r
182 /* Get P: Rp = Rxp*(Xpos/1024)*[(Z2/Z1)-1] */
\r
183 dwRaw[2] = ADC_GetTsPressure(pAdc);
\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
195 if (bTsFlags & TS_PEN_STAT)
\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
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
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
217 /*----------------------------------------------------------------------------
\r
219 *----------------------------------------------------------------------------*/
\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
228 void TSD_GetRawMeasurement(uint32_t *pData)
\r
233 yr = ADC_GetTsXPosition(pAdc);
\r
234 xr = ADC_GetTsYPosition(pAdc);
\r
236 xr = ADC_GetTsXPosition(pAdc);
\r
237 yr = ADC_GetTsYPosition(pAdc);
\r
239 pData[0] = ((xr & ADC_XPOSR_XPOS_Msk) >> ADC_XPOSR_XPOS_Pos) * 1024 ;
\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 ;
\r
242 pData[1] /= ((yr & ADC_YPOSR_YSCALE_Msk) >> ADC_YPOSR_YSCALE_Pos);
\r
248 void TSD_WaitPenPressed(void)
\r
251 uint8_t bFlags = 0;
\r
253 /* Wait for touch & end of conversion */
\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
266 * Wait pen released
\r
268 void TSD_WaitPenReleased(void)
\r
272 /* Wait for contact loss */
\r
273 while((ADC_GetStatus(pAdc) & ADC_ISR_NOPEN) == 0);
\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
283 void TSD_Initialize(void)
\r
289 /* Configuration */
\r
290 PMC_EnablePeripheral(ID_ADC);
\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
296 ADC_SetTriggerPeriod(pAdc, 20000000); /* 20ms */
\r
298 ADC_SetTsMode(pAdc, ADC_TSMR_TSMODE_4_WIRE);
\r
299 ADC_SetTsAverage(pAdc, ADC_TSMR_TSAV_NO_FILTER);
\r
301 ADC_SetTsPenDetect(pAdc, 1);
\r
302 ADC_SetTsDebounce(pAdc, BOARD_TOUCHSCREEN_DEBOUNCE);
\r
306 * Enable/Disable TSD capturing
\r
308 void TSD_Enable(uint8_t bEnDis)
\r
313 ADC_SetTsAverage(pAdc, ADC_TSMR_TSAV_NO_FILTER);
\r
314 ADC_TsCalibration(pAdc);
\r
315 ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_PEN_TRIG);
\r
316 ADC_EnableIt(pAdc, ADC_IER_PEN);
\r
320 ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_NO_TRIGGER);
\r
321 ADC_DisableIt(pAdc, TS_STATUSES);
\r
322 ADC_GetStatus(pAdc);
\r
323 ADC_GetTsXPosition(pAdc);
\r
324 ADC_GetTsYPosition(pAdc);
\r
325 ADC_GetTsPressure(pAdc);
\r
330 * Do touchscreen calibration
\r
331 * \param pLcdBuffer LCD buffer to use for displaying the calibration info.
\r
332 * \return 1 if calibration is Ok, 0 else
\r
334 uint8_t TSD_Calibrate(void)
\r
339 /* Calibration is done only once */
\r
340 if(TSDCom_IsCalibrationOk()) return 1;
\r
342 /* Disable touch */
\r
345 /* Enable capturing */
\r
346 ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_PEN_TRIG);
\r
348 /* Do calibration */
\r
349 ret = TSDCom_Calibrate();
\r
351 /* Configure interrupt generation
\r
352 Do it only if the calibration is Ok. */
\r
359 * Reset/stop the touchscreen
\r
361 void TSD_DeInitialize(void)
\r
364 /* Disable TS related interrupts */
\r
365 ADC_DisableIt(pAdc, TS_STATUSES);
\r
366 /* Disable Trigger */
\r
367 ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_NO_TRIGGER);
\r
368 /* Disable TS mode */
\r
369 ADC_SetTsMode(pAdc, ADC_TSMR_TSMODE_NONE);
\r
374 #endif /* #ifdef REG_ADC_TSMR */
\r