calibration.c 6.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
#include <rtgui/rtgui.h>
#include <rtgui/dc.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/window.h>

#include "touch.h"

#define CALIBRATION_STEP_LEFTTOP		0
#define CALIBRATION_STEP_RIGHTTOP		1
#define CALIBRATION_STEP_RIGHTBOTTOM	2
#define CALIBRATION_STEP_LEFTBOTTOM		3
#define CALIBRATION_STEP_CENTER			4

#define TOUCH_WIN_UPDATE				1
#define TOUCH_WIN_CLOSE					2

struct calibration_session
{
	rt_uint8_t step;

	struct calibration_data data;

	rt_uint16_t width; rt_uint16_t height;

	rt_device_t device;
	rt_thread_t tid;
};
static struct calibration_session* calibration_ptr = RT_NULL;

static void calibration_data_post(rt_uint16_t x, rt_uint16_t y)
{
	if (calibration_ptr != RT_NULL)
	{
		switch (calibration_ptr->step)
		{
		case CALIBRATION_STEP_LEFTTOP:
			calibration_ptr->data.min_x = x;
			calibration_ptr->data.min_y = y;
			break;
			
		case CALIBRATION_STEP_RIGHTTOP:
			calibration_ptr->data.max_x = x;
			calibration_ptr->data.min_y = (calibration_ptr->data.min_y + y)/2;
			break;
			
		case CALIBRATION_STEP_LEFTBOTTOM:
			calibration_ptr->data.min_x = (calibration_ptr->data.min_x + x)/2;
			calibration_ptr->data.max_y = y;
			break;

		case CALIBRATION_STEP_RIGHTBOTTOM:
			calibration_ptr->data.max_x = (calibration_ptr->data.max_x + x)/2;
			calibration_ptr->data.max_y = (calibration_ptr->data.max_y + y)/2;
			break;

		case CALIBRATION_STEP_CENTER:
			/* calibration done */
			{
				struct rtgui_event_command ecmd;
				RTGUI_EVENT_COMMAND_INIT(&ecmd);
				ecmd.command_id = TOUCH_WIN_CLOSE;

				rtgui_thread_send(calibration_ptr->tid, &ecmd.parent, sizeof(struct rtgui_event_command));
			}
			return;
		}

		calibration_ptr->step ++;

		/* post command event */
		{
			struct rtgui_event_command ecmd;
			RTGUI_EVENT_COMMAND_INIT(&ecmd);
			ecmd.command_id = TOUCH_WIN_UPDATE;

			rtgui_thread_send(calibration_ptr->tid, &ecmd.parent, sizeof(struct rtgui_event_command));
		}
	}
}

