查看: 1492|回复: 0
打印 上一主题 下一主题

在ucgui 上使用 tslib 做触摸屏校正的方法

[复制链接]
跳转到指定楼层
沙发
发表于 2015-9-19 09:56:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前段时间看了百为的tslib的一个例子,成功应用与 ucgui 上。

校正过程:

static BOOL perform_calibration(CALIBRATION_t *cal)
{
    int j;
    float n, x, y, x2, y2, xy, z, zx, zy;
    float det, a, b, c, e, f, i;
    float scaling = 65536.0;

    // Get sums for matrix
    n = x = y = x2 = y2 = xy = 0;

    for (j = 0; j < 5; j++)
    {
        n  += 1.0;
        x  += (float)cal->x[j];
        y  += (float)cal->y[j];
        x2 += (float)(cal->x[j] * cal->x[j]);
        y2 += (float)(cal->y[j] * cal->y[j]);
        xy += (float)(cal->x[j] * cal->y[j]);
    }

    // Get determinant of matrix -- check if determinant is too small
    det = n * (x2 * y2 - xy * xy) + x * (xy * y - x * y2) + y * (x * xy - y * x2);

    if (det < 0.1 && det > -0.1)
    {
        return (FALSE);
    }

    // Get elements of inverse matrix
    a = (x2 * y2 - xy * xy) / det;
    b = (xy * y - x * y2) / det;
    c = (x * xy - y * x2) / det;
    e = (n * y2 - y * y) / det;
    f = (x * y - n * xy) / det;
    i = (n * x2 - x * x) / det;

    // Get sums for x calibration
    z = zx = zy = 0;

    for (j = 0; j < 5; j++)
    {
        z  += (float)cal->xfb[j];
        zx += (float)(cal->xfb[j] * cal->x[j]);
        zy += (float)(cal->xfb[j] * cal->y[j]);
    }

    // Now multiply out to get the calibration for framebuffer x coord
    cal->a[0] = (int)((a * z + b * zx + c * zy) * (scaling));
    cal->a[1] = (int)((b * z + e * zx + f * zy) * (scaling));
    cal->a[2] = (int)((c * z + f * zx + i * zy) * (scaling));

    // Get sums for y calibration
    z = zx = zy = 0;

    for (j = 0; j < 5; j++)
    {
        z  += (float)cal->yfb[j];
        zx += (float)(cal->yfb[j] * cal->x[j]);
        zy += (float)(cal->yfb[j] * cal->y[j]);
    }

    // Now multiply out to get the calibration for framebuffer y coord
    cal->a[3] = (int)((a * z + b * zx + c * zy) * (scaling));
    cal->a[4] = (int)((b * z + e * zx + f * zy) * (scaling));
    cal->a[5] = (int)((c * z + f * zx + i * zy) * (scaling));

    // If we got here, we're OK, so assign scaling to a[6] and return
    cal->a[6] = (int)scaling;

    return (TRUE);
}

