00001
00038 #include <string.h>
00039 #include <progmem.h>
00040 #include <mainloop.h>
00041
00042 #include <gfx/gfx.h>
00043 #include <gfx/win.h>
00044 #include <gfx/wtk.h>
00045 #include <gfx/sysfont.h>
00046
00047 #include <touch/touch.h>
00048
00049 #include "app_calibrate.h"
00050
00063
00064 #define CAL_OFFSET 50
00065
00066 #define CAL_RADIUS 5
00067
00068 #define CAL_TRESHOLD 500
00069
00070 #define CAL_BG_COLOR GFX_COLOR(0, 0, 255)
00071
00072 #define CAL_FG_COLOR GFX_COLOR(255, 255, 255)
00073
00075
00077 #define abs(a) (((a) < 0) ? -(a) : (a))
00078
00080 struct touch_calibrate_context {
00082 struct workqueue_task task;
00084 struct workqueue_task *completed_task;
00086 struct touch_calibration_matrix cal_matrix;
00088 touch_event_handler_t old_handler;
00090 touch_calibration_points_t cal_points;
00092 struct touch_event event;
00094 uint8_t state;
00095 };
00096
00098 static struct touch_calibrate_context *calibrate_context;
00099
00101 static struct font sysfont2x;
00102
00108 static DEFINE_PROGMEM(char, calibrate_help_text[]) =
00109 "Touch screen calibration.\n\nTouch inside the circles.";
00110
00119 static void touch_calibrate_event_handler(const struct touch_event *event)
00120 {
00121 calibrate_context->event = *event;
00122 }
00123
00142 static void touch_calibrate_task_handler(struct workqueue_task *task)
00143 {
00144 int16_t dx;
00145 int16_t dy;
00146 struct touch_calibrate_context *cal_ctx;
00147
00148 cal_ctx = container_of(task, struct touch_calibrate_context, task);
00149
00150 switch (cal_ctx->state) {
00151 case 0:
00152 case 1:
00153 case 2:
00154
00155 workqueue_add_task(&main_workqueue, &cal_ctx->task);
00156
00157
00158 if (cal_ctx->event.type != TOUCH_RELEASE)
00159 break;
00160
00161
00162 cal_ctx->event.type = TOUCH_NO_EVENT;
00163 cal_ctx->cal_points[cal_ctx->state].raw_x =
00164 cal_ctx->event.point.raw_x;
00165 cal_ctx->cal_points[cal_ctx->state].raw_y =
00166 cal_ctx->event.point.raw_y;
00167
00168 dx = cal_ctx->cal_points[cal_ctx->state - 1].raw_x -
00169 cal_ctx->cal_points[cal_ctx->state].raw_x;
00170 dy = cal_ctx->cal_points[cal_ctx->state - 1].raw_y -
00171 cal_ctx->cal_points[cal_ctx->state].raw_y;
00172 dx = abs(dx);
00173 dy = abs(dy);
00174
00175
00176 if ((dx < CAL_TRESHOLD) && (dy < CAL_TRESHOLD))
00177 break;
00178
00179
00180 gfx_draw_circle(cal_ctx->cal_points[cal_ctx->state].panel_x,
00181 cal_ctx->cal_points[cal_ctx->state].panel_y,
00182 CAL_RADIUS, CAL_BG_COLOR, GFX_WHOLE);
00183
00184
00185 cal_ctx->state++;
00186
00187
00188 if (cal_ctx->state >= 3)
00189 break;
00190
00191
00192 gfx_draw_circle(cal_ctx->cal_points[cal_ctx->state].panel_x,
00193 cal_ctx->cal_points[cal_ctx->state].panel_y,
00194 CAL_RADIUS, CAL_FG_COLOR, GFX_WHOLE);
00195 break;
00196
00197 case 3:
00198
00199
00200
00201 gfx_draw_circle(cal_ctx->cal_points[2].panel_x,
00202 cal_ctx->cal_points[2].panel_y,
00203 CAL_RADIUS, CAL_BG_COLOR, GFX_WHOLE);
00204
00205
00206 touch_compute_calibration_matrix(cal_ctx->cal_points,
00207 &cal_ctx->cal_matrix);
00208
00209 touch_set_calibration_matrix(&cal_ctx->cal_matrix);
00210
00211
00212 touch_set_event_handler(cal_ctx->old_handler);
00213
00214
00215 membag_free(calibrate_context);
00216
00217
00218 if (calibrate_context->completed_task) {
00219 workqueue_add_task(&main_workqueue,
00220 calibrate_context->completed_task);
00221 }
00222
00223 break;
00224 }
00225 }
00226
00236 void app_touch_calibrate_setup(struct workqueue_task *completed_task)
00237 {
00238 calibrate_context =
00239 membag_alloc(sizeof(struct touch_calibrate_context));
00240 assert(calibrate_context);
00241
00242
00243 memcpy(&sysfont2x, &sysfont, sizeof(sysfont));
00244 sysfont2x.scale = 2;
00245
00246
00247 calibrate_context->old_handler = touch_get_event_handler();
00248 touch_set_event_handler(touch_calibrate_event_handler);
00249
00250
00251 gfx_set_clipping(0, 0, gfx_get_width(), gfx_get_height());
00252 gfx_draw_filled_rect(0, 0, gfx_get_width(), gfx_get_height(),
00253 CAL_BG_COLOR);
00254
00255 gfx_draw_progmem_string((const char __progmem_arg *)
00256 &calibrate_help_text, 10, 80, &sysfont2x, CAL_FG_COLOR,
00257 GFX_COLOR_TRANSPARENT);
00258
00259
00260 calibrate_context->cal_points[0].panel_x =
00261 (gfx_get_width() - CAL_OFFSET - 1);
00262 calibrate_context->cal_points[0].panel_y =
00263 (gfx_get_height() - CAL_OFFSET - 1);
00264 calibrate_context->cal_points[1].panel_x = (CAL_OFFSET);
00265 calibrate_context->cal_points[1].panel_y =
00266 (gfx_get_height() - CAL_OFFSET - 1);
00267 calibrate_context->cal_points[2].panel_x = (CAL_OFFSET);
00268 calibrate_context->cal_points[2].panel_y = (CAL_OFFSET);
00269
00270
00271 gfx_draw_circle(calibrate_context->cal_points[0].panel_x,
00272 calibrate_context->cal_points[0].panel_y,
00273 CAL_RADIUS, CAL_FG_COLOR, GFX_WHOLE);
00274
00275
00276 calibrate_context->state = 0;
00277
00278 calibrate_context->completed_task = completed_task;
00279
00280 workqueue_task_init(&calibrate_context->task,
00281 touch_calibrate_task_handler);
00282 workqueue_add_task(&main_workqueue, &calibrate_context->task);
00283 }
00284