aboutsummaryrefslogtreecommitdiff
path: root/keyboards/ploopyco/trackball_mini/trackball_mini.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/ploopyco/trackball_mini/trackball_mini.c')
-rw-r--r--keyboards/ploopyco/trackball_mini/trackball_mini.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/keyboards/ploopyco/trackball_mini/trackball_mini.c b/keyboards/ploopyco/trackball_mini/trackball_mini.c
new file mode 100644
index 000000000..4ae5df083
--- /dev/null
+++ b/keyboards/ploopyco/trackball_mini/trackball_mini.c
@@ -0,0 +1,235 @@
1/* Copyright 2021 Colin Lam (Ploopy Corporation)
2 * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
3 * Copyright 2019 Sunjun Kim
4 * Copyright 2019 Hiroyuki Okada
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "trackball_mini.h"
21
22#ifndef OPT_DEBOUNCE
23# define OPT_DEBOUNCE 5 // (ms) Time between scroll events
24#endif
25
26#ifndef SCROLL_BUTT_DEBOUNCE
27# define SCROLL_BUTT_DEBOUNCE 100 // (ms) Time between scroll events
28#endif
29
30#ifndef OPT_THRES
31# define OPT_THRES 150 // (0-1024) Threshold for actication
32#endif
33
34#ifndef OPT_SCALE
35# define OPT_SCALE 1 // Multiplier for wheel
36#endif
37
38#ifndef PLOOPY_DPI_OPTIONS
39# define PLOOPY_DPI_OPTIONS { CPI375, CPI750, CPI1375 }
40# ifndef PLOOPY_DPI_DEFAULT
41# define PLOOPY_DPI_DEFAULT 2
42# endif
43#endif
44
45#ifndef PLOOPY_DPI_DEFAULT
46# define PLOOPY_DPI_DEFAULT 1
47#endif
48
49// Transformation constants for delta-X and delta-Y
50const static float ADNS_X_TRANSFORM = -1.0;
51const static float ADNS_Y_TRANSFORM = 1.0;
52
53keyboard_config_t keyboard_config;
54uint16_t dpi_array[] = PLOOPY_DPI_OPTIONS;
55#define DPI_OPTION_SIZE (sizeof(dpi_array) / sizeof(uint16_t))
56
57// TODO: Implement libinput profiles
58// https://wayland.freedesktop.org/libinput/doc/latest/pointer-acceleration.html
59// Compile time accel selection
60// Valid options are ACC_NONE, ACC_LINEAR, ACC_CUSTOM, ACC_QUADRATIC
61
62// Trackball State
63bool is_scroll_clicked = false;
64bool BurstState = false; // init burst state for Trackball module
65uint16_t MotionStart = 0; // Timer for accel, 0 is resting state
66uint16_t lastScroll = 0; // Previous confirmed wheel event
67uint16_t lastMidClick = 0; // Stops scrollwheel from being read if it was pressed
68uint8_t OptLowPin = OPT_ENC1;
69bool debug_encoder = false;
70
71__attribute__((weak)) void process_wheel_user(report_mouse_t* mouse_report, int16_t h, int16_t v) {
72 mouse_report->h = h;
73 mouse_report->v = v;
74}
75
76__attribute__((weak)) void process_wheel(report_mouse_t* mouse_report) {
77 // If the mouse wheel was just released, do not scroll.
78 if (timer_elapsed(lastMidClick) < SCROLL_BUTT_DEBOUNCE)
79 return;
80
81 // Limit the number of scrolls per unit time.
82 if (timer_elapsed(lastScroll) < OPT_DEBOUNCE)
83 return;
84
85 // Don't scroll if the middle button is depressed.
86 if (is_scroll_clicked) {
87#ifndef IGNORE_SCROLL_CLICK
88 return;
89#endif
90 }
91
92 lastScroll = timer_read();
93 uint16_t p1 = adc_read(OPT_ENC1_MUX);
94 uint16_t p2 = adc_read(OPT_ENC2_MUX);
95
96 if (debug_encoder)
97 dprintf("OPT1: %d, OPT2: %d\n", p1, p2);
98
99 uint8_t dir = opt_encoder_handler(p1, p2);
100
101 if (dir == 0)
102 return;
103
104 process_wheel_user(mouse_report, mouse_report->h, (int)(mouse_report->v + (dir * OPT_SCALE)));
105}
106
107__attribute__((weak)) void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) {
108 // x and y are swapped
109 // the sensor is rotated
110 // by 90 degrees
111 int16_t temp = x;
112 x = y;
113 y = temp;
114
115 // Apply delta-X and delta-Y transformations.
116 float xt = (float) x * ADNS_X_TRANSFORM;
117 float yt = (float) y * ADNS_Y_TRANSFORM;
118
119 int16_t xti = xt;
120 int16_t yti = yt;
121
122 mouse_report->x = xti;
123 mouse_report->y = yti;
124}
125
126__attribute__((weak)) void process_mouse(report_mouse_t* mouse_report) {
127 report_adns_t data = adns_read_burst();
128
129 if (data.dx != 0 || data.dy != 0) {
130 if (debug_mouse)
131 dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy);
132
133 process_mouse_user(mouse_report, data.dx, data.dy);
134 }
135}
136
137bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
138 xprintf("KL: kc: %u, col: %u, row: %u, pressed: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
139
140 // Update Timer to prevent accidental scrolls
141 if ((record->event.key.col == 1) && (record->event.key.row == 0)) {
142 lastMidClick = timer_read();
143 is_scroll_clicked = record->event.pressed;
144 }
145
146 if (!process_record_user(keycode, record))
147 return false;
148
149 if (keycode == DPI_CONFIG && record->event.pressed) {
150 keyboard_config.dpi_config = (keyboard_config.dpi_config + 1) % DPI_OPTION_SIZE;
151 eeconfig_update_kb(keyboard_config.raw);
152 adns_set_cpi(dpi_array[keyboard_config.dpi_config]);
153 }
154
155/* If Mousekeys is disabled, then use handle the mouse button
156 * keycodes. This makes things simpler, and allows usage of
157 * the keycodes in a consistent manner. But only do this if
158 * Mousekeys is not enable, so it's not handled twice.
159 */
160#ifndef MOUSEKEY_ENABLE
161 if (IS_MOUSEKEY_BUTTON(keycode)) {
162 report_mouse_t currentReport = pointing_device_get_report();
163 if (record->event.pressed) {
164 currentReport.buttons |= 1 << (keycode - KC_MS_BTN1);
165 } else {
166 currentReport.buttons &= ~(1 << (keycode - KC_MS_BTN1));
167 }
168 pointing_device_set_report(currentReport);
169 pointing_device_send();
170 }
171#endif
172
173 return true;
174}
175
176// Hardware Setup
177void keyboard_pre_init_kb(void) {
178 // debug_enable = true;
179 // debug_matrix = true;
180 debug_mouse = true;
181 // debug_encoder = true;
182
183 setPinInput(OPT_ENC1);
184 setPinInput(OPT_ENC2);
185
186 /* Ground all output pins connected to ground. This provides additional
187 * pathways to ground. If you're messing with this, know this: driving ANY
188 * of these pins high will cause a short. On the MCU. Ka-blooey.
189 */
190#ifdef UNUSED_PINS
191 const pin_t unused_pins[] = UNUSED_PINS;
192
193 for (uint8_t i = 0; i < (sizeof(unused_pins) / sizeof(pin_t)); i++) {
194 setPinOutput(unused_pins[i]);
195 writePinLow(unused_pins[i]);
196 }
197#endif
198
199 keyboard_pre_init_user();
200}
201
202void pointing_device_init(void) {
203 adns_init();
204 opt_encoder_init();
205}
206
207void pointing_device_task(void) {
208 report_mouse_t mouse_report = pointing_device_get_report();
209 process_wheel(&mouse_report);
210 process_mouse(&mouse_report);
211 pointing_device_set_report(mouse_report);
212 pointing_device_send();
213}
214
215void eeconfig_init_kb(void) {
216 keyboard_config.dpi_config = PLOOPY_DPI_DEFAULT;
217 eeconfig_update_kb(keyboard_config.raw);
218 eeconfig_init_user();
219}
220
221void matrix_init_kb(void) {
222 // is safe to just read DPI setting since matrix init
223 // comes before pointing device init.
224 keyboard_config.raw = eeconfig_read_kb();
225 if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
226 eeconfig_init_kb();
227 }
228 matrix_init_user();
229}
230
231void keyboard_post_init_kb(void) {
232 adns_set_cpi(dpi_array[keyboard_config.dpi_config]);
233
234 keyboard_post_init_user();
235}