Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand digitizer feature. #15917

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
294 changes: 281 additions & 13 deletions docs/feature_digitizer.md

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions keyboards/handwired/digitizer_demo/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a license header.

But also, this may be better as a keymap for handwired/onekey

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, good call. I just wired up a promicro onekey board to test with, so I can make this suggested change.


#include "config_common.h"

/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0xD1D0
#define DEVICE_VER 0x0001
#define MANUFACTURER QMK
#define PRODUCT DigitizerDemo

/* key matrix size */
#define MATRIX_ROWS 2
#define MATRIX_COLS 5

/*
* Keyboard Matrix Assignments
*
* Change this to how you wired your keyboard
* COLS: AVR pins used for columns, left to right
* ROWS: AVR pins used for rows, top to bottom
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
*
*/
#define MATRIX_ROW_PINS { D1, D0 }
#define MATRIX_COL_PINS { D4, C6, D7, E6, B4 }
#define UNUSED_PINS

/* COL2ROW, ROW2COL */
#define DIODE_DIRECTION COL2ROW

/*
* Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk, and define SOFT_SERIAL_PIN.
*/
#define SOFT_SERIAL_PIN F4 // or D1, D2, D3, E6

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5

/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE

/* disable these deprecated features by default */
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION
12 changes: 12 additions & 0 deletions keyboards/handwired/digitizer_demo/digitizer_demo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "quantum.h"


#define LAYOUT( \
k00, k01, k02, k03, k04, \
k10, k11, k12, k13, k14 \
) { \
{ k00, k01, k02, k03, k04 }, \
{ k10, k11, k12, k13, k14 }, \
}
9 changes: 9 additions & 0 deletions keyboards/handwired/digitizer_demo/keymaps/default/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* Identify this digitizer as a less generic device */
#define DIGITIZER_USAGE_ID DIG_TOUCH_SCREEN

/* Set x/y resolution to match desired screen aspect ratio */
#define DIGITIZER_MAX_X 2560
#define DIGITIZER_MAX_Y 1440

/* Jitter x/y to simulate more realistic touch events for the OS */
#define DIGITIZER_FUZZ
47 changes: 47 additions & 0 deletions keyboards/handwired/digitizer_demo/keymaps/default/keymap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include QMK_KEYBOARD_H
#include "digitizer.h"
#include "math.h"


enum my_layers {
_BASE
};


enum my_keycodes {
MY_FUZZ = SAFE_RANGE
};


const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_BASE] = LAYOUT(
RESET, DZ_TIP1, DZ_BAR1, DZ_BAR2, MY_FUZZ,
DZ_P_C, DZ_P_U0, DZ_P_U1, DZ_P_U2, DZ_P_U3
),
};


bool process_record_user(uint16_t keycode, keyrecord_t *record) {
digitizer_t digitizer;
switch (keycode) {
case MY_FUZZ:
if (record->event.pressed) {
// Set mouse to the top of the screen, 50% of the way across
digitizer = digitizer_fuzz_xy(DIG_REL2ABS_X(0.5), 0);
// Press the tip switch (usually treated as left mouse button)
digitizer.buttons |= DIG_TIP_PRIMARY;
digitizer.inrange = true;
digitizer_set_report(digitizer);
return false;
} else {
// Release the tip switch
digitizer = digitizer_get_report();
digitizer.buttons &= ~DIG_TIP_PRIMARY;
digitizer.inrange = true;
digitizer_set_report(digitizer);
return false;
}
default:
return true;
}
}
2 changes: 2 additions & 0 deletions keyboards/handwired/digitizer_demo/keymaps/default/rules.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DIGITIZER_ENABLE = yes
POINTING_DEVICE_ENABLE = yes
19 changes: 19 additions & 0 deletions keyboards/handwired/digitizer_demo/rules.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# MCU name
MCU = atmega32u4

# Bootloader selection
BOOTLOADER = caterina

# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
MOUSEKEY_ENABLE = no # Mouse keys
EXTRAKEY_ENABLE = no # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
NKRO_ENABLE = no # Enable N-Key Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
AUDIO_ENABLE = no # Audio output
ENCODER_ENABLE = no # Encoder support
8 changes: 4 additions & 4 deletions keyboards/handwired/onekey/keymaps/digitizer/keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ void matrix_scan_user() {

timer = timer_read32();
digitizer_t digitizer;
digitizer.x = 0.5 - 0.2 * cos(timer_read() / 250. / 6.28);
digitizer.y = 0.5 - 0.2 * sin(timer_read() / 250. / 6.28);
digitizer.tipswitch = 0;
digitizer.inrange = 1;
digitizer.x = DIG_REL2ABS_X(0.5 - 0.2 * cos(timer_read() / 250. / 6.28));
digitizer.y = DIG_REL2ABS_Y(0.5 - 0.2 * sin(timer_read() / 250. / 6.28));
digitizer.buttons = 0;
digitizer.inrange = true;
digitizer_set_report(digitizer);
}
105 changes: 95 additions & 10 deletions quantum/digitizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,105 @@
*/
#include "digitizer.h"

