?? tsd_com.c
字號:
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "tsd.h"
#include <board.h>
#include <aic/aic.h>
#include <pio/pio.h>
#include <drivers/lcd/lcdd.h>
#include <drivers/lcd/draw.h>
#include <drivers/lcd/font.h>
#include <drivers/lcd/color.h>
#include <string.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Size in pixels of calibration points.
#define POINTS_SIZE 4
/// Maximum difference in pixels between the test point and the measured point.
#define POINTS_MAX_ERROR 8
/// Delay at the end of calibartion for result display (positive or negative)
#define DELAY_RESULT_DISPLAY 4000000
//------------------------------------------------------------------------------
// Local types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Point used during the touchscreen calibration process.
//------------------------------------------------------------------------------
typedef struct _CalibrationPoint {
/// Coordinate of point along the X-axis of the screen.
unsigned int x;
/// Coordinate of point along the Y-axis of the screen.
unsigned int y;
/// Calibration data of point.
unsigned int data[2];
} CalibrationPoint;
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// indicates if the touch screen has been calibrated.
/// If not, Callback functions are not called
static volatile unsigned char bCalibrationOk = 0;
/// Slope for interpoling touchscreen measurements along the X-axis.
static signed int xSlope;
/// Slope for interpoling touchscreen measurements along the Y-axis.
static signed int ySlope;
/// Calibration points
static CalibrationPoint calibrationPoints[] = {
// Top-left corner calibration point
{
BOARD_LCD_WIDTH / 10,
BOARD_LCD_HEIGHT / 10,
{0, 0}
},
// Top-right corner calibration point
{
BOARD_LCD_WIDTH - BOARD_LCD_WIDTH / 10,
BOARD_LCD_HEIGHT / 10,
{0, 0}
},
// Bottom-right corner calibration point
{
BOARD_LCD_WIDTH - BOARD_LCD_WIDTH / 10,
BOARD_LCD_HEIGHT - BOARD_LCD_HEIGHT / 10,
{0, 0}
},
// Bottom-left corner calibration point
{
BOARD_LCD_WIDTH / 10,
BOARD_LCD_HEIGHT - BOARD_LCD_HEIGHT / 10,
{0, 0}
}
};
/// Test point
static const CalibrationPoint testPoint = {
BOARD_LCD_WIDTH / 2,
BOARD_LCD_HEIGHT / 2,
{0, 0}
};
//------------------------------------------------------------------------------
// External functions
//------------------------------------------------------------------------------
extern void TSD_GetRawMeasurement(unsigned int *pData);
extern void TSD_WaitPenPressed(void);
extern void TSD_WaitPenReleased(void);
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Display a calibration point on the given buffer.
/// \param pLcdBuffer LCD buffer to draw on.
/// \param pPoint Calibration point to display.
//------------------------------------------------------------------------------
static void DrawCalibrationPoint(
void *pLcdBuffer,
const CalibrationPoint *pPoint)
{
LCDD_DrawRectangle(pLcdBuffer,
pPoint->x - POINTS_SIZE / 2,
pPoint->y - POINTS_SIZE / 2,
POINTS_SIZE,
POINTS_SIZE,
COLOR_RED);
}
//------------------------------------------------------------------------------
/// Clears a calibration point from the given buffer.
/// \param pLcdBuffer LCD buffer to draw on.
/// \param pPoint Calibration point to clear.
//------------------------------------------------------------------------------
static void ClearCalibrationPoint(
void *pLcdBuffer,
const CalibrationPoint *pPoint)
{
LCDD_DrawRectangle(pLcdBuffer,
pPoint->x - POINTS_SIZE / 2,
pPoint->y - POINTS_SIZE / 2,
POINTS_SIZE,
POINTS_SIZE,
COLOR_WHITE);
}
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Indicates if the calibration of the touch screen is Ok
/// \return 1 calibration Ok, 0 if not
//------------------------------------------------------------------------------
unsigned char TSDCom_IsCalibrationOk(void)
{
return bCalibrationOk;
}
//------------------------------------------------------------------------------
/// Interpolates the provided raw measurements using the previously calculated
/// slope. The resulting x and y coordinates are stored in an array.
/// \param pData Raw measurement data, as returned by TSD_GetRawMeasurement().
/// \param pPoint Array in which x and y will be stored.
//------------------------------------------------------------------------------
void TSDCom_InterpolateMeasurement(const unsigned int *pData, unsigned int *pPoint)
{
pPoint[0] = calibrationPoints[0].x
- (((signed int) calibrationPoints[0].data[0] - (signed int) pData[0]) * 1024)
/ xSlope;
pPoint[1] = calibrationPoints[0].y
- (((signed int) calibrationPoints[0].data[1] - (signed int) pData[1]) * 1024)
/ ySlope;
if(pPoint[0] & 0x80000000) // Is pPoint[0] negative ?
{
pPoint[0] = 0;
}
if(pPoint[0] > BOARD_LCD_WIDTH) // Is pPoint[0] bigger than the LCD width ?
{
pPoint[0] = BOARD_LCD_WIDTH;
}
if(pPoint[1] & 0x80000000) // Is pPoint[1] negative ?
{
pPoint[1] = 0;
}
if(pPoint[1] > BOARD_LCD_HEIGHT) // Is pPoint[1] bigger than the LCD width ?
{
pPoint[1] = BOARD_LCD_HEIGHT;
}
}
//------------------------------------------------------------------------------
/// 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)
{
void *pOldLcdBuffer;
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);
pOldLcdBuffer = LCDD_DisplayBuffer(pLcdBuffer);
// 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++);
// Restore old LCD buffer
LCDD_DisplayBuffer(pOldLcdBuffer);
return (xOk && yOk);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -