/**
 * 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]);
        }
        
    }
Пример #2
0
//------------------------------------------------------------------------------
/// 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;
        }
    }
}