/** * \brief Performs the calibration process using the provided buffer to display * information. * * \return True if calibration was successful; otherwise false. */ uint8_t TSDCom_Calibrate(void) { volatile uint32_t i; /* to keep the tempo with gcc code optimisation */ int32_t slope1, slope2; CalibrationPoint measuredPoint; uint8_t xOk, yOk; int32_t xDiff, yDiff; /* Calibration setup */ LCDD_Fill(COLOR_WHITE); LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK); LCDD_DrawString(1, 140, (uint8_t *)"Touch the dots to\ncalibrate the screen", COLOR_DARKBLUE); /* Calibration points */ for (i=0; i < 4; i++) { DrawCalibrationPoint(&calibrationPoints[i]); /* Wait for touch & end of conversion */ TSD_WaitPenPressed(); TSD_GetRawMeasurement(calibrationPoints[i].data); ClearCalibrationPoint(&calibrationPoints[i]); /* Wait for contact loss */ TSD_WaitPenReleased(); } /** * Calculate slopes using the calibration data * Theory behind those calculations: * - We suppose the touchscreen measurements are linear, so the following equations are true (simple * linear regression) for any two 'a' and 'b' points of the screen: * dx = (a.data[0] - b.data[0]) / (a.x - b.x) * dy = (a.data[1] - b.data[1]) / (a.y - b.y) * * - We calculate dx and dy (called xslope and yslope here) using the calibration points. * * - We can then use dx and dy to infer the position of a point 'p' given the measurements performed * by the touchscreen ('c' is any of the calibration points): * dx = (p.data[0] - c.data[0]) / (p.x - c.x) * dy = (p.data[1] - c.data[1]) / (p.y - c.y) * Thus: * p.x = c.x - (p.data[0] - c.data[0]) / dx * p.y = c.y - (p.data[1] - c.data[1]) / dy * * - Since there are four calibration points, dx and dy can be calculated twice, so we average * the two values. */ slope1 = ((int32_t) calibrationPoints[0].data[0]) - ((int32_t) calibrationPoints[1].data[0]); slope1 *= 1024; slope1 /= ((int32_t) calibrationPoints[0].x) - ((int32_t) calibrationPoints[1].x); slope2 = ((int32_t) calibrationPoints[2].data[0]) - ((int32_t) calibrationPoints[3].data[0]); slope2 *= 1024; slope2 /= ((int32_t) calibrationPoints[2].x) - ((int32_t) calibrationPoints[3].x); xSlope = (slope1 + slope2) / 2; slope1 = ((int32_t) calibrationPoints[0].data[1]) - ((int32_t) calibrationPoints[2].data[1]); slope1 *= 1024; slope1 /= ((int32_t) calibrationPoints[0].y) - ((int32_t) calibrationPoints[2].y); slope2 = ((int32_t) calibrationPoints[1].data[1]) - ((int32_t) calibrationPoints[3].data[1]); slope2 *= 1024; slope2 /= ((int32_t) calibrationPoints[1].y) - ((int32_t) calibrationPoints[3].y); ySlope = (slope1 + slope2) / 2; /* Test point */ LCDD_Fill(0xFFFFFF); LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK); LCDD_DrawString(1, 100, (uint8_t *)" Touch the point to\nvalidate calibration", COLOR_DARKBLUE); DrawCalibrationPoint(&testPoint); /* Wait for touch & end of conversion */ TSD_WaitPenPressed(); TSD_GetRawMeasurement(measuredPoint.data); TSDCom_InterpolateMeasurement(measuredPoint.data, (uint32_t *) &measuredPoint); DrawCalibrationPoint(&measuredPoint); /* Check resulting x and y */ xDiff = (int32_t) measuredPoint.x - (int32_t) testPoint.x; yDiff = (int32_t) measuredPoint.y - (int32_t) testPoint.y; xOk = (xDiff >= -POINTS_MAX_ERROR) && (xDiff <= POINTS_MAX_ERROR); yOk = (yDiff >= -POINTS_MAX_ERROR) && (yDiff <= POINTS_MAX_ERROR); /* Wait for contact loss */ TSD_WaitPenReleased(); /* Check calibration result */ if (xOk && yOk) { bCalibrationOk = 1; LCDD_Fill(COLOR_WHITE); LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK); LCDD_DrawString(80, 140, (uint8_t *)"Success !", COLOR_GREEN); } else { bCalibrationOk = 0; LCDD_Fill(COLOR_WHITE); LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK); LCDD_DrawString(40, 140, (uint8_t *)"Error too big", COLOR_RED); } /* Slight delay */ for (i = 0; i < DELAY_RESULT_DISPLAY; i++); return (xOk && yOk); }
//------------------------------------------------------------------------------ /// Performs the calibration process using the provided buffer to display /// information. /// \param pLcdBuffer LCD buffer to display. /// \return True if calibration was successful; otherwise false. //------------------------------------------------------------------------------ unsigned char TSDCom_Calibrate(void *pLcdBuffer) { #ifdef AT91C_ID_LCDC void *pOldLcdBuffer; #endif volatile unsigned int i; // to keep the tempo with gcc code optimisation signed int slope1, slope2; CalibrationPoint measuredPoint; unsigned char xOk, yOk; signed int xDiff, yDiff; // Calibration setup LCDD_Fill(pLcdBuffer, COLOR_WHITE); LCDD_DrawString(pLcdBuffer, 30, 50, "LCD calibration", COLOR_BLACK); LCDD_DrawString(pLcdBuffer, 1, 100, " Touch the dots to\ncalibrate the screen", COLOR_DARKBLUE); #ifdef AT91C_ID_LCDC pOldLcdBuffer = LCDD_DisplayBuffer(pLcdBuffer); #endif // Calibration points for (i=0; i < 4; i++) { DrawCalibrationPoint(pLcdBuffer, &calibrationPoints[i]); // Wait for touch & end of conversion TSD_WaitPenPressed(); TSD_GetRawMeasurement(calibrationPoints[i].data); ClearCalibrationPoint(pLcdBuffer, &calibrationPoints[i]); // Wait for contact loss TSD_WaitPenReleased(); } // Calculate slopes using the calibration data // Theory behind those calculations: // - We suppose the touchscreen measurements are linear, so the following equations are true (simple // linear regression) for any two 'a' and 'b' points of the screen: // dx = (a.data[0] - b.data[0]) / (a.x - b.x) // dy = (a.data[1] - b.data[1]) / (a.y - b.y) // // - We calculate dx and dy (called xslope and yslope here) using the calibration points. // // - We can then use dx and dy to infer the position of a point 'p' given the measurements performed // by the touchscreen ('c' is any of the calibration points): // dx = (p.data[0] - c.data[0]) / (p.x - c.x) // dy = (p.data[1] - c.data[1]) / (p.y - c.y) // Thus: // p.x = c.x - (p.data[0] - c.data[0]) / dx // p.y = c.y - (p.data[1] - c.data[1]) / dy // // - Since there are four calibration points, dx and dy can be calculated twice, so we average // the two values. slope1 = ((signed int) calibrationPoints[0].data[0]) - ((signed int) calibrationPoints[1].data[0]); slope1 *= 1024; slope1 /= ((signed int) calibrationPoints[0].x) - ((signed int) calibrationPoints[1].x); slope2 = ((signed int) calibrationPoints[2].data[0]) - ((signed int) calibrationPoints[3].data[0]); slope2 *= 1024; slope2 /= ((signed int) calibrationPoints[2].x) - ((signed int) calibrationPoints[3].x); xSlope = (slope1 + slope2) / 2; slope1 = ((signed int) calibrationPoints[0].data[1]) - ((signed int) calibrationPoints[2].data[1]); slope1 *= 1024; slope1 /= ((signed int) calibrationPoints[0].y) - ((signed int) calibrationPoints[2].y); slope2 = ((signed int) calibrationPoints[1].data[1]) - ((signed int) calibrationPoints[3].data[1]); slope2 *= 1024; slope2 /= ((signed int) calibrationPoints[1].y) - ((signed int) calibrationPoints[3].y); ySlope = (slope1 + slope2) / 2; // Test point LCDD_Fill(pLcdBuffer, 0xFFFFFF); LCDD_DrawString(pLcdBuffer, 30, 50, "LCD calibration", COLOR_BLACK); LCDD_DrawString(pLcdBuffer, 1, 100, " Touch the point to\nvalidate calibration", COLOR_DARKBLUE); DrawCalibrationPoint(pLcdBuffer, &testPoint); // Wait for touch & end of conversion TSD_WaitPenPressed(); TSD_GetRawMeasurement(measuredPoint.data); TSDCom_InterpolateMeasurement(measuredPoint.data, (unsigned int *) &measuredPoint); DrawCalibrationPoint(pLcdBuffer, &measuredPoint); // Check resulting x and y xDiff = (signed int) measuredPoint.x - (signed int) testPoint.x; yDiff = (signed int) measuredPoint.y - (signed int) testPoint.y; xOk = (xDiff >= -POINTS_MAX_ERROR) && (xDiff <= POINTS_MAX_ERROR); yOk = (yDiff >= -POINTS_MAX_ERROR) && (yDiff <= POINTS_MAX_ERROR); // Wait for contact loss TSD_WaitPenReleased(); // Check calibration result if (xOk && yOk) { bCalibrationOk = 1; LCDD_Fill(pLcdBuffer, COLOR_WHITE); LCDD_DrawString(pLcdBuffer, 30, 50, "LCD calibration", COLOR_BLACK); LCDD_DrawString(pLcdBuffer, 80, 100, "Success !", COLOR_GREEN); } else { bCalibrationOk = 0; LCDD_Fill(pLcdBuffer, COLOR_WHITE); LCDD_DrawString(pLcdBuffer, 30, 50, "LCD calibration", COLOR_BLACK); LCDD_DrawString(pLcdBuffer, 40, 100, "Error too big", COLOR_RED); } // Slight delay for (i = 0; i < DELAY_RESULT_DISPLAY; i++); #ifdef AT91C_ID_LCDC // Restore old LCD buffer LCDD_DisplayBuffer(pOldLcdBuffer); #endif return (xOk && yOk); }