rt_bool_t calibration_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
{
	switch (event->type)
	{
	case RTGUI_EVENT_PAINT:
	{
		struct rtgui_dc* dc;
		struct rtgui_rect rect;

		dc = rtgui_dc_begin_drawing(widget);
		if (dc == RT_NULL) break;

		/* get rect information */
		rtgui_widget_get_rect(widget, &rect);

		/* clear whole window */
		RTGUI_WIDGET_BACKGROUND(widget) = white;
		rtgui_dc_fill_rect(dc, &rect);

		/* reset color */
		RTGUI_WIDGET_BACKGROUND(widget) = green;
		RTGUI_WIDGET_FOREGROUND(widget) = black;

		switch (calibration_ptr->step)
		{
			case CALIBRATION_STEP_LEFTTOP:
				rtgui_dc_draw_hline(dc, 1, 1 + 15, 1);
				rtgui_dc_draw_vline(dc, 1, 1, 1 + 15);
				RTGUI_WIDGET_FOREGROUND(widget) = red;
				rtgui_dc_fill_circle(dc, 0, 0, 4);
				break;
				
			case CALIBRATION_STEP_RIGHTTOP:
				rtgui_dc_draw_hline(dc, calibration_ptr->width - 1 - 15, calibration_ptr->width - 1, 1);
				rtgui_dc_draw_vline(dc, calibration_ptr->width - 1, 1, 1 + 15);
				RTGUI_WIDGET_FOREGROUND(widget) = red;
				rtgui_dc_fill_circle(dc, calibration_ptr->width - 1, 0, 4);
				break;
				
			case CALIBRATION_STEP_LEFTBOTTOM:
				rtgui_dc_draw_hline(dc, 1, 1 + 15, calibration_ptr->height - 1);
				rtgui_dc_draw_vline(dc, 1, calibration_ptr->height - 1 - 15, calibration_ptr->height - 1);
				RTGUI_WIDGET_FOREGROUND(widget) = red;
				rtgui_dc_fill_circle(dc, 0, calibration_ptr->height - 1, 4);
				break;
			
			case CALIBRATION_STEP_RIGHTBOTTOM:
				rtgui_dc_draw_hline(dc, calibration_ptr->width - 1 - 15, calibration_ptr->width - 1, calibration_ptr->height - 1);
				rtgui_dc_draw_vline(dc, calibration_ptr->width - 1, calibration_ptr->height - 1 - 15, calibration_ptr->height - 1);
				RTGUI_WIDGET_FOREGROUND(widget) = red;
				rtgui_dc_fill_circle(dc, calibration_ptr->width - 1, calibration_ptr->height - 1, 4);
				break;
			
			case CALIBRATION_STEP_CENTER:
				rtgui_dc_draw_hline(dc, calibration_ptr->width/2 - 15, calibration_ptr->width/2 + 15, calibration_ptr->height/2);
				rtgui_dc_draw_vline(dc, calibration_ptr->width/2, calibration_ptr->height/2 - 15, calibration_ptr->height/2 + 15);
				RTGUI_WIDGET_FOREGROUND(widget) = red;
				rtgui_dc_fill_circle(dc, calibration_ptr->width/2, calibration_ptr->height/2, 4);
				break;
		}
		rtgui_dc_end_drawing(dc);
	}
		break;

	case RTGUI_EVENT_COMMAND:
		{
			struct rtgui_event_command* ecmd = (struct rtgui_event_command*)event;
			
			switch (ecmd->command_id)
			{
			case TOUCH_WIN_UPDATE:
				rtgui_widget_update(widget);
				break;
			case TOUCH_WIN_CLOSE:
				rtgui_win_close(RTGUI_WIN(widget));
				break;
			}
		}
		return RT_TRUE;

	default:
		rtgui_win_event_handler(widget, event);
	}

	return RT_FALSE;
}

void calibration_entry(void* parameter)
{
	rt_mq_t mq;
	rtgui_win_t* win;
	struct rtgui_rect rect;

	mq = rt_mq_create("cali", 40, 8, RT_IPC_FLAG_FIFO);
	if (mq == RT_NULL) return;

	rtgui_thread_register(rt_thread_self(), mq);

qiuyiuestc's avatar
qiuyiuestc 已提交
179
	rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &rect);
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

	/* set screen rect */
	calibration_ptr->width = rect.x2;
	calibration_ptr->height = rect.y2;

	/* create calibration window */
	win = rtgui_win_create(RT_NULL,
		"calibration", &rect, RTGUI_WIN_STYLE_NO_TITLE | RTGUI_WIN_STYLE_NO_BORDER);
	rtgui_widget_set_event_handler(RTGUI_WIDGET(win), calibration_event_handler);
	if (win != RT_NULL)
	{
		rtgui_win_show(win, RT_FALSE);
		// rtgui_widget_update(RTGUI_WIDGET(win));
		rtgui_win_event_loop(win);
	}

	rtgui_thread_deregister(rt_thread_self());
	rt_mq_delete(mq);

	/* set calibration data */
	rt_device_control(calibration_ptr->device, RT_TOUCH_CALIBRATION_DATA, &calibration_ptr->data);

	/* recover to normal */
	rt_device_control(calibration_ptr->device, RT_TOUCH_NORMAL, RT_NULL);

	/* release memory */
	rt_free(calibration_ptr);
	calibration_ptr = RT_NULL;
}

void calibration_init()
{
	rt_device_t device;

	device = rt_device_find("touch");
	if (device == RT_NULL) return; /* no this device */

	calibration_ptr = (struct calibration_session*)rt_malloc(sizeof(struct calibration_session));
	rt_memset(calibration_ptr, 0, sizeof(struct calibration_data));
	calibration_ptr->device = device;

	rt_device_control(calibration_ptr->device, RT_TOUCH_CALIBRATION, (void*)calibration_data_post);

	calibration_ptr->tid = rt_thread_create("cali", calibration_entry, RT_NULL,
		2048, 20, 5);
	if (calibration_ptr->tid != RT_NULL) rt_thread_startup(calibration_ptr->tid);
}
227 228

#ifdef RT_USING_FINSH
229 230 231 232 233 234
#include <finsh.h>
void calibration()
{
	calibration_init();
}
FINSH_FUNCTION_EXPORT(calibration, perform touch calibration);
235
#endif