From 81e85a1a4e4b1b7c5bbf1fcffe967a60639778c0 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 26 May 2017 20:35:31 +0200 Subject: [PATCH 1/2] - Added integration of IBM Trackpoint --- keyboards/handwired/trackpoint/Makefile | 3 + keyboards/handwired/trackpoint/README.md | 7 ++ keyboards/handwired/trackpoint/config.h | 75 +++++++++++++++++++ .../trackpoint/keymaps/default/keymap.c | 7 ++ keyboards/handwired/trackpoint/rules.mk | 25 +++++++ keyboards/handwired/trackpoint/trackpoint.c | 5 ++ keyboards/handwired/trackpoint/trackpoint.h | 13 ++++ tmk_core/common/action.c | 34 ++++++++- tmk_core/protocol/ps2_mouse.c | 29 +++---- 9 files changed, 180 insertions(+), 18 deletions(-) create mode 100644 keyboards/handwired/trackpoint/Makefile create mode 100644 keyboards/handwired/trackpoint/README.md create mode 100644 keyboards/handwired/trackpoint/config.h create mode 100644 keyboards/handwired/trackpoint/keymaps/default/keymap.c create mode 100644 keyboards/handwired/trackpoint/rules.mk create mode 100644 keyboards/handwired/trackpoint/trackpoint.c create mode 100644 keyboards/handwired/trackpoint/trackpoint.h diff --git a/keyboards/handwired/trackpoint/Makefile b/keyboards/handwired/trackpoint/Makefile new file mode 100644 index 0000000000..191c6bb664 --- /dev/null +++ b/keyboards/handwired/trackpoint/Makefile @@ -0,0 +1,3 @@ +ifndef MAKEFILE_INCLUDED + include ../../../Makefile +endif \ No newline at end of file diff --git a/keyboards/handwired/trackpoint/README.md b/keyboards/handwired/trackpoint/README.md new file mode 100644 index 0000000000..764ad984a4 --- /dev/null +++ b/keyboards/handwired/trackpoint/README.md @@ -0,0 +1,7 @@ +# IBM Trackpoint demonstration + +This is just a simple demo to show how to integrate IBM Trackpoint in QMK. + +Some documentation: +* [How to wire IBM Trackpoint](https://github.com/alonswartz/trackpoint) +* [QMK documentation](https://docs.qmk.fm/) diff --git a/keyboards/handwired/trackpoint/config.h b/keyboards/handwired/trackpoint/config.h new file mode 100644 index 0000000000..7558c03bf4 --- /dev/null +++ b/keyboards/handwired/trackpoint/config.h @@ -0,0 +1,75 @@ +#ifndef CONFIG_H + #define CONFIG_H + + #include "config_common.h" + + #define VENDOR_ID 0x1234 + #define PRODUCT_ID 0x5678 + #define DEVICE_VER 0x0001 + #define MANUFACTURER QMK + #define PRODUCT TRACKPOINT-DEMO + #define DESCRIPTION Simple demonstration for IBM Trackpoint integration + + #define MATRIX_ROWS 1 + #define MATRIX_COLS 3 + + #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 + + /* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ + /* set DDR of CLOCK as input to be slave */ + #define PS2_USART_INIT() do { \ + PS2_CLOCK_DDR &= ~(1<mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ + ) + +#endif diff --git a/keyboards/handwired/trackpoint/keymaps/default/keymap.c b/keyboards/handwired/trackpoint/keymaps/default/keymap.c new file mode 100644 index 0000000000..22e46d98a7 --- /dev/null +++ b/keyboards/handwired/trackpoint/keymaps/default/keymap.c @@ -0,0 +1,7 @@ +#include "trackpoint.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = KEYMAP( + KC_BTN1, KC_BTN3, KC_BTN2 \ + ) +}; diff --git a/keyboards/handwired/trackpoint/rules.mk b/keyboards/handwired/trackpoint/rules.mk new file mode 100644 index 0000000000..0609dd3043 --- /dev/null +++ b/keyboards/handwired/trackpoint/rules.mk @@ -0,0 +1,25 @@ +MCU = atmega32u4 +F_CPU = 16000000 +ARCH = AVR8 +F_USB = $(F_CPU) +OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT +OPT_DEFS += -DBOOTLOADER_SIZE=512 +BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000) +MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700) +EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450) +CONSOLE_ENABLE ?= yes # Console for debug(+400) +COMMAND_ENABLE ?= yes # Commands for debug and configuration +SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend +NKRO_ENABLE ?= no # USB Nkey Rollover +BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default +MIDI_ENABLE ?= no # MIDI controls +UNICODE_ENABLE ?= no # Unicode +BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID +AUDIO_ENABLE ?= no # Audio output on port C6 + +PS2_MOUSE_ENABLE ?= yes +PS2_USE_USART ?= yes + +ifndef QUANTUM_DIR + include ../../Makefile +endif diff --git a/keyboards/handwired/trackpoint/trackpoint.c b/keyboards/handwired/trackpoint/trackpoint.c new file mode 100644 index 0000000000..124995a642 --- /dev/null +++ b/keyboards/handwired/trackpoint/trackpoint.c @@ -0,0 +1,5 @@ +#include "trackpoint.h" + +void matrix_init_kb(void) { + +} diff --git a/keyboards/handwired/trackpoint/trackpoint.h b/keyboards/handwired/trackpoint/trackpoint.h new file mode 100644 index 0000000000..b5d73d7db5 --- /dev/null +++ b/keyboards/handwired/trackpoint/trackpoint.h @@ -0,0 +1,13 @@ +#ifndef TRACKPOINT_H +#define TRACKPOINT_H + +#include "quantum.h" + +#define KEYMAP( \ + k00, k01, k02 \ +) \ +{ \ + { k00, k01, k02} \ +} + +#endif diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index a534f818ec..f73b0fe807 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -34,6 +34,8 @@ along with this program. If not, see . #include "nodebug.h" #endif +int tp_buttons; + #ifdef FAUXCLICKY_ENABLE #include #endif @@ -311,11 +313,35 @@ void process_action(keyrecord_t *record, action_t action) /* Mouse key */ case ACT_MOUSEKEY: if (event.pressed) { - mousekey_on(action.key.code); - mousekey_send(); + switch (action.key.code) { + case KC_MS_BTN1: + tp_buttons |= (1<<0); + break; + case KC_MS_BTN2: + tp_buttons |= (1<<1); + break; + case KC_MS_BTN3: + tp_buttons |= (1<<2); + break; + default: + mousekey_on(action.key.code); + mousekey_send(); + } } else { - mousekey_off(action.key.code); - mousekey_send(); + switch (action.key.code) { + case KC_MS_BTN1: + tp_buttons &= ~(1<<0); + break; + case KC_MS_BTN2: + tp_buttons &= ~(1<<1); + break; + case KC_MS_BTN3: + tp_buttons &= ~(1<<2); + break; + default: + mousekey_off(action.key.code); + mousekey_send(); + } } break; #endif diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c index d9ccbecb43..4ed3cae1fd 100644 --- a/tmk_core/protocol/ps2_mouse.c +++ b/tmk_core/protocol/ps2_mouse.c @@ -72,12 +72,13 @@ void ps2_mouse_init_user(void) { void ps2_mouse_task(void) { static uint8_t buttons_prev = 0; + extern int tp_buttons; /* receives packet from mouse */ uint8_t rcv; rcv = ps2_host_send(PS2_MOUSE_READ_DATA); if (rcv == PS2_ACK) { - mouse_report.buttons = ps2_host_recv_response(); + mouse_report.buttons = ps2_host_recv_response() | tp_buttons; mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER; mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER; #ifdef PS2_MOUSE_ENABLE_SCROLLING @@ -106,34 +107,34 @@ void ps2_mouse_task(void) { #endif host_mouse_send(&mouse_report); } - + ps2_mouse_clear_report(&mouse_report); } void ps2_mouse_disable_data_reporting(void) { - PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); + PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); } void ps2_mouse_enable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting"); } -void ps2_mouse_set_remote_mode(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode"); +void ps2_mouse_set_remote_mode(void) { + PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode"); ps2_mouse_mode = PS2_MOUSE_REMOTE_MODE; } -void ps2_mouse_set_stream_mode(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode"); +void ps2_mouse_set_stream_mode(void) { + PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode"); ps2_mouse_mode = PS2_MOUSE_STREAM_MODE; } void ps2_mouse_set_scaling_2_1(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); + PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); } void ps2_mouse_set_scaling_1_1(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); + PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); } void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) { @@ -204,9 +205,9 @@ static inline void ps2_mouse_enable_scrolling(void) { #define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK) #define RELEASE_SCROLL_BUTTONS mouse_report->buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK) static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) { - static enum { - SCROLL_NONE, - SCROLL_BTN, + static enum { + SCROLL_NONE, + SCROLL_BTN, SCROLL_SENT, } scroll_state = SCROLL_NONE; static uint16_t scroll_button_time = 0; @@ -228,10 +229,10 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) { mouse_report->y = 0; } } else if (0 == (PS2_MOUSE_SCROLL_BTN_MASK & mouse_report->buttons)) { - // None of the scroll buttons are pressed + // None of the scroll buttons are pressed #if PS2_MOUSE_SCROLL_BTN_SEND - if (scroll_state == SCROLL_BTN + if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) { PRESS_SCROLL_BUTTONS; host_mouse_send(mouse_report); From 6b994ecd82f660feb44bac376ae7d0147d40d818 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 26 May 2017 21:27:11 +0200 Subject: [PATCH 2/2] - Added schematic for Trackpoint demonstration --- keyboards/handwired/trackpoint/README.md | 3 +++ keyboards/handwired/trackpoint/wiring.png | Bin 0 -> 7217 bytes 2 files changed, 3 insertions(+) create mode 100644 keyboards/handwired/trackpoint/wiring.png diff --git a/keyboards/handwired/trackpoint/README.md b/keyboards/handwired/trackpoint/README.md index 764ad984a4..a22fca295e 100644 --- a/keyboards/handwired/trackpoint/README.md +++ b/keyboards/handwired/trackpoint/README.md @@ -2,6 +2,9 @@ This is just a simple demo to show how to integrate IBM Trackpoint in QMK. +Wiring used in the demonstration: +![Wiring example](./wiring.png) + Some documentation: * [How to wire IBM Trackpoint](https://github.com/alonswartz/trackpoint) * [QMK documentation](https://docs.qmk.fm/) diff --git a/keyboards/handwired/trackpoint/wiring.png b/keyboards/handwired/trackpoint/wiring.png new file mode 100644 index 0000000000000000000000000000000000000000..45806e007bc4ff87592e86d72a8fdbbf96a6a6e3 GIT binary patch literal 7217 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 literal 0 HcmV?d00001