]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/keyboard.c
Fix wake from suspend LED functionality
[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 VELOCIKEY_ENABLE
79   #include "velocikey.h"
80 #endif
81
82 #ifdef MATRIX_HAS_GHOST
83 extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
84 static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata){
85     matrix_row_t out = 0;
86     for (uint8_t col = 0; col < MATRIX_COLS; col++) {
87         //read each key in the row data and check if the keymap defines it as a real key
88         if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1<<col))){
89             //this creates new row data, if a key is defined in the keymap, it will be set here
90             out |= 1<<col;
91         }
92     }
93     return out;
94 }
95
96 static inline bool popcount_more_than_one(matrix_row_t rowdata)
97 {
98     rowdata &= rowdata-1; //if there are less than two bits (keys) set, rowdata will become zero
99     return rowdata;
100 }
101
102 static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata)
103 {
104     /* No ghost exists when less than 2 keys are down on the row.
105     If there are "active" blanks in the matrix, the key can't be pressed by the user,
106     there is no doubt as to which keys are really being pressed.
107     The ghosts will be ignored, they are KC_NO.   */
108     rowdata = get_real_keys(row, rowdata);
109     if ((popcount_more_than_one(rowdata)) == 0){
110         return false;
111     }
112     /* Ghost occurs when the row shares a column line with other row,
113     and two columns are read on each row. Blanks in the matrix don't matter,
114     so they are filtered out.
115     If there are two or more real keys pressed and they match columns with
116     at least two of another row's real keys, the row will be ignored. Keep in mind,
117     we are checking one row at a time, not all of them at once.
118     */
119     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
120         if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)){
121             return true;
122         }
123     }
124     return false;
125 }
126
127 #endif
128
129 void disable_jtag(void) {
130 // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
131 #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
132     MCUCR |= _BV(JTD);
133     MCUCR |= _BV(JTD);
134 #endif
135 }
136
137 /** \brief matrix_setup
138  *
139  * FIXME: needs doc
140  */
141 __attribute__ ((weak))
142 void matrix_setup(void) {
143 }
144
145 /** \brief keyboard_pre_init_user
146  *
147  * FIXME: needs doc
148  */
149 __attribute__ ((weak))
150 void keyboard_pre_init_user(void) { }
151
152 /** \brief keyboard_pre_init_kb
153  *
154  * FIXME: needs doc
155  */
156 __attribute__ ((weak))
157 void keyboard_pre_init_kb(void) {
158   keyboard_pre_init_user();
159 }
160
161 /** \brief keyboard_post_init_user
162  *
163  * FIXME: needs doc
164  */
165
166 __attribute__ ((weak))
167 void keyboard_post_init_user() {}
168
169 /** \brief keyboard_post_init_kb
170  *
171  * FIXME: needs doc
172  */
173
174 __attribute__ ((weak))
175 void keyboard_post_init_kb(void) {
176   keyboard_post_init_user();
177 }
178
179 /** \brief keyboard_setup
180  *
181  * FIXME: needs doc
182  */
183 void keyboard_setup(void) {
184     disable_jtag();
185     matrix_setup();
186     keyboard_pre_init_kb();
187 }
188
189 /** \brief is_keyboard_master
190  *
191  * FIXME: needs doc
192  */
193 __attribute__((weak))
194 bool is_keyboard_master(void) {
195     return true;
196 }
197
198 /** \brief keyboard_init
199  *
200  * FIXME: needs doc
201  */
202 void keyboard_init(void) {
203     timer_init();
204     matrix_init();
205 #ifdef QWIIC_ENABLE
206     qwiic_init();
207 #endif
208 #ifdef PS2_MOUSE_ENABLE
209     ps2_mouse_init();
210 #endif
211 #ifdef SERIAL_MOUSE_ENABLE
212     serial_mouse_init();
213 #endif
214 #ifdef ADB_MOUSE_ENABLE
215     adb_mouse_init();
216 #endif
217 #ifdef BOOTMAGIC_ENABLE
218     bootmagic();
219 #else
220     magic();
221 #endif
222 #ifdef BACKLIGHT_ENABLE
223     backlight_init();
224 #endif
225 #ifdef RGBLIGHT_ENABLE
226     rgblight_init();
227 #endif
228 #ifdef STENO_ENABLE
229     steno_init();
230 #endif
231 #ifdef FAUXCLICKY_ENABLE
232     fauxclicky_init();
233 #endif
234 #ifdef POINTING_DEVICE_ENABLE
235     pointing_device_init();
236 #endif
237 #if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
238     keymap_config.nkro = 1;
239 #endif
240     keyboard_post_init_kb(); /* Always keep this last */
241 }
242
243 /** \brief Keyboard task: Do keyboard routine jobs
244  *
245  * Do routine keyboard jobs:
246  *
247  * * scan matrix
248  * * handle mouse movements
249  * * run visualizer code
250  * * handle midi commands
251  * * light LEDs
252  *
253  * This is repeatedly called as fast as possible.
254  */
255 void keyboard_task(void)
256 {
257     static matrix_row_t matrix_prev[MATRIX_ROWS];
258     static uint8_t led_status = 0;
259     matrix_row_t matrix_row = 0;
260     matrix_row_t matrix_change = 0;
261 #ifdef QMK_KEYS_PER_SCAN
262     uint8_t keys_processed = 0;
263 #endif
264
265     matrix_scan();
266
267     if (is_keyboard_master()) {
268         for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
269             matrix_row = matrix_get_row(r);
270             matrix_change = matrix_row ^ matrix_prev[r];
271             if (matrix_change) {
272 #ifdef MATRIX_HAS_GHOST
273                 if (has_ghost_in_row(r, matrix_row)) { continue; }
274 #endif
275                 if (debug_matrix) matrix_print();
276                 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
277                     if (matrix_change & ((matrix_row_t)1<<c)) {
278                         action_exec((keyevent_t){
279                             .key = (keypos_t){ .row = r, .col = c },
280                             .pressed = (matrix_row & ((matrix_row_t)1<<c)),
281                             .time = (timer_read() | 1) /* time should not be 0 */
282                         });
283                         // record a processed key
284                         matrix_prev[r] ^= ((matrix_row_t)1<<c);
285 #ifdef QMK_KEYS_PER_SCAN
286                         // only jump out if we have processed "enough" keys.
287                         if (++keys_processed >= QMK_KEYS_PER_SCAN)
288 #endif
289                         // process a key per task call
290                         goto MATRIX_LOOP_END;
291                     }
292                 }
293             }
294         }
295     }
296     // call with pseudo tick event when no real key event.
297 #ifdef QMK_KEYS_PER_SCAN
298     // we can get here with some keys processed now.
299     if (!keys_processed)
300 #endif
301     action_exec(TICK);
302
303 MATRIX_LOOP_END:
304
305 #ifdef QWIIC_ENABLE
306     qwiic_task();
307 #endif
308
309 #ifdef MOUSEKEY_ENABLE
310     // mousekey repeat & acceleration
311     mousekey_task();
312 #endif
313
314 #ifdef PS2_MOUSE_ENABLE
315     ps2_mouse_task();
316 #endif
317
318 #ifdef SERIAL_MOUSE_ENABLE
319     serial_mouse_task();
320 #endif
321
322 #ifdef ADB_MOUSE_ENABLE
323     adb_mouse_task();
324 #endif
325
326 #ifdef SERIAL_LINK_ENABLE
327         serial_link_update();
328 #endif
329
330 #ifdef VISUALIZER_ENABLE
331     visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds());
332 #endif
333
334 #ifdef POINTING_DEVICE_ENABLE
335     pointing_device_task();
336 #endif
337
338 #ifdef MIDI_ENABLE
339     midi_task();
340 #endif
341
342 #ifdef VELOCIKEY_ENABLE
343     if (velocikey_enabled()) { velocikey_decelerate();  }
344 #endif
345
346     // update LED
347     if (led_status != host_keyboard_leds()) {
348         led_status = host_keyboard_leds();
349         keyboard_set_leds(led_status);
350     }
351 }
352
353 /** \brief keyboard set leds
354  *
355  * FIXME: needs doc
356  */
357 void keyboard_set_leds(uint8_t leds)
358 {
359     if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
360     led_set(leds);
361 }