/** * Interrupt handler for the TouchScreen. * Handles pen press, pen move and pen release events * by invoking three callback functions. */ void TSD_Handler(uint32_t dwAdcStatus) { Adc *pAdc = ADC; uint32_t status; /* TSADC status */ status = dwAdcStatus; status &= /*ADC_GetItMask(pAdc) &*/ TS_STATUSES; if (status == 0) return; /* Pen released */ if (status & ADC_ISR_NOPEN) { if ((bTsFlags & TS_PEN_STAT) == 0) { /* Register last data */ memcpy(dwLastTsData, dwTsData, sizeof(dwTsData)); /* Invoke PenReleased callback */ if (TSDCom_IsCalibrationOk()) TSD_PenReleased(dwTsData[0], dwTsData[1]); } bTsFlags = 0; /* Stop periodic trigger & enable pen */ ADC_SetTsAverage(pAdc, ADC_TSMR_TSAV_NO_FILTER); ADC_SetTsDebounce(pAdc, BOARD_TOUCHSCREEN_DEBOUNCE); ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_PEN_TRIG); /* Disable pen release detect */ ADC_DisableIt(pAdc, ADC_IDR_NOPEN); /* Enable pen press detect */ ADC_EnableIt(pAdc, ADC_IER_PEN); } /* Pen pressed */ else if (status & ADC_ISR_PEN) { bTsFlags |= TS_PEN_STAT; /* Configure for peripdic trigger */ ADC_SetTsAverage(pAdc, ADC_TSMR_TSAV_AVG8CONV); ADC_SetTsDebounce(pAdc, 300); /* 300ns */ ADC_SetTriggerMode(pAdc, ADC_TRGR_TRGMOD_PERIOD_TRIG); /* Disable pen press detect */ ADC_DisableIt(pAdc, ADC_IDR_PEN); /* Enable pen release detect */ ADC_EnableIt(pAdc, ADC_IER_NOPEN|ADC_IER_XRDY|ADC_IER_YRDY|ADC_IER_PRDY); } else if (status & ADC_ISR_PENS) { /* X */ if (status & ADC_ISR_XRDY) { bTsFlags |= TS_X_RDY; } /* Y */ if (status & ADC_ISR_YRDY) { bTsFlags |= TS_Y_RDY; } /* P: (X/1024)*[(Z2/Z1)-1] */ if (status & ADC_ISR_PRDY) { bTsFlags |= TS_P_RDY; } } /* X,Y,P are ready */ if ((bTsFlags & TS_DATA_RDY) == TS_DATA_RDY) { uint32_t xpos, z2, z1; bTsFlags &= ~TS_DATA_RDY; /* Get X,Y */ TSD_GetRawMeasurement(dwRaw); /* Interprate X,Y */ TSDCom_InterpolateMeasurement(dwRaw, dwTsData); /* Get P: Rp = Rxp*(Xpos/1024)*[(Z2/Z1)-1] */ dwRaw[2] = ADC_GetTsPressure(pAdc); #ifdef TS_XY_SWAP xpos = (dwRaw[1]); #else xpos = (dwRaw[0]); #endif xpos = (xpos & ADC_XPOSR_XPOS_Msk) >> ADC_XPOSR_XPOS_Pos; z2 = (dwRaw[2] & ADC_PRESSR_Z2_Msk) >> ADC_PRESSR_Z2_Pos; z1 = (dwRaw[2] & ADC_PRESSR_Z1_Msk) >> ADC_PRESSR_Z1_Pos; dwTsData[2] = (xpos) * (z2 - z1) / z1; /* PenPress */ if (bTsFlags & TS_PEN_STAT) { bTsFlags &= ~TS_PEN_STAT; /* Invoke PenPress callback */ if (TSDCom_IsCalibrationOk()) TSD_PenPressed(dwTsData[0], dwTsData[1], dwTsData[2]); } /* Periodic if data change invoke callback */ if (dwTsData[0] != dwLastTsData[0] || dwTsData[1] != dwLastTsData[1] || dwTsData[2] != dwLastTsData[2] ) { /* Register last data */ memcpy(dwLastTsData, dwTsData, sizeof(dwTsData)); /* Invoke PenMoved callback */ if (TSDCom_IsCalibrationOk()) TSD_PenMoved(dwTsData[0], dwTsData[1], dwTsData[2]); } }
//------------------------------------------------------------------------------ /// Interrupt handler for the TSADC. Handles pen press, pen move and pen release /// events by invoking three callback functions. //------------------------------------------------------------------------------ static void InterruptHandler(void) { unsigned int status; unsigned int data[2]; static unsigned int newPoint[2]; static unsigned int point[2]; static unsigned char report = 0; // Retrieve TADC status // Bug fix: two step operation so IAR doesn't complain that the order of // volatile access is unspecified. status = AT91C_BASE_TSADC->TSADC_SR; status &= AT91C_BASE_TSADC->TSADC_IMR; // Pen release if ((status & AT91C_TSADC_NOCNT) == AT91C_TSADC_NOCNT) { // Invoke PenReleased callback if(TSDCom_IsCalibrationOk()) { TSD_PenReleased(point[0], point[1]); } // Stop periodic trigger mode TSADCC_SetDebounceTime(BOARD_TOUCHSCREEN_DEBOUNCE); AT91C_BASE_TSADC->TSADC_IDR = AT91C_TSADC_EOC3 | AT91C_TSADC_NOCNT; TSADCC_SetTriggerMode(AT91C_TSADC_TRGMOD_PENDET_TRIGGER); TSD_GetRawMeasurement(data); // Clear data registers AT91C_BASE_TSADC->TSADC_SR; AT91C_BASE_TSADC->TSADC_IER = AT91C_TSADC_PENCNT; } // Pen press else if ((status & AT91C_TSADC_PENCNT) == AT91C_TSADC_PENCNT) { // Invoke PenPressed callback with (x,y) coordinates while ((AT91C_BASE_TSADC->TSADC_SR & AT91C_TSADC_EOC3) != AT91C_TSADC_EOC3); TSD_GetRawMeasurement(data); TSDCom_InterpolateMeasurement(data, point); // Invoke PenPressed callback if(TSDCom_IsCalibrationOk()) { TSD_PenPressed(point[0], point[1]); } // Configure TSADC for periodic trigger TSADCC_SetDebounceTime(10); // 1ns AT91C_BASE_TSADC->TSADC_IER = AT91C_TSADC_EOC3 | AT91C_TSADC_NOCNT; AT91C_BASE_TSADC->TSADC_IDR = AT91C_TSADC_PENCNT; TSADCC_SetTriggerPeriod(10000000); // 10ms TSADCC_SetTriggerMode(AT91C_TSADC_TRGMOD_PERIODIC_TRIGGER); report = 0; } // Pen move else if ((status & AT91C_TSADC_EOC3) == AT91C_TSADC_EOC3) { // Invoke callback with LAST value measured // Explanation: the very last value that will be measured (just as the // pen is released) might be corrupted and there is no way to know. So // we just discard it. if (report) { memcpy(point, newPoint, sizeof(newPoint)); // Invoke PenMoved callback if(TSDCom_IsCalibrationOk()) { TSD_PenMoved(point[0], point[1]); } report = 0; } TSD_GetRawMeasurement(data); TSDCom_InterpolateMeasurement(data, newPoint); if ((newPoint[0] != point[0]) || (newPoint[1] != point[1])) { report = 1; } } }