calibration.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include <rtgui/rtgui.h>
  2. #include <rtgui/dc.h>
  3. #include <rtgui/rtgui_system.h>
  4. #include <rtgui/widgets/window.h>
  5. #include "touch.h"
  6. #define CALIBRATION_STEP_LEFTTOP 0
  7. #define CALIBRATION_STEP_RIGHTTOP 1
  8. #define CALIBRATION_STEP_RIGHTBOTTOM 2
  9. #define CALIBRATION_STEP_LEFTBOTTOM 3
  10. #define CALIBRATION_STEP_CENTER 4
  11. #define TOUCH_WIN_UPDATE 1
  12. #define TOUCH_WIN_CLOSE 2
  13. #define CALIBRATION_WIDTH 15
  14. #define CALIBRATION_HEIGHT 15
  15. struct calibration_session
  16. {
  17. rt_uint8_t step;
  18. struct calibration_data data;
  19. rt_uint16_t width; rt_uint16_t height;
  20. rt_device_t device;
  21. rt_thread_t tid;
  22. };
  23. static struct calibration_session* calibration_ptr = RT_NULL;
  24. static void calibration_data_post(rt_uint16_t x, rt_uint16_t y)
  25. {
  26. if (calibration_ptr != RT_NULL)
  27. {
  28. switch (calibration_ptr->step)
  29. {
  30. case CALIBRATION_STEP_LEFTTOP:
  31. calibration_ptr->data.min_x = x;
  32. calibration_ptr->data.min_y = y;
  33. break;
  34. case CALIBRATION_STEP_RIGHTTOP:
  35. calibration_ptr->data.max_x = x;
  36. calibration_ptr->data.min_y = (calibration_ptr->data.min_y + y)/2;
  37. break;
  38. case CALIBRATION_STEP_LEFTBOTTOM:
  39. calibration_ptr->data.min_x = (calibration_ptr->data.min_x + x)/2;
  40. calibration_ptr->data.max_y = y;
  41. break;
  42. case CALIBRATION_STEP_RIGHTBOTTOM:
  43. calibration_ptr->data.max_x = (calibration_ptr->data.max_x + x)/2;
  44. calibration_ptr->data.max_y = (calibration_ptr->data.max_y + y)/2;
  45. break;
  46. case CALIBRATION_STEP_CENTER:
  47. /* calibration done */
  48. {
  49. rt_uint16_t w, h;
  50. struct rtgui_event_command ecmd;
  51. RTGUI_EVENT_COMMAND_INIT(&ecmd);
  52. ecmd.command_id = TOUCH_WIN_CLOSE;
  53. /* calculate calibrated data */
  54. if (calibration_ptr->data.max_x > calibration_ptr->data.min_x)
  55. w = calibration_ptr->data.max_x - calibration_ptr->data.min_x;
  56. else
  57. w = calibration_ptr->data.min_x - calibration_ptr->data.max_x;
  58. w = (w/(calibration_ptr->width - 2 * CALIBRATION_WIDTH)) * CALIBRATION_WIDTH;
  59. if (calibration_ptr->data.max_y > calibration_ptr->data.min_y)
  60. h = calibration_ptr->data.max_y - calibration_ptr->data.min_y;
  61. else
  62. h = calibration_ptr->data.min_y - calibration_ptr->data.max_y;
  63. h = (h/(calibration_ptr->height - 2 * CALIBRATION_HEIGHT)) * CALIBRATION_HEIGHT;
  64. rt_kprintf("w: %d, h: %d\n", w, h);
  65. if (calibration_ptr->data.max_x > calibration_ptr->data.min_x)
  66. {
  67. calibration_ptr->data.min_x -= w;
  68. calibration_ptr->data.max_x += w;
  69. }
  70. else
  71. {
  72. calibration_ptr->data.min_x += w;
  73. calibration_ptr->data.max_x -= w;
  74. }
  75. if (calibration_ptr->data.max_y > calibration_ptr->data.min_y)
  76. {
  77. calibration_ptr->data.min_y -= h;
  78. calibration_ptr->data.max_y += h;
  79. }
  80. else
  81. {
  82. calibration_ptr->data.min_y += h;
  83. calibration_ptr->data.max_y -= h;
  84. }
  85. rt_kprintf("calibration data: (%d, %d), (%d, %d)\n",
  86. calibration_ptr->data.min_x,
  87. calibration_ptr->data.max_x,
  88. calibration_ptr->data.min_y,
  89. calibration_ptr->data.max_y);
  90. rtgui_thread_send(calibration_ptr->tid, &ecmd.parent, sizeof(struct rtgui_event_command));
  91. }
  92. return;
  93. }
  94. calibration_ptr->step ++;
  95. /* post command event */
  96. {
  97. struct rtgui_event_command ecmd;
  98. RTGUI_EVENT_COMMAND_INIT(&ecmd);
  99. ecmd.command_id = TOUCH_WIN_UPDATE;
  100. rtgui_thread_send(calibration_ptr->tid, &ecmd.parent, sizeof(struct rtgui_event_command));
  101. }
  102. }
  103. }
  104. rt_bool_t calibration_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
  105. {
  106. switch (event->type)
  107. {
  108. case RTGUI_EVENT_PAINT:
  109. {
  110. struct rtgui_dc* dc;
  111. struct rtgui_rect rect;
  112. dc = rtgui_dc_begin_drawing(widget);
  113. if (dc == RT_NULL) break;
  114. /* get rect information */
  115. rtgui_widget_get_rect(widget, &rect);
  116. /* clear whole window */
  117. RTGUI_WIDGET_BACKGROUND(widget) = white;
  118. rtgui_dc_fill_rect(dc, &rect);
  119. /* reset color */
  120. RTGUI_WIDGET_BACKGROUND(widget) = green;
  121. RTGUI_WIDGET_FOREGROUND(widget) = black;
  122. switch (calibration_ptr->step)
  123. {
  124. case CALIBRATION_STEP_LEFTTOP:
  125. rtgui_dc_draw_hline(dc, 0, 2 * CALIBRATION_WIDTH, CALIBRATION_HEIGHT);
  126. rtgui_dc_draw_vline(dc, CALIBRATION_WIDTH, 0, 2 * CALIBRATION_HEIGHT);
  127. RTGUI_WIDGET_FOREGROUND(widget) = red;
  128. rtgui_dc_fill_circle(dc, CALIBRATION_WIDTH, CALIBRATION_HEIGHT, 4);
  129. break;
  130. case CALIBRATION_STEP_RIGHTTOP:
  131. rtgui_dc_draw_hline(dc, calibration_ptr->width - 2 * CALIBRATION_WIDTH,
  132. calibration_ptr->width, CALIBRATION_HEIGHT);
  133. rtgui_dc_draw_vline(dc, calibration_ptr->width - CALIBRATION_WIDTH, 0, 2 * CALIBRATION_HEIGHT);
  134. RTGUI_WIDGET_FOREGROUND(widget) = red;
  135. rtgui_dc_fill_circle(dc, calibration_ptr->width - CALIBRATION_WIDTH, CALIBRATION_HEIGHT, 4);
  136. break;
  137. case CALIBRATION_STEP_LEFTBOTTOM:
  138. rtgui_dc_draw_hline(dc, 0, 2 * CALIBRATION_WIDTH, calibration_ptr->height - CALIBRATION_HEIGHT);
  139. rtgui_dc_draw_vline(dc, CALIBRATION_WIDTH, calibration_ptr->height - 2 * CALIBRATION_HEIGHT, calibration_ptr->height);
  140. RTGUI_WIDGET_FOREGROUND(widget) = red;
  141. rtgui_dc_fill_circle(dc, CALIBRATION_WIDTH, calibration_ptr->height - CALIBRATION_HEIGHT, 4);
  142. break;
  143. case CALIBRATION_STEP_RIGHTBOTTOM:
  144. rtgui_dc_draw_hline(dc, calibration_ptr->width - 2 * CALIBRATION_WIDTH,
  145. calibration_ptr->width, calibration_ptr->height - CALIBRATION_HEIGHT);
  146. rtgui_dc_draw_vline(dc, calibration_ptr->width - CALIBRATION_WIDTH, calibration_ptr->height - 2 * CALIBRATION_HEIGHT, calibration_ptr->height);
  147. RTGUI_WIDGET_FOREGROUND(widget) = red;
  148. rtgui_dc_fill_circle(dc, calibration_ptr->width - CALIBRATION_WIDTH, calibration_ptr->height - CALIBRATION_HEIGHT, 4);
  149. break;
  150. case CALIBRATION_STEP_CENTER:
  151. rtgui_dc_draw_hline(dc, calibration_ptr->width/2 - CALIBRATION_WIDTH, calibration_ptr->width/2 + CALIBRATION_WIDTH, calibration_ptr->height/2);
  152. rtgui_dc_draw_vline(dc, calibration_ptr->width/2, calibration_ptr->height/2 - CALIBRATION_HEIGHT, calibration_ptr->height/2 + CALIBRATION_HEIGHT);
  153. RTGUI_WIDGET_FOREGROUND(widget) = red;
  154. rtgui_dc_fill_circle(dc, calibration_ptr->width/2, calibration_ptr->height/2, 4);
  155. break;
  156. }
  157. rtgui_dc_end_drawing(dc);
  158. }
  159. break;
  160. case RTGUI_EVENT_COMMAND:
  161. {
  162. struct rtgui_event_command* ecmd = (struct rtgui_event_command*)event;
  163. switch (ecmd->command_id)
  164. {
  165. case TOUCH_WIN_UPDATE:
  166. rtgui_widget_update(widget);
  167. break;
  168. case TOUCH_WIN_CLOSE:
  169. rtgui_win_close(RTGUI_WIN(widget));
  170. break;
  171. }
  172. }
  173. return RT_TRUE;
  174. default:
  175. rtgui_win_event_handler(widget, event);
  176. }
  177. return RT_FALSE;
  178. }
  179. void calibration_entry(void* parameter)
  180. {
  181. rt_mq_t mq;
  182. rtgui_win_t* win;
  183. struct rtgui_rect rect;
  184. mq = rt_mq_create("cali", 40, 8, RT_IPC_FLAG_FIFO);
  185. if (mq == RT_NULL) return;
  186. rtgui_thread_register(rt_thread_self(), mq);
  187. rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &rect);
  188. /* set screen rect */
  189. calibration_ptr->width = rect.x2;
  190. calibration_ptr->height = rect.y2;
  191. /* create calibration window */
  192. win = rtgui_win_create(RT_NULL,
  193. "calibration", &rect, RTGUI_WIN_STYLE_NO_TITLE | RTGUI_WIN_STYLE_NO_BORDER);
  194. rtgui_widget_set_event_handler(RTGUI_WIDGET(win), calibration_event_handler);
  195. if (win != RT_NULL)
  196. {
  197. rtgui_win_show(win, RT_FALSE);
  198. // rtgui_widget_update(RTGUI_WIDGET(win));
  199. rtgui_win_event_loop(win);
  200. }
  201. rtgui_thread_deregister(rt_thread_self());
  202. rt_mq_delete(mq);
  203. /* set calibration data */
  204. rt_device_control(calibration_ptr->device, RT_TOUCH_CALIBRATION_DATA, &calibration_ptr->data);
  205. /* recover to normal */
  206. rt_device_control(calibration_ptr->device, RT_TOUCH_NORMAL, RT_NULL);
  207. /* release memory */
  208. rt_free(calibration_ptr);
  209. calibration_ptr = RT_NULL;
  210. }
  211. void calibration_init()
  212. {
  213. rt_device_t device;
  214. device = rt_device_find("touch");
  215. if (device == RT_NULL) return; /* no this device */
  216. calibration_ptr = (struct calibration_session*)rt_malloc(sizeof(struct calibration_session));
  217. rt_memset(calibration_ptr, 0, sizeof(struct calibration_data));
  218. calibration_ptr->device = device;
  219. rt_device_control(calibration_ptr->device, RT_TOUCH_CALIBRATION, (void*)calibration_data_post);
  220. calibration_ptr->tid = rt_thread_create("cali", calibration_entry, RT_NULL,
  221. 2048, 20, 5);
  222. if (calibration_ptr->tid != RT_NULL) rt_thread_startup(calibration_ptr->tid);
  223. }
  224. #ifdef RT_USING_FINSH
  225. #include <finsh.h>
  226. void calibration()
  227. {
  228. calibration_init();
  229. }
  230. FINSH_FUNCTION_EXPORT(calibration, perform touch calibration);
  231. #endif