/src/backend/sylixos_gmem/ftk_tscalibrate_sylixos.c

http://ftk.googlecode.com/ · C · 601 lines · 451 code · 81 blank · 69 comment · 52 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. * History:
  26. * ================================================================
  27. * 2011-07-08 JiaoJinXing <jiaojinxing1987@gmail.com> created
  28. *
  29. */
  30. /*
  31. * tslib/tests/ts_calibrate.c
  32. *
  33. * Copyright (C) 2001 Russell King.
  34. *
  35. * This file is placed under the GPL. Please see the file
  36. * COPYING for more details.
  37. *
  38. * $Id: ts_calibrate.c,v 1.8 2004/10/19 22:01:27 dlowder Exp $
  39. *
  40. * Basic test program for touchscreen library.
  41. */
  42. #include "ftk_display_sylixos.h"
  43. #include "ftk_source_sylixos.h"
  44. #include "ftk_tscalibrate_sylixos.h"
  45. #include <string.h>
  46. #include <mouse.h>
  47. #include <input_device.h>
  48. #include "font.h"
  49. void* ftk_display_bits(FtkDisplay* thiz, int* bpp);
  50. union multiptr
  51. {
  52. unsigned char *p8;
  53. unsigned short *p16;
  54. unsigned long *p32;
  55. };
  56. #define XORMODE 0x80000000
  57. static inline void __set_pixel(unsigned int bpp,
  58. union multiptr loc,
  59. unsigned int xormode,
  60. unsigned int color)
  61. {
  62. switch(bpp)
  63. {
  64. case 1:
  65. default:
  66. if (xormode)
  67. *loc.p8 ^= color;
  68. else
  69. *loc.p8 = color;
  70. break;
  71. case 2:
  72. if (xormode)
  73. *loc.p16 ^= color;
  74. else
  75. *loc.p16 = color;
  76. break;
  77. case 4:
  78. if (xormode)
  79. *loc.p32 ^= color;
  80. else
  81. *loc.p32 = color;
  82. break;
  83. }
  84. }
  85. static void draw_pixel(FtkDisplay* display, int x, int y, unsigned int colidx)
  86. {
  87. void* bits;
  88. int bpp;
  89. unsigned int xormode;
  90. union multiptr loc;
  91. if ((x < 0) || (x >= ftk_display_width(display)) ||
  92. (y < 0) || (y >= ftk_display_height(display)))
  93. {
  94. return;
  95. }
  96. bits = ftk_display_bits(display, &bpp);
  97. loc.p8 = (unsigned char *)bits + (ftk_display_width(display) * y + x) * bpp;
  98. xormode = colidx & XORMODE;
  99. colidx &= ~XORMODE;
  100. __set_pixel(bpp, loc, xormode, colidx);
  101. }
  102. static void draw_line(FtkDisplay* display, int x1, int y1, int x2, int y2, unsigned int colidx)
  103. {
  104. int tmp;
  105. int dx = x2 - x1;
  106. int dy = y2 - y1;
  107. if (abs(dx) < abs(dy))
  108. {
  109. if (y1 > y2)
  110. {
  111. tmp = x1; x1 = x2; x2 = tmp;
  112. tmp = y1; y1 = y2; y2 = tmp;
  113. dx = -dx; dy = -dy;
  114. }
  115. x1 <<= 16;
  116. /* dy is apriori >0 */
  117. dx = (dx << 16) / dy;
  118. while (y1 <= y2)
  119. {
  120. draw_pixel(display, x1 >> 16, y1, colidx);
  121. x1 += dx;
  122. y1++;
  123. }
  124. }
  125. else
  126. {
  127. if (x1 > x2)
  128. {
  129. tmp = x1; x1 = x2; x2 = tmp;
  130. tmp = y1; y1 = y2; y2 = tmp;
  131. dx = -dx; dy = -dy;
  132. }
  133. y1 <<= 16;
  134. dy = dx ? (dy << 16) / dx : 0;
  135. while (x1 <= x2)
  136. {
  137. draw_pixel(display, x1, y1 >> 16, colidx);
  138. y1 += dy;
  139. x1++;
  140. }
  141. }
  142. }
  143. static void draw_cross(FtkDisplay* display, int x, int y, unsigned int colidx)
  144. {
  145. draw_line(display, x - 10, y, x - 2, y, colidx);
  146. draw_line(display, x + 2, y, x + 10, y, colidx);
  147. draw_line(display, x, y - 10, x, y - 2, colidx);
  148. draw_line(display, x, y + 2, x, y + 10, colidx);
  149. draw_line(display, x - 6, y - 9, x - 9, y - 9, colidx);
  150. draw_line(display, x - 9, y - 8, x - 9, y - 6, colidx);
  151. draw_line(display, x - 9, y + 6, x - 9, y + 9, colidx);
  152. draw_line(display, x - 8, y + 9, x - 6, y + 9, colidx);
  153. draw_line(display, x + 6, y + 9, x + 9, y + 9, colidx);
  154. draw_line(display, x + 9, y + 8, x + 9, y + 6, colidx);
  155. draw_line(display, x + 9, y - 6, x + 9, y - 9, colidx);
  156. draw_line(display, x + 8, y - 9, x + 6, y - 9, colidx);
  157. }
  158. static void put_char(FtkDisplay* display, int x, int y, int c, unsigned int colidx)
  159. {
  160. int i, j, bits;
  161. for (i = 0; i < font_vga_8x16.height; i++)
  162. {
  163. bits = font_vga_8x16.data[font_vga_8x16.height * c + i];
  164. for (j = 0; j < font_vga_8x16.width; j++, bits <<= 1)
  165. {
  166. if (bits & 0x80)
  167. {
  168. draw_pixel(display, x + j, y + i, colidx);
  169. }
  170. else
  171. {
  172. draw_pixel(display, x + j, y + i, 0);
  173. }
  174. }
  175. }
  176. }
  177. static void put_string(FtkDisplay* display, int x, int y, const char *s, unsigned int colidx)
  178. {
  179. int i;
  180. for (i = 0; *s; i++, x += font_vga_8x16.width, s++)
  181. {
  182. put_char(display, x, y, *s, colidx);
  183. }
  184. }
  185. static void put_string_center(FtkDisplay* display, int x, int y, const char *s, unsigned int colidx)
  186. {
  187. size_t sl = strlen (s);
  188. put_string(display,
  189. x - (sl / 2) * font_vga_8x16.width,
  190. y - font_vga_8x16.height / 2,
  191. s,
  192. colidx);
  193. }
  194. typedef struct
  195. {
  196. int x[5], xfb[5];
  197. int y[5], yfb[5];
  198. int a[7];
  199. } calibration;
  200. struct ts_sample
  201. {
  202. int x;
  203. int y;
  204. unsigned int pressure;
  205. };
  206. static int ts_read_raw(int ts_fd, struct ts_sample* samp, int nr)
  207. {
  208. touchscreen_event_notify notify;
  209. fd_set rfds;
  210. FD_ZERO(&rfds);
  211. FD_SET(ts_fd, &rfds);
  212. if (select(ts_fd + 1, &rfds, NULL, NULL, NULL) != 1)
  213. {
  214. return -1;
  215. }
  216. if (read(ts_fd, (char *)&notify, sizeof(touchscreen_event_notify)) == sizeof(touchscreen_event_notify))
  217. {
  218. samp->x = notify.xanalog;
  219. samp->y = notify.yanalog;
  220. samp->pressure = notify.kstat & MOUSE_LEFT;
  221. return 1;
  222. }
  223. else
  224. {
  225. return -1;
  226. }
  227. }
  228. static int sort_by_x(const void* a, const void* b)
  229. {
  230. return (((struct ts_sample*)a)->x - ((struct ts_sample*)b)->x);
  231. }
  232. static int sort_by_y(const void* a, const void* b)
  233. {
  234. return (((struct ts_sample*)a)->y - ((struct ts_sample*)b)->y);
  235. }
  236. static void get_xy(int ts_fd, FtkDisplay* display, int* x, int* y)
  237. {
  238. #define MAX_SAMPLES 128
  239. struct ts_sample samp[MAX_SAMPLES];
  240. int index, middle;
  241. do
  242. {
  243. if (ts_read_raw(ts_fd, &samp[0], 1) < 0)
  244. {
  245. perror("ts_read_raw");
  246. continue;
  247. }
  248. } while (samp[0].pressure == 0);
  249. /* Now collect up to MAX_SAMPLES touches into the samp array. */
  250. index = 0;
  251. do
  252. {
  253. if (index < MAX_SAMPLES - 1)
  254. {
  255. index++;
  256. }
  257. if (ts_read_raw(ts_fd, &samp[index], 1) < 0)
  258. {
  259. perror("ts_read_raw");
  260. continue;
  261. }
  262. } while (samp[index].pressure > 0);
  263. printf("Took %d samples...\n", index);
  264. /*
  265. * At this point, we have samples in indices zero to (index-1)
  266. * which means that we have (index) number of samples. We want
  267. * to calculate the median of the samples so that wild outliers
  268. * don't skew the result. First off, let's assume that arrays
  269. * are one-based instead of zero-based. If this were the case
  270. * and index was odd, we would need sample number ((index+1)/2)
  271. * of a sorted array; if index was even, we would need the
  272. * average of sample number (index/2) and sample number
  273. * ((index/2)+1). To turn this into something useful for the
  274. * real world, we just need to subtract one off of the sample
  275. * numbers. So for when index is odd, we need sample number
  276. * (((index+1)/2)-1). Due to integer division truncation, we
  277. * can simplify this to just (index/2). When index is even, we
  278. * need the average of sample number ((index/2)-1) and sample
  279. * number (index/2). Calculate (index/2) now and we'll handle
  280. * the even odd stuff after we sort.
  281. */
  282. middle = index / 2;
  283. if (x)
  284. {
  285. qsort(samp, index, sizeof(struct ts_sample), sort_by_x);
  286. if (index & 1)
  287. {
  288. *x = samp[middle].x;
  289. }
  290. else
  291. {
  292. *x = (samp[middle-1].x + samp[middle].x) / 2;
  293. }
  294. }
  295. if (y)
  296. {
  297. qsort(samp, index, sizeof(struct ts_sample), sort_by_y);
  298. if (index & 1)
  299. {
  300. *y = samp[middle].y;
  301. }
  302. else
  303. {
  304. *y = (samp[middle-1].y + samp[middle].y) / 2;
  305. }
  306. }
  307. }
  308. static void get_sample(int ts_fd, FtkDisplay* display, calibration* cal, int index, int x, int y, const char* name)
  309. {
  310. static int last_x = -1, last_y;
  311. put_string_center(display,
  312. ftk_display_width(display) / 2,
  313. ftk_display_height(display) / 4 + 60,
  314. name,
  315. 0x0fffffff);
  316. if (last_x != -1)
  317. {
  318. #define NR_STEPS 10
  319. int dx = ((x - last_x) << 16) / NR_STEPS;
  320. int dy = ((y - last_y) << 16) / NR_STEPS;
  321. int i;
  322. last_x <<= 16;
  323. last_y <<= 16;
  324. for (i = 0; i < NR_STEPS; i++)
  325. {
  326. draw_cross(display, last_x >> 16, last_y >> 16, 0x0fffffff | XORMODE);
  327. usleep(1000);
  328. draw_cross(display, last_x >> 16, last_y >> 16, 0x0fffffff | XORMODE);
  329. last_x += dx;
  330. last_y += dy;
  331. }
  332. }
  333. draw_cross(display, x, y, 0x0fffffff | XORMODE);
  334. get_xy(ts_fd, display, &cal->x[index], &cal->y[index]);
  335. draw_cross(display, x, y, 0x0fffffff | XORMODE);
  336. last_x = cal->xfb[index] = x;
  337. last_y = cal->yfb[index] = y;
  338. printf("%s : X = %4d Y = %4d\n", name, cal->x[index], cal->y[index]);
  339. }
  340. static int perform_calibration(calibration* cal)
  341. {
  342. int j;
  343. float n, x, y, x2, y2, xy, z, zx, zy;
  344. float det, a, b, c, e, f, i;
  345. float scaling = 65536.0;
  346. // Get sums for matrix
  347. n = x = y = x2 = y2 = xy = 0;
  348. for (j = 0; j < 5; j++)
  349. {
  350. n += 1.0;
  351. x += (float)cal->x[j];
  352. y += (float)cal->y[j];
  353. x2 += (float)(cal->x[j]*cal->x[j]);
  354. y2 += (float)(cal->y[j]*cal->y[j]);
  355. xy += (float)(cal->x[j]*cal->y[j]);
  356. }
  357. // Get determinant of matrix -- check if determinant is too small
  358. det = n*(x2*y2 - xy*xy) + x*(xy*y - x*y2) + y*(x*xy - y*x2);
  359. if (det < 0.1 && det > -0.1)
  360. {
  361. printf("ts_calibrate: determinant is too small -- %f\n", det);
  362. return 0;
  363. }
  364. // Get elements of inverse matrix
  365. a = (x2*y2 - xy*xy) / det;
  366. b = (xy*y - x*y2) / det;
  367. c = (x*xy - y*x2) / det;
  368. e = (n*y2 - y*y) / det;
  369. f = (x*y - n*xy) / det;
  370. i = (n*x2 - x*x) / det;
  371. // Get sums for x calibration
  372. z = zx = zy = 0;
  373. for (j = 0; j < 5; j++)
  374. {
  375. z += (float) cal->xfb[j];
  376. zx += (float)(cal->xfb[j]*cal->x[j]);
  377. zy += (float)(cal->xfb[j]*cal->y[j]);
  378. }
  379. // Now multiply out to get the calibration for framebuffer x coord
  380. cal->a[0] = (int)((a*z + b*zx + c*zy)*(scaling));
  381. cal->a[1] = (int)((b*z + e*zx + f*zy)*(scaling));
  382. cal->a[2] = (int)((c*z + f*zx + i*zy)*(scaling));
  383. printf("%f %f %f\n",
  384. (a*z + b*zx + c*zy),
  385. (b*z + e*zx + f*zy),
  386. (c*z + f*zx + i*zy));
  387. // Get sums for y calibration
  388. z = zx = zy = 0;
  389. for (j = 0; j < 5; j++)
  390. {
  391. z += (float) cal->yfb[j];
  392. zx += (float)(cal->yfb[j]*cal->x[j]);
  393. zy += (float)(cal->yfb[j]*cal->y[j]);
  394. }
  395. // Now multiply out to get the calibration for framebuffer y coord
  396. cal->a[3] = (int)((a*z + b*zx + c*zy)*(scaling));
  397. cal->a[4] = (int)((b*z + e*zx + f*zy)*(scaling));
  398. cal->a[5] = (int)((c*z + f*zx + i*zy)*(scaling));
  399. printf("%f %f %f\n",
  400. (a*z + b*zx + c*zy),
  401. (b*z + e*zx + f*zy),
  402. (c*z + f*zx + i*zy));
  403. // If we got here, we're OK, so assign scaling to a[6] and return
  404. cal->a[6] = (int)scaling;
  405. return 1;
  406. }
  407. int ftk_sylixos_touchscreen_calibrate(int argc, char *argv[])
  408. {
  409. FtkDisplay* display;
  410. char namebuffer[PATH_MAX + 1];
  411. char* name;
  412. calibration cal;
  413. int xres;
  414. int yres;
  415. int cal_fd;
  416. int ts_fd;
  417. unsigned int i;
  418. struct stat sbuf;
  419. void* bits;
  420. int bpp;
  421. if (getenv_r("TSLIB_CALIBFILE", namebuffer, PATH_MAX + 1) >= 0)
  422. {
  423. name = namebuffer;
  424. }
  425. else
  426. {
  427. name = FTK_DEFAULT_CALIBFILE;
  428. }
  429. if (!(argc > 1 && (strcmp(argv[1], "ts") == 0)))
  430. {
  431. if (stat(name, &sbuf) == 0)
  432. {
  433. return 0;
  434. }
  435. }
  436. if (getenv_r("FRAMEBUFFER", namebuffer, PATH_MAX + 1) >= 0)
  437. {
  438. name = namebuffer;
  439. }
  440. else
  441. {
  442. name = FTK_DEFAULT_FRAMEBUFFER;
  443. }
  444. display = ftk_display_sylixos_create(name);
  445. if (display == NULL)
  446. {
  447. return -1;
  448. }
  449. xres = ftk_display_width(display);
  450. yres = ftk_display_height(display);
  451. bits = ftk_display_bits(display, &bpp);
  452. memset(bits, 0x00, xres * yres * bpp);
  453. if (getenv_r("TSLIB_TSDEVICE", namebuffer, PATH_MAX + 1) >= 0)
  454. {
  455. name = namebuffer;
  456. }
  457. else
  458. {
  459. name = FTK_DEFAULT_TOUCH;
  460. }
  461. ts_fd = open(name, O_RDONLY, 0666);
  462. if (ts_fd < 0)
  463. {
  464. ftk_display_destroy(display);
  465. return -1;
  466. }
  467. put_string_center(display,
  468. xres / 2,
  469. yres / 4,
  470. "TSLIB calibration utility",
  471. 0x0fffffff);
  472. put_string_center(display,
  473. xres / 2,
  474. yres / 4 + 20,
  475. "Touch crosshair to calibrate",
  476. 0x0fffffff);
  477. printf("xres = %d, yres = %d\n", xres, yres);
  478. get_sample(ts_fd, display, &cal, 0, 50, 50, " Top left ");
  479. get_sample(ts_fd, display, &cal, 1, xres - 50, 50, " Top right ");
  480. get_sample(ts_fd, display, &cal, 2, xres - 50, yres - 50, "Bottom right");
  481. get_sample(ts_fd, display, &cal, 3, 50, yres - 50, "Bottom left ");
  482. get_sample(ts_fd, display, &cal, 4, xres / 2, yres / 2, " Center ");
  483. if (perform_calibration(&cal))
  484. {
  485. printf("Calibration constants: ");
  486. for (i = 0; i < 7; i++)
  487. {
  488. printf("%d ", cal.a[i]);
  489. }
  490. printf("\n");
  491. if (getenv_r("TSLIB_CALIBFILE", namebuffer, PATH_MAX + 1) >= 0)
  492. {
  493. name = namebuffer;
  494. }
  495. else
  496. {
  497. name = FTK_DEFAULT_CALIBFILE;
  498. }
  499. cal_fd = creat(name, 0666);
  500. sprintf(namebuffer, "%d %d %d %d %d %d %d",
  501. cal.a[1],
  502. cal.a[2],
  503. cal.a[0],
  504. cal.a[4],
  505. cal.a[5],
  506. cal.a[3],
  507. cal.a[6]);
  508. write(cal_fd, namebuffer, strlen(namebuffer) + 1);
  509. close(cal_fd);
  510. i = 0;
  511. }
  512. else
  513. {
  514. printf("Calibration failed.\n");
  515. i = -1;
  516. }
  517. ftk_display_destroy(display);
  518. close(ts_fd);
  519. return i;
  520. }