digitizer_t digitizerReport = {.tipswitch = 0, .inrange = 0, .id = 0, .x = 0, .y = 0, .status = DZ_INITIALIZED};
digitizer_t digitizer_report = {
.inrange = false,
.buttons = 0,
.x = 0,
.y = 0,
.status = DZ_INITIALIZED
};

__attribute__((weak)) void digitizer_send(void) {
if (digitizerReport.status & DZ_UPDATED) {
host_digitizer_send(&digitizerReport);
digitizerReport.status &= ~DZ_UPDATED;
if (digitizer_report.status & DZ_UPDATED) {
host_digitizer_send(&digitizer_report);
digitizer_report.status &= ~DZ_UPDATED;
}
}

__attribute__((weak)) void digitizer_task(void) { digitizer_send(); }
__attribute__((weak)) void digitizer_task(void) {
digitizer_send();
}

digitizer_t digitizer_get_report(void) {
return digitizer_report;
}

void digitizer_set_report(digitizer_t digitizer) {
digitizer_report = digitizer;
digitizer_report.status |= DZ_UPDATED;
}


void digitizer_register_inrange() {
// Begin InRange "touch" event
digitizer_report.inrange = true;
host_digitizer_send(&digitizer_report);
digitizer_report.status &= ~DZ_UPDATED;
}

void digitizer_unregister_inrange() {
// End InRange "touch" event
digitizer_report.inrange = false;
host_digitizer_send(&digitizer_report);
digitizer_report.status &= ~DZ_UPDATED;
}

digitizer_t digitizer_get_report(void) { return digitizerReport; }
/** \brief Register InRange touch near current x/y
*
* A report is immediately sent touching a coordinate near x/y, and then a
* second report is immediately sent for a touch event precisely at x/y.
*
* If DIGITIZER_FUZZ_INRANGE is not defined, this function only sends one
* report precisely at x/y.
*/
void digitizer_fuzz_inrange(uint16_t x, uint16_t y) {
#ifdef DIGITIZER_FUZZ_INRANGE
// Linux ignores events when x/y coordinate hasn't changed; touch nearby
digitizer_report.x = DIG_FUZZ_X(x);
digitizer_report.y = DIG_FUZZ_Y(y);
digitizer_register_inrange();
#endif
// Touch precisely at x/y
digitizer_report.x = x;
digitizer_report.y = y;
digitizer_register_inrange();
}

/** \brief Register several small pointer movements around the current x/y
*
* Immediately "jitters" the mouse back and forth, causing some OSes to
* re-render the cursor at the last touched position.
*/
void digitizer_fuzz_mouse() {
#ifdef DIGITIZER_FUZZ_MOUSE
// OSX can skip rendering the cursor after a touch, until the mouse moves
report_mouse_t mouse_report;
mouse_report = pointing_device_get_report();
int kx = (digitizer_report.x >= DIGITIZER_MAX_X ? -1 : 1);
int ky = (digitizer_report.y >= DIGITIZER_MAX_Y ? -1 : 1);
for (uint8_t i = 0; i < DIGITIZER_FUZZ_MOUSE_TIMES; i++) {
// Nudge the mouse out...
mouse_report.x = kx * DIGITIZER_FUZZ_X;
mouse_report.y = ky * DIGITIZER_FUZZ_Y;
pointing_device_set_report(mouse_report);
pointing_device_send();
// ...and back in
mouse_report.x = -kx * DIGITIZER_FUZZ_X;
mouse_report.y = -ky * DIGITIZER_FUZZ_Y;
pointing_device_set_report(mouse_report);
pointing_device_send();
}
#endif
}

void digitizer_set_report(digitizer_t newDigitizerReport) {
digitizerReport = newDigitizerReport;
digitizerReport.status |= DZ_UPDATED;
}
digitizer_t digitizer_fuzz_xy(uint16_t x, uint16_t y) {
// Touch nearby x/y, then exactly x/y
digitizer_fuzz_inrange(x, y);
// Touch the correct x/y only briefly
digitizer_unregister_inrange();
#ifdef DIGITIZER_FUZZ_MOUSE
// Force OS to render the pointer at x/y
digitizer_fuzz_mouse();
#endif
return digitizer_report;
}
Loading