이로서 지터보정 및 리니어 보정이 linux-input 안에 통째로 붙었다.
jitter 보정은 커서 흔들림을 잡는 것이다. linear 보정은 캘리브레이션 정보에 근거하여 실측값을 뽑는다.
코드를 짤 때 주의사항은 adc 날값(=거대값)으로 지터를 잡아야 한다. 해상도에 맞게 보정된 값으로 지터를 잡으면 커서가 그리드 스냅에 걸린 것 처럼 움직일 것이다.
아래 코드에서 상수 2500은 adc에서 얻어오는 bit수에 따라 적절히 경험적 가감으로 정한다.
static void *linux_input_EventThread( DirectThread *thread, void *driver_data)
{
LinuxInputData *data = (LinuxInputData*) driver_data;
int readlen, status;
unsigned int i;
struct input_event levt[64]; // 실제 저장
fd_set set;
int temp_x, temp_y;
int prevx, prevy;
int dr2;
DFBInputEvent devt = { type: DIET_UNKNOWN, flags: DIEF_NONE };
while (1) {
// direct_thread_testcancel( thread );
readlen = read( data->fd, levt, sizeof(levt) );
if (readlen < 0 && errno != EINTR)
break;
// direct_thread_testcancel( thread );
if (readlen <= 0)
continue;
for (i = 0; i < readlen / sizeof(levt[0]); i++) {
DFBInputEvent temp;
if (levt[i].value) {
switch(levt[i].code) {
case ABS_X:
// 지터 보정
dr2 = (prevx - levt[i].value) * (prevx - levt[i].value);
if (dr2 < 2500)
levt[i].value = prevx;
else
prevx = levt[i].value;
// 리니어 보정
temp_x = levt[i].value;
levt[i].value = ( lin.a[2] +
lin.a[0]*temp_x +
lin.a[1]*temp_y ) / lin.a[6];
break;
case ABS_Y:
dr2 = (prevy - levt[i].value) * (prevy - levt[i].value);
if (dr2 < 2500)
levt[i].value = prevy;
else
prevy = levt[i].value;
temp_y = levt[i].value;
levt[i].value = ( lin.a[5] +
lin.a[3]*temp_x +
lin.a[4]*temp_y ) / lin.a[6];
break;
default:
break;
}
}
if (!translate_event( &levt[i], &temp )) {
// 눌림 시작과 끝에선 여기
continue;
}
// 계속이면.
/* Flush previous event with DIEF_FOLLOW? */
if (devt.type != DIET_UNKNOWN) {
/* Signal immediately following event. */
devt.flags |= DIEF_FOLLOW;
dfb_input_dispatch( data->device, &devt );
devt.type = DIET_UNKNOWN;
devt.flags = DIEF_NONE;
}
devt = temp;
}
/* Flush last event without DIEF_FOLLOW. */
if (devt.type != DIET_UNKNOWN) {
dfb_input_dispatch( data->device, &devt );
}
}
if (status <= 0)
D_PERROR ("linux_input thread died\n");
return NULL;
}