/*
    功能:读取触摸屏读坐标,该坐标未做转换,不能直接使用

    返回:0=无效坐标
          1=有效坐标

    说明:本函数连续采样2次,2次采样结果+-5范围内才算有效
*/
static BOOL TOUCH_MeasureXY(int *x, int *y)
{
    int x1, y1;
    int x2, y2;
    int i;

    x1 = TOUCH_X_MeasureX();
    y1 = TOUCH_X_MeasureY();

    for (i = 0; i < 1000; i++);

    x2 = TOUCH_X_MeasureX();
    y2 = TOUCH_X_MeasureY();

    if (ABS(x1 - x2) < 50 && ABS(y1 - y2) < 50)
    {
        *x = (x1 + x2) / 2;
        *y = (y1 + y2) / 2;

        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

static BOOL check_touch_pressed(int xPhys,
                                int yPhys)
{
    if ((xPhys < MIN_AD_X) ||
        (xPhys > MAX_AD_X) ||
        (yPhys < MIN_AD_Y) ||
        (yPhys > MAX_AD_Y))
    {
        return (FALSE);
    }

    return (TRUE);
}

static void get_sample(CALIBRATION_t *cal,
                       int index,
                       int x,
                       int y,
                       BOOL isRight)
{
    int xPhys, yPhys;

    GUI_SetColor(GUI_WHITE);
    GUI_FillCircle(x, y, 10);

    GUI_SetColor(GUI_RED);
    GUI_FillCircle(x, y, 5);

    GUI_SetColor(GUI_WHITE);

    if (isRight)
        GUI_DispStringAt(MSG_PRESS_HERE, x - 80, y - 8);
    else
        GUI_DispStringAt(MSG_PRESS_HERE, x + 20, y - 8);

    // Wait touch to release
    while (1)
    {
        if (TOUCH_MeasureXY(&xPhys, &yPhys))
        {
            if (!check_touch_pressed(xPhys, yPhys))
                break;
        }

        OSTimeDlyHMSM(0, 0, 0, 100);
    }

    // Wait touch pressed
    while(1)
    {
        if (TOUCH_MeasureXY(&xPhys, &yPhys))
        {
            if (check_touch_pressed(xPhys, yPhys))
            {
                if (TOUCH_MeasureXY(&cal->x[index], &cal->y[index]))
                    break;
            }
        }

        OSTimeDlyHMSM(0, 0, 0, 100);
    };

    /* Tell user to release */
    GUI_Clear();

    if (isRight)
        GUI_DispStringAt(MSG_COMPLETE, x - 80, y - 8);
    else
        GUI_DispStringAt(MSG_COMPLETE, x + 20,  y - 8);

    cal->xfb[index] = x;
    cal->yfb[index] = y;
}

/*********************************************************************
*
*       _ExecCalibration
*
**********************************************************************
*/
BOOL ExecCalibration(CALIBRATION_t *cal)
{
    BOOL result;
    GUI_RECT rect;

    int xPhys;
    int yPhys;

    /* _Calibrate upper left */
    GUI_SetBkColor(GUI_RED);
    GUI_Clear();
    GUI_SetFont(&GUI_FontHZ_SimSun_16);

    // Top Left
    get_sample(cal, 0, 50,             50,             FALSE);

    // Top Right
    get_sample(cal, 1, LCD_XSIZE - 50, 50,             TRUE);

    // Bottom Right
    get_sample(cal, 2, LCD_XSIZE - 50, LCD_YSIZE - 50, TRUE);

    // Bottom Left
    get_sample(cal, 3, 50,             LCD_YSIZE - 50, FALSE);

    // Center
    get_sample(cal, 4, LCD_XSIZE / 2,  LCD_YSIZE / 2,  FALSE);

    rect.x0 = 0;
    rect.x1 = LCD_XSIZE;
    rect.y0 = 50;
    rect.y1 = rect.y0 + 20;

    GUI_Clear();

    result = perform_calibration(cal);

    if (result)
        GUI_DispStringInRect(MSG_CALIBRATION_SUCCESSFUL,
                             &rect, GUI_TA_CENTER | GUI_TA_VCENTER);
    else
        GUI_DispStringInRect(MSG_CALIBRATION_SUCCESSFUL,
                             &rect, GUI_TA_CENTER | GUI_TA_VCENTER);

    rect.y0 = 80;
    rect.y1 = rect.y0 + 20;

    GUI_DispNextLine();

    GUI_DispStringInRect(MSG_PRESS_TOUCH_TO_CONTINUE,
                         &rect, GUI_TA_CENTER | GUI_TA_VCENTER);

    OSTimeDlyHMSM(0, 0, 0, 200);

    // Wait the touch to continue
    while (1)
    {
        if (TOUCH_MeasureXY(&xPhys, &yPhys))
        {
            if (check_touch_pressed(xPhys, yPhys))
                break;
        }

        OSTimeDlyHMSM(0, 0, 0, 10);
    }

    return (result);
}

复制代码


因为ucgui 内部使用的是简单的两点校正法,所以我们自己定义 GUI_TOUCH_Exec() 函数。

/*********************************************************************
*
*       _StoreUnstable
*/
static void _StoreUnstable(int x, int y)
{
    static int _xLast = -1;
    static int _yLast = -1;
    int xOut, yOut;

    if ((x != -1) &&
        (y != -1) &&
        (_xLast != -1) &&
        (_yLast != -1))
    {
        xOut = _xLast;
        yOut = _yLast;
    }
    else
    {
        xOut = -1;
        yOut = -1;
    }

    _xLast = x;
    _yLast = y;

    GUI_TOUCH_StoreUnstable(xOut, yOut);
}


/*********************************************************************
*
*       My_GUI_TOUCH_Exec
*/
void My_GUI_TOUCH_Exec()
{
    int xPhys, yPhys;
    int x, y;

    if (TOUCH_MeasureXY(&xPhys, &yPhys))
    {
        /* Convert values into logical values */
        x = (int)((mCurrentSettings.cal.a[0] + mCurrentSettings.cal.a[1] * xPhys +
                   mCurrentSettings.cal.a[2] * yPhys) / mCurrentSettings.cal.a[6]);

        y = (int)((mCurrentSettings.cal.a[3] + mCurrentSettings.cal.a[4] * xPhys +
                   mCurrentSettings.cal.a[5] * yPhys) / mCurrentSettings.cal.a[6]);

        if ((x < 0) || (x > LCD_XSIZE) || (y < 0) || (y > LCD_YSIZE))
        {
            _StoreUnstable(-1, -1);
        }
        else
        {
            _StoreUnstable(x, y);
        }
    }
}
复制代码


替换掉原来的 GUI_TOUCH_Exec 变成 My_GUI_TOUCH_Exec 即可。
转载
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表