QMK로 TrackPoint Drift 고치기

Corne Keyboard라는 오픈소스, 좌우 분리, 인체공학, DIY 친화적 키보드가 있습니다. 그런데 어느날 Holykeebs에서 IBM 빨콩으로 알려진 TrackPoint를 Corne에다가 끼얹은 키보드 조립 키트를 판매하고 있다는 것을 알았습니다. 즐겁게 구매하고 조립하여 사용해보니 대체로 마음에 들었지만 불편한 지점이 하나 있었습니다. (납땜하여 조립하고 QMK 펌웨어 설정하는 것이 어떤 부류의 사람들에겐 즐거움입니다… 특히 QMK 토끼구멍은 한 번 타고 내려가기 시작하면 시간가는 줄 모르고 파고들게 됩니다.)

불편한 지점은 바로 TrackPoint의 고질적인 문제인 Drift입니다. 예전에 사용했던 Tex Shinobi키보드에서도 겪었던 문제인데, 가끔씩 사용자 입력 없이도 포인터가 한 방향으로 잠시간 스물스물 떠내려가는 현상입니다.

문제 해결을 위해 연구(삽질)를 계속하다가 큰 기대 없이 Perplexity Deep Research에다가 해결법을 물어보았더니 Svalboard라는 대안키보드에서 이미 해결한 문제라는 답을 줍니다. 요약하면 Sprintek 트랙포인트에서 하드웨어적으로 기본 탑재된 Auto calibaration이 원하지 않는 시기에 동작하는 것이 문제의 원인이란 이야기입니다. 스발보드가 제안하는 해결책은 자동 캘리브레이션을 완전히 꺼버리는 것입니다.

자동 캘리브레이션 끄기

#ifdef PS2_ENABLE
#include "ps2_mouse.h"
#include "ps2.h"

void setup_trackpoint(void) {
    ps2_mouse_disable_data_reporting();

/*
From Sprintek:
E2 47 FA 10 - Disable drift correction. - Flips the bit, it should boot enabled.
This was given to us to stop the trackpoint from calibrating at bad times.
*/
    PS2_MOUSE_SEND(0xE2, "pts: 0xE2");
    PS2_MOUSE_SEND(0x80, "pts: 0x80");
    PS2_MOUSE_SEND(0xFA, "pts: 0xFA");
    uint8_t val;
    val = ps2_host_recv_response();

    if (~val & 0x10) {
        PS2_MOUSE_SEND(0xE2, "pts: 0xE2");
        PS2_MOUSE_SEND(0x47, "pts: 0x47");
        PS2_MOUSE_SEND(0xFA, "pts: 0xFA");
        PS2_MOUSE_SEND(0x10, "pts: 0x10");
        PS2_MOUSE_RECEIVE("drift correction - disable");
    }
/*
From Sprintek:
E2 81 92 XX - Set the deadzone - 0x0C default, claimed.
Increase this to get rid of the tail drift.
*/
    PS2_MOUSE_SEND(0xE2, "pts: 0xE2");
    PS2_MOUSE_SEND(0x81, "pts: 0x81");
    PS2_MOUSE_SEND(0x92, "pts: 0x92");
    PS2_MOUSE_SEND(0x0F, "pts: 0x0F");

    ps2_mouse_enable_data_reporting();
}
#endif

이것을 keymap.c파일에 추가하고 setup_trackpointkeyboard_post_init_user 같이 키보드가 처음 시작될 때 동작하는 부분에서 불러줍니다.

밑부분에 있는 데드존 설정은 아래에서 다시 설명합니다.

수동 캘리브레이션

원래 재조정이란 것은 드리프트를 방지하기 위해서 만들어진 기능이기 때문에, 자동으로 재조정을 안 한다면 원치 않는 순간에 자동 영점조정이 일어나서 발생하는 드리프트는 방지할 수 있지만, 자연적으로 발생하는 드리프트는 한 번 시작되면 영원히 지속되게 됩니다. 그래서 자연적인 드리프트가 발생할 때 수동으로 영점조절을 넣어줄 필요가 있습니다.

void recalibrate_pointer(void) {
#ifdef PS2_ENABLE
    PS2_MOUSE_SEND(0xE2, "pts: 0xE2");
    PS2_MOUSE_SEND(0x51, "pts: 0x51");
    PS2_MOUSE_RECEIVE("trackpoint - recalibrate");
#endif
}

이렇게 함수를 하나 추가해주고 키코드를 하나 추가해서 그것을 누를 때마다 호출해주면 수동으로 영점조정이 됩니다.

여기서 더 나아가면 포인터 x, y report의 히스토리를 추적하여 모종의 알고리즘으로 자연적인 드리프트를 감지해내고 수동 캘리브레이션을 자동(?)으로 호출하는 방법이나, 트랙포인트의 펌웨어를 더 파고 들어서 자동 영점조절의 강도를 조절하는 방법이 있겠습니다만 3개월 정도 사용결과 자동조절을 완전히 비활성화 하는 것으로 충분해 보입니다.

자 그럼 데드존은 왜 필요할까요? 데드존 설정은 미세한 포인터 움직임은 무시함으로써 수동 영점조절이 필요한 순간들을 대폭 감소시켜줍니다. 값이 너무 크면 정밀한 포인터 조작이 어려워지고, 너무 작으면 수동 영점조절을 자주 해줘야 합니다. 하드웨어마다 차이가 있을 수 있습니다만, 0x0F정도가 저에겐 딱 적당한 값이었습니다.

이외에도 Auto mouse layer 설정, Drag scroll 만들기, idle timer로 반자동 영점조정하기, Glob 키코드 추가하기 등 많은 주제들이 있으니 다음 기회에 다루어 보겠습니다.