]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/keyboard.c
Remove more commented out MCUs
[qmk_firmware.git] / tmk_core / common / keyboard.c
1 /*
2 Copyright 2011, 2012, 2013 Jun Wako <wakojun@gmail.com>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along 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 "print.h"
27 #include "debug.h"
28 #include "command.h"
29 #include "util.h"
30 #include "sendchar.h"
31 #include "eeconfig.h"
32 #include "backlight.h"
33 #include "action_layer.h"
34 #ifdef BOOTMAGIC_ENABLE
35 #   include "bootmagic.h"
36 #else
37 #   include "magic.h"
38 #endif
39 #ifdef MOUSEKEY_ENABLE
40 #   include "mousekey.h"
41 #endif
42 #ifdef PS2_MOUSE_ENABLE
43 #   include "ps2_mouse.h"
44 #endif
45 #ifdef SERIAL_MOUSE_ENABLE
46 #   include "serial_mouse.h"
47 #endif
48 #ifdef ADB_MOUSE_ENABLE
49 #   include "adb.h"
50 #endif
51 #ifdef RGBLIGHT_ENABLE
52 #   include "rgblight.h"
53 #endif
54 #ifdef STENO_ENABLE
55 #   include "process_steno.h"
56 #endif
57 #ifdef FAUXCLICKY_ENABLE
58 #   include "fauxclicky.h"
59 #endif
60 #ifdef SERIAL_LINK_ENABLE
61 #   include "serial_link/system/serial_link.h"
62 #endif
63 #ifdef VISUALIZER_ENABLE
64 #   include "visualizer/visualizer.h"
65 #endif
66 #ifdef POINTING_DEVICE_ENABLE
67 #   include "pointing_device.h"
68 #endif
69 #ifdef MIDI_ENABLE
70 #   include "process_midi.h"
71 #endif
72 #ifdef HD44780_ENABLE
73 #   include "hd44780.h"
74 #endif
75 #ifdef QWIIC_ENABLE
76 #   include "qwiic.h"
77 #endif
78 #ifdef OLED_DRIVER_ENABLE
79     #include "oled_driver.h"
80 #endif
81 #ifdef VELOCIKEY_ENABLE
82   #include "velocikey.h"
83 #endif
84
85 #ifdef MATRIX_HAS_GHOST
86 extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
87 static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata){
88     matrix_row_t out = 0;
89     for (uint8_t col = 0; col < MATRIX_COLS; col++) {
90         //read each key in the row data and check if the keymap defines it as a real key
91         if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1<<col))){
92             //this creates new row data, if a key is defined in the keymap, it will be set here
93             out |= 1<<col;
94         }
95     }
96     return out;
97 }
98
99 static inline bool popcount_more_than_one(matrix_row_t rowdata)
100 {
101     rowdata &= rowdata-1; //if there are less than two bits (keys) set, rowdata will become zero
102     return rowdata;
103 }
104
105 static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata)
106 {
107     /* No ghost exists when less than 2 keys are down on the row.
108     If there are "active" blanks in the matrix, the key can't be pressed by the user,
109     there is no doubt as to which keys are really being pressed.
110     The ghosts will be ignored, they are KC_NO.   */
111     rowdata = get_real_keys(row, rowdata);
112     if ((popcount_more_than_one(rowdata)) == 0){
113         return false;
114     }
115     /* Ghost occurs when the row shares a column line with other row,
116     and two columns are read on each row. Blanks in the matrix don't matter,
117     so they are filtered out.
118     If there are two or more real keys pressed and they match columns with
119     at least two of another row's real keys, the row will be ignored. Keep in mind,
120     we are checking one row at a time, not all of them at once.
121     */
122     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
123         if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)){
124             return true;
125         }
126     }
127     return false;
128 }
129
130 #endif
131
132 void disable_jtag(void) {
133 // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
134 #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
135     MCUCR |= _BV(JTD);
136     MCUCR |= _BV(JTD);
137 #endif
138 }
139
140 /** \brief matrix_setup
141  *
142  * FIXME: needs doc
143  */
144 __attribute__ ((weak))
145 void matrix_setup(void) {
146 }
147
148 /** \brief keyboard_pre_init_user
149  *
150  * FIXME: needs doc
151  */
152 __attribute__ ((weak))
153 void keyboard_pre_init_user(void) { }
154
155 /** \brief keyboard_pre_init_kb
156  *
157  * FIXME: needs doc
158  */
159 __attribute__ ((weak))
160 void keyboard_pre_init_kb(void) {
161   keyboard_pre_init_user();
162 }
163
164 /** \brief keyboard_post_init_user
165  *
166  * FIXME: needs doc
167  */
168
169 __attribute__ ((weak))
170 void keyboard_post_init_user() {}
171
172 /** \brief keyboard_post_init_kb
173  *
174  * FIXME: needs doc
175  */
176
177 __attribute__ ((weak))
178 void keyboard_post_init_kb(void) {
179   keyboard_post_init_user();
180 }
181
182 /** \brief keyboard_setup
183  *
184  * FIXME: needs doc
185  */
186 void keyboard_setup(void) {
187     disable_jtag();
188     matrix_setup();
189     keyboard_pre_init_kb();
190 }
191
192 /** \brief is_keyboard_master
193  *
194  * FIXME: needs doc
195  */
196 __attribute__((weak))
197 bool is_keyboard_master(void) {
198     return true;
199 }
200
201 /** \brief keyboard_init
202  *
203  * FIXME: needs doc
204  */
205 void keyboard_init(void) {
206     timer_init();
207     matrix_init();
208 #ifdef QWIIC_ENABLE
209     qwiic_init();
210 #endif
211 #ifdef OLED_DRIVER_ENABLE
212     oled_init(OLED_ROTATION_0);
213 #endif
214 #ifdef PS2_MOUSE_ENABLE
215     ps2_mouse_init();
216 #endif
217 #ifdef SERIAL_MOUSE_ENABLE
218     serial_mouse_init();
219 #endif
220 #ifdef ADB_MOUSE_ENABLE
221     adb_mouse_init();
222 #endif
223 #ifdef BOOTMAGIC_ENABLE
224     bootmagic();
225 #else
226     magic();
227 #endif
228 #ifdef BACKLIGHT_ENABLE
229     backlight_init();
230 #endif
231 #ifdef RGBLIGHT_ENABLE
232     rgblight_init();
233 #endif
234 #ifdef STENO_ENABLE
235     steno_init();
236 #endif
237 #ifdef FAUXCLICKY_ENABLE
238     fauxclicky_init();
239 #endif
240 #ifdef POINTING_DEVICE_ENABLE
241     pointing_device_init();
242 #endif
243 #if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
244     keymap_config.nkro = 1;
245 #endif
246     keyboard_post_init_kb(); /* Always keep this last */
247 }
248
249 /** \brief Keyboard task: Do keyboard routine jobs
250  *
251  * Do routine keyboard jobs:
252  *
253  * * scan matrix
254  * * handle mouse movements
255  * * run visualizer code
256  * * handle midi commands
257  * * light LEDs
258  *
259  * This is repeatedly called as fast as possible.
260  */
261 void keyboard_task(void)
262 {
263     static matrix_row_t matrix_prev[MATRIX_ROWS];
264     static uint8_t led_status = 0;
265     matrix_row_t matrix_row = 0;
266     matrix_row_t matrix_change = 0;
267 #ifdef QMK_KEYS_PER_SCAN
268     uint8_t keys_processed = 0;
269 #endif
270
271 #if defined(OLED_DRIVER_ENABLE) && !defined(OLED_DISABLE_TIMEOUT)
272     uint8_t ret = matrix_scan();
273 #else
274     matrix_scan();
275 #endif
276
277     if (is_keyboard_master()) {
278         for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
279             matrix_row = matrix_get_row(r);
280             matrix_change = matrix_row ^ matrix_prev[r];
281             if (matrix_change) {
282 #ifdef MATRIX_HAS_GHOST
283                 if (has_ghost_in_row(r, matrix_row)) { continue; }
284 #endif
285                 if (debug_matrix) matrix_print();
286                 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
287                     if (matrix_change & ((matrix_row_t)1<<c)) {
288                         action_exec((keyevent_t){
289                             .key = (keypos_t){ .row = r, .col = c },
290                             .pressed = (matrix_row & ((matrix_row_t)1<<c)),
291                             .time = (timer_read() | 1) /* time should not be 0 */
292                         });
293                         // record a processed key
294                         matrix_prev[r] ^= ((matrix_row_t)1<<c);
295 #ifdef QMK_KEYS_PER_SCAN
296                         // only jump out if we have processed "enough" keys.
297                         if (++keys_processed >= QMK_KEYS_PER_SCAN)
298 #endif
299                         // process a key per task call
300                         goto MATRIX_LOOP_END;
301                     }
302                 }
303             }
304         }
305     }
306     // call with pseudo tick event when no real key event.
307 #ifdef QMK_KEYS_PER_SCAN
308     // we can get here with some keys processed now.
309     if (!keys_processed)
310 #endif
311     action_exec(TICK);
312
313 MATRIX_LOOP_END:
314
315 #ifdef QWIIC_ENABLE
316     qwiic_task();
317 #endif
318
319 #ifdef OLED_DRIVER_ENABLE
320     oled_task();
321 #ifndef OLED_DISABLE_TIMEOUT
322     // Wake up oled if user is using those fabulous keys!
323     if (ret)
324         oled_on();
325 #endif
326 #endif
327
328 #ifdef MOUSEKEY_ENABLE
329     // mousekey repeat & acceleration
330     mousekey_task();
331 #endif
332
333 #ifdef PS2_MOUSE_ENABLE
334     ps2_mouse_task();
335 #endif
336
337 #ifdef SERIAL_MOUSE_ENABLE
338     serial_mouse_task();
339 #endif
340
341 #ifdef ADB_MOUSE_ENABLE
342     adb_mouse_task();
343 #endif
344
345 #ifdef SERIAL_LINK_ENABLE
346         serial_link_update();
347 #endif
348
349 #ifdef VISUALIZER_ENABLE
350     visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds());
351 #endif
352
353 #ifdef POINTING_DEVICE_ENABLE
354     pointing_device_task();
355 #endif
356
357 #ifdef MIDI_ENABLE
358     midi_task();
359 #endif
360
361 #ifdef VELOCIKEY_ENABLE
362     if (velocikey_enabled()) { velocikey_decelerate();  }
363 #endif
364
365     // update LED
366     if (led_status != host_keyboard_leds()) {
367         led_status = host_keyboard_leds();
368         keyboard_set_leds(led_status);
369     }
370 }
371
372 /** \brief keyboard set leds
373  *
374  * FIXME: needs doc
375  */
376 void keyboard_set_leds(uint8_t leds)
377 {
378     if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
379     led_set(leds);
380 }