さて分割キーボードもひと段落したので次の課題に取り組もうと思う。
トラックポイントを分割キーボードの右側に取り付けたい。
普通のThinkpadキーボードはH,J,Nの間にあるが、狭いし
ちょうど基盤の回路を引いた線が邪魔で穴があけられない。次回Kicadで設計するときは避けるようにしよう。
トラックポイントの生贄
すでに壊れてたので、本物のthinkpadキーボードから部品を拝借。
開封
Trackポイント ハック
上のサイトからどれが何ピンなのか理解する
以降写真撮り忘れたが、
ファームウェアを焼く
トラックポイントの実装
今回はQMKFirmwareにPS2 Mouseで接続する方法が載ってる
https://github.com/qmk/qmk_firmware/blob/master/docs/ja/feature_ps2_mouse.md
マウスホイールの実装
以下は実際に動いたサンプルソース
rules.mk
# トラックポイント接続用設定
PS2_MOUSE_ENABLE = yes
PS2_USE_BUSYWAIT = yes # <- 非推奨だが、空きポートを確保できないためこれで
#PS2_USE_INT = yes
#PS2_USE_USART = yes
OLED_DRIVER_ENABLE = no
# スクロールホイール用
MOUSEKEY_ENABLE = yes
ENCODER_ENABLE = yes
config.h
#pragma once
/*
* Busywait Version :id=busywait-version
* Note: This is not recommended, you may encounter jerky movement or unsent inputs. Please use interrupt or USART version if possible.
*/
/*
トラックポイント接続はここでハマった。PORTD,PIND,DDRDと公式ドキュメントに例が載ってるが、
CLOCK_BITの数字がPromicroのピン番号を表しているのかと思ったらそうではなかった。
最後のアルファベットが例えばATMega32U4上のD3ピンに接続したければ最後の一文字を「D」とし
PS2_CLOCK_BIT 3とするということだった。
これがドキュメント見ても理解できず時間を無駄にした。
QMKのドキュメントは説明が全然足りないよ。
*/
#ifdef PS2_USE_BUSYWAIT
# define PS2_CLOCK_PORT PORTD
# define PS2_CLOCK_PIN PIND
# define PS2_CLOCK_DDR DDRD
# define PS2_CLOCK_BIT 3
# define PS2_DATA_PORT PORTB
# define PS2_DATA_PIN PINB
# define PS2_DATA_DDR DDRB
# define PS2_DATA_BIT 1
#endif
/*
* Interrupt Version :id=interrupt-version
* The following example uses B5 for clock and B6 for data. You can use any INT or PCINT pin for clock, and any pin for data.
*/
#ifdef PS2_USE_INT
# define PS2_CLOCK_PORT PORTB
# define PS2_CLOCK_PIN PINB
# define PS2_CLOCK_DDR DDRB
# define PS2_CLOCK_BIT 5
# define PS2_DATA_PORT PORTB
# define PS2_DATA_PIN PINB
# define PS2_DATA_DDR DDRB
# define PS2_DATA_BIT 6
# define PS2_INT_INIT() do { \
PCICR |= (1<<PCIE0); \
} while (0)
# define PS2_INT_ON() do { \
PCMSK0 |= (1<<PCINT5); \
} while (0)
# define PS2_INT_OFF() do { \
PCMSK0 &= ~(1<<PCINT5); \
} while (0)
# define PS2_INT_VECT PCINT0_vect
#endif
/*
* USART Version :id=usart-version
* To use USART on the ATMega32u4, you have to use PD5 for clock and PD2 for data. If one of those are unavailable, you need to use interrupt version.
* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge
* set DDR of CLOCK as input to be slave
*/
#ifdef PS2_USE_USART
# define PS2_CLOCK_PORT PORTD
# define PS2_CLOCK_PIN PIND
# define PS2_CLOCK_DDR DDRD
# define PS2_CLOCK_BIT 5
# define PS2_DATA_PORT PORTD
# define PS2_DATA_PIN PIND
# define PS2_DATA_DDR DDRD
# define PS2_DATA_BIT 2
# define PS2_USART_INIT() do { \
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
UCSR1C = ((1 << UMSEL10) | \
(3 << UPM10) | \
(0 << USBS1) | \
(3 << UCSZ10) | \
(0 << UCPOL1)); \
UCSR1A = 0; \
UBRR1H = 0; \
UBRR1L = 0; \
} while (0)
# define PS2_USART_RX_INT_ON() do { \
UCSR1B = ((1 << RXCIE1) | \
(1 << RXEN1)); \
} while (0)
# define PS2_USART_RX_POLL_ON() do { \
UCSR1B = (1 << RXEN1); \
} while (0)
# define PS2_USART_OFF() do { \
UCSR1C = 0; \
UCSR1B &= ~((1 << RXEN1) | \
(1 << TXEN1)); \
} while (0)
# define PS2_USART_RX_READY (UCSR1A & (1<<RXC1))
# define PS2_USART_RX_DATA UDR1
# define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1)))
# define PS2_USART_RX_VECT USART1_RX_vect
#endif
#ifdef ENCODER_ENABLE
# define ENCODERS_PAD_A { F6 }
# define ENCODERS_PAD_B { F7 }
# define ENCODER_RESOLUTION 2
#endif
keymap.c
#include QMK_KEYBOARD_H
#include "keymap.h"
// Defines names for use in layer keycodes and the keymap
enum layer_names {
_BASE
};
// Defines the keycodes used by our macros in process_record_user
enum custom_keycodes {
QMKBEST = SAFE_RANGE,
QMKURL
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Base */
[_BASE] = LAYOUT(
KC_A, KC_B, \
KC_C, KC_D \
)
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
}
return true;
}
void matrix_init_user(void) {
// put your keyboard start-up code here
// runs once when the firmware starts up
}
void matrix_scan_user(void) {
// put your looping keyboard code here
// runs every cycle (a lot)
}
void encoder_update_user(uint8_t index, bool clockwise) {
// put your scroll wheel
if (index == 0) { /* First encoder */
if (clockwise) {
tap_code(KC_MS_WH_DOWN);
} else {
tap_code(KC_MS_WH_UP);
}
} else if (index == 1) { /* Second encoder */
if (clockwise) {
tap_code(KC_DOWN);
} else {
tap_code(KC_UP);
}
}
}
ブレッドボードに組み込んだ様子
ごちゃごちゃだけど、キーボードも、トラックポイントもマウスホイールもちゃんと動く。