aboutsummaryrefslogtreecommitdiff
path: root/quantum/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/keyboard.c')
-rw-r--r--quantum/keyboard.c569
1 files changed, 569 insertions, 0 deletions
diff --git a/quantum/keyboard.c b/quantum/keyboard.c
new file mode 100644
index 000000000..0eb41e7d3
--- /dev/null
+++ b/quantum/keyboard.c
@@ -0,0 +1,569 @@
1/*
2Copyright 2011, 2012, 2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include <stdint.h>
19#include "keyboard.h"
20#include "matrix.h"
21#include "keymap.h"
22#include "host.h"
23#include "led.h"
24#include "keycode.h"
25#include "timer.h"
26#include "sync_timer.h"
27#include "print.h"
28#include "debug.h"
29#include "command.h"
30#include "util.h"
31#include "sendchar.h"
32#include "eeconfig.h"
33#include "action_layer.h"
34#ifdef BACKLIGHT_ENABLE
35# include "backlight.h"
36#endif
37#ifdef MOUSEKEY_ENABLE
38# include "mousekey.h"
39#endif
40#ifdef PS2_MOUSE_ENABLE
41# include "ps2_mouse.h"
42#endif
43#ifdef SERIAL_MOUSE_ENABLE
44# include "serial_mouse.h"
45#endif
46#ifdef ADB_MOUSE_ENABLE
47# include "adb.h"
48#endif
49#ifdef RGBLIGHT_ENABLE
50# include "rgblight.h"
51#endif
52#ifdef LED_MATRIX_ENABLE
53# include "led_matrix.h"
54#endif
55#ifdef RGB_MATRIX_ENABLE
56# include "rgb_matrix.h"
57#endif
58#ifdef ENCODER_ENABLE
59# include "encoder.h"
60#endif
61#ifdef STENO_ENABLE
62# include "process_steno.h"
63#endif
64#ifdef SERIAL_LINK_ENABLE
65# include "serial_link/system/serial_link.h"
66#endif
67#ifdef VISUALIZER_ENABLE
68# include "visualizer/visualizer.h"
69#endif
70#ifdef POINTING_DEVICE_ENABLE
71# include "pointing_device.h"
72#endif
73#ifdef MIDI_ENABLE
74# include "process_midi.h"
75#endif
76#ifdef JOYSTICK_ENABLE
77# include "process_joystick.h"
78#endif
79#ifdef HD44780_ENABLE
80# include "hd44780.h"
81#endif
82#ifdef QWIIC_ENABLE
83# include "qwiic.h"
84#endif
85#ifdef OLED_DRIVER_ENABLE
86# include "oled_driver.h"
87#endif
88#ifdef ST7565_ENABLE
89# include "st7565.h"
90#endif
91#ifdef VELOCIKEY_ENABLE
92# include "velocikey.h"
93#endif
94#ifdef VIA_ENABLE
95# include "via.h"
96#endif
97#ifdef DIP_SWITCH_ENABLE
98# include "dip_switch.h"
99#endif
100#ifdef STM32_EEPROM_ENABLE
101# include "eeprom_stm32.h"
102#endif
103#ifdef EEPROM_DRIVER
104# include "eeprom_driver.h"
105#endif
106#if defined(CRC_ENABLE)
107# include "crc.h"
108#endif
109#ifdef DIGITIZER_ENABLE
110# include "digitizer.h"
111#endif
112
113static uint32_t last_input_modification_time = 0;
114uint32_t last_input_activity_time(void) { return last_input_modification_time; }
115uint32_t last_input_activity_elapsed(void) { return timer_elapsed32(last_input_modification_time); }
116
117static uint32_t last_matrix_modification_time = 0;
118uint32_t last_matrix_activity_time(void) { return last_matrix_modification_time; }
119uint32_t last_matrix_activity_elapsed(void) { return timer_elapsed32(last_matrix_modification_time); }
120void last_matrix_activity_trigger(void) { last_matrix_modification_time = last_input_modification_time = timer_read32(); }
121
122static uint32_t last_encoder_modification_time = 0;
123uint32_t last_encoder_activity_time(void) { return last_encoder_modification_time; }
124uint32_t last_encoder_activity_elapsed(void) { return timer_elapsed32(last_encoder_modification_time); }
125void last_encoder_activity_trigger(void) { last_encoder_modification_time = last_input_modification_time = timer_read32(); }
126
127// Only enable this if console is enabled to print to
128#if defined(DEBUG_MATRIX_SCAN_RATE)
129static uint32_t matrix_timer = 0;
130static uint32_t matrix_scan_count = 0;
131static uint32_t last_matrix_scan_count = 0;
132
133void matrix_scan_perf_task(void) {
134 matrix_scan_count++;
135
136 uint32_t timer_now = timer_read32();
137 if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) {
138# if defined(CONSOLE_ENABLE)
139 dprintf("matrix scan frequency: %lu\n", matrix_scan_count);
140# endif
141 last_matrix_scan_count = matrix_scan_count;
142 matrix_timer = timer_now;
143 matrix_scan_count = 0;
144 }
145}
146
147uint32_t get_matrix_scan_rate(void) { return last_matrix_scan_count; }
148#else
149# define matrix_scan_perf_task()
150#endif
151
152#ifdef MATRIX_HAS_GHOST
153extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
154static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata) {
155 matrix_row_t out = 0;
156 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
157 // read each key in the row data and check if the keymap defines it as a real key
158 if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1 << col))) {
159 // this creates new row data, if a key is defined in the keymap, it will be set here
160 out |= 1 << col;
161 }
162 }
163 return out;
164}
165
166static inline bool popcount_more_than_one(matrix_row_t rowdata) {
167 rowdata &= rowdata - 1; // if there are less than two bits (keys) set, rowdata will become zero
168 return rowdata;
169}
170
171static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) {
172 /* No ghost exists when less than 2 keys are down on the row.
173 If there are "active" blanks in the matrix, the key can't be pressed by the user,
174 there is no doubt as to which keys are really being pressed.
175 The ghosts will be ignored, they are KC_NO. */
176 rowdata = get_real_keys(row, rowdata);
177 if ((popcount_more_than_one(rowdata)) == 0) {
178 return false;
179 }
180 /* Ghost occurs when the row shares a column line with other row,
181 and two columns are read on each row. Blanks in the matrix don't matter,
182 so they are filtered out.
183 If there are two or more real keys pressed and they match columns with
184 at least two of another row's real keys, the row will be ignored. Keep in mind,
185 we are checking one row at a time, not all of them at once.
186 */
187 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
188 if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)) {
189 return true;
190 }
191 }
192 return false;
193}
194
195#endif
196
197void disable_jtag(void) {
198// To use PF4-7 (PC2-5 on ATmega32A), disable JTAG by writing JTD bit twice within four cycles.
199#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
200 MCUCR |= _BV(JTD);
201 MCUCR |= _BV(JTD);
202#elif defined(__AVR_ATmega32A__)
203 MCUCSR |= _BV(JTD);
204 MCUCSR |= _BV(JTD);
205#endif
206}
207
208/** \brief matrix_setup
209 *
210 * FIXME: needs doc
211 */
212__attribute__((weak)) void matrix_setup(void) {}
213
214/** \brief keyboard_pre_init_user
215 *
216 * FIXME: needs doc
217 */
218__attribute__((weak)) void keyboard_pre_init_user(void) {}
219
220/** \brief keyboard_pre_init_kb
221 *
222 * FIXME: needs doc
223 */
224__attribute__((weak)) void keyboard_pre_init_kb(void) { keyboard_pre_init_user(); }
225
226/** \brief keyboard_post_init_user
227 *
228 * FIXME: needs doc
229 */
230
231__attribute__((weak)) void keyboard_post_init_user() {}
232
233/** \brief keyboard_post_init_kb
234 *
235 * FIXME: needs doc
236 */
237
238__attribute__((weak)) void keyboard_post_init_kb(void) { keyboard_post_init_user(); }
239
240/** \brief keyboard_setup
241 *
242 * FIXME: needs doc
243 */
244void keyboard_setup(void) {
245#ifndef NO_JTAG_DISABLE
246 disable_jtag();
247#endif
248 print_set_sendchar(sendchar);
249#ifdef STM32_EEPROM_ENABLE
250 EEPROM_Init();
251#endif
252#ifdef EEPROM_DRIVER
253 eeprom_driver_init();
254#endif
255 matrix_setup();
256 keyboard_pre_init_kb();
257}
258
259#ifndef SPLIT_KEYBOARD
260
261/** \brief is_keyboard_master
262 *
263 * FIXME: needs doc
264 */
265__attribute__((weak)) bool is_keyboard_master(void) { return true; }
266
267/** \brief is_keyboard_left
268 *
269 * FIXME: needs doc
270 */
271__attribute__((weak)) bool is_keyboard_left(void) { return true; }
272
273#endif
274
275/** \brief should_process_keypress
276 *
277 * Override this function if you have a condition where keypresses processing should change:
278 * - splits where the slave side needs to process for rgb/oled functionality
279 */
280__attribute__((weak)) bool should_process_keypress(void) { return is_keyboard_master(); }
281
282/** \brief housekeeping_task_kb
283 *
284 * Override this function if you have a need to execute code for every keyboard main loop iteration.
285 * This is specific to keyboard-level functionality.
286 */
287__attribute__((weak)) void housekeeping_task_kb(void) {}
288
289/** \brief housekeeping_task_user
290 *
291 * Override this function if you have a need to execute code for every keyboard main loop iteration.
292 * This is specific to user/keymap-level functionality.
293 */
294__attribute__((weak)) void housekeeping_task_user(void) {}
295
296/** \brief housekeeping_task
297 *
298 * Invokes hooks for executing code after QMK is done after each loop iteration.
299 */
300void housekeeping_task(void) {
301 housekeeping_task_kb();
302 housekeeping_task_user();
303}
304
305/** \brief keyboard_init
306 *
307 * FIXME: needs doc
308 */
309void keyboard_init(void) {
310 timer_init();
311 sync_timer_init();
312 matrix_init();
313#if defined(CRC_ENABLE)
314 crc_init();
315#endif
316#ifdef VIA_ENABLE
317 via_init();
318#endif
319#ifdef QWIIC_ENABLE
320 qwiic_init();
321#endif
322#ifdef OLED_DRIVER_ENABLE
323 oled_init(OLED_ROTATION_0);
324#endif
325#ifdef ST7565_ENABLE
326 st7565_init(DISPLAY_ROTATION_0);
327#endif
328#ifdef PS2_MOUSE_ENABLE
329 ps2_mouse_init();
330#endif
331#ifdef SERIAL_MOUSE_ENABLE
332 serial_mouse_init();
333#endif
334#ifdef ADB_MOUSE_ENABLE
335 adb_mouse_init();
336#endif
337#ifdef BACKLIGHT_ENABLE
338 backlight_init();
339#endif
340#ifdef RGBLIGHT_ENABLE
341 rgblight_init();
342#endif
343#ifdef ENCODER_ENABLE
344 encoder_init();
345#endif
346#ifdef STENO_ENABLE
347 steno_init();
348#endif
349#ifdef POINTING_DEVICE_ENABLE
350 pointing_device_init();
351#endif
352#if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
353 keymap_config.nkro = 1;
354 eeconfig_update_keymap(keymap_config.raw);
355#endif
356#ifdef DIP_SWITCH_ENABLE
357 dip_switch_init();
358#endif
359
360#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)
361 debug_enable = true;
362#endif
363
364 keyboard_post_init_kb(); /* Always keep this last */
365}
366
367/** \brief key_event_task
368 *
369 * This function is responsible for calling into other systems when they need to respond to electrical switch press events.
370 * This is differnet than keycode events as no layer processing, or filtering occurs.
371 */
372void switch_events(uint8_t row, uint8_t col, bool pressed) {
373#if defined(LED_MATRIX_ENABLE)
374 process_led_matrix(row, col, pressed);
375#endif
376#if defined(RGB_MATRIX_ENABLE)
377 process_rgb_matrix(row, col, pressed);
378#endif
379}
380
381/** \brief Keyboard task: Do keyboard routine jobs
382 *
383 * Do routine keyboard jobs:
384 *
385 * * scan matrix
386 * * handle mouse movements
387 * * run visualizer code
388 * * handle midi commands
389 * * light LEDs
390 *
391 * This is repeatedly called as fast as possible.
392 */
393void keyboard_task(void) {
394 static matrix_row_t matrix_prev[MATRIX_ROWS];
395 static uint8_t led_status = 0;
396 matrix_row_t matrix_row = 0;
397 matrix_row_t matrix_change = 0;
398#ifdef QMK_KEYS_PER_SCAN
399 uint8_t keys_processed = 0;
400#endif
401#ifdef ENCODER_ENABLE
402 bool encoders_changed = false;
403#endif
404
405 uint8_t matrix_changed = matrix_scan();
406 if (matrix_changed) last_matrix_activity_trigger();
407
408 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
409 matrix_row = matrix_get_row(r);
410 matrix_change = matrix_row ^ matrix_prev[r];
411 if (matrix_change) {
412#ifdef MATRIX_HAS_GHOST
413 if (has_ghost_in_row(r, matrix_row)) {
414 continue;
415 }
416#endif
417 if (debug_matrix) matrix_print();
418 matrix_row_t col_mask = 1;
419 for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
420 if (matrix_change & col_mask) {
421 if (should_process_keypress()) {
422 action_exec((keyevent_t){
423 .key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */
424 });
425 }
426 // record a processed key
427 matrix_prev[r] ^= col_mask;
428
429 switch_events(r, c, (matrix_row & col_mask));
430
431#ifdef QMK_KEYS_PER_SCAN
432 // only jump out if we have processed "enough" keys.
433 if (++keys_processed >= QMK_KEYS_PER_SCAN)
434#endif
435 // process a key per task call
436 goto MATRIX_LOOP_END;
437 }
438 }
439 }
440 }
441 // call with pseudo tick event when no real key event.
442#ifdef QMK_KEYS_PER_SCAN
443 // we can get here with some keys processed now.
444 if (!keys_processed)
445#endif
446 action_exec(TICK);
447
448MATRIX_LOOP_END:
449
450#ifdef DEBUG_MATRIX_SCAN_RATE
451 matrix_scan_perf_task();
452#endif
453
454#if defined(RGBLIGHT_ENABLE)
455 rgblight_task();
456#endif
457
458#ifdef LED_MATRIX_ENABLE
459 led_matrix_task();
460#endif
461#ifdef RGB_MATRIX_ENABLE
462 rgb_matrix_task();
463#endif
464
465#if defined(BACKLIGHT_ENABLE)
466# if defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS)
467 backlight_task();
468# endif
469#endif
470
471#ifdef ENCODER_ENABLE
472 encoders_changed = encoder_read();
473 if (encoders_changed) last_encoder_activity_trigger();
474#endif
475
476#ifdef QWIIC_ENABLE
477 qwiic_task();
478#endif
479
480#ifdef OLED_DRIVER_ENABLE
481 oled_task();
482# ifndef OLED_DISABLE_TIMEOUT
483 // Wake up oled if user is using those fabulous keys or spinning those encoders!
484# ifdef ENCODER_ENABLE
485 if (matrix_changed || encoders_changed) oled_on();
486# else
487 if (matrix_changed) oled_on();
488# endif
489# endif
490#endif
491
492#ifdef ST7565_ENABLE
493 st7565_task();
494# ifndef ST7565_DISABLE_TIMEOUT
495 // Wake up display if user is using those fabulous keys or spinning those encoders!
496# ifdef ENCODER_ENABLE
497 if (matrix_changed || encoders_changed) st7565_on();
498# else
499 if (matrix_changed) st7565_on();
500# endif
501# endif
502#endif
503
504#ifdef MOUSEKEY_ENABLE
505 // mousekey repeat & acceleration
506 mousekey_task();
507#endif
508
509#ifdef PS2_MOUSE_ENABLE
510 ps2_mouse_task();
511#endif
512
513#ifdef SERIAL_MOUSE_ENABLE
514 serial_mouse_task();
515#endif
516
517#ifdef ADB_MOUSE_ENABLE
518 adb_mouse_task();
519#endif
520
521#ifdef SERIAL_LINK_ENABLE
522 serial_link_update();
523#endif
524
525#ifdef VISUALIZER_ENABLE
526 visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds());
527#endif
528
529#ifdef POINTING_DEVICE_ENABLE
530 pointing_device_task();
531#endif
532
533#ifdef MIDI_ENABLE
534 midi_task();
535#endif
536
537#ifdef VELOCIKEY_ENABLE
538 if (velocikey_enabled()) {
539 velocikey_decelerate();
540 }
541#endif
542
543#ifdef JOYSTICK_ENABLE
544 joystick_task();
545#endif
546
547#ifdef DIGITIZER_ENABLE
548 digitizer_task();
549#endif
550
551 // update LED
552 if (led_status != host_keyboard_leds()) {
553 led_status = host_keyboard_leds();
554 keyboard_set_leds(led_status);
555 }
556}
557
558/** \brief keyboard set leds
559 *
560 * FIXME: needs doc
561 */
562void keyboard_set_leds(uint8_t leds) {
563 if (debug_keyboard) {
564 debug("keyboard_set_led: ");
565 debug_hex8(leds);
566 debug("\n");
567 }
568 led_set(leds);
569}