Move rgblight and backlight task to common location (#7733)
[jackhill/qmk/firmware.git] / tmk_core / common / keyboard.c
CommitLineData
a074364c 1/*
aaa758f1 2Copyright 2011, 2012, 2013 Jun Wako <wakojun@gmail.com>
a074364c 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*/
06d21009 17
a074364c 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 "print.h"
27#include "debug.h"
28#include "command.h"
29#include "util.h"
30#include "sendchar.h"
aaa758f1 31#include "eeconfig.h"
07d0d5cb 32#include "action_layer.h"
abfd6ed9
JC
33#ifdef BACKLIGHT_ENABLE
34# include "backlight.h"
35#endif
ab19ebd0 36#ifdef BOOTMAGIC_ENABLE
b624f32f 37# include "bootmagic.h"
ab19ebd0 38#else
b624f32f 39# include "magic.h"
ab19ebd0 40#endif
a074364c 41#ifdef MOUSEKEY_ENABLE
b624f32f 42# include "mousekey.h"
a074364c 43#endif
44#ifdef PS2_MOUSE_ENABLE
b624f32f 45# include "ps2_mouse.h"
a074364c 46#endif
47#ifdef SERIAL_MOUSE_ENABLE
b624f32f 48# include "serial_mouse.h"
a074364c 49#endif
4d116a04 50#ifdef ADB_MOUSE_ENABLE
b624f32f 51# include "adb.h"
4d116a04 52#endif
69557190 53#ifdef RGBLIGHT_ENABLE
b624f32f 54# include "rgblight.h"
69557190 55#endif
f30f12ec 56#ifdef STENO_ENABLE
b624f32f 57# include "process_steno.h"
f30f12ec 58#endif
c68e596f 59#ifdef FAUXCLICKY_ENABLE
b624f32f 60# include "fauxclicky.h"
c68e596f 61#endif
4b45deb6 62#ifdef SERIAL_LINK_ENABLE
b624f32f 63# include "serial_link/system/serial_link.h"
4b45deb6 64#endif
07d0d5cb 65#ifdef VISUALIZER_ENABLE
b624f32f 66# include "visualizer/visualizer.h"
07d0d5cb 67#endif
ee132284 68#ifdef POINTING_DEVICE_ENABLE
b624f32f 69# include "pointing_device.h"
ee132284 70#endif
53ff8a31 71#ifdef MIDI_ENABLE
b624f32f 72# include "process_midi.h"
53ff8a31 73#endif
bbea9dad 74#ifdef HD44780_ENABLE
b624f32f 75# include "hd44780.h"
bbea9dad 76#endif
4099536c 77#ifdef QWIIC_ENABLE
b624f32f 78# include "qwiic.h"
4099536c 79#endif
e01b2d51 80#ifdef OLED_DRIVER_ENABLE
b624f32f 81# include "oled_driver.h"
e01b2d51 82#endif
c1c5922a 83#ifdef VELOCIKEY_ENABLE
b624f32f 84# include "velocikey.h"
c1c5922a 85#endif
320822d7
W
86#ifdef VIA_ENABLE
87# include "via.h"
88#endif
a074364c 89
cc5edb9e
JC
90// Only enable this if console is enabled to print to
91#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)
92static uint32_t matrix_timer = 0;
93static uint32_t matrix_scan_count = 0;
94
95void matrix_scan_perf_task(void) {
96 matrix_scan_count++;
97
98 uint32_t timer_now = timer_read32();
99 if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) {
100 dprintf("matrix scan frequency: %d\n", matrix_scan_count);
101
102 matrix_timer = timer_now;
103 matrix_scan_count = 0;
104 }
105}
106#else
107# define matrix_scan_perf_task()
108#endif
109
a074364c 110#ifdef MATRIX_HAS_GHOST
37f6f927 111extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
b624f32f 112static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata) {
37f6f927 113 matrix_row_t out = 0;
25c6ca75 114 for (uint8_t col = 0; col < MATRIX_COLS; col++) {
b624f32f 115 // read each key in the row data and check if the keymap defines it as a real key
116 if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1 << col))) {
117 // this creates new row data, if a key is defined in the keymap, it will be set here
118 out |= 1 << col;
37f6f927
J
119 }
120 }
121 return out;
122}
123
b624f32f 124static inline bool popcount_more_than_one(matrix_row_t rowdata) {
125 rowdata &= rowdata - 1; // if there are less than two bits (keys) set, rowdata will become zero
25c6ca75 126 return rowdata;
b9895771 127}
63d9698d 128
b624f32f 129static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) {
849ed5a6
J
130 /* No ghost exists when less than 2 keys are down on the row.
131 If there are "active" blanks in the matrix, the key can't be pressed by the user,
132 there is no doubt as to which keys are really being pressed.
133 The ghosts will be ignored, they are KC_NO. */
25c6ca75 134 rowdata = get_real_keys(row, rowdata);
b624f32f 135 if ((popcount_more_than_one(rowdata)) == 0) {
25c6ca75
J
136 return false;
137 }
138 /* Ghost occurs when the row shares a column line with other row,
139 and two columns are read on each row. Blanks in the matrix don't matter,
140 so they are filtered out.
141 If there are two or more real keys pressed and they match columns with
142 at least two of another row's real keys, the row will be ignored. Keep in mind,
143 we are checking one row at a time, not all of them at once.
144 */
b624f32f 145 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
146 if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)) {
8e88d55b 147 return true;
849ed5a6 148 }
a074364c 149 }
150 return false;
151}
99877cdf 152
a074364c 153#endif
154
a5fa75fc 155void disable_jtag(void) {
f2c179de 156// To use PF4-7 (PC2-5 on ATmega32A), disable JTAG by writing JTD bit twice within four cycles.
b624f32f 157#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
a5fa75fc
DN
158 MCUCR |= _BV(JTD);
159 MCUCR |= _BV(JTD);
f2c179de 160#elif defined(__AVR_ATmega32A__)
161 MCUCSR |= _BV(JTD);
162 MCUCSR |= _BV(JTD);
a5fa75fc
DN
163#endif
164}
165
7c9d5ace 166/** \brief matrix_setup
167 *
168 * FIXME: needs doc
169 */
b624f32f 170__attribute__((weak)) void matrix_setup(void) {}
a074364c 171
cc5c6b44
DJ
172/** \brief keyboard_pre_init_user
173 *
174 * FIXME: needs doc
175 */
b624f32f 176__attribute__((weak)) void keyboard_pre_init_user(void) {}
cc5c6b44
DJ
177
178/** \brief keyboard_pre_init_kb
179 *
180 * FIXME: needs doc
181 */
b624f32f 182__attribute__((weak)) void keyboard_pre_init_kb(void) { keyboard_pre_init_user(); }
cc5c6b44
DJ
183
184/** \brief keyboard_post_init_user
185 *
186 * FIXME: needs doc
187 */
188
b624f32f 189__attribute__((weak)) void keyboard_post_init_user() {}
cc5c6b44
DJ
190
191/** \brief keyboard_post_init_kb
192 *
193 * FIXME: needs doc
194 */
195
b624f32f 196__attribute__((weak)) void keyboard_post_init_kb(void) { keyboard_post_init_user(); }
cc5c6b44 197
7c9d5ace 198/** \brief keyboard_setup
199 *
200 * FIXME: needs doc
201 */
aaa758f1 202void keyboard_setup(void) {
f2c179de 203#ifndef NO_JTAG_DISABLE
a5fa75fc 204 disable_jtag();
f2c179de 205#endif
6b588eb7 206 matrix_setup();
cc5c6b44 207 keyboard_pre_init_kb();
6b588eb7 208}
209
7c9d5ace 210/** \brief is_keyboard_master
211 *
212 * FIXME: needs doc
213 */
b624f32f 214__attribute__((weak)) bool is_keyboard_master(void) { return true; }
25285a1c 215
7c9d5ace 216/** \brief keyboard_init
217 *
218 * FIXME: needs doc
219 */
aaa758f1 220void keyboard_init(void) {
a074364c 221 timer_init();
222 matrix_init();
320822d7
W
223#ifdef VIA_ENABLE
224 via_init();
225#endif
4099536c 226#ifdef QWIIC_ENABLE
227 qwiic_init();
228#endif
e01b2d51
X
229#ifdef OLED_DRIVER_ENABLE
230 oled_init(OLED_ROTATION_0);
231#endif
a074364c 232#ifdef PS2_MOUSE_ENABLE
233 ps2_mouse_init();
234#endif
235#ifdef SERIAL_MOUSE_ENABLE
236 serial_mouse_init();
237#endif
4d116a04 238#ifdef ADB_MOUSE_ENABLE
239 adb_mouse_init();
240#endif
a074364c 241#ifdef BOOTMAGIC_ENABLE
242 bootmagic();
ab19ebd0
JH
243#else
244 magic();
a074364c 245#endif
a074364c 246#ifdef BACKLIGHT_ENABLE
247 backlight_init();
248#endif
69557190
ET
249#ifdef RGBLIGHT_ENABLE
250 rgblight_init();
251#endif
f30f12ec
JW
252#ifdef STENO_ENABLE
253 steno_init();
254#endif
c68e596f
PIN
255#ifdef FAUXCLICKY_ENABLE
256 fauxclicky_init();
257#endif
ee132284
S
258#ifdef POINTING_DEVICE_ENABLE
259 pointing_device_init();
260#endif
1d13aa93 261#if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
558f3ec1 262 keymap_config.nkro = 1;
efb21c00 263 eeconfig_update_keymap(keymap_config.raw);
577971ab 264#endif
cc5c6b44 265 keyboard_post_init_kb(); /* Always keep this last */
a074364c 266}
267
7c9d5ace 268/** \brief Keyboard task: Do keyboard routine jobs
269 *
ee3b9d2e 270 * Do routine keyboard jobs:
7c9d5ace 271 *
272 * * scan matrix
273 * * handle mouse movements
274 * * run visualizer code
275 * * handle midi commands
276 * * light LEDs
277 *
8e88d55b
JH
278 * This is repeatedly called as fast as possible.
279 */
b624f32f 280void keyboard_task(void) {
8e88d55b 281 static matrix_row_t matrix_prev[MATRIX_ROWS];
b624f32f 282 static uint8_t led_status = 0;
283 matrix_row_t matrix_row = 0;
284 matrix_row_t matrix_change = 0;
39d3d923
S
285#ifdef QMK_KEYS_PER_SCAN
286 uint8_t keys_processed = 0;
287#endif
8e88d55b 288
e01b2d51
X
289#if defined(OLED_DRIVER_ENABLE) && !defined(OLED_DISABLE_TIMEOUT)
290 uint8_t ret = matrix_scan();
291#else
a074364c 292 matrix_scan();
e01b2d51 293#endif
3cf7f732 294
25285a1c
FS
295 if (is_keyboard_master()) {
296 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
b624f32f 297 matrix_row = matrix_get_row(r);
25285a1c
FS
298 matrix_change = matrix_row ^ matrix_prev[r];
299 if (matrix_change) {
a074364c 300#ifdef MATRIX_HAS_GHOST
b624f32f 301 if (has_ghost_in_row(r, matrix_row)) {
302 continue;
303 }
25285a1c
FS
304#endif
305 if (debug_matrix) matrix_print();
85f4c3eb
DJ
306 matrix_row_t col_mask = 1;
307 for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
308 if (matrix_change & col_mask) {
25285a1c 309 action_exec((keyevent_t){
85f4c3eb 310 .key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */
25285a1c
FS
311 });
312 // record a processed key
85f4c3eb 313 matrix_prev[r] ^= col_mask;
39d3d923
S
314#ifdef QMK_KEYS_PER_SCAN
315 // only jump out if we have processed "enough" keys.
316 if (++keys_processed >= QMK_KEYS_PER_SCAN)
317#endif
b624f32f 318 // process a key per task call
319 goto MATRIX_LOOP_END;
25285a1c 320 }
a074364c 321 }
322 }
323 }
324 }
8e88d55b 325 // call with pseudo tick event when no real key event.
39d3d923
S
326#ifdef QMK_KEYS_PER_SCAN
327 // we can get here with some keys processed now.
328 if (!keys_processed)
329#endif
b624f32f 330 action_exec(TICK);
8e88d55b
JH
331
332MATRIX_LOOP_END:
333
cc5edb9e
JC
334#ifdef DEBUG_MATRIX_SCAN_RATE
335 matrix_scan_perf_task();
336#endif
337
ba628a28
JC
338#if defined(RGBLIGHT_ANIMATIONS) && defined(RGBLIGHT_ENABLE)
339 rgblight_task();
340#endif
341
342#if defined(BACKLIGHT_ENABLE)
343# if defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS)
344 backlight_task();
345# endif
346#endif
347
4099536c 348#ifdef QWIIC_ENABLE
349 qwiic_task();
350#endif
351
e01b2d51
X
352#ifdef OLED_DRIVER_ENABLE
353 oled_task();
b624f32f 354# ifndef OLED_DISABLE_TIMEOUT
e01b2d51 355 // Wake up oled if user is using those fabulous keys!
b624f32f 356 if (ret) oled_on();
357# endif
e01b2d51
X
358#endif
359
a074364c 360#ifdef MOUSEKEY_ENABLE
8e88d55b 361 // mousekey repeat & acceleration
a074364c 362 mousekey_task();
363#endif
8e88d55b 364
a074364c 365#ifdef PS2_MOUSE_ENABLE
366 ps2_mouse_task();
367#endif
8e88d55b 368
a074364c 369#ifdef SERIAL_MOUSE_ENABLE
4b45deb6 370 serial_mouse_task();
a074364c 371#endif
8e88d55b 372
4d116a04 373#ifdef ADB_MOUSE_ENABLE
4b45deb6
FS
374 adb_mouse_task();
375#endif
376
377#ifdef SERIAL_LINK_ENABLE
b624f32f 378 serial_link_update();
4d116a04 379#endif
8e88d55b 380
07d0d5cb 381#ifdef VISUALIZER_ENABLE
9eb8d052 382 visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds());
07d0d5cb
FS
383#endif
384
ee132284
S
385#ifdef POINTING_DEVICE_ENABLE
386 pointing_device_task();
387#endif
388
53ff8a31 389#ifdef MIDI_ENABLE
390 midi_task();
391#endif
392
c1c5922a 393#ifdef VELOCIKEY_ENABLE
b624f32f 394 if (velocikey_enabled()) {
395 velocikey_decelerate();
396 }
c1c5922a
CL
397#endif
398
8e88d55b 399 // update LED
a074364c 400 if (led_status != host_keyboard_leds()) {
401 led_status = host_keyboard_leds();
402 keyboard_set_leds(led_status);
403 }
404}
405
7c9d5ace 406/** \brief keyboard set leds
407 *
408 * FIXME: needs doc
409 */
b624f32f 410void keyboard_set_leds(uint8_t leds) {
411 if (debug_keyboard) {
412 debug("keyboard_set_led: ");
413 debug_hex8(leds);
414 debug("\n");
415 }
a074364c 416 led_set(leds);
417}