aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/common
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/common')
-rw-r--r--tmk_core/common/action.c565
-rw-r--r--tmk_core/common/action.h82
-rw-r--r--tmk_core/common/action_code.h315
-rw-r--r--tmk_core/common/action_layer.c138
-rw-r--r--tmk_core/common/action_layer.h77
-rw-r--r--tmk_core/common/action_macro.c83
-rw-r--r--tmk_core/common/action_macro.h102
-rw-r--r--tmk_core/common/action_tapping.c376
-rw-r--r--tmk_core/common/action_tapping.h39
-rw-r--r--tmk_core/common/action_util.c307
-rw-r--r--tmk_core/common/action_util.h66
-rw-r--r--tmk_core/common/avr/bootloader.c148
-rw-r--r--tmk_core/common/avr/eeconfig.c45
-rw-r--r--tmk_core/common/avr/suspend.c122
-rw-r--r--tmk_core/common/avr/suspend_avr.h27
-rw-r--r--tmk_core/common/avr/timer.c117
-rw-r--r--tmk_core/common/avr/timer_avr.h42
-rw-r--r--tmk_core/common/avr/xprintf.S500
-rw-r--r--tmk_core/common/avr/xprintf.h111
-rw-r--r--tmk_core/common/backlight.c85
-rw-r--r--tmk_core/common/backlight.h40
-rw-r--r--tmk_core/common/bootloader.h25
-rw-r--r--tmk_core/common/bootmagic.c128
-rw-r--r--tmk_core/common/bootmagic.h100
-rw-r--r--tmk_core/common/command.c644
-rw-r--r--tmk_core/common/command.h35
-rw-r--r--tmk_core/common/debug.c24
-rw-r--r--tmk_core/common/debug.h117
-rw-r--r--tmk_core/common/eeconfig.h75
-rw-r--r--tmk_core/common/host.c97
-rw-r--r--tmk_core/common/host.h57
-rw-r--r--tmk_core/common/host_driver.h33
-rw-r--r--tmk_core/common/keyboard.c150
-rw-r--r--tmk_core/common/keyboard.h72
-rw-r--r--tmk_core/common/keycode.h489
-rw-r--r--tmk_core/common/keymap.c185
-rw-r--r--tmk_core/common/keymap.h71
-rw-r--r--tmk_core/common/led.h33
-rw-r--r--tmk_core/common/matrix.h68
-rw-r--r--tmk_core/common/mbed/bootloader.c4
-rw-r--r--tmk_core/common/mbed/suspend.c6
-rw-r--r--tmk_core/common/mbed/timer.c41
-rw-r--r--tmk_core/common/mbed/xprintf.cpp51
-rw-r--r--tmk_core/common/mbed/xprintf.h17
-rw-r--r--tmk_core/common/mousekey.c196
-rw-r--r--tmk_core/common/mousekey.h77
-rw-r--r--tmk_core/common/nodebug.h25
-rw-r--r--tmk_core/common/print.c48
-rw-r--r--tmk_core/common/print.h137
-rw-r--r--tmk_core/common/progmem.h12
-rw-r--r--tmk_core/common/report.h183
-rw-r--r--tmk_core/common/sendchar.h35
-rw-r--r--tmk_core/common/sendchar_null.c23
-rw-r--r--tmk_core/common/sendchar_uart.c25
-rw-r--r--tmk_core/common/sleep_led.c95
-rw-r--r--tmk_core/common/sleep_led.h21
-rw-r--r--tmk_core/common/suspend.h13
-rw-r--r--tmk_core/common/timer.h53
-rw-r--r--tmk_core/common/uart.c129
-rw-r--r--tmk_core/common/uart.h11
-rw-r--r--tmk_core/common/util.c101
-rw-r--r--tmk_core/common/util.h43
-rw-r--r--tmk_core/common/wait.h20
63 files changed, 7156 insertions, 0 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
new file mode 100644
index 000000000..ec8eeae7b
--- /dev/null
+++ b/tmk_core/common/action.c
@@ -0,0 +1,565 @@
1/*
2Copyright 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#include "host.h"
18#include "keycode.h"
19#include "keyboard.h"
20#include "mousekey.h"
21#include "command.h"
22#include "led.h"
23#include "backlight.h"
24#include "action_layer.h"
25#include "action_tapping.h"
26#include "action_macro.h"
27#include "action_util.h"
28#include "action.h"
29
30#ifdef DEBUG_ACTION
31#include "debug.h"
32#else
33#include "nodebug.h"
34#endif
35
36
37void action_exec(keyevent_t event)
38{
39 if (!IS_NOEVENT(event)) {
40 dprint("\n---- action_exec: start -----\n");
41 dprint("EVENT: "); debug_event(event); dprintln();
42 }
43
44 keyrecord_t record = { .event = event };
45
46#ifndef NO_ACTION_TAPPING
47 action_tapping_process(record);
48#else
49 process_action(&record);
50 if (!IS_NOEVENT(record.event)) {
51 dprint("processed: "); debug_record(record); dprintln();
52 }
53#endif
54}
55
56void process_action(keyrecord_t *record)
57{
58 keyevent_t event = record->event;
59#ifndef NO_ACTION_TAPPING
60 uint8_t tap_count = record->tap.count;
61#endif
62
63 if (IS_NOEVENT(event)) { return; }
64
65 action_t action = layer_switch_get_action(event.key);
66 dprint("ACTION: "); debug_action(action);
67#ifndef NO_ACTION_LAYER
68 dprint(" layer_state: "); layer_debug();
69 dprint(" default_layer_state: "); default_layer_debug();
70#endif
71 dprintln();
72
73 switch (action.kind.id) {
74 /* Key and Mods */
75 case ACT_LMODS:
76 case ACT_RMODS:
77 {
78 uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
79 action.key.mods<<4;
80 if (event.pressed) {
81 if (mods) {
82 add_weak_mods(mods);
83 send_keyboard_report();
84 }
85 register_code(action.key.code);
86 } else {
87 unregister_code(action.key.code);
88 if (mods) {
89 del_weak_mods(mods);
90 send_keyboard_report();
91 }
92 }
93 }
94 break;
95#ifndef NO_ACTION_TAPPING
96 case ACT_LMODS_TAP:
97 case ACT_RMODS_TAP:
98 {
99 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
100 action.key.mods<<4;
101 switch (action.layer_tap.code) {
102 #ifndef NO_ACTION_ONESHOT
103 case MODS_ONESHOT:
104 // Oneshot modifier
105 if (event.pressed) {
106 if (tap_count == 0) {
107 register_mods(mods);
108 }
109 else if (tap_count == 1) {
110 dprint("MODS_TAP: Oneshot: start\n");
111 set_oneshot_mods(mods);
112 }
113 else {
114 register_mods(mods);
115 }
116 } else {
117 if (tap_count == 0) {
118 clear_oneshot_mods();
119 unregister_mods(mods);
120 }
121 else if (tap_count == 1) {
122 // Retain Oneshot mods
123 }
124 else {
125 clear_oneshot_mods();
126 unregister_mods(mods);
127 }
128 }
129 break;
130 #endif
131 case MODS_TAP_TOGGLE:
132 if (event.pressed) {
133 if (tap_count <= TAPPING_TOGGLE) {
134 register_mods(mods);
135 }
136 } else {
137 if (tap_count < TAPPING_TOGGLE) {
138 unregister_mods(mods);
139 }
140 }
141 break;
142 default:
143 if (event.pressed) {
144 if (tap_count > 0) {
145 if (record->tap.interrupted) {
146 dprint("MODS_TAP: Tap: Cancel: add_mods\n");
147 // ad hoc: set 0 to cancel tap
148 record->tap.count = 0;
149 register_mods(mods);
150 } else {
151 dprint("MODS_TAP: Tap: register_code\n");
152 register_code(action.key.code);
153 }
154 } else {
155 dprint("MODS_TAP: No tap: add_mods\n");
156 register_mods(mods);
157 }
158 } else {
159 if (tap_count > 0) {
160 dprint("MODS_TAP: Tap: unregister_code\n");
161 unregister_code(action.key.code);
162 } else {
163 dprint("MODS_TAP: No tap: add_mods\n");
164 unregister_mods(mods);
165 }
166 }
167 break;
168 }
169 }
170 break;
171#endif
172#ifdef EXTRAKEY_ENABLE
173 /* other HID usage */
174 case ACT_USAGE:
175 switch (action.usage.page) {
176 case PAGE_SYSTEM:
177 if (event.pressed) {
178 host_system_send(action.usage.code);
179 } else {
180 host_system_send(0);
181 }
182 break;
183 case PAGE_CONSUMER:
184 if (event.pressed) {
185 host_consumer_send(action.usage.code);
186 } else {
187 host_consumer_send(0);
188 }
189 break;
190 }
191 break;
192#endif
193#ifdef MOUSEKEY_ENABLE
194 /* Mouse key */
195 case ACT_MOUSEKEY:
196 if (event.pressed) {
197 mousekey_on(action.key.code);
198 mousekey_send();
199 } else {
200 mousekey_off(action.key.code);
201 mousekey_send();
202 }
203 break;
204#endif
205#ifndef NO_ACTION_LAYER
206 case ACT_LAYER:
207 if (action.layer_bitop.on == 0) {
208 /* Default Layer Bitwise Operation */
209 if (!event.pressed) {
210 uint8_t shift = action.layer_bitop.part*4;
211 uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
212 uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
213 switch (action.layer_bitop.op) {
214 case OP_BIT_AND: default_layer_and(bits | mask); break;
215 case OP_BIT_OR: default_layer_or(bits | mask); break;
216 case OP_BIT_XOR: default_layer_xor(bits | mask); break;
217 case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
218 }
219 }
220 } else {
221 /* Layer Bitwise Operation */
222 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
223 (action.layer_bitop.on & ON_RELEASE)) {
224 uint8_t shift = action.layer_bitop.part*4;
225 uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
226 uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
227 switch (action.layer_bitop.op) {
228 case OP_BIT_AND: layer_and(bits | mask); break;
229 case OP_BIT_OR: layer_or(bits | mask); break;
230 case OP_BIT_XOR: layer_xor(bits | mask); break;
231 case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
232 }
233 }
234 }
235 break;
236 #ifndef NO_ACTION_TAPPING
237 case ACT_LAYER_TAP:
238 case ACT_LAYER_TAP_EXT:
239 switch (action.layer_tap.code) {
240 case 0xe0 ... 0xef:
241 /* layer On/Off with modifiers(left only) */
242 if (event.pressed) {
243 layer_on(action.layer_tap.val);
244 register_mods(action.layer_tap.code & 0x0f);
245 } else {
246 layer_off(action.layer_tap.val);
247 unregister_mods(action.layer_tap.code & 0x0f);
248 }
249 break;
250 case OP_TAP_TOGGLE:
251 /* tap toggle */
252 if (event.pressed) {
253 if (tap_count < TAPPING_TOGGLE) {
254 layer_invert(action.layer_tap.val);
255 }
256 } else {
257 if (tap_count <= TAPPING_TOGGLE) {
258 layer_invert(action.layer_tap.val);
259 }
260 }
261 break;
262 case OP_ON_OFF:
263 event.pressed ? layer_on(action.layer_tap.val) :
264 layer_off(action.layer_tap.val);
265 break;
266 case OP_OFF_ON:
267 event.pressed ? layer_off(action.layer_tap.val) :
268 layer_on(action.layer_tap.val);
269 break;
270 case OP_SET_CLEAR:
271 event.pressed ? layer_move(action.layer_tap.val) :
272 layer_clear();
273 break;
274 default:
275 /* tap key */
276 if (event.pressed) {
277 if (tap_count > 0) {
278 dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
279 register_code(action.layer_tap.code);
280 } else {
281 dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
282 layer_on(action.layer_tap.val);
283 }
284 } else {
285 if (tap_count > 0) {
286 dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
287 unregister_code(action.layer_tap.code);
288 } else {
289 dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
290 layer_off(action.layer_tap.val);
291 }
292 }
293 break;
294 }
295 break;
296 #endif
297#endif
298 /* Extentions */
299#ifndef NO_ACTION_MACRO
300 case ACT_MACRO:
301 action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
302 break;
303#endif
304#ifdef BACKLIGHT_ENABLE
305 case ACT_BACKLIGHT:
306 if (!event.pressed) {
307 switch (action.backlight.opt) {
308 case BACKLIGHT_INCREASE:
309 backlight_increase();
310 break;
311 case BACKLIGHT_DECREASE:
312 backlight_decrease();
313 break;
314 case BACKLIGHT_TOGGLE:
315 backlight_toggle();
316 break;
317 case BACKLIGHT_STEP:
318 backlight_step();
319 break;
320 case BACKLIGHT_LEVEL:
321 backlight_level(action.backlight.level);
322 break;
323 }
324 }
325 break;
326#endif
327 case ACT_COMMAND:
328 break;
329#ifndef NO_ACTION_FUNCTION
330 case ACT_FUNCTION:
331 action_function(record, action.func.id, action.func.opt);
332 break;
333#endif
334 default:
335 break;
336 }
337}
338
339
340
341
342/*
343 * Utilities for actions.
344 */
345void register_code(uint8_t code)
346{
347 if (code == KC_NO) {
348 return;
349 }
350
351#ifdef LOCKING_SUPPORT_ENABLE
352 else if (KC_LOCKING_CAPS == code) {
353#ifdef LOCKING_RESYNC_ENABLE
354 // Resync: ignore if caps lock already is on
355 if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
356#endif
357 add_key(KC_CAPSLOCK);
358 send_keyboard_report();
359 del_key(KC_CAPSLOCK);
360 send_keyboard_report();
361 }
362
363 else if (KC_LOCKING_NUM == code) {
364#ifdef LOCKING_RESYNC_ENABLE
365 if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
366#endif
367 add_key(KC_NUMLOCK);
368 send_keyboard_report();
369 del_key(KC_NUMLOCK);
370 send_keyboard_report();
371 }
372
373 else if (KC_LOCKING_SCROLL == code) {
374#ifdef LOCKING_RESYNC_ENABLE
375 if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
376#endif
377 add_key(KC_SCROLLLOCK);
378 send_keyboard_report();
379 del_key(KC_SCROLLLOCK);
380 send_keyboard_report();
381 }
382#endif
383
384 else if IS_KEY(code) {
385 // TODO: should push command_proc out of this block?
386 if (command_proc(code)) return;
387
388#ifndef NO_ACTION_ONESHOT
389/* TODO: remove
390 if (oneshot_state.mods && !oneshot_state.disabled) {
391 uint8_t tmp_mods = get_mods();
392 add_mods(oneshot_state.mods);
393
394 add_key(code);
395 send_keyboard_report();
396
397 set_mods(tmp_mods);
398 send_keyboard_report();
399 oneshot_cancel();
400 } else
401*/
402#endif
403 {
404 add_key(code);
405 send_keyboard_report();
406 }
407 }
408 else if IS_MOD(code) {
409 add_mods(MOD_BIT(code));
410 send_keyboard_report();
411 }
412 else if IS_SYSTEM(code) {
413 host_system_send(KEYCODE2SYSTEM(code));
414 }
415 else if IS_CONSUMER(code) {
416 host_consumer_send(KEYCODE2CONSUMER(code));
417 }
418}
419
420void unregister_code(uint8_t code)
421{
422 if (code == KC_NO) {
423 return;
424 }
425
426#ifdef LOCKING_SUPPORT_ENABLE
427 else if (KC_LOCKING_CAPS == code) {
428#ifdef LOCKING_RESYNC_ENABLE
429 // Resync: ignore if caps lock already is off
430 if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
431#endif
432 add_key(KC_CAPSLOCK);
433 send_keyboard_report();
434 del_key(KC_CAPSLOCK);
435 send_keyboard_report();
436 }
437
438 else if (KC_LOCKING_NUM == code) {
439#ifdef LOCKING_RESYNC_ENABLE
440 if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
441#endif
442 add_key(KC_NUMLOCK);
443 send_keyboard_report();
444 del_key(KC_NUMLOCK);
445 send_keyboard_report();
446 }
447
448 else if (KC_LOCKING_SCROLL == code) {
449#ifdef LOCKING_RESYNC_ENABLE
450 if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
451#endif
452 add_key(KC_SCROLLLOCK);
453 send_keyboard_report();
454 del_key(KC_SCROLLLOCK);
455 send_keyboard_report();
456 }
457#endif
458
459 else if IS_KEY(code) {
460 del_key(code);
461 send_keyboard_report();
462 }
463 else if IS_MOD(code) {
464 del_mods(MOD_BIT(code));
465 send_keyboard_report();
466 }
467 else if IS_SYSTEM(code) {
468 host_system_send(0);
469 }
470 else if IS_CONSUMER(code) {
471 host_consumer_send(0);
472 }
473}
474
475void register_mods(uint8_t mods)
476{
477 if (mods) {
478 add_mods(mods);
479 send_keyboard_report();
480 }
481}
482
483void unregister_mods(uint8_t mods)
484{
485 if (mods) {
486 del_mods(mods);
487 send_keyboard_report();
488 }
489}
490
491void clear_keyboard(void)
492{
493 clear_mods();
494 clear_keyboard_but_mods();
495}
496
497void clear_keyboard_but_mods(void)
498{
499 clear_weak_mods();
500 clear_keys();
501 send_keyboard_report();
502#ifdef MOUSEKEY_ENABLE
503 mousekey_clear();
504 mousekey_send();
505#endif
506#ifdef EXTRAKEY_ENABLE
507 host_system_send(0);
508 host_consumer_send(0);
509#endif
510}
511
512bool is_tap_key(keypos_t key)
513{
514 action_t action = layer_switch_get_action(key);
515
516 switch (action.kind.id) {
517 case ACT_LMODS_TAP:
518 case ACT_RMODS_TAP:
519 case ACT_LAYER_TAP:
520 case ACT_LAYER_TAP_EXT:
521 return true;
522 case ACT_MACRO:
523 case ACT_FUNCTION:
524 if (action.func.opt & FUNC_TAP) { return true; }
525 return false;
526 }
527 return false;
528}
529
530
531/*
532 * debug print
533 */
534void debug_event(keyevent_t event)
535{
536 dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
537}
538
539void debug_record(keyrecord_t record)
540{
541 debug_event(record.event);
542#ifndef NO_ACTION_TAPPING
543 dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
544#endif
545}
546
547void debug_action(action_t action)
548{
549 switch (action.kind.id) {
550 case ACT_LMODS: dprint("ACT_LMODS"); break;
551 case ACT_RMODS: dprint("ACT_RMODS"); break;
552 case ACT_LMODS_TAP: dprint("ACT_LMODS_TAP"); break;
553 case ACT_RMODS_TAP: dprint("ACT_RMODS_TAP"); break;
554 case ACT_USAGE: dprint("ACT_USAGE"); break;
555 case ACT_MOUSEKEY: dprint("ACT_MOUSEKEY"); break;
556 case ACT_LAYER: dprint("ACT_LAYER"); break;
557 case ACT_LAYER_TAP: dprint("ACT_LAYER_TAP"); break;
558 case ACT_LAYER_TAP_EXT: dprint("ACT_LAYER_TAP_EXT"); break;
559 case ACT_MACRO: dprint("ACT_MACRO"); break;
560 case ACT_COMMAND: dprint("ACT_COMMAND"); break;
561 case ACT_FUNCTION: dprint("ACT_FUNCTION"); break;
562 default: dprint("UNKNOWN"); break;
563 }
564 dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
565}
diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h
new file mode 100644
index 000000000..8a4736d7b
--- /dev/null
+++ b/tmk_core/common/action.h
@@ -0,0 +1,82 @@
1/*
2Copyright 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#ifndef ACTION_H
18#define ACTION_H
19
20#include <stdint.h>
21#include <stdbool.h>
22#include "keyboard.h"
23#include "keycode.h"
24#include "action_code.h"
25#include "action_macro.h"
26
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32/* tapping count and state */
33typedef struct {
34 bool interrupted :1;
35 bool reserved2 :1;
36 bool reserved1 :1;
37 bool reserved0 :1;
38 uint8_t count :4;
39} tap_t;
40
41/* Key event container for recording */
42typedef struct {
43 keyevent_t event;
44#ifndef NO_ACTION_TAPPING
45 tap_t tap;
46#endif
47} keyrecord_t;
48
49/* Execute action per keyevent */
50void action_exec(keyevent_t event);
51
52/* action for key */
53action_t action_for_key(uint8_t layer, keypos_t key);
54
55/* macro */
56const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt);
57
58/* user defined special function */
59void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
60
61/* Utilities for actions. */
62void process_action(keyrecord_t *record);
63void register_code(uint8_t code);
64void unregister_code(uint8_t code);
65void register_mods(uint8_t mods);
66void unregister_mods(uint8_t mods);
67//void set_mods(uint8_t mods);
68void clear_keyboard(void);
69void clear_keyboard_but_mods(void);
70void layer_switch(uint8_t new_layer);
71bool is_tap_key(keypos_t key);
72
73/* debug */
74void debug_event(keyevent_t event);
75void debug_record(keyrecord_t record);
76void debug_action(action_t action);
77
78#ifdef __cplusplus
79}
80#endif
81
82#endif /* ACTION_H */
diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h
new file mode 100644
index 000000000..bc40e2c6f
--- /dev/null
+++ b/tmk_core/common/action_code.h
@@ -0,0 +1,315 @@
1/*
2Copyright 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#ifndef ACTION_CODE_H
18#define ACTION_CODE_H
19
20/* Action codes
21 * ============
22 * 16bit code: action_kind(4bit) + action_parameter(12bit)
23 *
24 *
25 * Key Actions(00xx)
26 * -----------------
27 * ACT_MODS(000r):
28 * 000r|0000|0000 0000 No action code
29 * 000r|0000|0000 0001 Transparent code
30 * 000r|0000| keycode Key
31 * 000r|mods|0000 0000 Modifiers
32 * 000r|mods| keycode Modifiers+Key(Modified key)
33 * r: Left/Right flag(Left:0, Right:1)
34 *
35 * ACT_MODS_TAP(001r):
36 * 001r|mods|0000 0000 Modifiers with OneShot
37 * 001r|mods|0000 0001 Modifiers with tap toggle
38 * 001r|mods|0000 00xx (reserved)
39 * 001r|mods| keycode Modifiers with Tap Key(Dual role)
40 *
41 *
42 * Other Keys(01xx)
43 * ----------------
44 * ACT_USAGE(0100): TODO: Not needed?
45 * 0100|00| usage(10) System control(0x80) - General Desktop page(0x01)
46 * 0100|01| usage(10) Consumer control(0x01) - Consumer page(0x0C)
47 * 0100|10| usage(10) (reserved)
48 * 0100|11| usage(10) (reserved)
49 *
50 * ACT_MOUSEKEY(0110): TODO: Not needed?
51 * 0101|xxxx| keycode Mouse key
52 *
53 * 011x|xxxx xxxx xxxx (reseved)
54 *
55 *
56 * Layer Actions(10xx)
57 * -------------------
58 * ACT_LAYER(1000):
59 * 1000|oo00|pppE BBBB Default Layer Bitwise operation
60 * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET)
61 * ppp: 4-bit chunk part(0-7)
62 * EBBBB: bits and extra bit
63 * 1000|ooee|pppE BBBB Layer Bitwise Operation
64 * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET)
65 * ppp: 4-bit chunk part(0-7)
66 * EBBBB: bits and extra bit
67 * ee: on event(01:press, 10:release, 11:both)
68 *
69 * 1001|xxxx|xxxx xxxx (reserved)
70 * 1001|oopp|BBBB BBBB 8-bit Bitwise Operation???
71 *
72 * ACT_LAYER_TAP(101x):
73 * 101E|LLLL| keycode On/Off with tap key
74 * 101E|LLLL|1110 mods On/Off with modifiers(0xE0-EF)
75 * 101E|LLLL|1111 0000 Invert with tap toggle(0xF0)
76 * 101E|LLLL|1111 0001 On/Off
77 * 101E|LLLL|1111 0010 Off/On
78 * 101E|LLLL|1111 0011 Set/Clear
79 * 101E|LLLL|1111 xxxx Reserved(0xF4-FF)
80 * ELLLL: layer 0-31(E: extra bit for layer 16-31)
81 *
82 *
83 * Extensions(11xx)
84 * ----------------
85 * ACT_MACRO(1100):
86 * 1100|opt | id(8) Macro play?
87 * 1100|1111| id(8) Macro record?
88 *
89 * ACT_BACKLIGHT(1101):
90 * 1101|opt |level(8) Backlight commands
91 *
92 * ACT_COMMAND(1110):
93 * 1110|opt | id(8) Built-in Command exec
94 *
95 * ACT_FUNCTION(1111):
96 * 1111| address(12) Function?
97 * 1111|opt | id(8) Function?
98 */
99enum action_kind_id {
100 /* Key Actions */
101 ACT_MODS = 0b0000,
102 ACT_LMODS = 0b0000,
103 ACT_RMODS = 0b0001,
104 ACT_MODS_TAP = 0b0010,
105 ACT_LMODS_TAP = 0b0010,
106 ACT_RMODS_TAP = 0b0011,
107 /* Other Keys */
108 ACT_USAGE = 0b0100,
109 ACT_MOUSEKEY = 0b0101,
110 /* Layer Actions */
111 ACT_LAYER = 0b1000,
112 ACT_LAYER_TAP = 0b1010, /* Layer 0-15 */
113 ACT_LAYER_TAP_EXT = 0b1011, /* Layer 16-31 */
114 /* Extensions */
115 ACT_MACRO = 0b1100,
116 ACT_BACKLIGHT = 0b1101,
117 ACT_COMMAND = 0b1110,
118 ACT_FUNCTION = 0b1111
119};
120
121
122/* Action Code Struct
123 *
124 * NOTE:
125 * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
126 * AVR looks like a little endian in avr-gcc.
127 * Not portable across compiler/endianness?
128 *
129 * Byte order and bit order of 0x1234:
130 * Big endian: Little endian:
131 * -------------------- --------------------
132 * FEDC BA98 7654 3210 0123 4567 89AB CDEF
133 * 0001 0010 0011 0100 0010 1100 0100 1000
134 * 0x12 0x34 0x34 0x12
135 */
136typedef union {
137 uint16_t code;
138 struct action_kind {
139 uint16_t param :12;
140 uint8_t id :4;
141 } kind;
142 struct action_key {
143 uint8_t code :8;
144 uint8_t mods :4;
145 uint8_t kind :4;
146 } key;
147 struct action_layer_bitop {
148 uint8_t bits :4;
149 uint8_t xbit :1;
150 uint8_t part :3;
151 uint8_t on :2;
152 uint8_t op :2;
153 uint8_t kind :4;
154 } layer_bitop;
155 struct action_layer_tap {
156 uint8_t code :8;
157 uint8_t val :5;
158 uint8_t kind :3;
159 } layer_tap;
160 struct action_usage {
161 uint16_t code :10;
162 uint8_t page :2;
163 uint8_t kind :4;
164 } usage;
165 struct action_backlight {
166 uint8_t level :8;
167 uint8_t opt :4;
168 uint8_t kind :4;
169 } backlight;
170 struct action_command {
171 uint8_t id :8;
172 uint8_t opt :4;
173 uint8_t kind :4;
174 } command;
175 struct action_function {
176 uint8_t id :8;
177 uint8_t opt :4;
178 uint8_t kind :4;
179 } func;
180} action_t;
181
182
183/* action utility */
184#define ACTION_NO 0
185#define ACTION_TRANSPARENT 1
186#define ACTION(kind, param) ((kind)<<12 | (param))
187
188
189/*
190 * Key Actions
191 */
192/* Mod bits: 43210
193 * bit 0 ||||+- Control
194 * bit 1 |||+-- Shift
195 * bit 2 ||+--- Alt
196 * bit 3 |+---- Gui
197 * bit 4 +----- LR flag(Left:0, Right:1)
198 */
199enum mods_bit {
200 MOD_LCTL = 0x01,
201 MOD_LSFT = 0x02,
202 MOD_LALT = 0x04,
203 MOD_LGUI = 0x08,
204 MOD_RCTL = 0x11,
205 MOD_RSFT = 0x12,
206 MOD_RALT = 0x14,
207 MOD_RGUI = 0x18,
208};
209enum mods_codes {
210 MODS_ONESHOT = 0x00,
211 MODS_TAP_TOGGLE = 0x01,
212};
213#define ACTION_KEY(key) ACTION(ACT_MODS, (key))
214#define ACTION_MODS(mods) ACTION(ACT_MODS, ((mods)&0x1f)<<8 | 0)
215#define ACTION_MODS_KEY(mods, key) ACTION(ACT_MODS, ((mods)&0x1f)<<8 | (key))
216#define ACTION_MODS_TAP_KEY(mods, key) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | (key))
217#define ACTION_MODS_ONESHOT(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_ONESHOT)
218#define ACTION_MODS_TAP_TOGGLE(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_TAP_TOGGLE)
219
220
221/*
222 * Other Keys
223 */
224enum usage_pages {
225 PAGE_SYSTEM,
226 PAGE_CONSUMER
227};
228#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM<<10 | (id))
229#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER<<10 | (id))
230#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key)
231
232
233
234/*
235 * Layer Actions
236 */
237enum layer_param_on {
238 ON_PRESS = 1,
239 ON_RELEASE = 2,
240 ON_BOTH = 3,
241};
242enum layer_param_bit_op {
243 OP_BIT_AND = 0,
244 OP_BIT_OR = 1,
245 OP_BIT_XOR = 2,
246 OP_BIT_SET = 3,
247};
248enum layer_pram_tap_op {
249 OP_TAP_TOGGLE = 0xF0,
250 OP_ON_OFF,
251 OP_OFF_ON,
252 OP_SET_CLEAR,
253};
254#define ACTION_LAYER_BITOP(op, part, bits, on) (ACT_LAYER<<12 | (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f))
255#define ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
256/* Default Layer */
257#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_BIT_SET((layer)/4, 1<<((layer)%4))
258/* Layer Operation */
259#define ACTION_LAYER_CLEAR(on) ACTION_LAYER_BIT_AND(0, 0, (on))
260#define ACTION_LAYER_MOMENTARY(layer) ACTION_LAYER_ON_OFF(layer)
261#define ACTION_LAYER_TOGGLE(layer) ACTION_LAYER_INVERT(layer, ON_RELEASE)
262#define ACTION_LAYER_INVERT(layer, on) ACTION_LAYER_BIT_XOR((layer)/4, 1<<((layer)%4), (on))
263#define ACTION_LAYER_ON(layer, on) ACTION_LAYER_BIT_OR( (layer)/4, 1<<((layer)%4), (on))
264#define ACTION_LAYER_OFF(layer, on) ACTION_LAYER_BIT_AND((layer)/4, ~(1<<((layer)%4)), (on))
265#define ACTION_LAYER_SET(layer, on) ACTION_LAYER_BIT_SET((layer)/4, 1<<((layer)%4), (on))
266#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF)
267#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON)
268#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR)
269#define ACTION_LAYER_MODS(layer, mods) ACTION_LAYER_TAP((layer), 0xe0 | (mods)&0x0f)
270/* With Tapping */
271#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key))
272#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE)
273/* Bitwise Operation */
274#define ACTION_LAYER_BIT_AND(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on))
275#define ACTION_LAYER_BIT_OR( part, bits, on) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), (on))
276#define ACTION_LAYER_BIT_XOR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on))
277#define ACTION_LAYER_BIT_SET(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on))
278/* Default Layer Bitwise Operation */
279#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0)
280#define ACTION_DEFAULT_LAYER_BIT_OR( part, bits) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), 0)
281#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0)
282#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0)
283
284
285/*
286 * Extensions
287 */
288enum backlight_opt {
289 BACKLIGHT_INCREASE = 0,
290 BACKLIGHT_DECREASE = 1,
291 BACKLIGHT_TOGGLE = 2,
292 BACKLIGHT_STEP = 3,
293 BACKLIGHT_LEVEL = 4,
294};
295/* Macro */
296#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id))
297#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP<<8 | (id))
298#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt)<<8 | (id))
299/* Backlight */
300#define ACTION_BACKLIGHT_INCREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE << 8)
301#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8)
302#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8)
303#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
304#define ACTION_BACKLIGHT_LEVEL(level) ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | level)
305/* Command */
306#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (addr))
307/* Function */
308enum function_opts {
309 FUNC_TAP = 0x8, /* indciates function is tappable */
310};
311#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id))
312#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | (id))
313#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | (id))
314
315#endif /* ACTION_CODE_H */
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c
new file mode 100644
index 000000000..c535615f4
--- /dev/null
+++ b/tmk_core/common/action_layer.c
@@ -0,0 +1,138 @@
1#include <stdint.h>
2#include "keyboard.h"
3#include "action.h"
4#include "util.h"
5#include "action_layer.h"
6
7#ifdef DEBUG_ACTION
8#include "debug.h"
9#else
10#include "nodebug.h"
11#endif
12
13
14/*
15 * Default Layer State
16 */
17uint32_t default_layer_state = 0;
18
19static void default_layer_state_set(uint32_t state)
20{
21 debug("default_layer_state: ");
22 default_layer_debug(); debug(" to ");
23 default_layer_state = state;
24 default_layer_debug(); debug("\n");
25 clear_keyboard_but_mods(); // To avoid stuck keys
26}
27
28void default_layer_debug(void)
29{
30 dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
31}
32
33void default_layer_set(uint32_t state)
34{
35 default_layer_state_set(state);
36}
37
38#ifndef NO_ACTION_LAYER
39void default_layer_or(uint32_t state)
40{
41 default_layer_state_set(default_layer_state | state);
42}
43void default_layer_and(uint32_t state)
44{
45 default_layer_state_set(default_layer_state & state);
46}
47void default_layer_xor(uint32_t state)
48{
49 default_layer_state_set(default_layer_state ^ state);
50}
51#endif
52
53
54#ifndef NO_ACTION_LAYER
55/*
56 * Keymap Layer State
57 */
58uint32_t layer_state = 0;
59
60static void layer_state_set(uint32_t state)
61{
62 dprint("layer_state: ");
63 layer_debug(); dprint(" to ");
64 layer_state = state;
65 layer_debug(); dprintln();
66 clear_keyboard_but_mods(); // To avoid stuck keys
67}
68
69void layer_clear(void)
70{
71 layer_state_set(0);
72}
73
74void layer_move(uint8_t layer)
75{
76 layer_state_set(1UL<<layer);
77}
78
79void layer_on(uint8_t layer)
80{
81 layer_state_set(layer_state | (1UL<<layer));
82}
83
84void layer_off(uint8_t layer)
85{
86 layer_state_set(layer_state & ~(1UL<<layer));
87}
88
89void layer_invert(uint8_t layer)
90{
91 layer_state_set(layer_state ^ (1UL<<layer));
92}
93
94void layer_or(uint32_t state)
95{
96 layer_state_set(layer_state | state);
97}
98void layer_and(uint32_t state)
99{
100 layer_state_set(layer_state & state);
101}
102void layer_xor(uint32_t state)
103{
104 layer_state_set(layer_state ^ state);
105}
106
107void layer_debug(void)
108{
109 dprintf("%08lX(%u)", layer_state, biton32(layer_state));
110}
111#endif
112
113
114
115action_t layer_switch_get_action(keypos_t key)
116{
117 action_t action;
118 action.code = ACTION_TRANSPARENT;
119
120#ifndef NO_ACTION_LAYER
121 uint32_t layers = layer_state | default_layer_state;
122 /* check top layer first */
123 for (int8_t i = 31; i >= 0; i--) {
124 if (layers & (1UL<<i)) {
125 action = action_for_key(i, key);
126 if (action.code != ACTION_TRANSPARENT) {
127 return action;
128 }
129 }
130 }
131 /* fall back to layer 0 */
132 action = action_for_key(0, key);
133 return action;
134#else
135 action = action_for_key(biton32(default_layer_state), key);
136 return action;
137#endif
138}
diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h
new file mode 100644
index 000000000..b6da353cf
--- /dev/null
+++ b/tmk_core/common/action_layer.h
@@ -0,0 +1,77 @@
1/*
2Copyright 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#ifndef ACTION_LAYER_H
18#define ACTION_LAYER_H
19
20#include <stdint.h>
21#include "keyboard.h"
22#include "action.h"
23
24
25/*
26 * Default Layer
27 */
28extern uint32_t default_layer_state;
29void default_layer_debug(void);
30void default_layer_set(uint32_t state);
31
32#ifndef NO_ACTION_LAYER
33/* bitwise operation */
34void default_layer_or(uint32_t state);
35void default_layer_and(uint32_t state);
36void default_layer_xor(uint32_t state);
37#else
38#define default_layer_or(state)
39#define default_layer_and(state)
40#define default_layer_xor(state)
41#endif
42
43
44/*
45 * Keymap Layer
46 */
47#ifndef NO_ACTION_LAYER
48extern uint32_t layer_state;
49void layer_debug(void);
50void layer_clear(void);
51void layer_move(uint8_t layer);
52void layer_on(uint8_t layer);
53void layer_off(uint8_t layer);
54void layer_invert(uint8_t layer);
55/* bitwise operation */
56void layer_or(uint32_t state);
57void layer_and(uint32_t state);
58void layer_xor(uint32_t state);
59#else
60#define layer_state 0
61#define layer_clear()
62#define layer_move(layer)
63#define layer_on(layer)
64#define layer_off(layer)
65#define layer_invert(layer)
66
67#define layer_or(state)
68#define layer_and(state)
69#define layer_xor(state)
70#define layer_debug()
71#endif
72
73
74/* return action depending on current layer status */
75action_t layer_switch_get_action(keypos_t key);
76
77#endif
diff --git a/tmk_core/common/action_macro.c b/tmk_core/common/action_macro.c
new file mode 100644
index 000000000..ba93fc8b2
--- /dev/null
+++ b/tmk_core/common/action_macro.c
@@ -0,0 +1,83 @@
1/*
2Copyright 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#include "action.h"
18#include "action_util.h"
19#include "action_macro.h"
20#include "wait.h"
21
22#ifdef DEBUG_ACTION
23#include "debug.h"
24#else
25#include "nodebug.h"
26#endif
27
28
29#ifndef NO_ACTION_MACRO
30
31#define MACRO_READ() (macro = MACRO_GET(macro_p++))
32void action_macro_play(const macro_t *macro_p)
33{
34 macro_t macro = END;
35 uint8_t interval = 0;
36
37 if (!macro_p) return;
38 while (true) {
39 switch (MACRO_READ()) {
40 case KEY_DOWN:
41 MACRO_READ();
42 dprintf("KEY_DOWN(%02X)\n", macro);
43 if (IS_MOD(macro)) {
44 add_weak_mods(MOD_BIT(macro));
45 } else {
46 register_code(macro);
47 }
48 break;
49 case KEY_UP:
50 MACRO_READ();
51 dprintf("KEY_UP(%02X)\n", macro);
52 if (IS_MOD(macro)) {
53 del_weak_mods(MOD_BIT(macro));
54 } else {
55 unregister_code(macro);
56 }
57 break;
58 case WAIT:
59 MACRO_READ();
60 dprintf("WAIT(%u)\n", macro);
61 { uint8_t ms = macro; while (ms--) wait_ms(1); }
62 break;
63 case INTERVAL:
64 interval = MACRO_READ();
65 dprintf("INTERVAL(%u)\n", interval);
66 break;
67 case 0x04 ... 0x73:
68 dprintf("DOWN(%02X)\n", macro);
69 register_code(macro);
70 break;
71 case 0x84 ... 0xF3:
72 dprintf("UP(%02X)\n", macro);
73 unregister_code(macro&0x7F);
74 break;
75 case END:
76 default:
77 return;
78 }
79 // interval
80 { uint8_t ms = interval; while (ms--) wait_ms(1); }
81 }
82}
83#endif
diff --git a/tmk_core/common/action_macro.h b/tmk_core/common/action_macro.h
new file mode 100644
index 000000000..aedc32ec6
--- /dev/null
+++ b/tmk_core/common/action_macro.h
@@ -0,0 +1,102 @@
1/*
2Copyright 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#ifndef ACTION_MACRO_H
18#define ACTION_MACRO_H
19#include <stdint.h>
20#include "progmem.h"
21
22
23#define MACRO_NONE 0
24#define MACRO(...) ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
25#define MACRO_GET(p) pgm_read_byte(p)
26
27typedef uint8_t macro_t;
28
29
30#ifndef NO_ACTION_MACRO
31void action_macro_play(const macro_t *macro_p);
32#else
33#define action_macro_play(macro)
34#endif
35
36
37
38/* Macro commands
39 * code(0x04-73) // key down(1byte)
40 * code(0x04-73) | 0x80 // key up(1byte)
41 * { KEY_DOWN, code(0x04-0xff) } // key down(2bytes)
42 * { KEY_UP, code(0x04-0xff) } // key up(2bytes)
43 * WAIT // wait milli-seconds
44 * INTERVAL // set interval between macro commands
45 * END // stop macro execution
46 *
47 * Ideas(Not implemented):
48 * modifiers
49 * system usage
50 * consumer usage
51 * unicode usage
52 * function call
53 * conditionals
54 * loop
55 */
56enum macro_command_id{
57 /* 0x00 - 0x03 */
58 END = 0x00,
59 KEY_DOWN,
60 KEY_UP,
61
62 /* 0x04 - 0x73 (reserved for keycode down) */
63
64 /* 0x74 - 0x83 */
65 WAIT = 0x74,
66 INTERVAL,
67
68 /* 0x84 - 0xf3 (reserved for keycode up) */
69
70 /* 0xf4 - 0xff */
71};
72
73
74/* TODO: keycode:0x04-0x73 can be handled by 1byte command else 2bytes are needed
75 * if keycode between 0x04 and 0x73
76 * keycode / (keycode|0x80)
77 * else
78 * {KEY_DOWN, keycode} / {KEY_UP, keycode}
79*/
80#define DOWN(key) KEY_DOWN, (key)
81#define UP(key) KEY_UP, (key)
82#define TYPE(key) DOWN(key), UP(key)
83#define WAIT(ms) WAIT, (ms)
84#define INTERVAL(ms) INTERVAL, (ms)
85
86/* key down */
87#define D(key) DOWN(KC_##key)
88/* key up */
89#define U(key) UP(KC_##key)
90/* key type */
91#define T(key) TYPE(KC_##key)
92/* wait */
93#define W(ms) WAIT(ms)
94/* interval */
95#define I(ms) INTERVAL(ms)
96
97/* for backward comaptibility */
98#define MD(key) DOWN(KC_##key)
99#define MU(key) UP(KC_##key)
100
101
102#endif /* ACTION_MACRO_H */
diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c
new file mode 100644
index 000000000..826c23309
--- /dev/null
+++ b/tmk_core/common/action_tapping.c
@@ -0,0 +1,376 @@
1#include <stdint.h>
2#include <stdbool.h>
3#include "action.h"
4#include "action_layer.h"
5#include "action_tapping.h"
6#include "keycode.h"
7#include "timer.h"
8
9#ifdef DEBUG_ACTION
10#include "debug.h"
11#else
12#include "nodebug.h"
13#endif
14
15#ifndef NO_ACTION_TAPPING
16
17#define IS_TAPPING() !IS_NOEVENT(tapping_key.event)
18#define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
19#define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
20#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
21#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
22
23
24static keyrecord_t tapping_key = {};
25static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
26static uint8_t waiting_buffer_head = 0;
27static uint8_t waiting_buffer_tail = 0;
28
29static bool process_tapping(keyrecord_t *record);
30static bool waiting_buffer_enq(keyrecord_t record);
31static void waiting_buffer_clear(void);
32static bool waiting_buffer_typed(keyevent_t event);
33static bool waiting_buffer_has_anykey_pressed(void);
34static void waiting_buffer_scan_tap(void);
35static void debug_tapping_key(void);
36static void debug_waiting_buffer(void);
37
38
39void action_tapping_process(keyrecord_t record)
40{
41 if (process_tapping(&record)) {
42 if (!IS_NOEVENT(record.event)) {
43 debug("processed: "); debug_record(record); debug("\n");
44 }
45 } else {
46 if (!waiting_buffer_enq(record)) {
47 // clear all in case of overflow.
48 debug("OVERFLOW: CLEAR ALL STATES\n");
49 clear_keyboard();
50 waiting_buffer_clear();
51 tapping_key = (keyrecord_t){};
52 }
53 }
54
55 // process waiting_buffer
56 if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) {
57 debug("---- action_exec: process waiting_buffer -----\n");
58 }
59 for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
60 if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
61 debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
62 debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n");
63 } else {
64 break;
65 }
66 }
67 if (!IS_NOEVENT(record.event)) {
68 debug("\n");
69 }
70}
71
72
73/* Tapping
74 *
75 * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
76 * (without interfering by typing other key)
77 */
78/* return true when key event is processed or consumed. */
79bool process_tapping(keyrecord_t *keyp)
80{
81 keyevent_t event = keyp->event;
82
83 // if tapping
84 if (IS_TAPPING_PRESSED()) {
85 if (WITHIN_TAPPING_TERM(event)) {
86 if (tapping_key.tap.count == 0) {
87 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
88 // first tap!
89 debug("Tapping: First tap(0->1).\n");
90 tapping_key.tap.count = 1;
91 debug_tapping_key();
92 process_action(&tapping_key);
93
94 // copy tapping state
95 keyp->tap = tapping_key.tap;
96 // enqueue
97 return false;
98 }
99#if TAPPING_TERM >= 500
100 /* Process a key typed within TAPPING_TERM
101 * This can register the key before settlement of tapping,
102 * useful for long TAPPING_TERM but may prevent fast typing.
103 */
104 else if (IS_RELEASED(event) && waiting_buffer_typed(event)) {
105 debug("Tapping: End. No tap. Interfered by typing key\n");
106 process_action(&tapping_key);
107 tapping_key = (keyrecord_t){};
108 debug_tapping_key();
109 // enqueue
110 return false;
111 }
112#endif
113 /* Process release event of a key pressed before tapping starts
114 * Without this unexpected repeating will occur with having fast repeating setting
115 * https://github.com/tmk/tmk_keyboard/issues/60
116 */
117 else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
118 // Modifier should be retained till end of this tapping.
119 action_t action = layer_switch_get_action(event.key);
120 switch (action.kind.id) {
121 case ACT_LMODS:
122 case ACT_RMODS:
123 if (action.key.mods && !action.key.code) return false;
124 if (IS_MOD(action.key.code)) return false;
125 break;
126 case ACT_LMODS_TAP:
127 case ACT_RMODS_TAP:
128 if (action.key.mods && keyp->tap.count == 0) return false;
129 if (IS_MOD(action.key.code)) return false;
130 break;
131 }
132 // Release of key should be process immediately.
133 debug("Tapping: release event of a key pressed before tapping\n");
134 process_action(keyp);
135 return true;
136 }
137 else {
138 // set interrupted flag when other key preesed during tapping
139 if (event.pressed) {
140 tapping_key.tap.interrupted = true;
141 }
142 // enqueue
143 return false;
144 }
145 }
146 // tap_count > 0
147 else {
148 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
149 debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n");
150 keyp->tap = tapping_key.tap;
151 process_action(keyp);
152 tapping_key = *keyp;
153 debug_tapping_key();
154 return true;
155 }
156 else if (is_tap_key(event.key) && event.pressed) {
157 if (tapping_key.tap.count > 1) {
158 debug("Tapping: Start new tap with releasing last tap(>1).\n");
159 // unregister key
160 process_action(&(keyrecord_t){
161 .tap = tapping_key.tap,
162 .event.key = tapping_key.event.key,
163 .event.time = event.time,
164 .event.pressed = false
165 });
166 } else {
167 debug("Tapping: Start while last tap(1).\n");
168 }
169 tapping_key = *keyp;
170 waiting_buffer_scan_tap();
171 debug_tapping_key();
172 return true;
173 }
174 else {
175 if (!IS_NOEVENT(event)) {
176 debug("Tapping: key event while last tap(>0).\n");
177 }
178 process_action(keyp);
179 return true;
180 }
181 }
182 }
183 // after TAPPING_TERM
184 else {
185 if (tapping_key.tap.count == 0) {
186 debug("Tapping: End. Timeout. Not tap(0): ");
187 debug_event(event); debug("\n");
188 process_action(&tapping_key);
189 tapping_key = (keyrecord_t){};
190 debug_tapping_key();
191 return false;
192 } else {
193 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
194 debug("Tapping: End. last timeout tap release(>0).");
195 keyp->tap = tapping_key.tap;
196 process_action(keyp);
197 tapping_key = (keyrecord_t){};
198 return true;
199 }
200 else if (is_tap_key(event.key) && event.pressed) {
201 if (tapping_key.tap.count > 1) {
202 debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
203 // unregister key
204 process_action(&(keyrecord_t){
205 .tap = tapping_key.tap,
206 .event.key = tapping_key.event.key,
207 .event.time = event.time,
208 .event.pressed = false
209 });
210 } else {
211 debug("Tapping: Start while last timeout tap(1).\n");
212 }
213 tapping_key = *keyp;
214 waiting_buffer_scan_tap();
215 debug_tapping_key();
216 return true;
217 }
218 else {
219 if (!IS_NOEVENT(event)) {
220 debug("Tapping: key event while last timeout tap(>0).\n");
221 }
222 process_action(keyp);
223 return true;
224 }
225 }
226 }
227 } else if (IS_TAPPING_RELEASED()) {
228 if (WITHIN_TAPPING_TERM(event)) {
229 if (event.pressed) {
230 if (IS_TAPPING_KEY(event.key)) {
231 if (!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
232 // sequential tap.
233 keyp->tap = tapping_key.tap;
234 if (keyp->tap.count < 15) keyp->tap.count += 1;
235 debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
236 process_action(keyp);
237 tapping_key = *keyp;
238 debug_tapping_key();
239 return true;
240 } else {
241 // FIX: start new tap again
242 tapping_key = *keyp;
243 return true;
244 }
245 } else if (is_tap_key(event.key)) {
246 // Sequential tap can be interfered with other tap key.
247 debug("Tapping: Start with interfering other tap.\n");
248 tapping_key = *keyp;
249 waiting_buffer_scan_tap();
250 debug_tapping_key();
251 return true;
252 } else {
253 // should none in buffer
254 // FIX: interrupted when other key is pressed
255 tapping_key.tap.interrupted = true;
256 process_action(keyp);
257 return true;
258 }
259 } else {
260 if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
261 process_action(keyp);
262 return true;
263 }
264 } else {
265 // FIX: process_aciton here?
266 // timeout. no sequential tap.
267 debug("Tapping: End(Timeout after releasing last tap): ");
268 debug_event(event); debug("\n");
269 tapping_key = (keyrecord_t){};
270 debug_tapping_key();
271 return false;
272 }
273 }
274 // not tapping state
275 else {
276 if (event.pressed && is_tap_key(event.key)) {
277 debug("Tapping: Start(Press tap key).\n");
278 tapping_key = *keyp;
279 waiting_buffer_scan_tap();
280 debug_tapping_key();
281 return true;
282 } else {
283 process_action(keyp);
284 return true;
285 }
286 }
287}
288
289
290/*
291 * Waiting buffer
292 */
293bool waiting_buffer_enq(keyrecord_t record)
294{
295 if (IS_NOEVENT(record.event)) {
296 return true;
297 }
298
299 if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
300 debug("waiting_buffer_enq: Over flow.\n");
301 return false;
302 }
303
304 waiting_buffer[waiting_buffer_head] = record;
305 waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
306
307 debug("waiting_buffer_enq: "); debug_waiting_buffer();
308 return true;
309}
310
311void waiting_buffer_clear(void)
312{
313 waiting_buffer_head = 0;
314 waiting_buffer_tail = 0;
315}
316
317bool waiting_buffer_typed(keyevent_t event)
318{
319 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
320 if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) {
321 return true;
322 }
323 }
324 return false;
325}
326
327bool waiting_buffer_has_anykey_pressed(void)
328{
329 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
330 if (waiting_buffer[i].event.pressed) return true;
331 }
332 return false;
333}
334
335/* scan buffer for tapping */
336void waiting_buffer_scan_tap(void)
337{
338 // tapping already is settled
339 if (tapping_key.tap.count > 0) return;
340 // invalid state: tapping_key released && tap.count == 0
341 if (!tapping_key.event.pressed) return;
342
343 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
344 if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
345 !waiting_buffer[i].event.pressed &&
346 WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
347 tapping_key.tap.count = 1;
348 waiting_buffer[i].tap.count = 1;
349 process_action(&tapping_key);
350
351 debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
352 debug_waiting_buffer();
353 return;
354 }
355 }
356}
357
358
359/*
360 * debug print
361 */
362static void debug_tapping_key(void)
363{
364 debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n");
365}
366
367static void debug_waiting_buffer(void)
368{
369 debug("{ ");
370 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
371 debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" ");
372 }
373 debug("}\n");
374}
375
376#endif
diff --git a/tmk_core/common/action_tapping.h b/tmk_core/common/action_tapping.h
new file mode 100644
index 000000000..9b42d50dc
--- /dev/null
+++ b/tmk_core/common/action_tapping.h
@@ -0,0 +1,39 @@
1/*
2Copyright 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#ifndef ACTION_TAPPING_H
18#define ACTION_TAPPING_H
19
20
21
22/* period of tapping(ms) */
23#ifndef TAPPING_TERM
24#define TAPPING_TERM 200
25#endif
26
27/* tap count needed for toggling a feature */
28#ifndef TAPPING_TOGGLE
29#define TAPPING_TOGGLE 5
30#endif
31
32#define WAITING_BUFFER_SIZE 8
33
34
35#ifndef NO_ACTION_TAPPING
36void action_tapping_process(keyrecord_t record);
37#endif
38
39#endif
diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c
new file mode 100644
index 000000000..dbee630d1
--- /dev/null
+++ b/tmk_core/common/action_util.c
@@ -0,0 +1,307 @@
1/*
2Copyright 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#include "host.h"
18#include "report.h"
19#include "debug.h"
20#include "action_util.h"
21#include "timer.h"
22
23static inline void add_key_byte(uint8_t code);
24static inline void del_key_byte(uint8_t code);
25#ifdef NKRO_ENABLE
26static inline void add_key_bit(uint8_t code);
27static inline void del_key_bit(uint8_t code);
28#endif
29
30static uint8_t real_mods = 0;
31static uint8_t weak_mods = 0;
32
33#ifdef USB_6KRO_ENABLE
34#define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
35#define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
36#define RO_INC(a) RO_ADD(a, 1)
37#define RO_DEC(a) RO_SUB(a, 1)
38static int8_t cb_head = 0;
39static int8_t cb_tail = 0;
40static int8_t cb_count = 0;
41#endif
42
43// TODO: pointer variable is not needed
44//report_keyboard_t keyboard_report = {};
45report_keyboard_t *keyboard_report = &(report_keyboard_t){};
46
47#ifndef NO_ACTION_ONESHOT
48static int8_t oneshot_mods = 0;
49#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
50static int16_t oneshot_time = 0;
51#endif
52#endif
53
54
55void send_keyboard_report(void) {
56 keyboard_report->mods = real_mods;
57 keyboard_report->mods |= weak_mods;
58#ifndef NO_ACTION_ONESHOT
59 if (oneshot_mods) {
60#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
61 if (TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT) {
62 dprintf("Oneshot: timeout\n");
63 clear_oneshot_mods();
64 }
65#endif
66 keyboard_report->mods |= oneshot_mods;
67 if (has_anykey()) {
68 clear_oneshot_mods();
69 }
70 }
71#endif
72 host_keyboard_send(keyboard_report);
73}
74
75/* key */
76void add_key(uint8_t key)
77{
78#ifdef NKRO_ENABLE
79 if (keyboard_nkro) {
80 add_key_bit(key);
81 return;
82 }
83#endif
84 add_key_byte(key);
85}
86
87void del_key(uint8_t key)
88{
89#ifdef NKRO_ENABLE
90 if (keyboard_nkro) {
91 del_key_bit(key);
92 return;
93 }
94#endif
95 del_key_byte(key);
96}
97
98void clear_keys(void)
99{
100 // not clear mods
101 for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
102 keyboard_report->raw[i] = 0;
103 }
104}
105
106
107/* modifier */
108uint8_t get_mods(void) { return real_mods; }
109void add_mods(uint8_t mods) { real_mods |= mods; }
110void del_mods(uint8_t mods) { real_mods &= ~mods; }
111void set_mods(uint8_t mods) { real_mods = mods; }
112void clear_mods(void) { real_mods = 0; }
113
114/* weak modifier */
115uint8_t get_weak_mods(void) { return weak_mods; }
116void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
117void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
118void set_weak_mods(uint8_t mods) { weak_mods = mods; }
119void clear_weak_mods(void) { weak_mods = 0; }
120
121/* Oneshot modifier */
122#ifndef NO_ACTION_ONESHOT
123void set_oneshot_mods(uint8_t mods)
124{
125 oneshot_mods = mods;
126#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
127 oneshot_time = timer_read();
128#endif
129}
130void clear_oneshot_mods(void)
131{
132 oneshot_mods = 0;
133#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
134 oneshot_time = 0;
135#endif
136}
137#endif
138
139
140
141
142/*
143 * inspect keyboard state
144 */
145uint8_t has_anykey(void)
146{
147 uint8_t cnt = 0;
148 for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
149 if (keyboard_report->raw[i])
150 cnt++;
151 }
152 return cnt;
153}
154
155uint8_t has_anymod(void)
156{
157 return bitpop(real_mods);
158}
159
160uint8_t get_first_key(void)
161{
162#ifdef NKRO_ENABLE
163 if (keyboard_nkro) {
164 uint8_t i = 0;
165 for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
166 ;
167 return i<<3 | biton(keyboard_report->nkro.bits[i]);
168 }
169#endif
170#ifdef USB_6KRO_ENABLE
171 uint8_t i = cb_head;
172 do {
173 if (keyboard_report->keys[i] != 0) {
174 break;
175 }
176 i = RO_INC(i);
177 } while (i != cb_tail);
178 return keyboard_report->keys[i];
179#else
180 return keyboard_report->keys[0];
181#endif
182}
183
184
185
186/* local functions */
187static inline void add_key_byte(uint8_t code)
188{
189#ifdef USB_6KRO_ENABLE
190 int8_t i = cb_head;
191 int8_t empty = -1;
192 if (cb_count) {
193 do {
194 if (keyboard_report->keys[i] == code) {
195 return;
196 }
197 if (empty == -1 && keyboard_report->keys[i] == 0) {
198 empty = i;
199 }
200 i = RO_INC(i);
201 } while (i != cb_tail);
202 if (i == cb_tail) {
203 if (cb_tail == cb_head) {
204 // buffer is full
205 if (empty == -1) {
206 // pop head when has no empty space
207 cb_head = RO_INC(cb_head);
208 cb_count--;
209 }
210 else {
211 // left shift when has empty space
212 uint8_t offset = 1;
213 i = RO_INC(empty);
214 do {
215 if (keyboard_report->keys[i] != 0) {
216 keyboard_report->keys[empty] = keyboard_report->keys[i];
217 keyboard_report->keys[i] = 0;
218 empty = RO_INC(empty);
219 }
220 else {
221 offset++;
222 }
223 i = RO_INC(i);
224 } while (i != cb_tail);
225 cb_tail = RO_SUB(cb_tail, offset);
226 }
227 }
228 }
229 }
230 // add to tail
231 keyboard_report->keys[cb_tail] = code;
232 cb_tail = RO_INC(cb_tail);
233 cb_count++;
234#else
235 int8_t i = 0;
236 int8_t empty = -1;
237 for (; i < KEYBOARD_REPORT_KEYS; i++) {
238 if (keyboard_report->keys[i] == code) {
239 break;
240 }
241 if (empty == -1 && keyboard_report->keys[i] == 0) {
242 empty = i;
243 }
244 }
245 if (i == KEYBOARD_REPORT_KEYS) {
246 if (empty != -1) {
247 keyboard_report->keys[empty] = code;
248 }
249 }
250#endif
251}
252
253static inline void del_key_byte(uint8_t code)
254{
255#ifdef USB_6KRO_ENABLE
256 uint8_t i = cb_head;
257 if (cb_count) {
258 do {
259 if (keyboard_report->keys[i] == code) {
260 keyboard_report->keys[i] = 0;
261 cb_count--;
262 if (cb_count == 0) {
263 // reset head and tail
264 cb_tail = cb_head = 0;
265 }
266 if (i == RO_DEC(cb_tail)) {
267 // left shift when next to tail
268 do {
269 cb_tail = RO_DEC(cb_tail);
270 if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
271 break;
272 }
273 } while (cb_tail != cb_head);
274 }
275 break;
276 }
277 i = RO_INC(i);
278 } while (i != cb_tail);
279 }
280#else
281 for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
282 if (keyboard_report->keys[i] == code) {
283 keyboard_report->keys[i] = 0;
284 }
285 }
286#endif
287}
288
289#ifdef NKRO_ENABLE
290static inline void add_key_bit(uint8_t code)
291{
292 if ((code>>3) < KEYBOARD_REPORT_BITS) {
293 keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
294 } else {
295 dprintf("add_key_bit: can't add: %02X\n", code);
296 }
297}
298
299static inline void del_key_bit(uint8_t code)
300{
301 if ((code>>3) < KEYBOARD_REPORT_BITS) {
302 keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
303 } else {
304 dprintf("del_key_bit: can't del: %02X\n", code);
305 }
306}
307#endif
diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h
new file mode 100644
index 000000000..a955638b4
--- /dev/null
+++ b/tmk_core/common/action_util.h
@@ -0,0 +1,66 @@
1/*
2Copyright 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#ifndef ACTION_UTIL_H
18#define ACTION_UTIL_H
19
20#include <stdint.h>
21#include "report.h"
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27extern report_keyboard_t *keyboard_report;
28
29void send_keyboard_report(void);
30
31/* key */
32void add_key(uint8_t key);
33void del_key(uint8_t key);
34void clear_keys(void);
35
36/* modifier */
37uint8_t get_mods(void);
38void add_mods(uint8_t mods);
39void del_mods(uint8_t mods);
40void set_mods(uint8_t mods);
41void clear_mods(void);
42
43/* weak modifier */
44uint8_t get_weak_mods(void);
45void add_weak_mods(uint8_t mods);
46void del_weak_mods(uint8_t mods);
47void set_weak_mods(uint8_t mods);
48void clear_weak_mods(void);
49
50/* oneshot modifier */
51void set_oneshot_mods(uint8_t mods);
52void clear_oneshot_mods(void);
53void oneshot_toggle(void);
54void oneshot_enable(void);
55void oneshot_disable(void);
56
57/* inspect */
58uint8_t has_anykey(void);
59uint8_t has_anymod(void);
60uint8_t get_first_key(void);
61
62#ifdef __cplusplus
63}
64#endif
65
66#endif
diff --git a/tmk_core/common/avr/bootloader.c b/tmk_core/common/avr/bootloader.c
new file mode 100644
index 000000000..cda295b18
--- /dev/null
+++ b/tmk_core/common/avr/bootloader.c
@@ -0,0 +1,148 @@
1#include <stdint.h>
2#include <stdbool.h>
3#include <avr/io.h>
4#include <avr/interrupt.h>
5#include <avr/wdt.h>
6#include <util/delay.h>
7#include "bootloader.h"
8
9#ifdef PROTOCOL_LUFA
10#include <LUFA/Drivers/USB/USB.h>
11#endif
12
13
14/* Boot Section Size in *BYTEs*
15 * Teensy halfKay 512
16 * Teensy++ halfKay 1024
17 * Atmel DFU loader 4096
18 * LUFA bootloader 4096
19 * USBaspLoader 2048
20 */
21#ifndef BOOTLOADER_SIZE
22#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
23#define BOOTLOADER_SIZE 4096
24#endif
25
26#define FLASH_SIZE (FLASHEND + 1L)
27#define BOOTLOADER_START (FLASH_SIZE - BOOTLOADER_SIZE)
28
29
30/*
31 * Entering the Bootloader via Software
32 * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
33 */
34#define BOOTLOADER_RESET_KEY 0xB007B007
35uint32_t reset_key __attribute__ ((section (".noinit")));
36
37/* initialize MCU status by watchdog reset */
38void bootloader_jump(void) {
39#ifdef PROTOCOL_LUFA
40 USB_Disable();
41 cli();
42 _delay_ms(2000);
43#endif
44
45#ifdef PROTOCOL_PJRC
46 cli();
47 UDCON = 1;
48 USBCON = (1<<FRZCLK);
49 UCSR1B = 0;
50 _delay_ms(5);
51#endif
52
53 // watchdog reset
54 reset_key = BOOTLOADER_RESET_KEY;
55 wdt_enable(WDTO_250MS);
56 for (;;);
57}
58
59
60/* this runs before main() */
61void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
62void bootloader_jump_after_watchdog_reset(void)
63{
64 if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
65 reset_key = 0;
66
67 // My custom USBasploader requires this to come up.
68 MCUSR = 0;
69
70 // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
71 MCUSR &= ~(1<<WDRF);
72 wdt_disable();
73
74 // This is compled into 'icall', address should be in word unit, not byte.
75 ((void (*)(void))(BOOTLOADER_START/2))();
76 }
77}
78
79
80#if 0
81/* Jumping To The Bootloader
82 * http://www.pjrc.com/teensy/jump_to_bootloader.html
83 *
84 * This method doen't work when using LUFA. idk why.
85 * - needs to initialize more regisers or interrupt setting?
86 */
87void bootloader_jump(void) {
88#ifdef PROTOCOL_LUFA
89 USB_Disable();
90 cli();
91 _delay_ms(2000);
92#endif
93
94#ifdef PROTOCOL_PJRC
95 cli();
96 UDCON = 1;
97 USBCON = (1<<FRZCLK);
98 UCSR1B = 0;
99 _delay_ms(5);
100#endif
101
102 /*
103 * Initialize
104 */
105#if defined(__AVR_AT90USB162__)
106 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
107 TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
108 DDRB = 0; DDRC = 0; DDRD = 0;
109 PORTB = 0; PORTC = 0; PORTD = 0;
110#elif defined(__AVR_ATmega32U4__)
111 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
112 TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
113 DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
114 PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
115#elif defined(__AVR_AT90USB646__)
116 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
117 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
118 DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
119 PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
120#elif defined(__AVR_AT90USB1286__)
121 EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
122 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
123 DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
124 PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
125#endif
126
127 /*
128 * USBaspLoader
129 */
130#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
131 // This makes custom USBasploader come up.
132 MCUSR = 0;
133
134 // initialize ports
135 PORTB = 0; PORTC= 0; PORTD = 0;
136 DDRB = 0; DDRC= 0; DDRD = 0;
137
138 // disable interrupts
139 EIMSK = 0; EECR = 0; SPCR = 0;
140 ACSR = 0; SPMCSR = 0; WDTCSR = 0; PCICR = 0;
141 TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0;
142 ADCSRA = 0; TWCR = 0; UCSR0B = 0;
143#endif
144
145 // This is compled into 'icall', address should be in word unit, not byte.
146 ((void (*)(void))(BOOTLOADER_START/2))();
147}
148#endif
diff --git a/tmk_core/common/avr/eeconfig.c b/tmk_core/common/avr/eeconfig.c
new file mode 100644
index 000000000..5bd47dc6a
--- /dev/null
+++ b/tmk_core/common/avr/eeconfig.c
@@ -0,0 +1,45 @@
1#include <stdint.h>
2#include <stdbool.h>
3#include <avr/eeprom.h>
4#include "eeconfig.h"
5
6void eeconfig_init(void)
7{
8 eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
9 eeprom_write_byte(EECONFIG_DEBUG, 0);
10 eeprom_write_byte(EECONFIG_DEFAULT_LAYER, 0);
11 eeprom_write_byte(EECONFIG_KEYMAP, 0);
12 eeprom_write_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
13#ifdef BACKLIGHT_ENABLE
14 eeprom_write_byte(EECONFIG_BACKLIGHT, 0);
15#endif
16}
17
18void eeconfig_enable(void)
19{
20 eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
21}
22
23void eeconfig_disable(void)
24{
25 eeprom_write_word(EECONFIG_MAGIC, 0xFFFF);
26}
27
28bool eeconfig_is_enabled(void)
29{
30 return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
31}
32
33uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); }
34void eeconfig_write_debug(uint8_t val) { eeprom_write_byte(EECONFIG_DEBUG, val); }
35
36uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); }
37void eeconfig_write_default_layer(uint8_t val) { eeprom_write_byte(EECONFIG_DEFAULT_LAYER, val); }
38
39uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMAP); }
40void eeconfig_write_keymap(uint8_t val) { eeprom_write_byte(EECONFIG_KEYMAP, val); }
41
42#ifdef BACKLIGHT_ENABLE
43uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
44void eeconfig_write_backlight(uint8_t val) { eeprom_write_byte(EECONFIG_BACKLIGHT, val); }
45#endif
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c
new file mode 100644
index 000000000..80243f02b
--- /dev/null
+++ b/tmk_core/common/avr/suspend.c
@@ -0,0 +1,122 @@
1#include <stdbool.h>
2#include <avr/sleep.h>
3#include <avr/wdt.h>
4#include <avr/interrupt.h>
5#include "matrix.h"
6#include "action.h"
7#include "backlight.h"
8#include "suspend_avr.h"
9#include "suspend.h"
10#include "timer.h"
11#ifdef PROTOCOL_LUFA
12#include "lufa.h"
13#endif
14
15
16#define wdt_intr_enable(value) \
17__asm__ __volatile__ ( \
18 "in __tmp_reg__,__SREG__" "\n\t" \
19 "cli" "\n\t" \
20 "wdr" "\n\t" \
21 "sts %0,%1" "\n\t" \
22 "out __SREG__,__tmp_reg__" "\n\t" \
23 "sts %0,%2" "\n\t" \
24 : /* no outputs */ \
25 : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
26 "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
27 "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
28 _BV(WDIE) | (value & 0x07)) ) \
29 : "r0" \
30)
31
32
33void suspend_idle(uint8_t time)
34{
35 cli();
36 set_sleep_mode(SLEEP_MODE_IDLE);
37 sleep_enable();
38 sei();
39 sleep_cpu();
40 sleep_disable();
41}
42
43/* Power down MCU with watchdog timer
44 * wdto: watchdog timer timeout defined in <avr/wdt.h>
45 * WDTO_15MS
46 * WDTO_30MS
47 * WDTO_60MS
48 * WDTO_120MS
49 * WDTO_250MS
50 * WDTO_500MS
51 * WDTO_1S
52 * WDTO_2S
53 * WDTO_4S
54 * WDTO_8S
55 */
56static uint8_t wdt_timeout = 0;
57static void power_down(uint8_t wdto)
58{
59#ifdef PROTOCOL_LUFA
60 if (USB_DeviceState == DEVICE_STATE_Configured) return;
61#endif
62 wdt_timeout = wdto;
63
64 // Watchdog Interrupt Mode
65 wdt_intr_enable(wdto);
66
67 // TODO: more power saving
68 // See PicoPower application note
69 // - I/O port input with pullup
70 // - prescale clock
71 // - BOD disable
72 // - Power Reduction Register PRR
73 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
74 sleep_enable();
75 sei();
76 sleep_cpu();
77 sleep_disable();
78
79 // Disable watchdog after sleep
80 wdt_disable();
81}
82
83void suspend_power_down(void)
84{
85 power_down(WDTO_15MS);
86}
87
88bool suspend_wakeup_condition(void)
89{
90 matrix_power_up();
91 matrix_scan();
92 matrix_power_down();
93 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
94 if (matrix_get_row(r)) return true;
95 }
96 return false;
97}
98
99// run immediately after wakeup
100void suspend_wakeup_init(void)
101{
102 // clear keyboard state
103 clear_keyboard();
104#ifdef BACKLIGHT_ENABLE
105 backlight_init();
106#endif
107}
108
109#ifndef NO_SUSPEND_POWER_DOWN
110/* watchdog timeout */
111ISR(WDT_vect)
112{
113 // compensate timer for sleep
114 switch (wdt_timeout) {
115 case WDTO_15MS:
116 timer_count += 15 + 2; // WDTO_15MS + 2(from observation)
117 break;
118 default:
119 ;
120 }
121}
122#endif
diff --git a/tmk_core/common/avr/suspend_avr.h b/tmk_core/common/avr/suspend_avr.h
new file mode 100644
index 000000000..357102da4
--- /dev/null
+++ b/tmk_core/common/avr/suspend_avr.h
@@ -0,0 +1,27 @@
1#ifndef SUSPEND_AVR_H
2#define SUSPEND_AVR_H
3
4#include <stdint.h>
5#include <stdbool.h>
6#include <avr/sleep.h>
7#include <avr/wdt.h>
8#include <avr/interrupt.h>
9
10
11#define wdt_intr_enable(value) \
12__asm__ __volatile__ ( \
13 "in __tmp_reg__,__SREG__" "\n\t" \
14 "cli" "\n\t" \
15 "wdr" "\n\t" \
16 "sts %0,%1" "\n\t" \
17 "out __SREG__,__tmp_reg__" "\n\t" \
18 "sts %0,%2" "\n\t" \
19 : /* no outputs */ \
20 : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
21 "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
22 "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
23 _BV(WDIE) | (value & 0x07)) ) \
24 : "r0" \
25)
26
27#endif
diff --git a/tmk_core/common/avr/timer.c b/tmk_core/common/avr/timer.c
new file mode 100644
index 000000000..292b41c3a
--- /dev/null
+++ b/tmk_core/common/avr/timer.c
@@ -0,0 +1,117 @@
1/*
2Copyright 2011 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 <avr/io.h>
19#include <avr/interrupt.h>
20#include <stdint.h>
21#include "timer_avr.h"
22#include "timer.h"
23
24
25// counter resolution 1ms
26// NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
27volatile uint32_t timer_count = 0;
28
29void timer_init(void)
30{
31 // Timer0 CTC mode
32 TCCR0A = 0x02;
33
34#if TIMER_PRESCALER == 1
35 TCCR0B = 0x01;
36#elif TIMER_PRESCALER == 8
37 TCCR0B = 0x02;
38#elif TIMER_PRESCALER == 64
39 TCCR0B = 0x03;
40#elif TIMER_PRESCALER == 256
41 TCCR0B = 0x04;
42#elif TIMER_PRESCALER == 1024
43 TCCR0B = 0x05;
44#else
45# error "Timer prescaler value is NOT vaild."
46#endif
47
48 OCR0A = TIMER_RAW_TOP;
49 TIMSK0 = (1<<OCIE0A);
50}
51
52inline
53void timer_clear(void)
54{
55 uint8_t sreg = SREG;
56 cli();
57 timer_count = 0;
58 SREG = sreg;
59}
60
61inline
62uint16_t timer_read(void)
63{
64 uint32_t t;
65
66 uint8_t sreg = SREG;
67 cli();
68 t = timer_count;
69 SREG = sreg;
70
71 return (t & 0xFFFF);
72}
73
74inline
75uint32_t timer_read32(void)
76{
77 uint32_t t;
78
79 uint8_t sreg = SREG;
80 cli();
81 t = timer_count;
82 SREG = sreg;
83
84 return t;
85}
86
87inline
88uint16_t timer_elapsed(uint16_t last)
89{
90 uint32_t t;
91
92 uint8_t sreg = SREG;
93 cli();
94 t = timer_count;
95 SREG = sreg;
96
97 return TIMER_DIFF_16((t & 0xFFFF), last);
98}
99
100inline
101uint32_t timer_elapsed32(uint32_t last)
102{
103 uint32_t t;
104
105 uint8_t sreg = SREG;
106 cli();
107 t = timer_count;
108 SREG = sreg;
109
110 return TIMER_DIFF_32(t, last);
111}
112
113// excecuted once per 1ms.(excess for just timer count?)
114ISR(TIMER0_COMPA_vect)
115{
116 timer_count++;
117}
diff --git a/tmk_core/common/avr/timer_avr.h b/tmk_core/common/avr/timer_avr.h
new file mode 100644
index 000000000..0e85eb101
--- /dev/null
+++ b/tmk_core/common/avr/timer_avr.h
@@ -0,0 +1,42 @@
1/*
2Copyright 2011 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#ifndef TIMER_AVR_H
19#define TIMER_AVR_H 1
20
21#include <stdint.h>
22
23#ifndef TIMER_PRESCALER
24# if F_CPU > 16000000
25# define TIMER_PRESCALER 256
26# elif F_CPU > 2000000
27# define TIMER_PRESCALER 64
28# elif F_CPU > 250000
29# define TIMER_PRESCALER 8
30# else
31# define TIMER_PRESCALER 1
32# endif
33#endif
34#define TIMER_RAW_FREQ (F_CPU/TIMER_PRESCALER)
35#define TIMER_RAW TCNT0
36#define TIMER_RAW_TOP (TIMER_RAW_FREQ/1000)
37
38#if (TIMER_RAW_TOP > 255)
39# error "Timer0 can't count 1ms at this clock freq. Use larger prescaler."
40#endif
41
42#endif
diff --git a/tmk_core/common/avr/xprintf.S b/tmk_core/common/avr/xprintf.S
new file mode 100644
index 000000000..0cec70ce2
--- /dev/null
+++ b/tmk_core/common/avr/xprintf.S
@@ -0,0 +1,500 @@
1;---------------------------------------------------------------------------;
2; Extended itoa, puts, printf and atoi (C)ChaN, 2011
3;---------------------------------------------------------------------------;
4
5 // Base size is 152 bytes
6#define CR_CRLF 0 // Convert \n to \r\n (+10 bytes)
7#define USE_XPRINTF 1 // Enable xprintf function (+194 bytes)
8#define USE_XSPRINTF 0 // Add xsprintf function (+78 bytes)
9#define USE_XFPRINTF 0 // Add xfprintf function (+54 bytes)
10#define USE_XATOI 0 // Enable xatoi function (+182 bytes)
11
12
13#if FLASHEND > 0x1FFFF
14#error xitoa module does not support 256K devices
15#endif
16
17.nolist
18#include <avr/io.h> // Include device specific definitions.
19.list
20
21#ifdef SPM_PAGESIZE // Recent devices have "lpm Rd,Z+" and "movw".
22.macro _LPMI reg
23 lpm \reg, Z+
24.endm
25.macro _MOVW dh,dl, sh,sl
26 movw \dl, \sl
27.endm
28#else // Earlier devices do not have "lpm Rd,Z+" nor "movw".
29.macro _LPMI reg
30 lpm
31 mov \reg, r0
32 adiw ZL, 1
33.endm
34.macro _MOVW dh,dl, sh,sl
35 mov \dl, \sl
36 mov \dh, \sh
37.endm
38#endif
39
40
41
42;---------------------------------------------------------------------------
43; Stub function to forward to user output function
44;
45;Prototype: void xputc (char chr // a character to be output
46; );
47;Size: 12/12 words
48
49.section .bss
50.global xfunc_out ; xfunc_out must be initialized before using this module.
51xfunc_out: .ds.w 1
52.section .text
53
54
55.func xputc
56.global xputc
57xputc:
58#if CR_CRLF
59 cpi r24, 10 ;LF --> CRLF
60 brne 1f ;
61 ldi r24, 13 ;
62 rcall 1f ;
63 ldi r24, 10 ;/
641:
65#endif
66 push ZH
67 push ZL
68 lds ZL, xfunc_out+0 ;Pointer to the registered output function.
69 lds ZH, xfunc_out+1 ;/
70 sbiw ZL, 0 ;Skip if null
71 breq 2f ;/
72 icall
732: pop ZL
74 pop ZH
75 ret
76.endfunc
77
78
79
80;---------------------------------------------------------------------------
81; Direct ROM string output
82;
83;Prototype: void xputs (const char *str_p // rom string to be output
84; );
85
86.func xputs
87.global xputs
88xputs:
89 _MOVW ZH,ZL, r25,r24 ; Z = pointer to rom string
901: _LPMI r24
91 cpi r24, 0
92 breq 2f
93 rcall xputc
94 rjmp 1b
952: ret
96.endfunc
97
98
99;---------------------------------------------------------------------------
100; Extended direct numeral string output (32bit version)
101;
102;Prototype: void xitoa (long value, // value to be output
103; char radix, // radix
104; char width); // minimum width
105;
106
107.func xitoa
108.global xitoa
109xitoa:
110 ;r25:r22 = value, r20 = base, r18 = digits
111 clr r31 ;r31 = stack level
112 ldi r30, ' ' ;r30 = sign
113 ldi r19, ' ' ;r19 = filler
114 sbrs r20, 7 ;When base indicates signd format and the value
115 rjmp 0f ;is minus, add a '-'.
116 neg r20 ;
117 sbrs r25, 7 ;
118 rjmp 0f ;
119 ldi r30, '-' ;
120 com r22 ;
121 com r23 ;
122 com r24 ;
123 com r25 ;
124 adc r22, r1 ;
125 adc r23, r1 ;
126 adc r24, r1 ;
127 adc r25, r1 ;/
1280: sbrs r18, 7 ;When digits indicates zero filled,
129 rjmp 1f ;filler is '0'.
130 neg r18 ;
131 ldi r19, '0' ;/
132 ;----- string conversion loop
1331: ldi r21, 32 ;r26 = r25:r22 % r20
134 clr r26 ;r25:r22 /= r20
1352: lsl r22 ;
136 rol r23 ;
137 rol r24 ;
138 rol r25 ;
139 rol r26 ;
140 cp r26, r20 ;
141 brcs 3f ;
142 sub r26, r20 ;
143 inc r22 ;
1443: dec r21 ;
145 brne 2b ;/
146 cpi r26, 10 ;r26 is a numeral digit '0'-'F'
147 brcs 4f ;
148 subi r26, -7 ;
1494: subi r26, -'0' ;/
150 push r26 ;Stack it
151 inc r31 ;/
152 cp r22, r1 ;Repeat until r25:r22 gets zero
153 cpc r23, r1 ;
154 cpc r24, r1 ;
155 cpc r25, r1 ;
156 brne 1b ;/
157
158 cpi r30, '-' ;Minus sign if needed
159 brne 5f ;
160 push r30 ;
161 inc r31 ;/
1625: cp r31, r18 ;Filler
163 brcc 6f ;
164 push r19 ;
165 inc r31 ;
166 rjmp 5b ;/
167
1686: pop r24 ;Flush stacked digits and exit
169 rcall xputc ;
170 dec r31 ;
171 brne 6b ;/
172
173 ret
174.endfunc
175
176
177
178;---------------------------------------------------------------------------;
179; Formatted string output (16/32bit version)
180;
181;Prototype:
182; void __xprintf (const char *format_p, ...);
183; void __xsprintf(char*, const char *format_p, ...);
184; void __xfprintf(void(*func)(char), const char *format_p, ...);
185;
186
187#if USE_XPRINTF
188
189.func xvprintf
190xvprintf:
191 ld ZL, Y+ ;Z = pointer to format string
192 ld ZH, Y+ ;/
193
1940: _LPMI r24 ;Get a format char
195 cpi r24, 0 ;End of format string?
196 breq 90f ;/
197 cpi r24, '%' ;Is format?
198 breq 20f ;/
1991: rcall xputc ;Put a normal character
200 rjmp 0b ;/
20190: ret
202
20320: ldi r18, 0 ;r18: digits
204 clt ;T: filler
205 _LPMI r21 ;Get flags
206 cpi r21, '%' ;Is a %?
207 breq 1b ;/
208 cpi r21, '0' ;Zero filled?
209 brne 23f ;
210 set ;/
21122: _LPMI r21 ;Get width
21223: cpi r21, '9'+1 ;
213 brcc 24f ;
214 subi r21, '0' ;
215 brcs 90b ;
216 lsl r18 ;
217 mov r0, r18 ;
218 lsl r18 ;
219 lsl r18 ;
220 add r18, r0 ;
221 add r18, r21 ;
222 rjmp 22b ;/
223
22424: brtc 25f ;get value (low word)
225 neg r18 ;
22625: ld r24, Y+ ;
227 ld r25, Y+ ;/
228 cpi r21, 'c' ;Is type character?
229 breq 1b ;/
230 cpi r21, 's' ;Is type RAM string?
231 breq 50f ;/
232 cpi r21, 'S' ;Is type ROM string?
233 breq 60f ;/
234 _MOVW r23,r22,r25,r24 ;r25:r22 = value
235 clr r24 ;
236 clr r25 ;
237 clt ;/
238 cpi r21, 'l' ;Is long int?
239 brne 26f ;
240 ld r24, Y+ ;get value (high word)
241 ld r25, Y+ ;
242 set ;
243 _LPMI r21 ;/
24426: cpi r21, 'd' ;Is type signed decimal?
245 brne 27f ;/
246 ldi r20, -10 ;
247 brts 40f ;
248 sbrs r23, 7 ;
249 rjmp 40f ;
250 ldi r24, -1 ;
251 ldi r25, -1 ;
252 rjmp 40f ;/
25327: cpi r21, 'u' ;Is type unsigned decimal?
254 ldi r20, 10 ;
255 breq 40f ;/
256 cpi r21, 'X' ;Is type hexdecimal?
257 ldi r20, 16 ;
258 breq 40f ;/
259 cpi r21, 'b' ;Is type binary?
260 ldi r20, 2 ;
261 breq 40f ;/
262 ret ;abort
26340: push ZH ;Output the value
264 push ZL ;
265 rcall xitoa ;
26642: pop ZL ;
267 pop ZH ;
268 rjmp 0b ;/
269
27050: push ZH ;Put a string on the RAM
271 push ZL
272 _MOVW ZH,ZL, r25,r24
27351: ld r24, Z+
274 cpi r24, 0
275 breq 42b
276 rcall xputc
277 rjmp 51b
278
27960: push ZH ;Put a string on the ROM
280 push ZL
281 rcall xputs
282 rjmp 42b
283.endfunc
284
285
286.func __xprintf
287.global __xprintf
288__xprintf:
289 push YH
290 push YL
291 in YL, _SFR_IO_ADDR(SPL)
292#ifdef SPH
293 in YH, _SFR_IO_ADDR(SPH)
294#else
295 clr YH
296#endif
297 adiw YL, 5 ;Y = pointer to arguments
298 rcall xvprintf
299 pop YL
300 pop YH
301 ret
302.endfunc
303
304
305#if USE_XSPRINTF
306
307.func __xsprintf
308putram:
309 _MOVW ZH,ZL, r15,r14
310 st Z+, r24
311 _MOVW r15,r14, ZH,ZL
312 ret
313.global __xsprintf
314__xsprintf:
315 push YH
316 push YL
317 in YL, _SFR_IO_ADDR(SPL)
318#ifdef SPH
319 in YH, _SFR_IO_ADDR(SPH)
320#else
321 clr YH
322#endif
323 adiw YL, 5 ;Y = pointer to arguments
324 lds ZL, xfunc_out+0 ;Save registered output function
325 lds ZH, xfunc_out+1 ;
326 push ZL ;
327 push ZH ;/
328 ldi ZL, lo8(pm(putram));Set local output function
329 ldi ZH, hi8(pm(putram));
330 sts xfunc_out+0, ZL ;
331 sts xfunc_out+1, ZH ;/
332 push r15 ;Initialize pointer to string buffer
333 push r14 ;
334 ld r14, Y+ ;
335 ld r15, Y+ ;/
336 rcall xvprintf
337 _MOVW ZH,ZL, r15,r14 ;Terminate string
338 st Z, r1 ;
339 pop r14 ;
340 pop r15 ;/
341 pop ZH ;Restore registered output function
342 pop ZL ;
343 sts xfunc_out+0, ZL ;
344 sts xfunc_out+1, ZH ;/
345 pop YL
346 pop YH
347 ret
348.endfunc
349#endif
350
351
352#if USE_XFPRINTF
353.func __xfprintf
354.global __xfprintf
355__xfprintf:
356 push YH
357 push YL
358 in YL, _SFR_IO_ADDR(SPL)
359#ifdef SPH
360 in YH, _SFR_IO_ADDR(SPH)
361#else
362 clr YH
363#endif
364 adiw YL, 5 ;Y = pointer to arguments
365 lds ZL, xfunc_out+0 ;Save registered output function
366 lds ZH, xfunc_out+1 ;
367 push ZL ;
368 push ZH ;/
369 ld ZL, Y+ ;Set output function
370 ld ZH, Y+ ;
371 sts xfunc_out+0, ZL ;
372 sts xfunc_out+1, ZH ;/
373 rcall xvprintf
374 pop ZH ;Restore registered output function
375 pop ZL ;
376 sts xfunc_out+0, ZL ;
377 sts xfunc_out+1, ZH ;/
378 pop YL
379 pop YH
380 ret
381.endfunc
382#endif
383
384#endif
385
386
387
388;---------------------------------------------------------------------------
389; Extended numeral string input
390;
391;Prototype:
392; char xatoi ( /* 1: Successful, 0: Failed */
393; const char **str, /* pointer to pointer to source string */
394; long *res /* result */
395; );
396;
397
398
399#if USE_XATOI
400.func xatoi
401.global xatoi
402xatoi:
403 _MOVW r1, r0, r23, r22
404 _MOVW XH, XL, r25, r24
405 ld ZL, X+
406 ld ZH, X+
407 clr r18 ;r21:r18 = 0;
408 clr r19 ;
409 clr r20 ;
410 clr r21 ;/
411 clt ;T = 0;
412
413 ldi r25, 10 ;r25 = 10;
414 rjmp 41f ;/
41540: adiw ZL, 1 ;Z++;
41641: ld r22, Z ;r22 = *Z;
417 cpi r22, ' ' ;if(r22 == ' ') continue
418 breq 40b ;/
419 brcs 70f ;if(r22 < ' ') error;
420 cpi r22, '-' ;if(r22 == '-') {
421 brne 42f ; T = 1;
422 set ; continue;
423 rjmp 40b ;}
42442: cpi r22, '9'+1 ;if(r22 > '9') error;
425 brcc 70f ;/
426 cpi r22, '0' ;if(r22 < '0') error;
427 brcs 70f ;/
428 brne 51f ;if(r22 > '0') cv_start;
429 ldi r25, 8 ;r25 = 8;
430 adiw ZL, 1 ;r22 = *(++Z);
431 ld r22, Z ;/
432 cpi r22, ' '+1 ;if(r22 <= ' ') exit;
433 brcs 80f ;/
434 cpi r22, 'b' ;if(r22 == 'b') {
435 brne 43f ; r25 = 2;
436 ldi r25, 2 ; cv_start;
437 rjmp 50f ;}
43843: cpi r22, 'x' ;if(r22 != 'x') error;
439 brne 51f ;/
440 ldi r25, 16 ;r25 = 16;
441
44250: adiw ZL, 1 ;Z++;
443 ld r22, Z ;r22 = *Z;
44451: cpi r22, ' '+1 ;if(r22 <= ' ') break;
445 brcs 80f ;/
446 cpi r22, 'a' ;if(r22 >= 'a') r22 =- 0x20;
447 brcs 52f ;
448 subi r22, 0x20 ;/
44952: subi r22, '0' ;if((r22 -= '0') < 0) error;
450 brcs 70f ;/
451 cpi r22, 10 ;if(r22 >= 10) {
452 brcs 53f ; r22 -= 7;
453 subi r22, 7 ; if(r22 < 10)
454 cpi r22, 10 ;
455 brcs 70f ;}
45653: cp r22, r25 ;if(r22 >= r25) error;
457 brcc 70f ;/
45860: ldi r24, 33 ;r21:r18 *= r25;
459 sub r23, r23 ;
46061: brcc 62f ;
461 add r23, r25 ;
46262: lsr r23 ;
463 ror r21 ;
464 ror r20 ;
465 ror r19 ;
466 ror r18 ;
467 dec r24 ;
468 brne 61b ;/
469 add r18, r22 ;r21:r18 += r22;
470 adc r19, r24 ;
471 adc r20, r24 ;
472 adc r21, r24 ;/
473 rjmp 50b ;repeat
474
47570: ldi r24, 0
476 rjmp 81f
47780: ldi r24, 1
47881: brtc 82f
479 clr r22
480 com r18
481 com r19
482 com r20
483 com r21
484 adc r18, r22
485 adc r19, r22
486 adc r20, r22
487 adc r21, r22
48882: st -X, ZH
489 st -X, ZL
490 _MOVW XH, XL, r1, r0
491 st X+, r18
492 st X+, r19
493 st X+, r20
494 st X+, r21
495 clr r1
496 ret
497.endfunc
498#endif
499
500
diff --git a/tmk_core/common/avr/xprintf.h b/tmk_core/common/avr/xprintf.h
new file mode 100644
index 000000000..59c6f2531
--- /dev/null
+++ b/tmk_core/common/avr/xprintf.h
@@ -0,0 +1,111 @@
1/*---------------------------------------------------------------------------
2 Extended itoa, puts and printf (C)ChaN, 2011
3-----------------------------------------------------------------------------*/
4
5#ifndef XPRINTF_H
6#define XPRINTF_H
7
8#include <inttypes.h>
9#include <avr/pgmspace.h>
10
11#ifdef __cplusplus
12extern "C" {
13#endif
14
15extern void (*xfunc_out)(uint8_t);
16#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)
17
18/* This is a pointer to user defined output function. It must be initialized
19 before using this modle.
20*/
21
22void xputc(char chr);
23
24/* This is a stub function to forward outputs to user defined output function.
25 All outputs from this module are output via this function.
26*/
27
28
29/*-----------------------------------------------------------------------------*/
30void xputs(const char *string_p);
31
32/* The string placed in the ROM is forwarded to xputc() directly.
33*/
34
35
36/*-----------------------------------------------------------------------------*/
37void xitoa(long value, char radix, char width);
38
39/* Extended itoa().
40
41 value radix width output
42 100 10 6 " 100"
43 100 10 -6 "000100"
44 100 10 0 "100"
45 4294967295 10 0 "4294967295"
46 4294967295 -10 0 "-1"
47 655360 16 -8 "000A0000"
48 1024 16 0 "400"
49 0x55 2 -8 "01010101"
50*/
51
52
53/*-----------------------------------------------------------------------------*/
54#define xprintf(format, ...) __xprintf(PSTR(format), ##__VA_ARGS__)
55#define xsprintf(str, format, ...) __xsprintf(str, PSTR(format), ##__VA_ARGS__)
56#define xfprintf(func, format, ...) __xfprintf(func, PSTR(format), ##__VA_ARGS__)
57
58void __xprintf(const char *format_p, ...); /* Send formatted string to the registered device */
59void __xsprintf(char*, const char *format_p, ...); /* Put formatted string to the memory */
60void __xfprintf(void(*func)(uint8_t), const char *format_p, ...); /* Send formatted string to the specified device */
61
62/* Format string is placed in the ROM. The format flags is similar to printf().
63
64 %[flag][width][size]type
65
66 flag
67 A '0' means filled with '0' when output is shorter than width.
68 ' ' is used in default. This is effective only numeral type.
69 width
70 Minimum width in decimal number. This is effective only numeral type.
71 Default width is zero.
72 size
73 A 'l' means the argument is long(32bit). Default is short(16bit).
74 This is effective only numeral type.
75 type
76 'c' : Character, argument is the value
77 's' : String placed on the RAM, argument is the pointer
78 'S' : String placed on the ROM, argument is the pointer
79 'd' : Signed decimal, argument is the value
80 'u' : Unsigned decimal, argument is the value
81 'X' : Hexdecimal, argument is the value
82 'b' : Binary, argument is the value
83 '%' : '%'
84
85*/
86
87
88/*-----------------------------------------------------------------------------*/
89char xatoi(char **str, long *ret);
90
91/* Get value of the numeral string.
92
93 str
94 Pointer to pointer to source string
95
96 "0b11001010" binary
97 "0377" octal
98 "0xff800" hexdecimal
99 "1250000" decimal
100 "-25000" decimal
101
102 ret
103 Pointer to return value
104*/
105
106#ifdef __cplusplus
107}
108#endif
109
110#endif
111
diff --git a/tmk_core/common/backlight.c b/tmk_core/common/backlight.c
new file mode 100644
index 000000000..558ad9b01
--- /dev/null
+++ b/tmk_core/common/backlight.c
@@ -0,0 +1,85 @@
1/*
2Copyright 2013 Mathias Andersson <wraul@dbox.se>
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 "backlight.h"
19#include "eeconfig.h"
20#include "debug.h"
21
22backlight_config_t backlight_config;
23
24void backlight_init(void)
25{
26 /* check signature */
27 if (!eeconfig_is_enabled()) {
28 eeconfig_init();
29 }
30 backlight_config.raw = eeconfig_read_backlight();
31 backlight_set(backlight_config.enable ? backlight_config.level : 0);
32}
33
34void backlight_increase(void)
35{
36 if(backlight_config.level < BACKLIGHT_LEVELS)
37 {
38 backlight_config.level++;
39 backlight_config.enable = 1;
40 eeconfig_write_backlight(backlight_config.raw);
41 }
42 dprintf("backlight increase: %u\n", backlight_config.level);
43 backlight_set(backlight_config.level);
44}
45
46void backlight_decrease(void)
47{
48 if(backlight_config.level > 0)
49 {
50 backlight_config.level--;
51 backlight_config.enable = !!backlight_config.level;
52 eeconfig_write_backlight(backlight_config.raw);
53 }
54 dprintf("backlight decrease: %u\n", backlight_config.level);
55 backlight_set(backlight_config.level);
56}
57
58void backlight_toggle(void)
59{
60 backlight_config.enable ^= 1;
61 eeconfig_write_backlight(backlight_config.raw);
62 dprintf("backlight toggle: %u\n", backlight_config.enable);
63 backlight_set(backlight_config.enable ? backlight_config.level : 0);
64}
65
66void backlight_step(void)
67{
68 backlight_config.level++;
69 if(backlight_config.level > BACKLIGHT_LEVELS)
70 {
71 backlight_config.level = 0;
72 }
73 backlight_config.enable = !!backlight_config.level;
74 eeconfig_write_backlight(backlight_config.raw);
75 dprintf("backlight step: %u\n", backlight_config.level);
76 backlight_set(backlight_config.level);
77}
78
79void backlight_level(uint8_t level)
80{
81 backlight_config.level ^= level;
82 backlight_config.enable = !!backlight_config.level;
83 eeconfig_write_backlight(backlight_config.raw);
84 backlight_set(backlight_config.level);
85}
diff --git a/tmk_core/common/backlight.h b/tmk_core/common/backlight.h
new file mode 100644
index 000000000..525ec8bbe
--- /dev/null
+++ b/tmk_core/common/backlight.h
@@ -0,0 +1,40 @@
1/*
2Copyright 2013 Mathias Andersson <wraul@dbox.se>
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#ifndef BACKLIGHT_H
19#define BACKLIGHT_H
20
21#include <stdint.h>
22#include <stdbool.h>
23
24typedef union {
25 uint8_t raw;
26 struct {
27 bool enable :1;
28 uint8_t level :7;
29 };
30} backlight_config_t;
31
32void backlight_init(void);
33void backlight_increase(void);
34void backlight_decrease(void);
35void backlight_toggle(void);
36void backlight_step(void);
37void backlight_set(uint8_t level);
38void backlight_level(uint8_t level);
39
40#endif
diff --git a/tmk_core/common/bootloader.h b/tmk_core/common/bootloader.h
new file mode 100644
index 000000000..44775039d
--- /dev/null
+++ b/tmk_core/common/bootloader.h
@@ -0,0 +1,25 @@
1/*
2Copyright 2011 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#ifndef BOOTLOADER_H
19#define BOOTLOADER_H
20
21
22/* give code for your bootloader to come up if needed */
23void bootloader_jump(void);
24
25#endif
diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c
new file mode 100644
index 000000000..b002a5856
--- /dev/null
+++ b/tmk_core/common/bootmagic.c
@@ -0,0 +1,128 @@
1#include <stdint.h>
2#include <stdbool.h>
3#include <util/delay.h>
4#include "matrix.h"
5#include "bootloader.h"
6#include "debug.h"
7#include "keymap.h"
8#include "host.h"
9#include "action_layer.h"
10#include "eeconfig.h"
11#include "bootmagic.h"
12
13
14void bootmagic(void)
15{
16 /* check signature */
17 if (!eeconfig_is_enabled()) {
18 eeconfig_init();
19 }
20
21 /* do scans in case of bounce */
22 print("boogmagic scan: ... ");
23 uint8_t scan = 100;
24 while (scan--) { matrix_scan(); _delay_ms(10); }
25 print("done.\n");
26
27 /* bootmagic skip */
28 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) {
29 return;
30 }
31
32 /* eeconfig clear */
33 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) {
34 eeconfig_init();
35 }
36
37 /* bootloader */
38 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) {
39 bootloader_jump();
40 }
41
42 /* debug enable */
43 debug_config.raw = eeconfig_read_debug();
44 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) {
45 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) {
46 debug_config.matrix = !debug_config.matrix;
47 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) {
48 debug_config.keyboard = !debug_config.keyboard;
49 } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) {
50 debug_config.mouse = !debug_config.mouse;
51 } else {
52 debug_config.enable = !debug_config.enable;
53 }
54 }
55 eeconfig_write_debug(debug_config.raw);
56
57 /* keymap config */
58 keymap_config.raw = eeconfig_read_keymap();
59 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) {
60 keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
61 }
62 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) {
63 keymap_config.capslock_to_control = !keymap_config.capslock_to_control;
64 }
65 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) {
66 keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
67 }
68 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) {
69 keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
70 }
71 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) {
72 keymap_config.no_gui = !keymap_config.no_gui;
73 }
74 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) {
75 keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc;
76 }
77 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) {
78 keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace;
79 }
80 if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) {
81 keymap_config.nkro = !keymap_config.nkro;
82 }
83 eeconfig_write_keymap(keymap_config.raw);
84
85#ifdef NKRO_ENABLE
86 keyboard_nkro = keymap_config.nkro;
87#endif
88
89 /* default layer */
90 uint8_t default_layer = 0;
91 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { default_layer |= (1<<0); }
92 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { default_layer |= (1<<1); }
93 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { default_layer |= (1<<2); }
94 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { default_layer |= (1<<3); }
95 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { default_layer |= (1<<4); }
96 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { default_layer |= (1<<5); }
97 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { default_layer |= (1<<6); }
98 if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { default_layer |= (1<<7); }
99 if (default_layer) {
100 eeconfig_write_default_layer(default_layer);
101 default_layer_set((uint32_t)default_layer);
102 } else {
103 default_layer = eeconfig_read_default_layer();
104 default_layer_set((uint32_t)default_layer);
105 }
106}
107
108static bool scan_keycode(uint8_t keycode)
109{
110 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
111 matrix_row_t matrix_row = matrix_get_row(r);
112 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
113 if (matrix_row & ((matrix_row_t)1<<c)) {
114 if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) {
115 return true;
116 }
117 }
118 }
119 }
120 return false;
121}
122
123bool bootmagic_scan_keycode(uint8_t keycode)
124{
125 if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false;
126
127 return scan_keycode(keycode);
128}
diff --git a/tmk_core/common/bootmagic.h b/tmk_core/common/bootmagic.h
new file mode 100644
index 000000000..8f6618f4b
--- /dev/null
+++ b/tmk_core/common/bootmagic.h
@@ -0,0 +1,100 @@
1#ifndef BOOTMAGIC_H
2#define BOOTMAGIC_H
3
4
5/* bootmagic salt key */
6#ifndef BOOTMAGIC_KEY_SALT
7#define BOOTMAGIC_KEY_SALT KC_SPACE
8#endif
9
10/* skip bootmagic and eeconfig */
11#ifndef BOOTMAGIC_KEY_SKIP
12#define BOOTMAGIC_KEY_SKIP KC_ESC
13#endif
14
15/* eeprom clear */
16#ifndef BOOTMAGIC_KEY_EEPROM_CLEAR
17#define BOOTMAGIC_KEY_EEPROM_CLEAR KC_BSPACE
18#endif
19
20/* kick up bootloader */
21#ifndef BOOTMAGIC_KEY_BOOTLOADER
22#define BOOTMAGIC_KEY_BOOTLOADER KC_B
23#endif
24
25/* debug enable */
26#ifndef BOOTMAGIC_KEY_DEBUG_ENABLE
27#define BOOTMAGIC_KEY_DEBUG_ENABLE KC_D
28#endif
29#ifndef BOOTMAGIC_KEY_DEBUG_MATRIX
30#define BOOTMAGIC_KEY_DEBUG_MATRIX KC_X
31#endif
32#ifndef BOOTMAGIC_KEY_DEBUG_KEYBOARD
33#define BOOTMAGIC_KEY_DEBUG_KEYBOARD KC_K
34#endif
35#ifndef BOOTMAGIC_KEY_DEBUG_MOUSE
36#define BOOTMAGIC_KEY_DEBUG_MOUSE KC_M
37#endif
38
39/*
40 * keymap config
41 */
42#ifndef BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK
43#define BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK KC_LCTRL
44#endif
45#ifndef BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL
46#define BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL KC_CAPSLOCK
47#endif
48#ifndef BOOTMAGIC_KEY_SWAP_LALT_LGUI
49#define BOOTMAGIC_KEY_SWAP_LALT_LGUI KC_LALT
50#endif
51#ifndef BOOTMAGIC_KEY_SWAP_RALT_RGUI
52#define BOOTMAGIC_KEY_SWAP_RALT_RGUI KC_RALT
53#endif
54#ifndef BOOTMAGIC_KEY_NO_GUI
55#define BOOTMAGIC_KEY_NO_GUI KC_LGUI
56#endif
57#ifndef BOOTMAGIC_KEY_SWAP_GRAVE_ESC
58#define BOOTMAGIC_KEY_SWAP_GRAVE_ESC KC_GRAVE
59#endif
60#ifndef BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE
61#define BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE KC_BSLASH
62#endif
63#ifndef BOOTMAGIC_HOST_NKRO
64#define BOOTMAGIC_HOST_NKRO KC_N
65#endif
66
67
68/*
69 * change default layer
70 */
71#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_0
72#define BOOTMAGIC_KEY_DEFAULT_LAYER_0 KC_0
73#endif
74#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_1
75#define BOOTMAGIC_KEY_DEFAULT_LAYER_1 KC_1
76#endif
77#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_2
78#define BOOTMAGIC_KEY_DEFAULT_LAYER_2 KC_2
79#endif
80#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_3
81#define BOOTMAGIC_KEY_DEFAULT_LAYER_3 KC_3
82#endif
83#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_4
84#define BOOTMAGIC_KEY_DEFAULT_LAYER_4 KC_4
85#endif
86#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_5
87#define BOOTMAGIC_KEY_DEFAULT_LAYER_5 KC_5
88#endif
89#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_6
90#define BOOTMAGIC_KEY_DEFAULT_LAYER_6 KC_6
91#endif
92#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7
93#define BOOTMAGIC_KEY_DEFAULT_LAYER_7 KC_7
94#endif
95
96
97void bootmagic(void);
98bool bootmagic_scan_keycode(uint8_t keycode);
99
100#endif
diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c
new file mode 100644
index 000000000..fbaa9f2d7
--- /dev/null
+++ b/tmk_core/common/command.c
@@ -0,0 +1,644 @@
1/*
2Copyright 2011 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#include <stdint.h>
18#include <stdbool.h>
19#include <util/delay.h>
20#include "keycode.h"
21#include "host.h"
22#include "keymap.h"
23#include "print.h"
24#include "debug.h"
25#include "util.h"
26#include "timer.h"
27#include "keyboard.h"
28#include "bootloader.h"
29#include "action_layer.h"
30#include "action_util.h"
31#include "eeconfig.h"
32#include "sleep_led.h"
33#include "led.h"
34#include "command.h"
35#include "backlight.h"
36
37#ifdef MOUSEKEY_ENABLE
38#include "mousekey.h"
39#endif
40
41#ifdef PROTOCOL_PJRC
42# include "usb_keyboard.h"
43# ifdef EXTRAKEY_ENABLE
44# include "usb_extra.h"
45# endif
46#endif
47
48#ifdef PROTOCOL_VUSB
49# include "usbdrv.h"
50#endif
51
52
53static bool command_common(uint8_t code);
54static void command_common_help(void);
55static bool command_console(uint8_t code);
56static void command_console_help(void);
57#ifdef MOUSEKEY_ENABLE
58static bool mousekey_console(uint8_t code);
59static void mousekey_console_help(void);
60#endif
61
62static uint8_t numkey2num(uint8_t code);
63static void switch_default_layer(uint8_t layer);
64
65
66command_state_t command_state = ONESHOT;
67
68
69bool command_proc(uint8_t code)
70{
71 switch (command_state) {
72 case ONESHOT:
73 if (!IS_COMMAND())
74 return false;
75 return (command_extra(code) || command_common(code));
76 break;
77 case CONSOLE:
78 if (IS_COMMAND())
79 return (command_extra(code) || command_common(code));
80 else
81 return (command_console_extra(code) || command_console(code));
82 break;
83#ifdef MOUSEKEY_ENABLE
84 case MOUSEKEY:
85 mousekey_console(code);
86 break;
87#endif
88 default:
89 command_state = ONESHOT;
90 return false;
91 }
92 return true;
93}
94
95/* TODO: Refactoring is needed. */
96/* This allows to define extra commands. return false when not processed. */
97bool command_extra(uint8_t code) __attribute__ ((weak));
98bool command_extra(uint8_t code)
99{
100 return false;
101}
102
103bool command_console_extra(uint8_t code) __attribute__ ((weak));
104bool command_console_extra(uint8_t code)
105{
106 return false;
107}
108
109
110/***********************************************************
111 * Command common
112 ***********************************************************/
113static void command_common_help(void)
114{
115 print("\n\n----- Command Help -----\n");
116 print("c: enter console mode\n");
117 print("d: toggle debug enable\n");
118 print("x: toggle matrix debug\n");
119 print("k: toggle keyboard debug\n");
120 print("m: toggle mouse debug\n");
121#ifdef SLEEP_LED_ENABLE
122 print("z: toggle sleep LED test\n");
123#endif
124 print("v: print device version & info\n");
125 print("t: print timer count\n");
126 print("s: print status\n");
127 print("e: print eeprom config\n");
128#ifdef NKRO_ENABLE
129 print("n: toggle NKRO\n");
130#endif
131 print("0/F10: switch to Layer0 \n");
132 print("1/F1: switch to Layer1 \n");
133 print("2/F2: switch to Layer2 \n");
134 print("3/F3: switch to Layer3 \n");
135 print("4/F4: switch to Layer4 \n");
136 print("PScr: power down/remote wake-up\n");
137 print("Caps: Lock Keyboard(Child Proof)\n");
138 print("Paus: jump to bootloader\n");
139}
140
141#ifdef BOOTMAGIC_ENABLE
142static void print_eeconfig(void)
143{
144 print("default_layer: "); print_dec(eeconfig_read_default_layer()); print("\n");
145
146 debug_config_t dc;
147 dc.raw = eeconfig_read_debug();
148 print("debug_config.raw: "); print_hex8(dc.raw); print("\n");
149 print(".enable: "); print_dec(dc.enable); print("\n");
150 print(".matrix: "); print_dec(dc.matrix); print("\n");
151 print(".keyboard: "); print_dec(dc.keyboard); print("\n");
152 print(".mouse: "); print_dec(dc.mouse); print("\n");
153
154 keymap_config_t kc;
155 kc.raw = eeconfig_read_keymap();
156 print("keymap_config.raw: "); print_hex8(kc.raw); print("\n");
157 print(".swap_control_capslock: "); print_dec(kc.swap_control_capslock); print("\n");
158 print(".capslock_to_control: "); print_dec(kc.capslock_to_control); print("\n");
159 print(".swap_lalt_lgui: "); print_dec(kc.swap_lalt_lgui); print("\n");
160 print(".swap_ralt_rgui: "); print_dec(kc.swap_ralt_rgui); print("\n");
161 print(".no_gui: "); print_dec(kc.no_gui); print("\n");
162 print(".swap_grave_esc: "); print_dec(kc.swap_grave_esc); print("\n");
163 print(".swap_backslash_backspace: "); print_dec(kc.swap_backslash_backspace); print("\n");
164 print(".nkro: "); print_dec(kc.nkro); print("\n");
165
166#ifdef BACKLIGHT_ENABLE
167 backlight_config_t bc;
168 bc.raw = eeconfig_read_backlight();
169 print("backlight_config.raw: "); print_hex8(bc.raw); print("\n");
170 print(".enable: "); print_dec(bc.enable); print("\n");
171 print(".level: "); print_dec(bc.level); print("\n");
172#endif
173}
174#endif
175
176static bool command_common(uint8_t code)
177{
178 static host_driver_t *host_driver = 0;
179 switch (code) {
180#ifdef SLEEP_LED_ENABLE
181 case KC_Z:
182 // test breathing sleep LED
183 print("Sleep LED test\n");
184 sleep_led_toggle();
185 led_set(host_keyboard_leds());
186 break;
187#endif
188#ifdef BOOTMAGIC_ENABLE
189 case KC_E:
190 print("eeconfig:\n");
191 print_eeconfig();
192 break;
193#endif
194 case KC_CAPSLOCK:
195 if (host_get_driver()) {
196 host_driver = host_get_driver();
197 clear_keyboard();
198 host_set_driver(0);
199 print("Locked.\n");
200 } else {
201 host_set_driver(host_driver);
202 print("Unlocked.\n");
203 }
204 break;
205 case KC_H:
206 case KC_SLASH: /* ? */
207 command_common_help();
208 break;
209 case KC_C:
210 debug_matrix = false;
211 debug_keyboard = false;
212 debug_mouse = false;
213 debug_enable = false;
214 command_console_help();
215 print("\nEnter Console Mode\n");
216 print("C> ");
217 command_state = CONSOLE;
218 break;
219 case KC_PAUSE:
220 clear_keyboard();
221 print("\n\nJump to bootloader... ");
222 _delay_ms(1000);
223 bootloader_jump(); // not return
224 print("not supported.\n");
225 break;
226 case KC_D:
227 if (debug_enable) {
228 print("\nDEBUG: disabled.\n");
229 debug_matrix = false;
230 debug_keyboard = false;
231 debug_mouse = false;
232 debug_enable = false;
233 } else {
234 print("\nDEBUG: enabled.\n");
235 debug_enable = true;
236 }
237 break;
238 case KC_X: // debug matrix toggle
239 debug_matrix = !debug_matrix;
240 if (debug_matrix) {
241 print("\nDEBUG: matrix enabled.\n");
242 debug_enable = true;
243 } else {
244 print("\nDEBUG: matrix disabled.\n");
245 }
246 break;
247 case KC_K: // debug keyboard toggle
248 debug_keyboard = !debug_keyboard;
249 if (debug_keyboard) {
250 print("\nDEBUG: keyboard enabled.\n");
251 debug_enable = true;
252 } else {
253 print("\nDEBUG: keyboard disabled.\n");
254 }
255 break;
256 case KC_M: // debug mouse toggle
257 debug_mouse = !debug_mouse;
258 if (debug_mouse) {
259 print("\nDEBUG: mouse enabled.\n");
260 debug_enable = true;
261 } else {
262 print("\nDEBUG: mouse disabled.\n");
263 }
264 break;
265 case KC_V: // print version & information
266 print("\n\n----- Version -----\n");
267 print("DESC: " STR(DESCRIPTION) "\n");
268 print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
269 "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
270 "VER: " STR(DEVICE_VER) "\n");
271 print("BUILD: " STR(VERSION) " (" __TIME__ " " __DATE__ ")\n");
272 /* build options */
273 print("OPTIONS:"
274#ifdef PROTOCOL_PJRC
275 " PJRC"
276#endif
277#ifdef PROTOCOL_LUFA
278 " LUFA"
279#endif
280#ifdef PROTOCOL_VUSB
281 " VUSB"
282#endif
283#ifdef BOOTMAGIC_ENABLE
284 " BOOTMAGIC"
285#endif
286#ifdef MOUSEKEY_ENABLE
287 " MOUSEKEY"
288#endif
289#ifdef EXTRAKEY_ENABLE
290 " EXTRAKEY"
291#endif
292#ifdef CONSOLE_ENABLE
293 " CONSOLE"
294#endif
295#ifdef COMMAND_ENABLE
296 " COMMAND"
297#endif
298#ifdef NKRO_ENABLE
299 " NKRO"
300#endif
301#ifdef KEYMAP_SECTION_ENABLE
302 " KEYMAP_SECTION"
303#endif
304 " " STR(BOOTLOADER_SIZE) "\n");
305
306 print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
307 " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
308 " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n");
309 break;
310 case KC_T: // print timer
311 print_val_hex32(timer_count);
312 break;
313 case KC_S:
314 print("\n\n----- Status -----\n");
315 print_val_hex8(host_keyboard_leds());
316 print_val_hex8(keyboard_protocol);
317 print_val_hex8(keyboard_idle);
318#ifdef PROTOCOL_PJRC
319 print_val_hex8(UDCON);
320 print_val_hex8(UDIEN);
321 print_val_hex8(UDINT);
322 print_val_hex8(usb_keyboard_leds);
323 print_val_hex8(usb_keyboard_idle_count);
324#endif
325
326#ifdef PROTOCOL_PJRC
327# if USB_COUNT_SOF
328 print_val_hex8(usbSofCount);
329# endif
330#endif
331 break;
332#ifdef NKRO_ENABLE
333 case KC_N:
334 clear_keyboard(); //Prevents stuck keys.
335 keyboard_nkro = !keyboard_nkro;
336 if (keyboard_nkro)
337 print("NKRO: enabled\n");
338 else
339 print("NKRO: disabled\n");
340 break;
341#endif
342#ifdef EXTRAKEY_ENABLE
343 case KC_PSCREEN:
344 // TODO: Power key should take this feature? otherwise any key during suspend.
345#ifdef PROTOCOL_PJRC
346 if (suspend && remote_wakeup) {
347 usb_remote_wakeup();
348 } else {
349 host_system_send(SYSTEM_POWER_DOWN);
350 host_system_send(0);
351 _delay_ms(500);
352 }
353#else
354 host_system_send(SYSTEM_POWER_DOWN);
355 _delay_ms(100);
356 host_system_send(0);
357 _delay_ms(500);
358#endif
359 break;
360#endif
361 case KC_ESC:
362 case KC_GRV:
363 case KC_0:
364 switch_default_layer(0);
365 break;
366 case KC_1 ... KC_9:
367 switch_default_layer((code - KC_1) + 1);
368 break;
369 case KC_F1 ... KC_F12:
370 switch_default_layer((code - KC_F1) + 1);
371 break;
372 default:
373 print("?");
374 return false;
375 }
376 return true;
377}
378
379
380/***********************************************************
381 * Command console
382 ***********************************************************/
383static void command_console_help(void)
384{
385 print("\n\n----- Console Help -----\n");
386 print("ESC/q: quit\n");
387#ifdef MOUSEKEY_ENABLE
388 print("m: mousekey\n");
389#endif
390}
391
392static bool command_console(uint8_t code)
393{
394 switch (code) {
395 case KC_H:
396 case KC_SLASH: /* ? */
397 command_console_help();
398 break;
399 case KC_Q:
400 case KC_ESC:
401 print("\nQuit Console Mode\n");
402 command_state = ONESHOT;
403 return false;
404#ifdef MOUSEKEY_ENABLE
405 case KC_M:
406 mousekey_console_help();
407 print("\nEnter Mousekey Console\n");
408 print("M0>");
409 command_state = MOUSEKEY;
410 return true;
411#endif
412 default:
413 print("?");
414 return false;
415 }
416 print("C> ");
417 return true;
418}
419
420
421#ifdef MOUSEKEY_ENABLE
422/***********************************************************
423 * Mousekey console
424 ***********************************************************/
425static uint8_t mousekey_param = 0;
426
427static void mousekey_param_print(void)
428{
429 print("\n\n----- Mousekey Parameters -----\n");
430 print("1: mk_delay(*10ms): "); pdec(mk_delay); print("\n");
431 print("2: mk_interval(ms): "); pdec(mk_interval); print("\n");
432 print("3: mk_max_speed: "); pdec(mk_max_speed); print("\n");
433 print("4: mk_time_to_max: "); pdec(mk_time_to_max); print("\n");
434 print("5: mk_wheel_max_speed: "); pdec(mk_wheel_max_speed); print("\n");
435 print("6: mk_wheel_time_to_max: "); pdec(mk_wheel_time_to_max); print("\n");
436}
437
438#define PRINT_SET_VAL(v) print(#v " = "); print_dec(v); print("\n");
439static void mousekey_param_inc(uint8_t param, uint8_t inc)
440{
441 switch (param) {
442 case 1:
443 if (mk_delay + inc < UINT8_MAX)
444 mk_delay += inc;
445 else
446 mk_delay = UINT8_MAX;
447 PRINT_SET_VAL(mk_delay);
448 break;
449 case 2:
450 if (mk_interval + inc < UINT8_MAX)
451 mk_interval += inc;
452 else
453 mk_interval = UINT8_MAX;
454 PRINT_SET_VAL(mk_interval);
455 break;
456 case 3:
457 if (mk_max_speed + inc < UINT8_MAX)
458 mk_max_speed += inc;
459 else
460 mk_max_speed = UINT8_MAX;
461 PRINT_SET_VAL(mk_max_speed);
462 break;
463 case 4:
464 if (mk_time_to_max + inc < UINT8_MAX)
465 mk_time_to_max += inc;
466 else
467 mk_time_to_max = UINT8_MAX;
468 PRINT_SET_VAL(mk_time_to_max);
469 break;
470 case 5:
471 if (mk_wheel_max_speed + inc < UINT8_MAX)
472 mk_wheel_max_speed += inc;
473 else
474 mk_wheel_max_speed = UINT8_MAX;
475 PRINT_SET_VAL(mk_wheel_max_speed);
476 break;
477 case 6:
478 if (mk_wheel_time_to_max + inc < UINT8_MAX)
479 mk_wheel_time_to_max += inc;
480 else
481 mk_wheel_time_to_max = UINT8_MAX;
482 PRINT_SET_VAL(mk_wheel_time_to_max);
483 break;
484 }
485}
486
487static void mousekey_param_dec(uint8_t param, uint8_t dec)
488{
489 switch (param) {
490 case 1:
491 if (mk_delay > dec)
492 mk_delay -= dec;
493 else
494 mk_delay = 0;
495 PRINT_SET_VAL(mk_delay);
496 break;
497 case 2:
498 if (mk_interval > dec)
499 mk_interval -= dec;
500 else
501 mk_interval = 0;
502 PRINT_SET_VAL(mk_interval);
503 break;
504 case 3:
505 if (mk_max_speed > dec)
506 mk_max_speed -= dec;
507 else
508 mk_max_speed = 0;
509 PRINT_SET_VAL(mk_max_speed);
510 break;
511 case 4:
512 if (mk_time_to_max > dec)
513 mk_time_to_max -= dec;
514 else
515 mk_time_to_max = 0;
516 PRINT_SET_VAL(mk_time_to_max);
517 break;
518 case 5:
519 if (mk_wheel_max_speed > dec)
520 mk_wheel_max_speed -= dec;
521 else
522 mk_wheel_max_speed = 0;
523 PRINT_SET_VAL(mk_wheel_max_speed);
524 break;
525 case 6:
526 if (mk_wheel_time_to_max > dec)
527 mk_wheel_time_to_max -= dec;
528 else
529 mk_wheel_time_to_max = 0;
530 PRINT_SET_VAL(mk_wheel_time_to_max);
531 break;
532 }
533}
534
535static void mousekey_console_help(void)
536{
537 print("\n\n----- Mousekey Parameters Help -----\n");
538 print("ESC/q: quit\n");
539 print("1: select mk_delay(*10ms)\n");
540 print("2: select mk_interval(ms)\n");
541 print("3: select mk_max_speed\n");
542 print("4: select mk_time_to_max\n");
543 print("5: select mk_wheel_max_speed\n");
544 print("6: select mk_wheel_time_to_max\n");
545 print("p: print parameters\n");
546 print("d: set default values\n");
547 print("up: increase parameters(+1)\n");
548 print("down: decrease parameters(-1)\n");
549 print("pgup: increase parameters(+10)\n");
550 print("pgdown: decrease parameters(-10)\n");
551 print("\nspeed = delta * max_speed * (repeat / time_to_max)\n");
552 print("where delta: cursor="); pdec(MOUSEKEY_MOVE_DELTA);
553 print(", wheel="); pdec(MOUSEKEY_WHEEL_DELTA); print("\n");
554 print("See http://en.wikipedia.org/wiki/Mouse_keys\n");
555}
556
557static bool mousekey_console(uint8_t code)
558{
559 switch (code) {
560 case KC_H:
561 case KC_SLASH: /* ? */
562 mousekey_console_help();
563 break;
564 case KC_Q:
565 case KC_ESC:
566 mousekey_param = 0;
567 print("\nQuit Mousekey Console\n");
568 print("C> ");
569 command_state = CONSOLE;
570 return false;
571 case KC_P:
572 mousekey_param_print();
573 break;
574 case KC_1:
575 case KC_2:
576 case KC_3:
577 case KC_4:
578 case KC_5:
579 case KC_6:
580 case KC_7:
581 case KC_8:
582 case KC_9:
583 case KC_0:
584 mousekey_param = numkey2num(code);
585 print("selected parameter: "); pdec(mousekey_param); print("\n");
586 break;
587 case KC_UP:
588 mousekey_param_inc(mousekey_param, 1);
589 break;
590 case KC_DOWN:
591 mousekey_param_dec(mousekey_param, 1);
592 break;
593 case KC_PGUP:
594 mousekey_param_inc(mousekey_param, 10);
595 break;
596 case KC_PGDN:
597 mousekey_param_dec(mousekey_param, 10);
598 break;
599 case KC_D:
600 mk_delay = MOUSEKEY_DELAY/10;
601 mk_interval = MOUSEKEY_INTERVAL;
602 mk_max_speed = MOUSEKEY_MAX_SPEED;
603 mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
604 mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
605 mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
606 print("set default values.\n");
607 break;
608 default:
609 print("?");
610 return false;
611 }
612 print("M"); pdec(mousekey_param); print("> ");
613 return true;
614}
615#endif
616
617
618/***********************************************************
619 * Utilities
620 ***********************************************************/
621static uint8_t numkey2num(uint8_t code)
622{
623 switch (code) {
624 case KC_1: return 1;
625 case KC_2: return 2;
626 case KC_3: return 3;
627 case KC_4: return 4;
628 case KC_5: return 5;
629 case KC_6: return 6;
630 case KC_7: return 7;
631 case KC_8: return 8;
632 case KC_9: return 9;
633 case KC_0: return 0;
634 }
635 return 0;
636}
637
638static void switch_default_layer(uint8_t layer)
639{
640 print("switch_default_layer: "); print_dec(biton32(default_layer_state));
641 print(" to "); print_dec(layer); print("\n");
642 default_layer_set(1UL<<layer);
643 clear_keyboard();
644}
diff --git a/tmk_core/common/command.h b/tmk_core/common/command.h
new file mode 100644
index 000000000..b57a6c1ce
--- /dev/null
+++ b/tmk_core/common/command.h
@@ -0,0 +1,35 @@
1/*
2Copyright 2011 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#ifndef COMMAND_H
19#define COMMAND
20
21/* TODO: Refactoring */
22typedef enum { ONESHOT, CONSOLE, MOUSEKEY } command_state_t;
23extern command_state_t command_state;
24
25/* This allows to extend commands. Return false when command is not processed. */
26bool command_extra(uint8_t code);
27bool command_console_extra(uint8_t code);
28
29#ifdef COMMAND_ENABLE
30bool command_proc(uint8_t code);
31#else
32#define command_proc(code) false
33#endif
34
35#endif
diff --git a/tmk_core/common/debug.c b/tmk_core/common/debug.c
new file mode 100644
index 000000000..18613fc28
--- /dev/null
+++ b/tmk_core/common/debug.c
@@ -0,0 +1,24 @@
1#include <stdbool.h>
2#include "debug.h"
3
4#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
5
6debug_config_t debug_config = {
7/* GCC Bug 10676 - Using unnamed fields in initializers
8 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676 */
9#if GCC_VERSION >= 40600
10 .enable = false,
11 .matrix = false,
12 .keyboard = false,
13 .mouse = false,
14 .reserved = 0
15#else
16 {
17 false, // .enable
18 false, // .matrix
19 false, // .keyboard
20 false, // .mouse
21 0 // .reserved
22 }
23#endif
24};
diff --git a/tmk_core/common/debug.h b/tmk_core/common/debug.h
new file mode 100644
index 000000000..3cbe2092d
--- /dev/null
+++ b/tmk_core/common/debug.h
@@ -0,0 +1,117 @@
1/*
2Copyright 2011 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#ifndef DEBUG_H
19#define DEBUG_H 1
20
21#include <stdbool.h>
22#include "print.h"
23
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29/*
30 * Debug output control
31 */
32typedef union {
33 struct {
34 bool enable:1;
35 bool matrix:1;
36 bool keyboard:1;
37 bool mouse:1;
38 uint8_t reserved:4;
39 };
40 uint8_t raw;
41} debug_config_t;
42
43extern debug_config_t debug_config;
44
45#ifdef __cplusplus
46}
47#endif
48
49/* for backward compatibility */
50#define debug_enable (debug_config.enable)
51#define debug_matrix (debug_config.matrix)
52#define debug_keyboard (debug_config.keyboard)
53#define debug_mouse (debug_config.mouse)
54
55
56/*
57 * Debug print utils
58 */
59#ifndef NO_DEBUG
60
61#define dprint(s) do { if (debug_enable) print(s); } while (0)
62#define dprintln(s) do { if (debug_enable) println(s); } while (0)
63#define dprintf(fmt, ...) do { if (debug_enable) xprintf(fmt, ##__VA_ARGS__); } while (0)
64#define dmsg(s) dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s))
65
66/* Deprecated. DO NOT USE these anymore, use dprintf instead. */
67#define debug(s) do { if (debug_enable) print(s); } while (0)
68#define debugln(s) do { if (debug_enable) println(s); } while (0)
69#define debug_msg(s) do { \
70 if (debug_enable) { \
71 print(__FILE__); print(" at "); print_dec(__LINE__); print(" in "); print(": "); print(s); \
72 } \
73} while (0)
74#define debug_dec(data) do { if (debug_enable) print_dec(data); } while (0)
75#define debug_decs(data) do { if (debug_enable) print_decs(data); } while (0)
76#define debug_hex4(data) do { if (debug_enable) print_hex4(data); } while (0)
77#define debug_hex8(data) do { if (debug_enable) print_hex8(data); } while (0)
78#define debug_hex16(data) do { if (debug_enable) print_hex16(data); } while (0)
79#define debug_hex32(data) do { if (debug_enable) print_hex32(data); } while (0)
80#define debug_bin8(data) do { if (debug_enable) print_bin8(data); } while (0)
81#define debug_bin16(data) do { if (debug_enable) print_bin16(data); } while (0)
82#define debug_bin32(data) do { if (debug_enable) print_bin32(data); } while (0)
83#define debug_bin_reverse8(data) do { if (debug_enable) print_bin_reverse8(data); } while (0)
84#define debug_bin_reverse16(data) do { if (debug_enable) print_bin_reverse16(data); } while (0)
85#define debug_bin_reverse32(data) do { if (debug_enable) print_bin_reverse32(data); } while (0)
86#define debug_hex(data) debug_hex8(data)
87#define debug_bin(data) debug_bin8(data)
88#define debug_bin_reverse(data) debug_bin8(data)
89
90#else /* NO_DEBUG */
91
92#define dprint(s)
93#define dprintln(s)
94#define dprintf(fmt, ...)
95#define dmsg(s)
96#define debug(s)
97#define debugln(s)
98#define debug_msg(s)
99#define debug_dec(data)
100#define debug_decs(data)
101#define debug_hex4(data)
102#define debug_hex8(data)
103#define debug_hex16(data)
104#define debug_hex32(data)
105#define debug_bin8(data)
106#define debug_bin16(data)
107#define debug_bin32(data)
108#define debug_bin_reverse8(data)
109#define debug_bin_reverse16(data)
110#define debug_bin_reverse32(data)
111#define debug_hex(data)
112#define debug_bin(data)
113#define debug_bin_reverse(data)
114
115#endif /* NO_DEBUG */
116
117#endif
diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h
new file mode 100644
index 000000000..3cd1a174f
--- /dev/null
+++ b/tmk_core/common/eeconfig.h
@@ -0,0 +1,75 @@
1/*
2Copyright 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#ifndef EECONFIG_H
19#define EECONFIG_H
20
21#include <stdint.h>
22#include <stdbool.h>
23
24
25#define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED
26
27/* eeprom parameteter address */
28#define EECONFIG_MAGIC (uint16_t *)0
29#define EECONFIG_DEBUG (uint8_t *)2
30#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
31#define EECONFIG_KEYMAP (uint8_t *)4
32#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
33#define EECONFIG_BACKLIGHT (uint8_t *)6
34
35
36/* debug bit */
37#define EECONFIG_DEBUG_ENABLE (1<<0)
38#define EECONFIG_DEBUG_MATRIX (1<<1)
39#define EECONFIG_DEBUG_KEYBOARD (1<<2)
40#define EECONFIG_DEBUG_MOUSE (1<<3)
41
42/* keyconf bit */
43#define EECONFIG_KEYMAP_SWAP_CONTROL_CAPSLOCK (1<<0)
44#define EECONFIG_KEYMAP_CAPSLOCK_TO_CONTROL (1<<1)
45#define EECONFIG_KEYMAP_SWAP_LALT_LGUI (1<<2)
46#define EECONFIG_KEYMAP_SWAP_RALT_RGUI (1<<3)
47#define EECONFIG_KEYMAP_NO_GUI (1<<4)
48#define EECONFIG_KEYMAP_SWAP_GRAVE_ESC (1<<5)
49#define EECONFIG_KEYMAP_SWAP_BACKSLASH_BACKSPACE (1<<6)
50#define EECONFIG_KEYMAP_NKRO (1<<7)
51
52
53bool eeconfig_is_enabled(void);
54
55void eeconfig_init(void);
56
57void eeconfig_enable(void);
58
59void eeconfig_disable(void);
60
61uint8_t eeconfig_read_debug(void);
62void eeconfig_write_debug(uint8_t val);
63
64uint8_t eeconfig_read_default_layer(void);
65void eeconfig_write_default_layer(uint8_t val);
66
67uint8_t eeconfig_read_keymap(void);
68void eeconfig_write_keymap(uint8_t val);
69
70#ifdef BACKLIGHT_ENABLE
71uint8_t eeconfig_read_backlight(void);
72void eeconfig_write_backlight(uint8_t val);
73#endif
74
75#endif
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c
new file mode 100644
index 000000000..e9b791670
--- /dev/null
+++ b/tmk_core/common/host.c
@@ -0,0 +1,97 @@
1/*
2Copyright 2011,2012 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 <avr/interrupt.h>
20#include "keycode.h"
21#include "host.h"
22#include "util.h"
23#include "debug.h"
24
25
26#ifdef NKRO_ENABLE
27bool keyboard_nkro = true;
28#endif
29
30static host_driver_t *driver;
31static uint16_t last_system_report = 0;
32static uint16_t last_consumer_report = 0;
33
34
35void host_set_driver(host_driver_t *d)
36{
37 driver = d;
38}
39
40host_driver_t *host_get_driver(void)
41{
42 return driver;
43}
44
45uint8_t host_keyboard_leds(void)
46{
47 if (!driver) return 0;
48 return (*driver->keyboard_leds)();
49}
50/* send report */
51void host_keyboard_send(report_keyboard_t *report)
52{
53 if (!driver) return;
54 (*driver->send_keyboard)(report);
55
56 if (debug_keyboard) {
57 dprint("keyboard_report: ");
58 for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
59 dprintf("%02X ", report->raw[i]);
60 }
61 dprint("\n");
62 }
63}
64
65void host_mouse_send(report_mouse_t *report)
66{
67 if (!driver) return;
68 (*driver->send_mouse)(report);
69}
70
71void host_system_send(uint16_t report)
72{
73 if (report == last_system_report) return;
74 last_system_report = report;
75
76 if (!driver) return;
77 (*driver->send_system)(report);
78}
79
80void host_consumer_send(uint16_t report)
81{
82 if (report == last_consumer_report) return;
83 last_consumer_report = report;
84
85 if (!driver) return;
86 (*driver->send_consumer)(report);
87}
88
89uint16_t host_last_sysytem_report(void)
90{
91 return last_system_report;
92}
93
94uint16_t host_last_consumer_report(void)
95{
96 return last_consumer_report;
97}
diff --git a/tmk_core/common/host.h b/tmk_core/common/host.h
new file mode 100644
index 000000000..918af69e8
--- /dev/null
+++ b/tmk_core/common/host.h
@@ -0,0 +1,57 @@
1/*
2Copyright 2011 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#ifndef HOST_H
19#define HOST_H
20
21#include <stdint.h>
22#include <stdbool.h>
23#include "report.h"
24#include "host_driver.h"
25
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31#ifdef NKRO_ENABLE
32extern bool keyboard_nkro;
33#endif
34
35extern uint8_t keyboard_idle;
36extern uint8_t keyboard_protocol;
37
38
39/* host driver */
40void host_set_driver(host_driver_t *driver);
41host_driver_t *host_get_driver(void);
42
43/* host driver interface */
44uint8_t host_keyboard_leds(void);
45void host_keyboard_send(report_keyboard_t *report);
46void host_mouse_send(report_mouse_t *report);
47void host_system_send(uint16_t data);
48void host_consumer_send(uint16_t data);
49
50uint16_t host_last_sysytem_report(void);
51uint16_t host_last_consumer_report(void);
52
53#ifdef __cplusplus
54}
55#endif
56
57#endif
diff --git a/tmk_core/common/host_driver.h b/tmk_core/common/host_driver.h
new file mode 100644
index 000000000..edb9e5dd9
--- /dev/null
+++ b/tmk_core/common/host_driver.h
@@ -0,0 +1,33 @@
1/*
2Copyright 2011 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#ifndef HOST_DRIVER_H
19#define HOST_DRIVER_H
20
21#include <stdint.h>
22#include "report.h"
23
24
25typedef struct {
26 uint8_t (*keyboard_leds)(void);
27 void (*send_keyboard)(report_keyboard_t *);
28 void (*send_mouse)(report_mouse_t *);
29 void (*send_system)(uint16_t);
30 void (*send_consumer)(uint16_t);
31} host_driver_t;
32
33#endif
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
new file mode 100644
index 000000000..1e3fb510a
--- /dev/null
+++ b/tmk_core/common/keyboard.c
@@ -0,0 +1,150 @@
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#include <stdint.h>
18#include "keyboard.h"
19#include "matrix.h"
20#include "keymap.h"
21#include "host.h"
22#include "led.h"
23#include "keycode.h"
24#include "timer.h"
25#include "print.h"
26#include "debug.h"
27#include "command.h"
28#include "util.h"
29#include "sendchar.h"
30#include "bootmagic.h"
31#include "eeconfig.h"
32#include "backlight.h"
33#ifdef MOUSEKEY_ENABLE
34# include "mousekey.h"
35#endif
36#ifdef PS2_MOUSE_ENABLE
37# include "ps2_mouse.h"
38#endif
39#ifdef SERIAL_MOUSE_ENABLE
40#include "serial_mouse.h"
41#endif
42
43
44#ifdef MATRIX_HAS_GHOST
45static bool has_ghost_in_row(uint8_t row)
46{
47 matrix_row_t matrix_row = matrix_get_row(row);
48 // No ghost exists when less than 2 keys are down on the row
49 if (((matrix_row - 1) & matrix_row) == 0)
50 return false;
51
52 // Ghost occurs when the row shares column line with other row
53 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
54 if (i != row && (matrix_get_row(i) & matrix_row))
55 return true;
56 }
57 return false;
58}
59#endif
60
61
62void keyboard_init(void)
63{
64 timer_init();
65 matrix_init();
66#ifdef PS2_MOUSE_ENABLE
67 ps2_mouse_init();
68#endif
69#ifdef SERIAL_MOUSE_ENABLE
70 serial_mouse_init();
71#endif
72
73
74#ifdef BOOTMAGIC_ENABLE
75 bootmagic();
76#endif
77
78#ifdef BACKLIGHT_ENABLE
79 backlight_init();
80#endif
81}
82
83/*
84 * Do keyboard routine jobs: scan mantrix, light LEDs, ...
85 * This is repeatedly called as fast as possible.
86 */
87void keyboard_task(void)
88{
89 static matrix_row_t matrix_prev[MATRIX_ROWS];
90 static uint8_t led_status = 0;
91 matrix_row_t matrix_row = 0;
92 matrix_row_t matrix_change = 0;
93
94 matrix_scan();
95 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
96 matrix_row = matrix_get_row(r);
97 matrix_change = matrix_row ^ matrix_prev[r];
98 if (matrix_change) {
99 if (debug_matrix) matrix_print();
100#ifdef MATRIX_HAS_GHOST
101 if (has_ghost_in_row(r)) {
102 matrix_prev[r] = matrix_row;
103 continue;
104 }
105#endif
106 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
107 if (matrix_change & ((matrix_row_t)1<<c)) {
108 action_exec((keyevent_t){
109 .key = (keypos_t){ .row = r, .col = c },
110 .pressed = (matrix_row & ((matrix_row_t)1<<c)),
111 .time = (timer_read() | 1) /* time should not be 0 */
112 });
113 // record a processed key
114 matrix_prev[r] ^= ((matrix_row_t)1<<c);
115 // process a key per task call
116 goto MATRIX_LOOP_END;
117 }
118 }
119 }
120 }
121 // call with pseudo tick event when no real key event.
122 action_exec(TICK);
123
124MATRIX_LOOP_END:
125
126#ifdef MOUSEKEY_ENABLE
127 // mousekey repeat & acceleration
128 mousekey_task();
129#endif
130
131#ifdef PS2_MOUSE_ENABLE
132 ps2_mouse_task();
133#endif
134
135#ifdef SERIAL_MOUSE_ENABLE
136 serial_mouse_task();
137#endif
138
139 // update LED
140 if (led_status != host_keyboard_leds()) {
141 led_status = host_keyboard_leds();
142 keyboard_set_leds(led_status);
143 }
144}
145
146void keyboard_set_leds(uint8_t leds)
147{
148 if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
149 led_set(leds);
150}
diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h
new file mode 100644
index 000000000..6442716fc
--- /dev/null
+++ b/tmk_core/common/keyboard.h
@@ -0,0 +1,72 @@
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#ifndef KEYBOARD_H
19#define KEYBOARD_H
20
21#include <stdbool.h>
22#include <stdint.h>
23
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29/* key matrix position */
30typedef struct {
31 uint8_t col;
32 uint8_t row;
33} keypos_t;
34
35/* key event */
36typedef struct {
37 keypos_t key;
38 bool pressed;
39 uint16_t time;
40} keyevent_t;
41
42/* equivalent test of keypos_t */
43#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col)
44
45/* Rules for No Event:
46 * 1) (time == 0) to handle (keyevent_t){} as empty event
47 * 2) Matrix(255, 255) to make TICK event available
48 */
49static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); }
50static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); }
51static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) && !event.pressed); }
52
53/* Tick event */
54#define TICK (keyevent_t){ \
55 .key = (keypos_t){ .row = 255, .col = 255 }, \
56 .pressed = false, \
57 .time = (timer_read() | 1) \
58}
59
60
61void keyboard_init(void);
62void keyboard_task(void);
63void keyboard_set_leds(uint8_t leds);
64
65__attribute__ ((weak)) void matrix_power_up(void) {}
66__attribute__ ((weak)) void matrix_power_down(void) {}
67
68#ifdef __cplusplus
69}
70#endif
71
72#endif
diff --git a/tmk_core/common/keycode.h b/tmk_core/common/keycode.h
new file mode 100644
index 000000000..ac4ef00db
--- /dev/null
+++ b/tmk_core/common/keycode.h
@@ -0,0 +1,489 @@
1/*
2Copyright 2011,2012 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/*
19 * Keycodes based on HID Usage Keyboard/Keypad Page(0x07) plus special codes
20 * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
21 */
22#ifndef KEYCODE_H
23#define KEYCODE_H
24
25
26#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED)
27#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF)
28#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL)
29#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI)
30
31
32#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
33#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
34#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_WFAV)
35#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31)
36#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2)
37#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT)
38#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN5)
39#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT)
40#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2)
41
42#define MOD_BIT(code) (1<<MOD_INDEX(code))
43#define MOD_INDEX(code) ((code) & 0x07)
44#define FN_BIT(code) (1<<FN_INDEX(code))
45#define FN_INDEX(code) ((code) - KC_FN0)
46#define FN_MIN KC_FN0
47#define FN_MAX KC_FN31
48
49
50/*
51 * Short names for ease of definition of keymap
52 */
53#define KC_LCTL KC_LCTRL
54#define KC_RCTL KC_RCTRL
55#define KC_LSFT KC_LSHIFT
56#define KC_RSFT KC_RSHIFT
57#define KC_ESC KC_ESCAPE
58#define KC_BSPC KC_BSPACE
59#define KC_ENT KC_ENTER
60#define KC_DEL KC_DELETE
61#define KC_INS KC_INSERT
62#define KC_CAPS KC_CAPSLOCK
63#define KC_CLCK KC_CAPSLOCK
64#define KC_RGHT KC_RIGHT
65#define KC_PGDN KC_PGDOWN
66#define KC_PSCR KC_PSCREEN
67#define KC_SLCK KC_SCROLLLOCK
68#define KC_PAUS KC_PAUSE
69#define KC_BRK KC_PAUSE
70#define KC_NLCK KC_NUMLOCK
71#define KC_SPC KC_SPACE
72#define KC_MINS KC_MINUS
73#define KC_EQL KC_EQUAL
74#define KC_GRV KC_GRAVE
75#define KC_RBRC KC_RBRACKET
76#define KC_LBRC KC_LBRACKET
77#define KC_COMM KC_COMMA
78#define KC_BSLS KC_BSLASH
79#define KC_SLSH KC_SLASH
80#define KC_SCLN KC_SCOLON
81#define KC_QUOT KC_QUOTE
82#define KC_APP KC_APPLICATION
83#define KC_NUHS KC_NONUS_HASH
84#define KC_NUBS KC_NONUS_BSLASH
85#define KC_LCAP KC_LOCKING_CAPS
86#define KC_LNUM KC_LOCKING_NUM
87#define KC_LSCR KC_LOCKING_SCROLL
88#define KC_ERAS KC_ALT_ERASE,
89#define KC_CLR KC_CLEAR
90/* Japanese specific */
91#define KC_ZKHK KC_GRAVE
92#define KC_RO KC_INT1
93#define KC_KANA KC_INT2
94#define KC_JYEN KC_INT3
95#define KC_HENK KC_INT4
96#define KC_MHEN KC_INT5
97/* Keypad */
98#define KC_P1 KC_KP_1
99#define KC_P2 KC_KP_2
100#define KC_P3 KC_KP_3
101#define KC_P4 KC_KP_4
102#define KC_P5 KC_KP_5
103#define KC_P6 KC_KP_6
104#define KC_P7 KC_KP_7
105#define KC_P8 KC_KP_8
106#define KC_P9 KC_KP_9
107#define KC_P0 KC_KP_0
108#define KC_PDOT KC_KP_DOT
109#define KC_PCMM KC_KP_COMMA
110#define KC_PSLS KC_KP_SLASH
111#define KC_PAST KC_KP_ASTERISK
112#define KC_PMNS KC_KP_MINUS
113#define KC_PPLS KC_KP_PLUS
114#define KC_PEQL KC_KP_EQUAL
115#define KC_PENT KC_KP_ENTER
116/* Mousekey */
117#define KC_MS_U KC_MS_UP
118#define KC_MS_D KC_MS_DOWN
119#define KC_MS_L KC_MS_LEFT
120#define KC_MS_R KC_MS_RIGHT
121#define KC_BTN1 KC_MS_BTN1
122#define KC_BTN2 KC_MS_BTN2
123#define KC_BTN3 KC_MS_BTN3
124#define KC_BTN4 KC_MS_BTN4
125#define KC_BTN5 KC_MS_BTN5
126#define KC_WH_U KC_MS_WH_UP
127#define KC_WH_D KC_MS_WH_DOWN
128#define KC_WH_L KC_MS_WH_LEFT
129#define KC_WH_R KC_MS_WH_RIGHT
130#define KC_ACL0 KC_MS_ACCEL0
131#define KC_ACL1 KC_MS_ACCEL1
132#define KC_ACL2 KC_MS_ACCEL2
133/* Sytem Control */
134#define KC_PWR KC_SYSTEM_POWER
135#define KC_SLEP KC_SYSTEM_SLEEP
136#define KC_WAKE KC_SYSTEM_WAKE
137/* Consumer Page */
138#define KC_MUTE KC_AUDIO_MUTE
139#define KC_VOLU KC_AUDIO_VOL_UP
140#define KC_VOLD KC_AUDIO_VOL_DOWN
141#define KC_MNXT KC_MEDIA_NEXT_TRACK
142#define KC_MPRV KC_MEDIA_PREV_TRACK
143#define KC_MFFD KC_MEDIA_FAST_FORWARD
144#define KC_MRWD KC_MEDIA_REWIND
145#define KC_MSTP KC_MEDIA_STOP
146#define KC_MPLY KC_MEDIA_PLAY_PAUSE
147#define KC_MSEL KC_MEDIA_SELECT
148#define KC_EJCT KC_MEDIA_EJECT
149#define KC_MAIL KC_MAIL
150#define KC_CALC KC_CALCULATOR
151#define KC_MYCM KC_MY_COMPUTER
152#define KC_WSCH KC_WWW_SEARCH
153#define KC_WHOM KC_WWW_HOME
154#define KC_WBAK KC_WWW_BACK
155#define KC_WFWD KC_WWW_FORWARD
156#define KC_WSTP KC_WWW_STOP
157#define KC_WREF KC_WWW_REFRESH
158#define KC_WFAV KC_WWW_FAVORITES
159/* Transparent */
160#define KC_TRANSPARENT 1
161#define KC_TRNS KC_TRANSPARENT
162
163
164
165/* USB HID Keyboard/Keypad Usage(0x07) */
166enum hid_keyboard_keypad_usage {
167 KC_NO = 0x00,
168 KC_ROLL_OVER,
169 KC_POST_FAIL,
170 KC_UNDEFINED,
171 KC_A,
172 KC_B,
173 KC_C,
174 KC_D,
175 KC_E,
176 KC_F,
177 KC_G,
178 KC_H,
179 KC_I,
180 KC_J,
181 KC_K,
182 KC_L,
183 KC_M, /* 0x10 */
184 KC_N,
185 KC_O,
186 KC_P,
187 KC_Q,
188 KC_R,
189 KC_S,
190 KC_T,
191 KC_U,
192 KC_V,
193 KC_W,
194 KC_X,
195 KC_Y,
196 KC_Z,
197 KC_1,
198 KC_2,
199 KC_3, /* 0x20 */
200 KC_4,
201 KC_5,
202 KC_6,
203 KC_7,
204 KC_8,
205 KC_9,
206 KC_0,
207 KC_ENTER,
208 KC_ESCAPE,
209 KC_BSPACE,
210 KC_TAB,
211 KC_SPACE,
212 KC_MINUS,
213 KC_EQUAL,
214 KC_LBRACKET,
215 KC_RBRACKET, /* 0x30 */
216 KC_BSLASH, /* \ (and |) */
217 KC_NONUS_HASH, /* Non-US # and ~ */
218 KC_SCOLON, /* ; (and :) */
219 KC_QUOTE, /* ' and " */
220 KC_GRAVE, /* Grave accent and tilde */
221 KC_COMMA, /* , and < */
222 KC_DOT, /* . and > */
223 KC_SLASH, /* / and ? */
224 KC_CAPSLOCK,
225 KC_F1,
226 KC_F2,
227 KC_F3,
228 KC_F4,
229 KC_F5,
230 KC_F6,
231 KC_F7, /* 0x40 */
232 KC_F8,
233 KC_F9,
234 KC_F10,
235 KC_F11,
236 KC_F12,
237 KC_PSCREEN,
238 KC_SCROLLLOCK,
239 KC_PAUSE,
240 KC_INSERT,
241 KC_HOME,
242 KC_PGUP,
243 KC_DELETE,
244 KC_END,
245 KC_PGDOWN,
246 KC_RIGHT,
247 KC_LEFT, /* 0x50 */
248 KC_DOWN,
249 KC_UP,
250 KC_NUMLOCK,
251 KC_KP_SLASH,
252 KC_KP_ASTERISK,
253 KC_KP_MINUS,
254 KC_KP_PLUS,
255 KC_KP_ENTER,
256 KC_KP_1,
257 KC_KP_2,
258 KC_KP_3,
259 KC_KP_4,
260 KC_KP_5,
261 KC_KP_6,
262 KC_KP_7,
263 KC_KP_8, /* 0x60 */
264 KC_KP_9,
265 KC_KP_0,
266 KC_KP_DOT,
267 KC_NONUS_BSLASH, /* Non-US \ and | */
268 KC_APPLICATION,
269 KC_POWER,
270 KC_KP_EQUAL,
271 KC_F13,
272 KC_F14,
273 KC_F15,
274 KC_F16,
275 KC_F17,
276 KC_F18,
277 KC_F19,
278 KC_F20,
279 KC_F21, /* 0x70 */
280 KC_F22,
281 KC_F23,
282 KC_F24,
283 KC_EXECUTE,
284 KC_HELP,
285 KC_MENU,
286 KC_SELECT,
287 KC_STOP,
288 KC_AGAIN,
289 KC_UNDO,
290 KC_CUT,
291 KC_COPY,
292 KC_PASTE,
293 KC_FIND,
294 KC__MUTE,
295 KC__VOLUP, /* 0x80 */
296 KC__VOLDOWN,
297 KC_LOCKING_CAPS, /* locking Caps Lock */
298 KC_LOCKING_NUM, /* locking Num Lock */
299 KC_LOCKING_SCROLL, /* locking Scroll Lock */
300 KC_KP_COMMA,
301 KC_KP_EQUAL_AS400, /* equal sign on AS/400 */
302 KC_INT1,
303 KC_INT2,
304 KC_INT3,
305 KC_INT4,
306 KC_INT5,
307 KC_INT6,
308 KC_INT7,
309 KC_INT8,
310 KC_INT9,
311 KC_LANG1, /* 0x90 */
312 KC_LANG2,
313 KC_LANG3,
314 KC_LANG4,
315 KC_LANG5,
316 KC_LANG6,
317 KC_LANG7,
318 KC_LANG8,
319 KC_LANG9,
320 KC_ALT_ERASE,
321 KC_SYSREQ,
322 KC_CANCEL,
323 KC_CLEAR,
324 KC_PRIOR,
325 KC_RETURN,
326 KC_SEPARATOR,
327 KC_OUT, /* 0xA0 */
328 KC_OPER,
329 KC_CLEAR_AGAIN,
330 KC_CRSEL,
331 KC_EXSEL, /* 0xA4 */
332
333 /* NOTE: 0xA5-DF are used for internal special purpose */
334
335#if 0
336 /* NOTE: Following codes(0xB0-DD) are not used. Leave them for reference. */
337 KC_KP_00 = 0xB0,
338 KC_KP_000,
339 KC_THOUSANDS_SEPARATOR,
340 KC_DECIMAL_SEPARATOR,
341 KC_CURRENCY_UNIT,
342 KC_CURRENCY_SUB_UNIT,
343 KC_KP_LPAREN,
344 KC_KP_RPAREN,
345 KC_KP_LCBRACKET, /* { */
346 KC_KP_RCBRACKET, /* } */
347 KC_KP_TAB,
348 KC_KP_BSPACE,
349 KC_KP_A,
350 KC_KP_B,
351 KC_KP_C,
352 KC_KP_D,
353 KC_KP_E, /* 0xC0 */
354 KC_KP_F,
355 KC_KP_XOR,
356 KC_KP_HAT,
357 KC_KP_PERC,
358 KC_KP_LT,
359 KC_KP_GT,
360 KC_KP_AND,
361 KC_KP_LAZYAND,
362 KC_KP_OR,
363 KC_KP_LAZYOR,
364 KC_KP_COLON,
365 KC_KP_HASH,
366 KC_KP_SPACE,
367 KC_KP_ATMARK,
368 KC_KP_EXCLAMATION,
369 KC_KP_MEM_STORE, /* 0xD0 */
370 KC_KP_MEM_RECALL,
371 KC_KP_MEM_CLEAR,
372 KC_KP_MEM_ADD,
373 KC_KP_MEM_SUB,
374 KC_KP_MEM_MUL,
375 KC_KP_MEM_DIV,
376 KC_KP_PLUS_MINUS,
377 KC_KP_CLEAR,
378 KC_KP_CLEAR_ENTRY,
379 KC_KP_BINARY,
380 KC_KP_OCTAL,
381 KC_KP_DECIMAL,
382 KC_KP_HEXADECIMAL, /* 0xDD */
383#endif
384
385 /* Modifiers */
386 KC_LCTRL = 0xE0,
387 KC_LSHIFT,
388 KC_LALT,
389 KC_LGUI,
390 KC_RCTRL,
391 KC_RSHIFT,
392 KC_RALT,
393 KC_RGUI,
394
395 /* NOTE: 0xE8-FF are used for internal special purpose */
396};
397
398/* Special keycodes */
399/* NOTE: 0xA5-DF and 0xE8-FF are used for internal special purpose */
400enum internal_special_keycodes {
401 /* System Control */
402 KC_SYSTEM_POWER = 0xA5,
403 KC_SYSTEM_SLEEP,
404 KC_SYSTEM_WAKE,
405
406 /* Media Control */
407 KC_AUDIO_MUTE,
408 KC_AUDIO_VOL_UP,
409 KC_AUDIO_VOL_DOWN,
410 KC_MEDIA_NEXT_TRACK,
411 KC_MEDIA_PREV_TRACK,
412 KC_MEDIA_STOP,
413 KC_MEDIA_PLAY_PAUSE,
414 KC_MEDIA_SELECT,
415 KC_MEDIA_EJECT,
416 KC_MAIL,
417 KC_CALCULATOR,
418 KC_MY_COMPUTER,
419 KC_WWW_SEARCH,
420 KC_WWW_HOME,
421 KC_WWW_BACK,
422 KC_WWW_FORWARD,
423 KC_WWW_STOP,
424 KC_WWW_REFRESH,
425 KC_WWW_FAVORITES,
426 KC_MEDIA_FAST_FORWARD,
427 KC_MEDIA_REWIND, /* 0xBC */
428
429 /* Fn key */
430 KC_FN0 = 0xC0,
431 KC_FN1,
432 KC_FN2,
433 KC_FN3,
434 KC_FN4,
435 KC_FN5,
436 KC_FN6,
437 KC_FN7,
438 KC_FN8,
439 KC_FN9,
440 KC_FN10,
441 KC_FN11,
442 KC_FN12,
443 KC_FN13,
444 KC_FN14,
445 KC_FN15,
446
447 KC_FN16 = 0xD0,
448 KC_FN17,
449 KC_FN18,
450 KC_FN19,
451 KC_FN20,
452 KC_FN21,
453 KC_FN22,
454 KC_FN23,
455 KC_FN24,
456 KC_FN25,
457 KC_FN26,
458 KC_FN27,
459 KC_FN28,
460 KC_FN29,
461 KC_FN30,
462 KC_FN31, /* 0xDF */
463
464 /**************************************/
465 /* 0xE0-E7 for Modifiers. DO NOT USE. */
466 /**************************************/
467
468 /* Mousekey */
469 KC_MS_UP = 0xF0,
470 KC_MS_DOWN,
471 KC_MS_LEFT,
472 KC_MS_RIGHT,
473 KC_MS_BTN1,
474 KC_MS_BTN2,
475 KC_MS_BTN3,
476 KC_MS_BTN4,
477 KC_MS_BTN5, /* 0xF8 */
478 /* Mousekey wheel */
479 KC_MS_WH_UP,
480 KC_MS_WH_DOWN,
481 KC_MS_WH_LEFT,
482 KC_MS_WH_RIGHT, /* 0xFC */
483 /* Mousekey accel */
484 KC_MS_ACCEL0,
485 KC_MS_ACCEL1,
486 KC_MS_ACCEL2 /* 0xFF */
487};
488
489#endif /* KEYCODE_H */
diff --git a/tmk_core/common/keymap.c b/tmk_core/common/keymap.c
new file mode 100644
index 000000000..4c0b61b8c
--- /dev/null
+++ b/tmk_core/common/keymap.c
@@ -0,0 +1,185 @@
1/*
2Copyright 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#include "keymap.h"
18#include "report.h"
19#include "keycode.h"
20#include "action_layer.h"
21#include "action.h"
22#include "action_macro.h"
23#include "debug.h"
24
25
26static action_t keycode_to_action(uint8_t keycode);
27
28
29/* converts key to action */
30action_t action_for_key(uint8_t layer, keypos_t key)
31{
32 uint8_t keycode = keymap_key_to_keycode(layer, key);
33 switch (keycode) {
34 case KC_FN0 ... KC_FN31:
35 return keymap_fn_to_action(keycode);
36#ifdef BOOTMAGIC_ENABLE
37 case KC_CAPSLOCK:
38 case KC_LOCKING_CAPS:
39 if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
40 return keycode_to_action(KC_LCTL);
41 }
42 return keycode_to_action(keycode);
43 case KC_LCTL:
44 if (keymap_config.swap_control_capslock) {
45 return keycode_to_action(KC_CAPSLOCK);
46 }
47 return keycode_to_action(KC_LCTL);
48 case KC_LALT:
49 if (keymap_config.swap_lalt_lgui) {
50 if (keymap_config.no_gui) {
51 return keycode_to_action(ACTION_NO);
52 }
53 return keycode_to_action(KC_LGUI);
54 }
55 return keycode_to_action(KC_LALT);
56 case KC_LGUI:
57 if (keymap_config.swap_lalt_lgui) {
58 return keycode_to_action(KC_LALT);
59 }
60 if (keymap_config.no_gui) {
61 return keycode_to_action(ACTION_NO);
62 }
63 return keycode_to_action(KC_LGUI);
64 case KC_RALT:
65 if (keymap_config.swap_ralt_rgui) {
66 if (keymap_config.no_gui) {
67 return keycode_to_action(ACTION_NO);
68 }
69 return keycode_to_action(KC_RGUI);
70 }
71 return keycode_to_action(KC_RALT);
72 case KC_RGUI:
73 if (keymap_config.swap_ralt_rgui) {
74 return keycode_to_action(KC_RALT);
75 }
76 if (keymap_config.no_gui) {
77 return keycode_to_action(ACTION_NO);
78 }
79 return keycode_to_action(KC_RGUI);
80 case KC_GRAVE:
81 if (keymap_config.swap_grave_esc) {
82 return keycode_to_action(KC_ESC);
83 }
84 return keycode_to_action(KC_GRAVE);
85 case KC_ESC:
86 if (keymap_config.swap_grave_esc) {
87 return keycode_to_action(KC_GRAVE);
88 }
89 return keycode_to_action(KC_ESC);
90 case KC_BSLASH:
91 if (keymap_config.swap_backslash_backspace) {
92 return keycode_to_action(KC_BSPACE);
93 }
94 return keycode_to_action(KC_BSLASH);
95 case KC_BSPACE:
96 if (keymap_config.swap_backslash_backspace) {
97 return keycode_to_action(KC_BSLASH);
98 }
99 return keycode_to_action(KC_BSPACE);
100#endif
101 default:
102 return keycode_to_action(keycode);
103 }
104}
105
106
107/* Macro */
108__attribute__ ((weak))
109const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
110{
111 return MACRO_NONE;
112}
113
114/* Function */
115__attribute__ ((weak))
116void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
117{
118}
119
120
121
122/* translates keycode to action */
123static action_t keycode_to_action(uint8_t keycode)
124{
125 action_t action;
126 switch (keycode) {
127 case KC_A ... KC_EXSEL:
128 case KC_LCTRL ... KC_RGUI:
129 action.code = ACTION_KEY(keycode);
130 break;
131 case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
132 action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
133 break;
134 case KC_AUDIO_MUTE ... KC_WWW_FAVORITES:
135 action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
136 break;
137 case KC_MS_UP ... KC_MS_ACCEL2:
138 action.code = ACTION_MOUSEKEY(keycode);
139 break;
140 case KC_TRNS:
141 action.code = ACTION_TRANSPARENT;
142 break;
143 default:
144 action.code = ACTION_NO;
145 break;
146 }
147 return action;
148}
149
150
151
152#ifdef USE_LEGACY_KEYMAP
153/*
154 * Legacy keymap support
155 * Consider using new keymap API instead.
156 */
157__attribute__ ((weak))
158uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
159{
160 return keymap_get_keycode(layer, key.row, key.col);
161}
162
163
164/* Legacy keymap support */
165__attribute__ ((weak))
166action_t keymap_fn_to_action(uint8_t keycode)
167{
168 action_t action = { .code = ACTION_NO };
169 switch (keycode) {
170 case KC_FN0 ... KC_FN31:
171 {
172 uint8_t layer = keymap_fn_layer(FN_INDEX(keycode));
173 uint8_t key = keymap_fn_keycode(FN_INDEX(keycode));
174 if (key) {
175 action.code = ACTION_LAYER_TAP_KEY(layer, key);
176 } else {
177 action.code = ACTION_LAYER_MOMENTARY(layer);
178 }
179 }
180 return action;
181 default:
182 return action;
183 }
184}
185#endif
diff --git a/tmk_core/common/keymap.h b/tmk_core/common/keymap.h
new file mode 100644
index 000000000..e1a6f992e
--- /dev/null
+++ b/tmk_core/common/keymap.h
@@ -0,0 +1,71 @@
1/*
2Copyright 2011 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#ifndef KEYMAP_H
19#define KEYMAP_H
20
21#include <stdint.h>
22#include <stdbool.h>
23#include "action.h"
24
25
26#ifdef BOOTMAGIC_ENABLE
27/* NOTE: Not portable. Bit field order depends on implementation */
28typedef union {
29 uint8_t raw;
30 struct {
31 bool swap_control_capslock:1;
32 bool capslock_to_control:1;
33 bool swap_lalt_lgui:1;
34 bool swap_ralt_rgui:1;
35 bool no_gui:1;
36 bool swap_grave_esc:1;
37 bool swap_backslash_backspace:1;
38 bool nkro:1;
39 };
40} keymap_config_t;
41keymap_config_t keymap_config;
42#endif
43
44
45/* translates key to keycode */
46uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
47
48/* translates Fn keycode to action */
49action_t keymap_fn_to_action(uint8_t keycode);
50
51
52
53#ifdef USE_LEGACY_KEYMAP
54/*
55 * Legacy keymap
56 * Consider using new keymap API above instead.
57 */
58/* keycode of key */
59__attribute__ ((deprecated))
60uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col);
61
62/* layer to move during press Fn key */
63__attribute__ ((deprecated))
64uint8_t keymap_fn_layer(uint8_t fn_bits);
65
66/* keycode to send when release Fn key without using */
67__attribute__ ((deprecated))
68uint8_t keymap_fn_keycode(uint8_t fn_bits);
69#endif
70
71#endif
diff --git a/tmk_core/common/led.h b/tmk_core/common/led.h
new file mode 100644
index 000000000..402a247b9
--- /dev/null
+++ b/tmk_core/common/led.h
@@ -0,0 +1,33 @@
1/*
2Copyright 2011 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#ifndef LED_H
19#define LED_H
20#include "stdint.h"
21
22
23/* keyboard LEDs */
24#define USB_LED_NUM_LOCK 0
25#define USB_LED_CAPS_LOCK 1
26#define USB_LED_SCROLL_LOCK 2
27#define USB_LED_COMPOSE 3
28#define USB_LED_KANA 4
29
30
31void led_set(uint8_t usb_led);
32
33#endif
diff --git a/tmk_core/common/matrix.h b/tmk_core/common/matrix.h
new file mode 100644
index 000000000..107ee7265
--- /dev/null
+++ b/tmk_core/common/matrix.h
@@ -0,0 +1,68 @@
1/*
2Copyright 2011 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#ifndef MATRIX_H
19#define MATRIX_H
20
21#include <stdint.h>
22#include <stdbool.h>
23
24
25#if (MATRIX_COLS <= 8)
26typedef uint8_t matrix_row_t;
27#elif (MATRIX_COLS <= 16)
28typedef uint16_t matrix_row_t;
29#elif (MATRIX_COLS <= 32)
30typedef uint32_t matrix_row_t;
31#else
32#error "MATRIX_COLS: invalid value"
33#endif
34
35#define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col))
36
37
38#ifdef __cplusplus
39extern "C" {
40#endif
41
42/* number of matrix rows */
43uint8_t matrix_rows(void);
44/* number of matrix columns */
45uint8_t matrix_cols(void);
46/* intialize matrix for scaning. should be called once. */
47void matrix_init(void);
48/* scan all key states on matrix */
49uint8_t matrix_scan(void);
50/* whether modified from previous scan. used after matrix_scan. */
51bool matrix_is_modified(void) __attribute__ ((deprecated));
52/* whether a swtich is on */
53bool matrix_is_on(uint8_t row, uint8_t col);
54/* matrix state on row */
55matrix_row_t matrix_get_row(uint8_t row);
56/* print matrix for debug */
57void matrix_print(void);
58
59
60/* power control */
61void matrix_power_up(void);
62void matrix_power_down(void);
63
64#ifdef __cplusplus
65}
66#endif
67
68#endif
diff --git a/tmk_core/common/mbed/bootloader.c b/tmk_core/common/mbed/bootloader.c
new file mode 100644
index 000000000..b51e83943
--- /dev/null
+++ b/tmk_core/common/mbed/bootloader.c
@@ -0,0 +1,4 @@
1#include "bootloader.h"
2
3
4void bootloader_jump(void) {}
diff --git a/tmk_core/common/mbed/suspend.c b/tmk_core/common/mbed/suspend.c
new file mode 100644
index 000000000..32651574f
--- /dev/null
+++ b/tmk_core/common/mbed/suspend.c
@@ -0,0 +1,6 @@
1#include <stdbool.h>
2
3
4void suspend_power_down(void) {}
5bool suspend_wakeup_condition(void) { return true; }
6void suspend_wakeup_init(void) {}
diff --git a/tmk_core/common/mbed/timer.c b/tmk_core/common/mbed/timer.c
new file mode 100644
index 000000000..c357ceb78
--- /dev/null
+++ b/tmk_core/common/mbed/timer.c
@@ -0,0 +1,41 @@
1#include "cmsis.h"
2#include "timer.h"
3
4/* Mill second tick count */
5volatile uint32_t timer_count = 0;
6
7/* Timer interrupt handler */
8void SysTick_Handler(void) {
9 timer_count++;
10}
11
12void timer_init(void)
13{
14 timer_count = 0;
15 SysTick_Config(SystemCoreClock / 1000); /* 1ms tick */
16}
17
18void timer_clear(void)
19{
20 timer_count = 0;
21}
22
23uint16_t timer_read(void)
24{
25 return (uint16_t)(timer_count & 0xFFFF);
26}
27
28uint32_t timer_read32(void)
29{
30 return timer_count;
31}
32
33uint16_t timer_elapsed(uint16_t last)
34{
35 return TIMER_DIFF_16(timer_read(), last);
36}
37
38uint32_t timer_elapsed32(uint32_t last)
39{
40 return TIMER_DIFF_32(timer_read32(), last);
41}
diff --git a/tmk_core/common/mbed/xprintf.cpp b/tmk_core/common/mbed/xprintf.cpp
new file mode 100644
index 000000000..3647ece75
--- /dev/null
+++ b/tmk_core/common/mbed/xprintf.cpp
@@ -0,0 +1,51 @@
1#include <cstdarg>
2//#include <stdarg.h>
3#include "mbed.h"
4#include "mbed/xprintf.h"
5
6
7#define STRING_STACK_LIMIT 120
8
9//TODO
10int xprintf(const char* format, ...) { return 0; }
11
12#if 0
13/* mbed Serial */
14Serial ser(UART_TX, UART_RX);
15
16/* TODO: Need small implementation for embedded */
17int xprintf(const char* format, ...)
18{
19 /* copy from mbed/common/RawSerial.cpp */
20 std::va_list arg;
21 va_start(arg, format);
22 int len = vsnprintf(NULL, 0, format, arg);
23 if (len < STRING_STACK_LIMIT) {
24 char temp[STRING_STACK_LIMIT];
25 vsprintf(temp, format, arg);
26 ser.puts(temp);
27 } else {
28 char *temp = new char[len + 1];
29 vsprintf(temp, format, arg);
30 ser.puts(temp);
31 delete[] temp;
32 }
33 va_end(arg);
34 return len;
35
36/* Fail: __builtin_va_arg_pack?
37 * https://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/Constructing-Calls.html#Constructing-Calls
38 void *arg = __builtin_apply_args();
39 void *ret = __builtin_apply((void*)(&(ser.printf)), arg, 100);
40 __builtin_return(ret)
41*/
42/* Fail: varargs can not be passed to printf
43 //int r = ser.printf("test %i\r\n", 123);
44 va_list arg;
45 va_start(arg, format);
46 int r = ser.printf(format, arg);
47 va_end(arg);
48 return r;
49*/
50}
51#endif
diff --git a/tmk_core/common/mbed/xprintf.h b/tmk_core/common/mbed/xprintf.h
new file mode 100644
index 000000000..26bc529e5
--- /dev/null
+++ b/tmk_core/common/mbed/xprintf.h
@@ -0,0 +1,17 @@
1#ifndef XPRINTF_H
2#define XPRINTF_H
3
4//#define xprintf(format, ...) __xprintf(format, ##__VA_ARGS__)
5
6#ifdef __cplusplus
7extern "C" {
8#endif
9
10int xprintf(const char *format, ...);
11
12#ifdef __cplusplus
13}
14#endif
15
16
17#endif
diff --git a/tmk_core/common/mousekey.c b/tmk_core/common/mousekey.c
new file mode 100644
index 000000000..23469476e
--- /dev/null
+++ b/tmk_core/common/mousekey.c
@@ -0,0 +1,196 @@
1/*
2Copyright 2011 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 "keycode.h"
20#include "host.h"
21#include "timer.h"
22#include "print.h"
23#include "debug.h"
24#include "mousekey.h"
25
26
27
28static report_mouse_t mouse_report = {};
29static uint8_t mousekey_repeat = 0;
30static uint8_t mousekey_accel = 0;
31
32static void mousekey_debug(void);
33
34
35/*
36 * Mouse keys acceleration algorithm
37 * http://en.wikipedia.org/wiki/Mouse_keys
38 *
39 * speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
40 */
41/* milliseconds between the initial key press and first repeated motion event (0-2550) */
42uint8_t mk_delay = MOUSEKEY_DELAY/10;
43/* milliseconds between repeated motion events (0-255) */
44uint8_t mk_interval = MOUSEKEY_INTERVAL;
45/* steady speed (in action_delta units) applied each event (0-255) */
46uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED;
47/* number of events (count) accelerating to steady speed (0-255) */
48uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
49/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
50//int8_t mk_curve = 0;
51/* wheel params */
52uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
53uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
54
55
56static uint16_t last_timer = 0;
57
58
59static uint8_t move_unit(void)
60{
61 uint16_t unit;
62 if (mousekey_accel & (1<<0)) {
63 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/4;
64 } else if (mousekey_accel & (1<<1)) {
65 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/2;
66 } else if (mousekey_accel & (1<<2)) {
67 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
68 } else if (mousekey_repeat == 0) {
69 unit = MOUSEKEY_MOVE_DELTA;
70 } else if (mousekey_repeat >= mk_time_to_max) {
71 unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
72 } else {
73 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
74 }
75 return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
76}
77
78static uint8_t wheel_unit(void)
79{
80 uint16_t unit;
81 if (mousekey_accel & (1<<0)) {
82 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/4;
83 } else if (mousekey_accel & (1<<1)) {
84 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/2;
85 } else if (mousekey_accel & (1<<2)) {
86 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
87 } else if (mousekey_repeat == 0) {
88 unit = MOUSEKEY_WHEEL_DELTA;
89 } else if (mousekey_repeat >= mk_wheel_time_to_max) {
90 unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
91 } else {
92 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
93 }
94 return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
95}
96
97void mousekey_task(void)
98{
99 if (timer_elapsed(last_timer) < (mousekey_repeat ? mk_interval : mk_delay*10))
100 return;
101
102 if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
103 return;
104
105 if (mousekey_repeat != UINT8_MAX)
106 mousekey_repeat++;
107
108
109 if (mouse_report.x > 0) mouse_report.x = move_unit();
110 if (mouse_report.x < 0) mouse_report.x = move_unit() * -1;
111 if (mouse_report.y > 0) mouse_report.y = move_unit();
112 if (mouse_report.y < 0) mouse_report.y = move_unit() * -1;
113
114 /* diagonal move [1/sqrt(2) = 0.7] */
115 if (mouse_report.x && mouse_report.y) {
116 mouse_report.x *= 0.7;
117 mouse_report.y *= 0.7;
118 }
119
120 if (mouse_report.v > 0) mouse_report.v = wheel_unit();
121 if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1;
122 if (mouse_report.h > 0) mouse_report.h = wheel_unit();
123 if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1;
124
125 mousekey_send();
126}
127
128void mousekey_on(uint8_t code)
129{
130 if (code == KC_MS_UP) mouse_report.y = move_unit() * -1;
131 else if (code == KC_MS_DOWN) mouse_report.y = move_unit();
132 else if (code == KC_MS_LEFT) mouse_report.x = move_unit() * -1;
133 else if (code == KC_MS_RIGHT) mouse_report.x = move_unit();
134 else if (code == KC_MS_WH_UP) mouse_report.v = wheel_unit();
135 else if (code == KC_MS_WH_DOWN) mouse_report.v = wheel_unit() * -1;
136 else if (code == KC_MS_WH_LEFT) mouse_report.h = wheel_unit() * -1;
137 else if (code == KC_MS_WH_RIGHT) mouse_report.h = wheel_unit();
138 else if (code == KC_MS_BTN1) mouse_report.buttons |= MOUSE_BTN1;
139 else if (code == KC_MS_BTN2) mouse_report.buttons |= MOUSE_BTN2;
140 else if (code == KC_MS_BTN3) mouse_report.buttons |= MOUSE_BTN3;
141 else if (code == KC_MS_BTN4) mouse_report.buttons |= MOUSE_BTN4;
142 else if (code == KC_MS_BTN5) mouse_report.buttons |= MOUSE_BTN5;
143 else if (code == KC_MS_ACCEL0) mousekey_accel |= (1<<0);
144 else if (code == KC_MS_ACCEL1) mousekey_accel |= (1<<1);
145 else if (code == KC_MS_ACCEL2) mousekey_accel |= (1<<2);
146}
147
148void mousekey_off(uint8_t code)
149{
150 if (code == KC_MS_UP && mouse_report.y < 0) mouse_report.y = 0;
151 else if (code == KC_MS_DOWN && mouse_report.y > 0) mouse_report.y = 0;
152 else if (code == KC_MS_LEFT && mouse_report.x < 0) mouse_report.x = 0;
153 else if (code == KC_MS_RIGHT && mouse_report.x > 0) mouse_report.x = 0;
154 else if (code == KC_MS_WH_UP && mouse_report.v > 0) mouse_report.v = 0;
155 else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) mouse_report.v = 0;
156 else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) mouse_report.h = 0;
157 else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) mouse_report.h = 0;
158 else if (code == KC_MS_BTN1) mouse_report.buttons &= ~MOUSE_BTN1;
159 else if (code == KC_MS_BTN2) mouse_report.buttons &= ~MOUSE_BTN2;
160 else if (code == KC_MS_BTN3) mouse_report.buttons &= ~MOUSE_BTN3;
161 else if (code == KC_MS_BTN4) mouse_report.buttons &= ~MOUSE_BTN4;
162 else if (code == KC_MS_BTN5) mouse_report.buttons &= ~MOUSE_BTN5;
163 else if (code == KC_MS_ACCEL0) mousekey_accel &= ~(1<<0);
164 else if (code == KC_MS_ACCEL1) mousekey_accel &= ~(1<<1);
165 else if (code == KC_MS_ACCEL2) mousekey_accel &= ~(1<<2);
166
167 if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
168 mousekey_repeat = 0;
169}
170
171void mousekey_send(void)
172{
173 mousekey_debug();
174 host_mouse_send(&mouse_report);
175 last_timer = timer_read();
176}
177
178void mousekey_clear(void)
179{
180 mouse_report = (report_mouse_t){};
181 mousekey_repeat = 0;
182 mousekey_accel = 0;
183}
184
185static void mousekey_debug(void)
186{
187 if (!debug_mouse) return;
188 print("mousekey [btn|x y v h](rep/acl): [");
189 phex(mouse_report.buttons); print("|");
190 print_decs(mouse_report.x); print(" ");
191 print_decs(mouse_report.y); print(" ");
192 print_decs(mouse_report.v); print(" ");
193 print_decs(mouse_report.h); print("](");
194 print_dec(mousekey_repeat); print("/");
195 print_dec(mousekey_accel); print(")\n");
196}
diff --git a/tmk_core/common/mousekey.h b/tmk_core/common/mousekey.h
new file mode 100644
index 000000000..6eede06b4
--- /dev/null
+++ b/tmk_core/common/mousekey.h
@@ -0,0 +1,77 @@
1/*
2Copyright 2011 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#ifndef MOUSEKEY_H
19#define MOUSEKEY_H
20
21#include <stdbool.h>
22#include "host.h"
23
24
25/* max value on report descriptor */
26#define MOUSEKEY_MOVE_MAX 127
27#define MOUSEKEY_WHEEL_MAX 127
28
29#ifndef MOUSEKEY_MOVE_DELTA
30#define MOUSEKEY_MOVE_DELTA 5
31#endif
32#ifndef MOUSEKEY_WHEEL_DELTA
33#define MOUSEKEY_WHEEL_DELTA 1
34#endif
35#ifndef MOUSEKEY_DELAY
36#define MOUSEKEY_DELAY 300
37#endif
38#ifndef MOUSEKEY_INTERVAL
39#define MOUSEKEY_INTERVAL 50
40#endif
41#ifndef MOUSEKEY_MAX_SPEED
42#define MOUSEKEY_MAX_SPEED 10
43#endif
44#ifndef MOUSEKEY_TIME_TO_MAX
45#define MOUSEKEY_TIME_TO_MAX 20
46#endif
47#ifndef MOUSEKEY_WHEEL_MAX_SPEED
48#define MOUSEKEY_WHEEL_MAX_SPEED 8
49#endif
50#ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
51#define MOUSEKEY_WHEEL_TIME_TO_MAX 40
52#endif
53
54
55#ifdef __cplusplus
56extern "C" {
57#endif
58
59extern uint8_t mk_delay;
60extern uint8_t mk_interval;
61extern uint8_t mk_max_speed;
62extern uint8_t mk_time_to_max;
63extern uint8_t mk_wheel_max_speed;
64extern uint8_t mk_wheel_time_to_max;
65
66
67void mousekey_task(void);
68void mousekey_on(uint8_t code);
69void mousekey_off(uint8_t code);
70void mousekey_clear(void);
71void mousekey_send(void);
72
73#ifdef __cplusplus
74}
75#endif
76
77#endif
diff --git a/tmk_core/common/nodebug.h b/tmk_core/common/nodebug.h
new file mode 100644
index 000000000..93309ada4
--- /dev/null
+++ b/tmk_core/common/nodebug.h
@@ -0,0 +1,25 @@
1/*
2Copyright 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#ifndef NODEBUG_H
19#define NODEBUG_H 1
20
21#define NO_DEBUG
22#include "debug.h"
23#undef NO_DEBUG
24
25#endif
diff --git a/tmk_core/common/print.c b/tmk_core/common/print.c
new file mode 100644
index 000000000..ca94e1e5d
--- /dev/null
+++ b/tmk_core/common/print.c
@@ -0,0 +1,48 @@
1/* Copyright 2012,2013 Jun Wako <wakojun@gmail.com> */
2/* Very basic print functions, intended to be used with usb_debug_only.c
3 * http://www.pjrc.com/teensy/
4 * Copyright (c) 2008 PJRC.COM, LLC
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include <stdint.h>
26#include "print.h"
27
28
29#ifndef NO_PRINT
30
31#if defined(__AVR__)
32
33#define sendchar(c) xputc(c)
34
35
36void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))
37{
38 xdev_out(sendchar_func);
39}
40
41#elif defined(__arm__)
42
43// TODO
44//void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { }
45
46#endif
47
48#endif
diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h
new file mode 100644
index 000000000..c0e9e1430
--- /dev/null
+++ b/tmk_core/common/print.h
@@ -0,0 +1,137 @@
1/* Copyright 2012 Jun Wako <wakojun@gmail.com> */
2/* Very basic print functions, intended to be used with usb_debug_only.c
3 * http://www.pjrc.com/teensy/
4 * Copyright (c) 2008 PJRC.COM, LLC
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#ifndef PRINT_H__
26#define PRINT_H__ 1
27
28#include <stdint.h>
29#include <stdbool.h>
30#include "util.h"
31
32
33
34
35#ifndef NO_PRINT
36
37
38#if defined(__AVR__)
39
40#include "avr/xprintf.h"
41#define print(s) xputs(PSTR(s))
42#define println(s) xputs(PSTR(s "\r\n"))
43
44#ifdef __cplusplus
45extern "C"
46#endif
47/* function pointer of sendchar to be used by print utility */
48void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
49
50#elif defined(__arm__)
51
52#include "mbed/xprintf.h"
53
54#define print(s) xprintf(s)
55#define println(s) xprintf(s "\r\n")
56
57/* TODO: to select output destinations: UART/USBSerial */
58#define print_set_sendchar(func)
59
60#endif /* __AVR__ */
61
62
63/* decimal */
64#define print_dec(i) xprintf("%u", i)
65#define print_decs(i) xprintf("%d", i)
66/* hex */
67#define print_hex4(i) xprintf("%X", i)
68#define print_hex8(i) xprintf("%02X", i)
69#define print_hex16(i) xprintf("%04X", i)
70#define print_hex32(i) xprintf("%08lX", i)
71/* binary */
72#define print_bin4(i) xprintf("%04b", i)
73#define print_bin8(i) xprintf("%08b", i)
74#define print_bin16(i) xprintf("%016b", i)
75#define print_bin32(i) xprintf("%032lb", i)
76#define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
77#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i))
78#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i))
79/* print value utility */
80#define print_val_dec(v) xprintf(#v ": %u\n", v)
81#define print_val_decs(v) xprintf(#v ": %d\n", v)
82#define print_val_hex8(v) xprintf(#v ": %X\n", v)
83#define print_val_hex16(v) xprintf(#v ": %02X\n", v)
84#define print_val_hex32(v) xprintf(#v ": %04lX\n", v)
85#define print_val_bin8(v) xprintf(#v ": %08b\n", v)
86#define print_val_bin16(v) xprintf(#v ": %016b\n", v)
87#define print_val_bin32(v) xprintf(#v ": %032lb\n", v)
88#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v))
89#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v))
90#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v))
91
92#else /* NO_PRINT */
93
94#define xprintf
95#define print
96#define println
97#define print_set_sendchar(func)
98#define print_dec(data)
99#define print_decs(data)
100#define print_hex4(data)
101#define print_hex8(data)
102#define print_hex16(data)
103#define print_hex32(data)
104#define print_bin4(data)
105#define print_bin8(data)
106#define print_bin16(data)
107#define print_bin32(data)
108#define print_bin_reverse8(data)
109#define print_bin_reverse16(data)
110#define print_bin_reverse32(data)
111#define print_val_dec(v)
112#define print_val_decs(v)
113#define print_val_hex8(v)
114#define print_val_hex16(v)
115#define print_val_hex32(v)
116#define print_val_bin8(v)
117#define print_val_bin16(v)
118#define print_val_bin32(v)
119#define print_val_bin_reverse8(v)
120#define print_val_bin_reverse16(v)
121#define print_val_bin_reverse32(v)
122
123#endif /* NO_PRINT */
124
125
126/* Backward compatiblitly for old name */
127#define pdec(data) print_dec(data)
128#define pdec16(data) print_dec(data)
129#define phex(data) print_hex8(data)
130#define phex16(data) print_hex16(data)
131#define pbin(data) print_bin8(data)
132#define pbin16(data) print_bin16(data)
133#define pbin_reverse(data) print_bin_reverse8(data)
134#define pbin_reverse16(data) print_bin_reverse16(data)
135
136
137#endif
diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h
new file mode 100644
index 000000000..199b1bedf
--- /dev/null
+++ b/tmk_core/common/progmem.h
@@ -0,0 +1,12 @@
1#ifndef PROGMEM_H
2#define PROGMEM_H 1
3
4#if defined(__AVR__)
5# include <avr/pgmspace.h>
6#elif defined(__arm__)
7# define PROGMEM
8# define pgm_read_byte(p) *(p)
9# define pgm_read_word(p) *(p)
10#endif
11
12#endif
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
new file mode 100644
index 000000000..f6c0a315d
--- /dev/null
+++ b/tmk_core/common/report.h
@@ -0,0 +1,183 @@
1/*
2Copyright 2011,2012 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#ifndef REPORT_H
19#define REPORT_H
20
21#include <stdint.h>
22#include "keycode.h"
23
24
25/* report id */
26#define REPORT_ID_MOUSE 1
27#define REPORT_ID_SYSTEM 2
28#define REPORT_ID_CONSUMER 3
29
30/* mouse buttons */
31#define MOUSE_BTN1 (1<<0)
32#define MOUSE_BTN2 (1<<1)
33#define MOUSE_BTN3 (1<<2)
34#define MOUSE_BTN4 (1<<3)
35#define MOUSE_BTN5 (1<<4)
36
37/* Consumer Page(0x0C)
38 * following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
39 */
40#define AUDIO_MUTE 0x00E2
41#define AUDIO_VOL_UP 0x00E9
42#define AUDIO_VOL_DOWN 0x00EA
43#define TRANSPORT_NEXT_TRACK 0x00B5
44#define TRANSPORT_PREV_TRACK 0x00B6
45#define TRANSPORT_STOP 0x00B7
46#define TRANSPORT_STOP_EJECT 0x00CC
47#define TRANSPORT_PLAY_PAUSE 0x00CD
48/* application launch */
49#define AL_CC_CONFIG 0x0183
50#define AL_EMAIL 0x018A
51#define AL_CALCULATOR 0x0192
52#define AL_LOCAL_BROWSER 0x0194
53/* application control */
54#define AC_SEARCH 0x0221
55#define AC_HOME 0x0223
56#define AC_BACK 0x0224
57#define AC_FORWARD 0x0225
58#define AC_STOP 0x0226
59#define AC_REFRESH 0x0227
60#define AC_BOOKMARKS 0x022A
61/* supplement for Bluegiga iWRAP HID(not supported by Windows?) */
62#define AL_LOCK 0x019E
63#define TRANSPORT_RECORD 0x00B2
64#define TRANSPORT_FAST_FORWARD 0x00B3
65#define TRANSPORT_REWIND 0x00B4
66#define TRANSPORT_EJECT 0x00B8
67#define AC_MINIMIZE 0x0206
68
69/* Generic Desktop Page(0x01) - system power control */
70#define SYSTEM_POWER_DOWN 0x0081
71#define SYSTEM_SLEEP 0x0082
72#define SYSTEM_WAKE_UP 0x0083
73
74
75/* key report size(NKRO or boot mode) */
76#if defined(PROTOCOL_PJRC) && defined(NKRO_ENABLE)
77# include "usb.h"
78# define KEYBOARD_REPORT_SIZE KBD2_SIZE
79# define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
80# define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
81
82#elif defined(PROTOCOL_LUFA) && defined(NKRO_ENABLE)
83# include "protocol/lufa/descriptor.h"
84# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
85# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
86# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
87
88#else
89# define KEYBOARD_REPORT_SIZE 8
90# define KEYBOARD_REPORT_KEYS 6
91#endif
92
93
94#ifdef __cplusplus
95extern "C" {
96#endif
97
98/*
99 * keyboard report is 8-byte array retains state of 8 modifiers and 6 keys.
100 *
101 * byte |0 |1 |2 |3 |4 |5 |6 |7
102 * -----+--------+--------+--------+--------+--------+--------+--------+--------
103 * desc |mods |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5]
104 *
105 * It is exended to 16 bytes to retain 120keys+8mods when NKRO mode.
106 *
107 * byte |0 |1 |2 |3 |4 |5 |6 |7 ... |15
108 * -----+--------+--------+--------+--------+--------+--------+--------+-------- +--------
109 * desc |mods |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6] ... |bit[14]
110 *
111 * mods retains state of 8 modifiers.
112 *
113 * bit |0 |1 |2 |3 |4 |5 |6 |7
114 * -----+--------+--------+--------+--------+--------+--------+--------+--------
115 * desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui
116 *
117 */
118typedef union {
119 uint8_t raw[KEYBOARD_REPORT_SIZE];
120 struct {
121 uint8_t mods;
122 uint8_t reserved;
123 uint8_t keys[KEYBOARD_REPORT_KEYS];
124 };
125#ifdef NKRO_ENABLE
126 struct {
127 uint8_t mods;
128 uint8_t bits[KEYBOARD_REPORT_BITS];
129 } nkro;
130#endif
131} __attribute__ ((packed)) report_keyboard_t;
132/*
133typedef struct {
134 uint8_t mods;
135 uint8_t reserved;
136 uint8_t keys[REPORT_KEYS];
137} __attribute__ ((packed)) report_keyboard_t;
138*/
139
140typedef struct {
141 uint8_t buttons;
142 int8_t x;
143 int8_t y;
144 int8_t v;
145 int8_t h;
146} __attribute__ ((packed)) report_mouse_t;
147
148
149/* keycode to system usage */
150#define KEYCODE2SYSTEM(key) \
151 (key == KC_SYSTEM_POWER ? SYSTEM_POWER_DOWN : \
152 (key == KC_SYSTEM_SLEEP ? SYSTEM_SLEEP : \
153 (key == KC_SYSTEM_WAKE ? SYSTEM_WAKE_UP : 0)))
154
155/* keycode to consumer usage */
156#define KEYCODE2CONSUMER(key) \
157 (key == KC_AUDIO_MUTE ? AUDIO_MUTE : \
158 (key == KC_AUDIO_VOL_UP ? AUDIO_VOL_UP : \
159 (key == KC_AUDIO_VOL_DOWN ? AUDIO_VOL_DOWN : \
160 (key == KC_MEDIA_NEXT_TRACK ? TRANSPORT_NEXT_TRACK : \
161 (key == KC_MEDIA_PREV_TRACK ? TRANSPORT_PREV_TRACK : \
162 (key == KC_MEDIA_FAST_FORWARD ? TRANSPORT_FAST_FORWARD : \
163 (key == KC_MEDIA_REWIND ? TRANSPORT_REWIND : \
164 (key == KC_MEDIA_STOP ? TRANSPORT_STOP : \
165 (key == KC_MEDIA_EJECT ? TRANSPORT_STOP_EJECT : \
166 (key == KC_MEDIA_PLAY_PAUSE ? TRANSPORT_PLAY_PAUSE : \
167 (key == KC_MEDIA_SELECT ? AL_CC_CONFIG : \
168 (key == KC_MAIL ? AL_EMAIL : \
169 (key == KC_CALCULATOR ? AL_CALCULATOR : \
170 (key == KC_MY_COMPUTER ? AL_LOCAL_BROWSER : \
171 (key == KC_WWW_SEARCH ? AC_SEARCH : \
172 (key == KC_WWW_HOME ? AC_HOME : \
173 (key == KC_WWW_BACK ? AC_BACK : \
174 (key == KC_WWW_FORWARD ? AC_FORWARD : \
175 (key == KC_WWW_STOP ? AC_STOP : \
176 (key == KC_WWW_REFRESH ? AC_REFRESH : \
177 (key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))))))
178
179#ifdef __cplusplus
180}
181#endif
182
183#endif
diff --git a/tmk_core/common/sendchar.h b/tmk_core/common/sendchar.h
new file mode 100644
index 000000000..7a64d00c7
--- /dev/null
+++ b/tmk_core/common/sendchar.h
@@ -0,0 +1,35 @@
1/*
2Copyright 2011 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#ifndef SENDCHAR_H
19#define SENDCHAR_H
20
21#include <stdint.h>
22
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28/* transmit a character. return 0 on success, -1 on error. */
29int8_t sendchar(uint8_t c);
30
31#ifdef __cplusplus
32}
33#endif
34
35#endif
diff --git a/tmk_core/common/sendchar_null.c b/tmk_core/common/sendchar_null.c
new file mode 100644
index 000000000..293330622
--- /dev/null
+++ b/tmk_core/common/sendchar_null.c
@@ -0,0 +1,23 @@
1/*
2Copyright 2011 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#include "sendchar.h"
18
19
20int8_t sendchar(uint8_t c)
21{
22 return 0;
23}
diff --git a/tmk_core/common/sendchar_uart.c b/tmk_core/common/sendchar_uart.c
new file mode 100644
index 000000000..0241859eb
--- /dev/null
+++ b/tmk_core/common/sendchar_uart.c
@@ -0,0 +1,25 @@
1/*
2Copyright 2011 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#include "uart.h"
18#include "sendchar.h"
19
20
21int8_t sendchar(uint8_t c)
22{
23 uart_putchar(c);
24 return 0;
25}
diff --git a/tmk_core/common/sleep_led.c b/tmk_core/common/sleep_led.c
new file mode 100644
index 000000000..dab3eb0f3
--- /dev/null
+++ b/tmk_core/common/sleep_led.c
@@ -0,0 +1,95 @@
1#include <stdint.h>
2#include <avr/io.h>
3#include <avr/interrupt.h>
4#include <avr/pgmspace.h>
5#include "led.h"
6#include "sleep_led.h"
7
8/* Software PWM
9 * ______ ______ __
10 * | ON |___OFF___| ON |___OFF___| ....
11 * |<-------------->|<-------------->|<- ....
12 * PWM period PWM period
13 *
14 * 256 interrupts/period[resolution]
15 * 64 periods/second[frequency]
16 * 256*64 interrupts/second
17 * F_CPU/(256*64) clocks/interrupt
18 */
19#define SLEEP_LED_TIMER_TOP F_CPU/(256*64)
20
21void sleep_led_init(void)
22{
23 /* Timer1 setup */
24 /* CTC mode */
25 TCCR1B |= _BV(WGM12);
26 /* Clock selelct: clk/1 */
27 TCCR1B |= _BV(CS10);
28 /* Set TOP value */
29 uint8_t sreg = SREG;
30 cli();
31 OCR1AH = (SLEEP_LED_TIMER_TOP>>8)&0xff;
32 OCR1AL = SLEEP_LED_TIMER_TOP&0xff;
33 SREG = sreg;
34}
35
36void sleep_led_enable(void)
37{
38 /* Enable Compare Match Interrupt */
39 TIMSK1 |= _BV(OCIE1A);
40}
41
42void sleep_led_disable(void)
43{
44 /* Disable Compare Match Interrupt */
45 TIMSK1 &= ~_BV(OCIE1A);
46}
47
48void sleep_led_toggle(void)
49{
50 /* Disable Compare Match Interrupt */
51 TIMSK1 ^= _BV(OCIE1A);
52}
53
54
55/* Breathing Sleep LED brighness(PWM On period) table
56 * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
57 *
58 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
59 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
60 */
61static const uint8_t breathing_table[64] PROGMEM = {
620, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
6315, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
64255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
6515, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
66};
67
68ISR(TIMER1_COMPA_vect)
69{
70 /* Software PWM
71 * timer:1111 1111 1111 1111
72 * \_____/\/ \_______/____ count(0-255)
73 * \ \______________ duration of step(4)
74 * \__________________ index of step table(0-63)
75 */
76 static union {
77 uint16_t row;
78 struct {
79 uint8_t count:8;
80 uint8_t duration:2;
81 uint8_t index:6;
82 } pwm;
83 } timer = { .row = 0 };
84
85 timer.row++;
86
87 // LED on
88 if (timer.pwm.count == 0) {
89 led_set(1<<USB_LED_CAPS_LOCK);
90 }
91 // LED off
92 if (timer.pwm.count == pgm_read_byte(&breathing_table[timer.pwm.index])) {
93 led_set(0);
94 }
95}
diff --git a/tmk_core/common/sleep_led.h b/tmk_core/common/sleep_led.h
new file mode 100644
index 000000000..6bdcf558a
--- /dev/null
+++ b/tmk_core/common/sleep_led.h
@@ -0,0 +1,21 @@
1#ifndef SLEEP_LED_H
2#define SLEEP_LED_H
3
4
5#ifdef SLEEP_LED_ENABLE
6
7void sleep_led_init(void);
8void sleep_led_enable(void);
9void sleep_led_disable(void);
10void sleep_led_toggle(void);
11
12#else
13
14#define sleep_led_init()
15#define sleep_led_enable()
16#define sleep_led_disable()
17#define sleep_led_toggle()
18
19#endif
20
21#endif
diff --git a/tmk_core/common/suspend.h b/tmk_core/common/suspend.h
new file mode 100644
index 000000000..80617a824
--- /dev/null
+++ b/tmk_core/common/suspend.h
@@ -0,0 +1,13 @@
1#ifndef SUSPEND_H
2#define SUSPEND_H
3
4#include <stdint.h>
5#include <stdbool.h>
6
7
8void suspend_idle(uint8_t timeout);
9void suspend_power_down(void);
10bool suspend_wakeup_condition(void);
11void suspend_wakeup_init(void);
12
13#endif
diff --git a/tmk_core/common/timer.h b/tmk_core/common/timer.h
new file mode 100644
index 000000000..fe23f87ae
--- /dev/null
+++ b/tmk_core/common/timer.h
@@ -0,0 +1,53 @@
1/*
2Copyright 2011 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#ifndef TIMER_H
19#define TIMER_H 1
20
21#include <stdint.h>
22
23#if defined(__AVR__)
24#include "avr/timer_avr.h"
25#endif
26
27
28#define TIMER_DIFF(a, b, max) ((a) >= (b) ? (a) - (b) : (max) - (b) + (a))
29#define TIMER_DIFF_8(a, b) TIMER_DIFF(a, b, UINT8_MAX)
30#define TIMER_DIFF_16(a, b) TIMER_DIFF(a, b, UINT16_MAX)
31#define TIMER_DIFF_32(a, b) TIMER_DIFF(a, b, UINT32_MAX)
32#define TIMER_DIFF_RAW(a, b) TIMER_DIFF_8(a, b)
33
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39extern volatile uint32_t timer_count;
40
41
42void timer_init(void);
43void timer_clear(void);
44uint16_t timer_read(void);
45uint32_t timer_read32(void);
46uint16_t timer_elapsed(uint16_t last);
47uint32_t timer_elapsed32(uint32_t last);
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
diff --git a/tmk_core/common/uart.c b/tmk_core/common/uart.c
new file mode 100644
index 000000000..c17649b08
--- /dev/null
+++ b/tmk_core/common/uart.c
@@ -0,0 +1,129 @@
1// TODO: Teensy support(ATMega32u4/AT90USB128)
2// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
3/* UART Example for Teensy USB Development Board
4 * http://www.pjrc.com/teensy/
5 * Copyright (c) 2009 PJRC.COM, LLC
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26// Version 1.0: Initial Release
27// Version 1.1: Add support for Teensy 2.0, minor optimizations
28
29
30#include <avr/io.h>
31#include <avr/interrupt.h>
32
33#include "uart.h"
34
35// These buffers may be any size from 2 to 256 bytes.
36#define RX_BUFFER_SIZE 64
37#define TX_BUFFER_SIZE 40
38
39static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
40static volatile uint8_t tx_buffer_head;
41static volatile uint8_t tx_buffer_tail;
42static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
43static volatile uint8_t rx_buffer_head;
44static volatile uint8_t rx_buffer_tail;
45
46// Initialize the UART
47void uart_init(uint32_t baud)
48{
49 cli();
50 UBRR0 = (F_CPU / 4 / baud - 1) / 2;
51 UCSR0A = (1<<U2X0);
52 UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
53 UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
54 tx_buffer_head = tx_buffer_tail = 0;
55 rx_buffer_head = rx_buffer_tail = 0;
56 sei();
57}
58
59// Transmit a byte
60void uart_putchar(uint8_t c)
61{
62 uint8_t i;
63
64 i = tx_buffer_head + 1;
65 if (i >= TX_BUFFER_SIZE) i = 0;
66 while (tx_buffer_tail == i) ; // wait until space in buffer
67 //cli();
68 tx_buffer[i] = c;
69 tx_buffer_head = i;
70 UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0);
71 //sei();
72}
73
74// Receive a byte
75uint8_t uart_getchar(void)
76{
77 uint8_t c, i;
78
79 while (rx_buffer_head == rx_buffer_tail) ; // wait for character
80 i = rx_buffer_tail + 1;
81 if (i >= RX_BUFFER_SIZE) i = 0;
82 c = rx_buffer[i];
83 rx_buffer_tail = i;
84 return c;
85}
86
87// Return the number of bytes waiting in the receive buffer.
88// Call this before uart_getchar() to check if it will need
89// to wait for a byte to arrive.
90uint8_t uart_available(void)
91{
92 uint8_t head, tail;
93
94 head = rx_buffer_head;
95 tail = rx_buffer_tail;
96 if (head >= tail) return head - tail;
97 return RX_BUFFER_SIZE + head - tail;
98}
99
100// Transmit Interrupt
101ISR(USART_UDRE_vect)
102{
103 uint8_t i;
104
105 if (tx_buffer_head == tx_buffer_tail) {
106 // buffer is empty, disable transmit interrupt
107 UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
108 } else {
109 i = tx_buffer_tail + 1;
110 if (i >= TX_BUFFER_SIZE) i = 0;
111 UDR0 = tx_buffer[i];
112 tx_buffer_tail = i;
113 }
114}
115
116// Receive Interrupt
117ISR(USART_RX_vect)
118{
119 uint8_t c, i;
120
121 c = UDR0;
122 i = rx_buffer_head + 1;
123 if (i >= RX_BUFFER_SIZE) i = 0;
124 if (i != rx_buffer_tail) {
125 rx_buffer[i] = c;
126 rx_buffer_head = i;
127 }
128}
129
diff --git a/tmk_core/common/uart.h b/tmk_core/common/uart.h
new file mode 100644
index 000000000..41136a396
--- /dev/null
+++ b/tmk_core/common/uart.h
@@ -0,0 +1,11 @@
1#ifndef _uart_included_h_
2#define _uart_included_h_
3
4#include <stdint.h>
5
6void uart_init(uint32_t baud);
7void uart_putchar(uint8_t c);
8uint8_t uart_getchar(void);
9uint8_t uart_available(void);
10
11#endif
diff --git a/tmk_core/common/util.c b/tmk_core/common/util.c
new file mode 100644
index 000000000..7e0d54299
--- /dev/null
+++ b/tmk_core/common/util.c
@@ -0,0 +1,101 @@
1/*
2Copyright 2011 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 "util.h"
19
20// bit population - return number of on-bit
21uint8_t bitpop(uint8_t bits)
22{
23 uint8_t c;
24 for (c = 0; bits; c++)
25 bits &= bits - 1;
26 return c;
27/*
28 const uint8_t bit_count[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
29 return bit_count[bits>>4] + bit_count[bits&0x0F]
30*/
31}
32
33uint8_t bitpop16(uint16_t bits)
34{
35 uint8_t c;
36 for (c = 0; bits; c++)
37 bits &= bits - 1;
38 return c;
39}
40
41uint8_t bitpop32(uint32_t bits)
42{
43 uint8_t c;
44 for (c = 0; bits; c++)
45 bits &= bits - 1;
46 return c;
47}
48
49// most significant on-bit - return highest location of on-bit
50// NOTE: return 0 when bit0 is on or all bits are off
51uint8_t biton(uint8_t bits)
52{
53 uint8_t n = 0;
54 if (bits >> 4) { bits >>= 4; n += 4;}
55 if (bits >> 2) { bits >>= 2; n += 2;}
56 if (bits >> 1) { bits >>= 1; n += 1;}
57 return n;
58}
59
60uint8_t biton16(uint16_t bits)
61{
62 uint8_t n = 0;
63 if (bits >> 8) { bits >>= 8; n += 8;}
64 if (bits >> 4) { bits >>= 4; n += 4;}
65 if (bits >> 2) { bits >>= 2; n += 2;}
66 if (bits >> 1) { bits >>= 1; n += 1;}
67 return n;
68}
69
70uint8_t biton32(uint32_t bits)
71{
72 uint8_t n = 0;
73 if (bits >>16) { bits >>=16; n +=16;}
74 if (bits >> 8) { bits >>= 8; n += 8;}
75 if (bits >> 4) { bits >>= 4; n += 4;}
76 if (bits >> 2) { bits >>= 2; n += 2;}
77 if (bits >> 1) { bits >>= 1; n += 1;}
78 return n;
79}
80
81
82
83uint8_t bitrev(uint8_t bits)
84{
85 bits = (bits & 0x0f)<<4 | (bits & 0xf0)>>4;
86 bits = (bits & 0b00110011)<<2 | (bits & 0b11001100)>>2;
87 bits = (bits & 0b01010101)<<1 | (bits & 0b10101010)>>1;
88 return bits;
89}
90
91uint16_t bitrev16(uint16_t bits)
92{
93 bits = bitrev(bits & 0x00ff)<<8 | bitrev((bits & 0xff00)>>8);
94 return bits;
95}
96
97uint32_t bitrev32(uint32_t bits)
98{
99 bits = (uint32_t)bitrev16(bits & 0x0000ffff)<<16 | bitrev16((bits & 0xffff0000)>>16);
100 return bits;
101}
diff --git a/tmk_core/common/util.h b/tmk_core/common/util.h
new file mode 100644
index 000000000..7451cc084
--- /dev/null
+++ b/tmk_core/common/util.h
@@ -0,0 +1,43 @@
1/*
2Copyright 2011 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#ifndef UTIL_H
19#define UTIL_H
20
21#include <stdint.h>
22
23// convert to L string
24#define LSTR(s) XLSTR(s)
25#define XLSTR(s) L ## #s
26// convert to string
27#define STR(s) XSTR(s)
28#define XSTR(s) #s
29
30
31uint8_t bitpop(uint8_t bits);
32uint8_t bitpop16(uint16_t bits);
33uint8_t bitpop32(uint32_t bits);
34
35uint8_t biton(uint8_t bits);
36uint8_t biton16(uint16_t bits);
37uint8_t biton32(uint32_t bits);
38
39uint8_t bitrev(uint8_t bits);
40uint16_t bitrev16(uint16_t bits);
41uint32_t bitrev32(uint32_t bits);
42
43#endif
diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h
new file mode 100644
index 000000000..40d00b0c7
--- /dev/null
+++ b/tmk_core/common/wait.h
@@ -0,0 +1,20 @@
1#ifndef WAIT_H
2#define WAIT_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#if defined(__AVR__)
9# include <util/delay.h>
10# define wait_ms(ms) _delay_ms(ms)
11# define wait_us(us) _delay_us(us)
12#elif defined(__arm__)
13# include "wait_api.h"
14#endif
15
16#ifdef __cplusplus
17}
18#endif
19
20#endif