forked from qmk/qmk_firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Digitizer feature improvements (qmk#19034)
- Loading branch information
Showing
10 changed files
with
298 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,117 @@ | ||
## Digitizer | ||
# Digitizer :id=digitizer | ||
|
||
The digitizer HID interface allows setting the mouse cursor position at absolute coordinates, unlike the Pointing Device feature that applies relative displacements. | ||
Digitizers allow the mouse cursor to be placed at absolute coordinates, unlike the [Pointing Device](feature_pointing_device.md) feature which applies relative displacements. | ||
|
||
To enable the digitizer interface, add the following line to your rules.mk: | ||
This feature implements a stylus device with a tip switch and barrel switch (generally equivalent to the primary and secondary mouse buttons respectively). Tip pressure is not currently implemented. | ||
|
||
## Usage :id=usage | ||
|
||
Add the following to your `rules.mk`: | ||
|
||
```make | ||
DIGITIZER_ENABLE = yes | ||
``` | ||
|
||
In order to change the mouse cursor position from your keymap.c file, include the digitizer header : | ||
## Positioning :id=positioning | ||
|
||
The X and Y coordinates are normalized, meaning their value must be set between 0 and 1. For the X component, the value `0` is the leftmost position, whereas the value `1` is the rightmost position. Similarly for the Y component, `0` is at the top and `1` at the bottom. | ||
|
||
?> Since there is no display attached, the OS will likely map these coordinates to the virtual desktop. This may be important to know if you have multiple monitors. | ||
|
||
## Examples :id=examples | ||
|
||
This example simply places the cursor in the middle of the screen: | ||
|
||
```c | ||
#include "digitizer.h" | ||
digitizer_in_range_on(); | ||
digitizer_set_position(0.5, 0.5); | ||
``` | ||
This gives you access to the `digitizer` structure which members allow you to change the cursor position. | ||
|
||
The coordinates are normalized, meaning there value must be set between 0 and 1. For the `x` coordinate, the value `0` is the leftmost position, whereas the value `1` is the rightmost position. | ||
For the `y` coordinate, `0` is at the top and `1` at the bottom. | ||
The "in range" indicator is required to be on for the change in coordinates to be taken. It can then be turned off again to signal the end of the digitizer interaction, but it is not strictly required. | ||
Here is an example setting the cursor in the middle of the screen: | ||
You can also modify the digitizer state directly, if you need to change multiple fields in a single report: | ||
```c | ||
digitizer_t digitizer; | ||
digitizer.x = 0.5; | ||
digitizer.y = 0.5; | ||
digitizer.tipswitch = 0; | ||
digitizer.inrange = 1; | ||
digitizer_set_report(digitizer); | ||
digitizer_state.in_range = true; | ||
digitizer_state.dirty = true; | ||
digitizer_flush(); | ||
``` | ||
|
||
The `tipswitch` member triggers what equates to a click when set to `1`. The `inrange` member is required for the change in coordinates to be taken. It can then be set to `0` in a new report to signal the end of the digitizer interaction, but it is not strictly required. | ||
`digitizer_state` is a struct of type `digitizer_t`. | ||
|
||
|
||
## API :id=api | ||
|
||
### `struct digitizer_t` :id=api-digitizer-t | ||
|
||
Contains the state of the digitizer. | ||
|
||
#### Members :id=api-digitizer-t-members | ||
|
||
- `bool in_range` | ||
Indicates to the host that the contact is within range (ie. close to or in contact with the digitizer surface). | ||
- `bool tip` | ||
The state of the tip switch. | ||
- `bool barrel` | ||
The state of the barrel switch. | ||
- `float x` | ||
The X coordinate of the digitizer contact. | ||
- `float y` | ||
The Y coordinate of the digitizer contact. | ||
- `bool dirty` | ||
Whether the current state needs to be sent to the host. | ||
|
||
--- | ||
|
||
### `void digitizer_flush(void)` :id=api-digitizer-flush | ||
|
||
Send the digitizer report to the host if it is marked as dirty. | ||
|
||
--- | ||
|
||
### `void digitizer_in_range_on(void)` :api-digitizer-in-range-on | ||
|
||
Assert the "in range" indicator, and flush the report. | ||
|
||
--- | ||
|
||
### `void digitizer_in_range_off(void)` :api-digitizer-in-range-off | ||
|
||
Deassert the "in range" indicator, and flush the report. | ||
|
||
--- | ||
|
||
### `void digitizer_tip_switch_on(void)` :api-digitizer-tip-switch-on | ||
|
||
Assert the tip switch, and flush the report. | ||
|
||
--- | ||
|
||
### `void digitizer_tip_switch_off(void)` :api-digitizer-tip-switch-off | ||
|
||
Deassert the tip switch, and flush the report. | ||
|
||
--- | ||
|
||
### `void digitizer_barrel_switch_on(void)` :api-digitizer-barrel-switch-on | ||
|
||
Assert the barrel switch, and flush the report. | ||
|
||
--- | ||
|
||
### `void digitizer_barrel_switch_off(void)` :api-digitizer-barrel-switch-off | ||
|
||
Deassert the barrel switch, and flush the report. | ||
|
||
--- | ||
|
||
### `void digitizer_set_position(float x, float y)` :api-digitizer-set-position | ||
|
||
Set the absolute X and Y position of the digitizer contact, and flush the report. | ||
|
||
#### Arguments :id=api-digitizer-set-position-arguments | ||
|
||
Once all members are set to the desired value, the `status` member needs its bitmask `DZ_UPDATED` to be set so the report is sent during the next main loop iteration. | ||
- `float x` | ||
The X value of the contact position, from 0 to 1. | ||
- `float y` | ||
The Y value of the contact position, from 0 to 1. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,58 @@ | ||
/* Copyright 2021 QMK | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
/* Copyright 2021 QMK | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include QMK_KEYBOARD_H | ||
|
||
#include "digitizer.h" | ||
#include <math.h> | ||
|
||
#include "math.h" | ||
enum custom_keycodes { | ||
DG_TIP = SAFE_RANGE, | ||
}; | ||
|
||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(KC_A)}; | ||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||
LAYOUT_ortho_1x1(DG_TIP) | ||
}; | ||
|
||
uint32_t timer = 0; | ||
|
||
void keyboard_post_init_user(void) { | ||
digitizer_in_range_on(); | ||
} | ||
|
||
void matrix_scan_user() { | ||
if (timer_elapsed32(timer) < 200) { | ||
return; | ||
} | ||
|
||
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_set_report(digitizer); | ||
|
||
timer = timer_read32(); | ||
|
||
float x = 0.5 - 0.2 * cos(timer / 250. / 6.28); | ||
float y = 0.5 - 0.2 * sin(timer / 250. / 6.28); | ||
digitizer_set_position(x, y); | ||
} | ||
|
||
bool process_record_user(uint16_t keycode, keyrecord_t *record) { | ||
switch (keycode) { | ||
case DG_TIP: | ||
if (record->event.pressed) { | ||
digitizer_tip_switch_on(); | ||
} else { | ||
digitizer_tip_switch_off(); | ||
} | ||
return false; | ||
} | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.