PageRenderTime 550ms CodeModel.GetById 141ms app.highlight 224ms RepoModel.GetById 178ms app.codeStats 1ms

/src/backend/sylixos_gmem/ftk_tscalibrate_sylixos.c

http://ftk.googlecode.com/
C | 601 lines | 451 code | 81 blank | 69 comment | 51 complexity | b8ac204f73bde0aa7b99e15de8a158bb MD5 | raw file
  1/*
  2 * File: ftk_tscalibrate_sylixos.c
  3 * Author:  JiaoJinXing <jiaojinxing1987@gmail.com>
  4 * Brief:   sylixos touchscreen calibrate.
  5 *
  6 * Copyright (c) 2009 - 2010  Li XianJing <xianjimli@hotmail.com>
  7 *
  8 * Licensed under the Academic Free License version 2.1
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License as published by
 12 * the Free Software Foundation; either version 2 of the License, or
 13 * (at your option) any later version.
 14 *
 15 * This program is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 * GNU General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU General Public License
 21 * along with this program; if not, write to the Free Software
 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23 */
 24
 25/*
 26 * History:
 27 * ================================================================
 28 * 2011-07-08 JiaoJinXing <jiaojinxing1987@gmail.com> created
 29 *
 30 */
 31
 32/*
 33 *  tslib/tests/ts_calibrate.c
 34 *
 35 *  Copyright (C) 2001 Russell King.
 36 *
 37 * This file is placed under the GPL.  Please see the file
 38 * COPYING for more details.
 39 *
 40 * $Id: ts_calibrate.c,v 1.8 2004/10/19 22:01:27 dlowder Exp $
 41 *
 42 * Basic test program for touchscreen library.
 43 */
 44
 45#include "ftk_display_sylixos.h"

 46#include "ftk_source_sylixos.h"

 47#include "ftk_tscalibrate_sylixos.h"

 48#include <string.h>

 49#include <mouse.h>

 50#include <input_device.h>

 51#include "font.h"

 52
 53void* ftk_display_bits(FtkDisplay* thiz, int* bpp);
 54
 55union multiptr
 56{
 57    unsigned char  *p8;
 58    unsigned short *p16;
 59    unsigned long  *p32;
 60};
 61
 62#define XORMODE 0x80000000

 63
 64static inline void __set_pixel(unsigned int   bpp,
 65                               union multiptr loc,
 66                               unsigned int   xormode,
 67                               unsigned int   color)
 68{
 69    switch(bpp)
 70    {
 71    case 1:
 72    default:
 73        if (xormode)
 74            *loc.p8 ^= color;
 75        else
 76            *loc.p8 = color;
 77        break;
 78
 79    case 2:
 80        if (xormode)
 81            *loc.p16 ^= color;
 82        else
 83            *loc.p16 = color;
 84        break;
 85
 86    case 4:
 87        if (xormode)
 88            *loc.p32 ^= color;
 89        else
 90            *loc.p32 = color;
 91        break;
 92    }
 93}
 94
 95static void draw_pixel(FtkDisplay* display, int x, int y, unsigned int colidx)
 96{
 97    void*          bits;
 98    int            bpp;
 99    unsigned int   xormode;
100    union multiptr loc;
101
102    if ((x < 0) || (x >= ftk_display_width(display)) ||
103        (y < 0) || (y >= ftk_display_height(display)))
104    {
105        return;
106    }
107
108    bits    = ftk_display_bits(display, &bpp);
109    loc.p8  = (unsigned char *)bits + (ftk_display_width(display) * y + x) * bpp;
110
111    xormode = colidx & XORMODE;
112    colidx &= ~XORMODE;
113
114    __set_pixel(bpp, loc, xormode, colidx);
115}
116
117static void draw_line(FtkDisplay* display, int x1, int y1, int x2, int y2, unsigned int colidx)
118{
119    int tmp;
120    int dx = x2 - x1;
121    int dy = y2 - y1;
122
123    if (abs(dx) < abs(dy))
124    {
125        if (y1 > y2)
126        {
127            tmp = x1; x1 = x2; x2 = tmp;
128            tmp = y1; y1 = y2; y2 = tmp;
129            dx = -dx; dy = -dy;
130        }
131        x1 <<= 16;
132        /* dy is apriori >0 */
133        dx = (dx << 16) / dy;
134        while (y1 <= y2)
135        {
136            draw_pixel(display, x1 >> 16, y1, colidx);
137            x1 += dx;
138            y1++;
139        }
140    }
141    else
142    {
143        if (x1 > x2)
144        {
145            tmp = x1; x1 = x2; x2 = tmp;
146            tmp = y1; y1 = y2; y2 = tmp;
147            dx = -dx; dy = -dy;
148        }
149        y1 <<= 16;
150        dy = dx ? (dy << 16) / dx : 0;
151        while (x1 <= x2)
152        {
153            draw_pixel(display, x1, y1 >> 16, colidx);
154            y1 += dy;
155            x1++;
156        }
157    }
158}
159
160static void draw_cross(FtkDisplay* display, int x, int y, unsigned int colidx)
161{
162    draw_line(display, x - 10, y, x - 2, y, colidx);
163    draw_line(display, x + 2, y, x + 10, y, colidx);
164    draw_line(display, x, y - 10, x, y - 2, colidx);
165    draw_line(display, x, y + 2, x, y + 10, colidx);
166
167    draw_line(display, x - 6, y - 9, x - 9, y - 9, colidx);
168    draw_line(display, x - 9, y - 8, x - 9, y - 6, colidx);
169    draw_line(display, x - 9, y + 6, x - 9, y + 9, colidx);
170    draw_line(display, x - 8, y + 9, x - 6, y + 9, colidx);
171    draw_line(display, x + 6, y + 9, x + 9, y + 9, colidx);
172    draw_line(display, x + 9, y + 8, x + 9, y + 6, colidx);
173    draw_line(display, x + 9, y - 6, x + 9, y - 9, colidx);
174    draw_line(display, x + 8, y - 9, x + 6, y - 9, colidx);
175}
176
177static void put_char(FtkDisplay* display, int x, int y, int c, unsigned int colidx)
178{
179    int i, j, bits;
180
181    for (i = 0; i < font_vga_8x16.height; i++)
182    {
183        bits = font_vga_8x16.data[font_vga_8x16.height * c + i];
184        for (j = 0; j < font_vga_8x16.width; j++, bits <<= 1)
185        {
186            if (bits & 0x80)
187            {
188                draw_pixel(display, x + j, y + i, colidx);
189            }
190            else
191            {
192                draw_pixel(display, x + j, y + i, 0);
193            }
194        }
195    }
196}
197
198static void put_string(FtkDisplay* display, int x, int y, const char *s, unsigned int colidx)
199{
200    int i;
201
202    for (i = 0; *s; i++, x += font_vga_8x16.width, s++)
203    {
204        put_char(display, x, y, *s, colidx);
205    }
206}
207
208static void put_string_center(FtkDisplay* display, int x, int y, const char *s, unsigned int colidx)
209{
210    size_t sl = strlen (s);
211
212    put_string(display,
213               x - (sl / 2) * font_vga_8x16.width,
214               y - font_vga_8x16.height / 2,
215               s,
216               colidx);
217}
218
219typedef struct
220{
221    int x[5], xfb[5];
222    int y[5], yfb[5];
223    int a[7];
224} calibration;
225
226struct ts_sample
227{
228    int          x;
229    int          y;
230    unsigned int pressure;
231};
232
233static int ts_read_raw(int ts_fd, struct ts_sample* samp, int nr)
234{
235    touchscreen_event_notify notify;
236    fd_set                   rfds;
237
238    FD_ZERO(&rfds);
239
240    FD_SET(ts_fd, &rfds);
241
242    if (select(ts_fd + 1, &rfds, NULL, NULL, NULL) != 1)
243    {
244        return -1;
245    }
246
247    if (read(ts_fd, (char *)&notify, sizeof(touchscreen_event_notify)) == sizeof(touchscreen_event_notify))
248    {
249        samp->x        = notify.xanalog;
250        samp->y        = notify.yanalog;
251        samp->pressure = notify.kstat & MOUSE_LEFT;
252        return 1;
253    }
254    else
255    {
256        return -1;
257    }
258}
259
260static int sort_by_x(const void* a, const void* b)
261{
262    return (((struct ts_sample*)a)->x - ((struct ts_sample*)b)->x);
263}
264
265static int sort_by_y(const void* a, const void* b)
266{
267    return (((struct ts_sample*)a)->y - ((struct ts_sample*)b)->y);
268}
269
270static void get_xy(int ts_fd, FtkDisplay* display, int* x, int* y)
271{
272#define MAX_SAMPLES 128

273    struct ts_sample samp[MAX_SAMPLES];
274    int index, middle;
275
276    do
277    {
278        if (ts_read_raw(ts_fd, &samp[0], 1) < 0)
279        {
280            perror("ts_read_raw");
281            continue;
282        }
283    } while (samp[0].pressure == 0);
284
285    /* Now collect up to MAX_SAMPLES touches into the samp array. */
286    index = 0;
287    do
288    {
289        if (index < MAX_SAMPLES - 1)
290        {
291            index++;
292        }
293        if (ts_read_raw(ts_fd, &samp[index], 1) < 0)
294        {
295            perror("ts_read_raw");
296            continue;
297        }
298    } while (samp[index].pressure > 0);
299
300    printf("Took %d samples...\n", index);
301
302    /*
303     * At this point, we have samples in indices zero to (index-1)
304     * which means that we have (index) number of samples.  We want
305     * to calculate the median of the samples so that wild outliers
306     * don't skew the result.  First off, let's assume that arrays
307     * are one-based instead of zero-based.  If this were the case
308     * and index was odd, we would need sample number ((index+1)/2)
309     * of a sorted array; if index was even, we would need the
310     * average of sample number (index/2) and sample number
311     * ((index/2)+1).  To turn this into something useful for the
312     * real world, we just need to subtract one off of the sample
313     * numbers.  So for when index is odd, we need sample number
314     * (((index+1)/2)-1).  Due to integer division truncation, we
315     * can simplify this to just (index/2).  When index is even, we
316     * need the average of sample number ((index/2)-1) and sample
317     * number (index/2).  Calculate (index/2) now and we'll handle
318     * the even odd stuff after we sort.
319     */
320    middle = index / 2;
321    if (x)
322    {
323        qsort(samp, index, sizeof(struct ts_sample), sort_by_x);
324        if (index & 1)
325        {
326            *x = samp[middle].x;
327        }
328        else
329        {
330            *x = (samp[middle-1].x + samp[middle].x) / 2;
331        }
332    }
333
334    if (y)
335    {
336        qsort(samp, index, sizeof(struct ts_sample), sort_by_y);
337        if (index & 1)
338        {
339            *y = samp[middle].y;
340        }
341        else
342        {
343            *y = (samp[middle-1].y + samp[middle].y) / 2;
344        }
345    }
346}
347
348static void get_sample(int ts_fd, FtkDisplay* display, calibration* cal, int index, int x, int y, const char* name)
349{
350    static int last_x = -1, last_y;
351
352    put_string_center(display,
353                      ftk_display_width(display) / 2,
354                      ftk_display_height(display) / 4 + 60,
355                      name,
356                      0x0fffffff);
357
358    if (last_x != -1)
359    {
360#define NR_STEPS 10

361        int dx = ((x - last_x) << 16) / NR_STEPS;
362        int dy = ((y - last_y) << 16) / NR_STEPS;
363        int i;
364
365        last_x <<= 16;
366        last_y <<= 16;
367        for (i = 0; i < NR_STEPS; i++)
368        {
369            draw_cross(display, last_x >> 16, last_y >> 16, 0x0fffffff | XORMODE);
370            usleep(1000);
371            draw_cross(display, last_x >> 16, last_y >> 16, 0x0fffffff | XORMODE);
372            last_x += dx;
373            last_y += dy;
374        }
375    }
376
377    draw_cross(display, x, y, 0x0fffffff | XORMODE);
378    get_xy(ts_fd, display, &cal->x[index], &cal->y[index]);
379    draw_cross(display, x, y, 0x0fffffff | XORMODE);
380
381    last_x = cal->xfb[index] = x;
382    last_y = cal->yfb[index] = y;
383
384    printf("%s : X = %4d Y = %4d\n", name, cal->x[index], cal->y[index]);
385}
386
387static int perform_calibration(calibration* cal)
388{
389    int   j;
390    float n, x, y, x2, y2, xy, z, zx, zy;
391    float det, a, b, c, e, f, i;
392    float scaling = 65536.0;
393
394    // Get sums for matrix
395    n = x = y = x2 = y2 = xy = 0;
396    for (j = 0; j < 5; j++)
397    {
398        n  += 1.0;
399        x  += (float)cal->x[j];
400        y  += (float)cal->y[j];
401        x2 += (float)(cal->x[j]*cal->x[j]);
402        y2 += (float)(cal->y[j]*cal->y[j]);
403        xy += (float)(cal->x[j]*cal->y[j]);
404    }
405
406    // Get determinant of matrix -- check if determinant is too small
407    det = n*(x2*y2 - xy*xy) + x*(xy*y - x*y2) + y*(x*xy - y*x2);
408    if (det < 0.1 && det > -0.1)
409    {
410        printf("ts_calibrate: determinant is too small -- %f\n", det);
411        return 0;
412    }
413
414    // Get elements of inverse matrix
415    a = (x2*y2 - xy*xy) / det;
416    b = (xy*y  - x*y2)  / det;
417    c = (x*xy  - y*x2)  / det;
418    e = (n*y2  - y*y)   / det;
419    f = (x*y   - n*xy)  / det;
420    i = (n*x2  - x*x)   / det;
421
422    // Get sums for x calibration
423    z = zx = zy = 0;
424    for (j = 0; j < 5; j++)
425    {
426        z  += (float) cal->xfb[j];
427        zx += (float)(cal->xfb[j]*cal->x[j]);
428        zy += (float)(cal->xfb[j]*cal->y[j]);
429    }
430
431    // Now multiply out to get the calibration for framebuffer x coord
432    cal->a[0] = (int)((a*z + b*zx + c*zy)*(scaling));
433    cal->a[1] = (int)((b*z + e*zx + f*zy)*(scaling));
434    cal->a[2] = (int)((c*z + f*zx + i*zy)*(scaling));
435
436    printf("%f %f %f\n",
437            (a*z + b*zx + c*zy),
438            (b*z + e*zx + f*zy),
439            (c*z + f*zx + i*zy));
440
441    // Get sums for y calibration
442    z = zx = zy = 0;
443    for (j = 0; j < 5; j++)
444    {
445        z  += (float) cal->yfb[j];
446        zx += (float)(cal->yfb[j]*cal->x[j]);
447        zy += (float)(cal->yfb[j]*cal->y[j]);
448    }
449
450    // Now multiply out to get the calibration for framebuffer y coord
451    cal->a[3] = (int)((a*z + b*zx + c*zy)*(scaling));
452    cal->a[4] = (int)((b*z + e*zx + f*zy)*(scaling));
453    cal->a[5] = (int)((c*z + f*zx + i*zy)*(scaling));
454
455    printf("%f %f %f\n",
456            (a*z + b*zx + c*zy),
457            (b*z + e*zx + f*zy),
458            (c*z + f*zx + i*zy));
459
460    // If we got here, we're OK, so assign scaling to a[6] and return
461    cal->a[6] = (int)scaling;
462
463    return 1;
464}
465
466int ftk_sylixos_touchscreen_calibrate(int argc, char *argv[])
467{
468    FtkDisplay*  display;
469    char         namebuffer[PATH_MAX + 1];
470    char*        name;
471    calibration  cal;
472    int          xres;
473    int          yres;
474    int          cal_fd;
475    int          ts_fd;
476    unsigned int i;
477    struct stat  sbuf;
478    void*        bits;
479    int          bpp;
480
481    if (getenv_r("TSLIB_CALIBFILE", namebuffer, PATH_MAX + 1) >= 0)
482    {
483        name = namebuffer;
484    }
485    else
486    {
487        name = FTK_DEFAULT_CALIBFILE;
488    }
489
490    if (!(argc > 1 && (strcmp(argv[1], "ts") == 0)))
491    {
492        if (stat(name, &sbuf) == 0)
493        {
494            return 0;
495        }
496    }
497
498    if (getenv_r("FRAMEBUFFER", namebuffer, PATH_MAX + 1) >= 0)
499    {
500        name = namebuffer;
501    }
502    else
503    {
504        name = FTK_DEFAULT_FRAMEBUFFER;
505    }
506
507    display = ftk_display_sylixos_create(name);
508    if (display == NULL)
509    {
510        return -1;
511    }
512
513    xres = ftk_display_width(display);
514    yres = ftk_display_height(display);
515
516    bits = ftk_display_bits(display, &bpp);
517    memset(bits, 0x00, xres * yres * bpp);
518
519    if (getenv_r("TSLIB_TSDEVICE", namebuffer, PATH_MAX + 1) >= 0)
520    {
521        name = namebuffer;
522    }
523    else
524    {
525        name = FTK_DEFAULT_TOUCH;
526    }
527
528    ts_fd = open(name, O_RDONLY, 0666);
529    if (ts_fd < 0)
530    {
531        ftk_display_destroy(display);
532        return -1;
533    }
534
535    put_string_center(display,
536                      xres / 2,
537                      yres / 4,
538                      "TSLIB calibration utility",
539                      0x0fffffff);
540
541    put_string_center(display,
542                      xres / 2,
543                      yres / 4 + 20,
544                      "Touch crosshair to calibrate",
545                      0x0fffffff);
546
547    printf("xres = %d, yres = %d\n", xres, yres);
548
549    get_sample(ts_fd, display, &cal, 0, 50,        50,        "  Top left  ");
550    get_sample(ts_fd, display, &cal, 1, xres - 50, 50,        "  Top right ");
551    get_sample(ts_fd, display, &cal, 2, xres - 50, yres - 50, "Bottom right");
552    get_sample(ts_fd, display, &cal, 3, 50,        yres - 50, "Bottom left ");
553    get_sample(ts_fd, display, &cal, 4, xres / 2,  yres / 2,  "   Center   ");
554
555    if (perform_calibration(&cal))
556    {
557        printf("Calibration constants: ");
558        for (i = 0; i < 7; i++)
559        {
560            printf("%d ", cal.a[i]);
561        }
562        printf("\n");
563
564        if (getenv_r("TSLIB_CALIBFILE", namebuffer, PATH_MAX + 1) >= 0)
565        {
566            name = namebuffer;
567        }
568        else
569        {
570            name = FTK_DEFAULT_CALIBFILE;
571        }
572
573        cal_fd = creat(name, 0666);
574
575        sprintf(namebuffer, "%d %d %d %d %d %d %d",
576                cal.a[1],
577                cal.a[2],
578                cal.a[0],
579                cal.a[4],
580                cal.a[5],
581                cal.a[3],
582                cal.a[6]);
583
584        write(cal_fd, namebuffer, strlen(namebuffer) + 1);
585
586        close(cal_fd);
587
588        i = 0;
589    }
590    else
591    {
592        printf("Calibration failed.\n");
593        i = -1;
594    }
595
596    ftk_display_destroy(display);
597
598    close(ts_fd);
599
600    return i;
601}