pencal.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. int debug = 0;
  5. struct Cal {
  6. double scalex;
  7. double transx;
  8. double scaley;
  9. double transy;
  10. } cal;
  11. /* Calibrate the pen */
  12. Point pts[5];
  13. Point pens[5];
  14. Point up = { 0, -10};
  15. Point down = { 0, 10};
  16. Point left = {-10, 0};
  17. Point right = { 10, 0};
  18. Point
  19. pen2scr(Point p)
  20. {
  21. return Pt(p.x * cal.scalex / 65536.0 + cal.transx,
  22. p.y * cal.scaley / 65536.0 + cal.transy);
  23. }
  24. Point
  25. scr2pen(Point p)
  26. {
  27. return Pt((p.x - cal.transx) * 65536.0 / cal.scalex,
  28. (p.y + cal.transy) * 65536.0 / cal.scaley);
  29. }
  30. void
  31. cross(Point p) {
  32. draw(screen, screen->r, display->white, nil, ZP);
  33. line(screen, addpt(p, up), addpt(p, down), Endsquare, Endsquare, 0, display->black, ZP);
  34. line(screen, addpt(p, left), addpt(p, right), Endsquare, Endsquare, 0, display->black, ZP);
  35. flushimage(display, 1);
  36. }
  37. Point
  38. getmouse(int mouse) {
  39. static char buf[50];
  40. int x, y, b, n;
  41. Point p;
  42. n = 0;
  43. p.x = p.y = 0;
  44. do {
  45. if (read(mouse, buf, 48) != 48)
  46. sysfatal("read: %r");
  47. if (debug > 1) fprint(2, "%s\n", buf);
  48. if (buf[0] == 'r') {
  49. b = 1;
  50. continue;
  51. }
  52. if (buf[0] != 'm')
  53. sysfatal("mouse message: %s", buf);
  54. x = strtol(buf+1, nil, 10);
  55. y = strtol(buf+13, nil, 10);
  56. b = strtol(buf+25, nil, 10);
  57. p.x = (n * p.x + x)/(n+1);
  58. p.y = (n * p.y + y)/(n+1);
  59. n++;
  60. } while (b & 0x7);
  61. return p;
  62. }
  63. void
  64. main(int argc, char **argv) {
  65. int i, mouse, mousectl, wctl;
  66. Rectangle r, oldsize;
  67. ARGBEGIN{
  68. case 'd':
  69. debug = 1;
  70. break;
  71. }ARGEND;
  72. if ((mouse = open("/dev/mouse", OREAD)) < 0
  73. && (mouse = open("#m/mouse", OREAD)) < 0)
  74. sysfatal("#m/mouse: %r");
  75. mousectl = open("#m/mousectl", ORDWR);
  76. if (mousectl < 0)
  77. sysfatal("#m/mousectl: %r");
  78. if(initdraw(nil, nil, "calibrate") < 0)
  79. sysfatal("initdraw: %r\n");
  80. again:
  81. r = insetrect(display->image->r, 2);
  82. wctl = open("/dev/wctl", ORDWR);
  83. if (wctl >= 0) {
  84. char buf[4*12+1];
  85. buf[48] = 0;
  86. oldsize = screen->r;
  87. if (fprint(wctl, "resize -r %R", r) <= 0)
  88. sysfatal("write /dev/wctl, %r");
  89. if (getwindow(display, Refbackup) < 0)
  90. sysfatal("getwindow");
  91. if (debug) fprint(2, "resize: %R\n", screen->r);
  92. if (read(mousectl, buf, 48) != 48)
  93. sysfatal("read mousectl: %r");
  94. if (debug > 1) fprint(2, "mousectl %s\n", buf);
  95. if (buf[0] != 'c')
  96. sysfatal("mousectl message: %s", buf);
  97. cal.scalex = strtol(buf+ 1, nil, 10);
  98. cal.scaley = strtol(buf+13, nil, 10);
  99. cal.transx = strtol(buf+25, nil, 10);
  100. cal.transy = strtol(buf+37, nil, 10);
  101. } else {
  102. fprint(mousectl, "calibrate");
  103. cal.scalex = 1<<16;
  104. cal.scaley = 1<<16;
  105. cal.transx = 0;
  106. cal.transy = 0;
  107. }
  108. fprint(2, "calibrate %ld %ld %ld %ld (old)\n",
  109. (long)cal.scalex, (long)cal.scaley, (long)cal.transx, (long)cal.transy);
  110. if (debug) fprint(2, "screen coords %R\n", screen->r);
  111. pts[0] = addpt(Pt( 16, 16), screen->r.min);
  112. pts[1] = addpt(Pt( 16, -16), Pt(screen->r.min.x, screen->r.max.y));
  113. pts[2] = addpt(Pt(-16, 16), Pt(screen->r.max.x, screen->r.min.y));
  114. pts[3] = addpt(Pt(-16, -16), screen->r.max);
  115. pts[4] = Pt((screen->r.max.x + screen->r.min.x)/2,
  116. (screen->r.max.y + screen->r.min.y)/2);;
  117. for (i = 0; i < 4; i++) {
  118. cross(pts[i]);
  119. pens[i] = scr2pen(getmouse(mouse));
  120. if (debug) fprint(2, "%P\n", pens[i]);
  121. }
  122. cal.scalex = (pts[2].x + pts[3].x - pts[0].x - pts[1].x) * 65536.0 /
  123. (pens[2].x + pens[3].x - pens[0].x - pens[1].x);
  124. cal.scaley = (pts[1].y + pts[3].y - pts[0].y - pts[2].y) * 65536.0 /
  125. (pens[1].y + pens[3].y - pens[0].y - pens[2].y);
  126. cal.transx = pts[0].x - (pens[0].x*cal.scalex) / 65536.0;
  127. cal.transy = pts[0].y - (pens[0].y*cal.scaley) / 65536.0;
  128. if (debug) fprint(2, "scale [%f, %f], trans [%f, %f]\n",
  129. cal.scalex, cal.scaley, cal.transx, cal.transy);
  130. fprint(mousectl, "calibrate %ld %ld %ld %ld",
  131. (long)cal.scalex, (long)cal.scaley, (long)cal.transx, (long)cal.transy);
  132. cross(pts[4]);
  133. pens[4] = getmouse(mouse);
  134. draw(screen, screen->r, display->white, nil, ZP);
  135. flushimage(display, 1);
  136. if (abs(pts[4].x-pens[4].x) > 4 || abs(pts[4].y-pens[4].y) > 4) {
  137. fprint(2, "Calibration inaccurate: %P -> %P\n", pts[4], pens[4]);
  138. goto again;
  139. } else {
  140. fprint(2, "Calibration ok: %P -> %P\n", pts[4], pens[4]);
  141. }
  142. print("calibrate='%ld %ld %ld %ld'\n",
  143. (long)cal.scalex, (long)cal.scaley, (long)cal.transx, (long)cal.transy);
  144. if (debug)
  145. for (i = 0; i < 4; i++) {
  146. cross(pts[i]);
  147. pens[i] = getmouse(mouse);
  148. if (debug) fprint(2, "%P\n", pens[i]);
  149. }
  150. if (wctl >= 0)
  151. fprint(wctl, "resize -r %R", oldsize);
  152. }