diff options
| author | tmk <hasu@tmk-kbd.com> | 2015-04-10 01:32:04 +0900 |
|---|---|---|
| committer | tmk <hasu@tmk-kbd.com> | 2015-04-10 01:32:04 +0900 |
| commit | 1a02ebcc612e9a9c0d87e02295c7258de3a70ccc (patch) | |
| tree | e517f3c70bb2d542797e57d13e9023c84af230fb /tmk_core/common | |
| parent | 6746e37088ce8ba03529c1226bd216705edb2b1f (diff) | |
| parent | a074364c3731d66b56d988c8a6c960a83ea0e0a1 (diff) | |
| download | qmk_firmware-1a02ebcc612e9a9c0d87e02295c7258de3a70ccc.tar.gz qmk_firmware-1a02ebcc612e9a9c0d87e02295c7258de3a70ccc.zip | |
Merge commit 'a074364c3731d66b56d988c8a6c960a83ea0e0a1' as 'tmk_core'
Diffstat (limited to 'tmk_core/common')
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 | /* | ||
| 2 | Copyright 2012,2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | |||
| 37 | void 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 | |||
| 56 | void 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 | */ | ||
| 345 | void 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 | |||
| 420 | void 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 | |||
| 475 | void register_mods(uint8_t mods) | ||
| 476 | { | ||
| 477 | if (mods) { | ||
| 478 | add_mods(mods); | ||
| 479 | send_keyboard_report(); | ||
| 480 | } | ||
| 481 | } | ||
| 482 | |||
| 483 | void unregister_mods(uint8_t mods) | ||
| 484 | { | ||
| 485 | if (mods) { | ||
| 486 | del_mods(mods); | ||
| 487 | send_keyboard_report(); | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | void clear_keyboard(void) | ||
| 492 | { | ||
| 493 | clear_mods(); | ||
| 494 | clear_keyboard_but_mods(); | ||
| 495 | } | ||
| 496 | |||
| 497 | void 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 | |||
| 512 | bool 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 | */ | ||
| 534 | void 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 | |||
| 539 | void 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 | |||
| 547 | void 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 | /* | ||
| 2 | Copyright 2012,2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | ||
| 29 | extern "C" { | ||
| 30 | #endif | ||
| 31 | |||
| 32 | /* tapping count and state */ | ||
| 33 | typedef 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 */ | ||
| 42 | typedef 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 */ | ||
| 50 | void action_exec(keyevent_t event); | ||
| 51 | |||
| 52 | /* action for key */ | ||
| 53 | action_t action_for_key(uint8_t layer, keypos_t key); | ||
| 54 | |||
| 55 | /* macro */ | ||
| 56 | const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); | ||
| 57 | |||
| 58 | /* user defined special function */ | ||
| 59 | void action_function(keyrecord_t *record, uint8_t id, uint8_t opt); | ||
| 60 | |||
| 61 | /* Utilities for actions. */ | ||
| 62 | void process_action(keyrecord_t *record); | ||
| 63 | void register_code(uint8_t code); | ||
| 64 | void unregister_code(uint8_t code); | ||
| 65 | void register_mods(uint8_t mods); | ||
| 66 | void unregister_mods(uint8_t mods); | ||
| 67 | //void set_mods(uint8_t mods); | ||
| 68 | void clear_keyboard(void); | ||
| 69 | void clear_keyboard_but_mods(void); | ||
| 70 | void layer_switch(uint8_t new_layer); | ||
| 71 | bool is_tap_key(keypos_t key); | ||
| 72 | |||
| 73 | /* debug */ | ||
| 74 | void debug_event(keyevent_t event); | ||
| 75 | void debug_record(keyrecord_t record); | ||
| 76 | void 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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | */ | ||
| 99 | enum 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 | */ | ||
| 136 | typedef 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 | */ | ||
| 199 | enum 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 | }; | ||
| 209 | enum 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 | */ | ||
| 224 | enum 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 | */ | ||
| 237 | enum layer_param_on { | ||
| 238 | ON_PRESS = 1, | ||
| 239 | ON_RELEASE = 2, | ||
| 240 | ON_BOTH = 3, | ||
| 241 | }; | ||
| 242 | enum 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 | }; | ||
| 248 | enum 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 | */ | ||
| 288 | enum 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 */ | ||
| 308 | enum 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 | */ | ||
| 17 | uint32_t default_layer_state = 0; | ||
| 18 | |||
| 19 | static 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 | |||
| 28 | void default_layer_debug(void) | ||
| 29 | { | ||
| 30 | dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state)); | ||
| 31 | } | ||
| 32 | |||
| 33 | void default_layer_set(uint32_t state) | ||
| 34 | { | ||
| 35 | default_layer_state_set(state); | ||
| 36 | } | ||
| 37 | |||
| 38 | #ifndef NO_ACTION_LAYER | ||
| 39 | void default_layer_or(uint32_t state) | ||
| 40 | { | ||
| 41 | default_layer_state_set(default_layer_state | state); | ||
| 42 | } | ||
| 43 | void default_layer_and(uint32_t state) | ||
| 44 | { | ||
| 45 | default_layer_state_set(default_layer_state & state); | ||
| 46 | } | ||
| 47 | void 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 | */ | ||
| 58 | uint32_t layer_state = 0; | ||
| 59 | |||
| 60 | static 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 | |||
| 69 | void layer_clear(void) | ||
| 70 | { | ||
| 71 | layer_state_set(0); | ||
| 72 | } | ||
| 73 | |||
| 74 | void layer_move(uint8_t layer) | ||
| 75 | { | ||
| 76 | layer_state_set(1UL<<layer); | ||
| 77 | } | ||
| 78 | |||
| 79 | void layer_on(uint8_t layer) | ||
| 80 | { | ||
| 81 | layer_state_set(layer_state | (1UL<<layer)); | ||
| 82 | } | ||
| 83 | |||
| 84 | void layer_off(uint8_t layer) | ||
| 85 | { | ||
| 86 | layer_state_set(layer_state & ~(1UL<<layer)); | ||
| 87 | } | ||
| 88 | |||
| 89 | void layer_invert(uint8_t layer) | ||
| 90 | { | ||
| 91 | layer_state_set(layer_state ^ (1UL<<layer)); | ||
| 92 | } | ||
| 93 | |||
| 94 | void layer_or(uint32_t state) | ||
| 95 | { | ||
| 96 | layer_state_set(layer_state | state); | ||
| 97 | } | ||
| 98 | void layer_and(uint32_t state) | ||
| 99 | { | ||
| 100 | layer_state_set(layer_state & state); | ||
| 101 | } | ||
| 102 | void layer_xor(uint32_t state) | ||
| 103 | { | ||
| 104 | layer_state_set(layer_state ^ state); | ||
| 105 | } | ||
| 106 | |||
| 107 | void layer_debug(void) | ||
| 108 | { | ||
| 109 | dprintf("%08lX(%u)", layer_state, biton32(layer_state)); | ||
| 110 | } | ||
| 111 | #endif | ||
| 112 | |||
| 113 | |||
| 114 | |||
| 115 | action_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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | */ | ||
| 28 | extern uint32_t default_layer_state; | ||
| 29 | void default_layer_debug(void); | ||
| 30 | void default_layer_set(uint32_t state); | ||
| 31 | |||
| 32 | #ifndef NO_ACTION_LAYER | ||
| 33 | /* bitwise operation */ | ||
| 34 | void default_layer_or(uint32_t state); | ||
| 35 | void default_layer_and(uint32_t state); | ||
| 36 | void 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 | ||
| 48 | extern uint32_t layer_state; | ||
| 49 | void layer_debug(void); | ||
| 50 | void layer_clear(void); | ||
| 51 | void layer_move(uint8_t layer); | ||
| 52 | void layer_on(uint8_t layer); | ||
| 53 | void layer_off(uint8_t layer); | ||
| 54 | void layer_invert(uint8_t layer); | ||
| 55 | /* bitwise operation */ | ||
| 56 | void layer_or(uint32_t state); | ||
| 57 | void layer_and(uint32_t state); | ||
| 58 | void 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 */ | ||
| 75 | action_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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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++)) | ||
| 32 | void 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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | |||
| 27 | typedef uint8_t macro_t; | ||
| 28 | |||
| 29 | |||
| 30 | #ifndef NO_ACTION_MACRO | ||
| 31 | void 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 | */ | ||
| 56 | enum 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 | |||
| 24 | static keyrecord_t tapping_key = {}; | ||
| 25 | static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {}; | ||
| 26 | static uint8_t waiting_buffer_head = 0; | ||
| 27 | static uint8_t waiting_buffer_tail = 0; | ||
| 28 | |||
| 29 | static bool process_tapping(keyrecord_t *record); | ||
| 30 | static bool waiting_buffer_enq(keyrecord_t record); | ||
| 31 | static void waiting_buffer_clear(void); | ||
| 32 | static bool waiting_buffer_typed(keyevent_t event); | ||
| 33 | static bool waiting_buffer_has_anykey_pressed(void); | ||
| 34 | static void waiting_buffer_scan_tap(void); | ||
| 35 | static void debug_tapping_key(void); | ||
| 36 | static void debug_waiting_buffer(void); | ||
| 37 | |||
| 38 | |||
| 39 | void 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. */ | ||
| 79 | bool 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 | */ | ||
| 293 | bool 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 | |||
| 311 | void waiting_buffer_clear(void) | ||
| 312 | { | ||
| 313 | waiting_buffer_head = 0; | ||
| 314 | waiting_buffer_tail = 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | bool 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 | |||
| 327 | bool 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 */ | ||
| 336 | void 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 | */ | ||
| 362 | static void debug_tapping_key(void) | ||
| 363 | { | ||
| 364 | debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n"); | ||
| 365 | } | ||
| 366 | |||
| 367 | static 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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | ||
| 36 | void 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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #include "host.h" | ||
| 18 | #include "report.h" | ||
| 19 | #include "debug.h" | ||
| 20 | #include "action_util.h" | ||
| 21 | #include "timer.h" | ||
| 22 | |||
| 23 | static inline void add_key_byte(uint8_t code); | ||
| 24 | static inline void del_key_byte(uint8_t code); | ||
| 25 | #ifdef NKRO_ENABLE | ||
| 26 | static inline void add_key_bit(uint8_t code); | ||
| 27 | static inline void del_key_bit(uint8_t code); | ||
| 28 | #endif | ||
| 29 | |||
| 30 | static uint8_t real_mods = 0; | ||
| 31 | static 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) | ||
| 38 | static int8_t cb_head = 0; | ||
| 39 | static int8_t cb_tail = 0; | ||
| 40 | static int8_t cb_count = 0; | ||
| 41 | #endif | ||
| 42 | |||
| 43 | // TODO: pointer variable is not needed | ||
| 44 | //report_keyboard_t keyboard_report = {}; | ||
| 45 | report_keyboard_t *keyboard_report = &(report_keyboard_t){}; | ||
| 46 | |||
| 47 | #ifndef NO_ACTION_ONESHOT | ||
| 48 | static int8_t oneshot_mods = 0; | ||
| 49 | #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) | ||
| 50 | static int16_t oneshot_time = 0; | ||
| 51 | #endif | ||
| 52 | #endif | ||
| 53 | |||
| 54 | |||
| 55 | void 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 */ | ||
| 76 | void 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 | |||
| 87 | void 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 | |||
| 98 | void 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 */ | ||
| 108 | uint8_t get_mods(void) { return real_mods; } | ||
| 109 | void add_mods(uint8_t mods) { real_mods |= mods; } | ||
| 110 | void del_mods(uint8_t mods) { real_mods &= ~mods; } | ||
| 111 | void set_mods(uint8_t mods) { real_mods = mods; } | ||
| 112 | void clear_mods(void) { real_mods = 0; } | ||
| 113 | |||
| 114 | /* weak modifier */ | ||
| 115 | uint8_t get_weak_mods(void) { return weak_mods; } | ||
| 116 | void add_weak_mods(uint8_t mods) { weak_mods |= mods; } | ||
| 117 | void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; } | ||
| 118 | void set_weak_mods(uint8_t mods) { weak_mods = mods; } | ||
| 119 | void clear_weak_mods(void) { weak_mods = 0; } | ||
| 120 | |||
| 121 | /* Oneshot modifier */ | ||
| 122 | #ifndef NO_ACTION_ONESHOT | ||
| 123 | void 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 | } | ||
| 130 | void 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 | */ | ||
| 145 | uint8_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 | |||
| 155 | uint8_t has_anymod(void) | ||
| 156 | { | ||
| 157 | return bitpop(real_mods); | ||
| 158 | } | ||
| 159 | |||
| 160 | uint8_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 */ | ||
| 187 | static 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 | |||
| 253 | static 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 | ||
| 290 | static 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 | |||
| 299 | static 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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #ifndef ACTION_UTIL_H | ||
| 18 | #define ACTION_UTIL_H | ||
| 19 | |||
| 20 | #include <stdint.h> | ||
| 21 | #include "report.h" | ||
| 22 | |||
| 23 | #ifdef __cplusplus | ||
| 24 | extern "C" { | ||
| 25 | #endif | ||
| 26 | |||
| 27 | extern report_keyboard_t *keyboard_report; | ||
| 28 | |||
| 29 | void send_keyboard_report(void); | ||
| 30 | |||
| 31 | /* key */ | ||
| 32 | void add_key(uint8_t key); | ||
| 33 | void del_key(uint8_t key); | ||
| 34 | void clear_keys(void); | ||
| 35 | |||
| 36 | /* modifier */ | ||
| 37 | uint8_t get_mods(void); | ||
| 38 | void add_mods(uint8_t mods); | ||
| 39 | void del_mods(uint8_t mods); | ||
| 40 | void set_mods(uint8_t mods); | ||
| 41 | void clear_mods(void); | ||
| 42 | |||
| 43 | /* weak modifier */ | ||
| 44 | uint8_t get_weak_mods(void); | ||
| 45 | void add_weak_mods(uint8_t mods); | ||
| 46 | void del_weak_mods(uint8_t mods); | ||
| 47 | void set_weak_mods(uint8_t mods); | ||
| 48 | void clear_weak_mods(void); | ||
| 49 | |||
| 50 | /* oneshot modifier */ | ||
| 51 | void set_oneshot_mods(uint8_t mods); | ||
| 52 | void clear_oneshot_mods(void); | ||
| 53 | void oneshot_toggle(void); | ||
| 54 | void oneshot_enable(void); | ||
| 55 | void oneshot_disable(void); | ||
| 56 | |||
| 57 | /* inspect */ | ||
| 58 | uint8_t has_anykey(void); | ||
| 59 | uint8_t has_anymod(void); | ||
| 60 | uint8_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 | ||
| 35 | uint32_t reset_key __attribute__ ((section (".noinit"))); | ||
| 36 | |||
| 37 | /* initialize MCU status by watchdog reset */ | ||
| 38 | void 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() */ | ||
| 61 | void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3"))); | ||
| 62 | void 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 | */ | ||
| 87 | void 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 | |||
| 6 | void 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 | |||
| 18 | void eeconfig_enable(void) | ||
| 19 | { | ||
| 20 | eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); | ||
| 21 | } | ||
| 22 | |||
| 23 | void eeconfig_disable(void) | ||
| 24 | { | ||
| 25 | eeprom_write_word(EECONFIG_MAGIC, 0xFFFF); | ||
| 26 | } | ||
| 27 | |||
| 28 | bool eeconfig_is_enabled(void) | ||
| 29 | { | ||
| 30 | return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER); | ||
| 31 | } | ||
| 32 | |||
| 33 | uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); } | ||
| 34 | void eeconfig_write_debug(uint8_t val) { eeprom_write_byte(EECONFIG_DEBUG, val); } | ||
| 35 | |||
| 36 | uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); } | ||
| 37 | void eeconfig_write_default_layer(uint8_t val) { eeprom_write_byte(EECONFIG_DEFAULT_LAYER, val); } | ||
| 38 | |||
| 39 | uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMAP); } | ||
| 40 | void eeconfig_write_keymap(uint8_t val) { eeprom_write_byte(EECONFIG_KEYMAP, val); } | ||
| 41 | |||
| 42 | #ifdef BACKLIGHT_ENABLE | ||
| 43 | uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); } | ||
| 44 | void 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 | |||
| 33 | void 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 | */ | ||
| 56 | static uint8_t wdt_timeout = 0; | ||
| 57 | static 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 | |||
| 83 | void suspend_power_down(void) | ||
| 84 | { | ||
| 85 | power_down(WDTO_15MS); | ||
| 86 | } | ||
| 87 | |||
| 88 | bool 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 | ||
| 100 | void 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 */ | ||
| 111 | ISR(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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <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; }} | ||
| 27 | volatile uint32_t timer_count = 0; | ||
| 28 | |||
| 29 | void 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 | |||
| 52 | inline | ||
| 53 | void timer_clear(void) | ||
| 54 | { | ||
| 55 | uint8_t sreg = SREG; | ||
| 56 | cli(); | ||
| 57 | timer_count = 0; | ||
| 58 | SREG = sreg; | ||
| 59 | } | ||
| 60 | |||
| 61 | inline | ||
| 62 | uint16_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 | |||
| 74 | inline | ||
| 75 | uint32_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 | |||
| 87 | inline | ||
| 88 | uint16_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 | |||
| 100 | inline | ||
| 101 | uint32_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?) | ||
| 114 | ISR(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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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. | ||
| 51 | xfunc_out: .ds.w 1 | ||
| 52 | .section .text | ||
| 53 | |||
| 54 | |||
| 55 | .func xputc | ||
| 56 | .global xputc | ||
| 57 | xputc: | ||
| 58 | #if CR_CRLF | ||
| 59 | cpi r24, 10 ;LF --> CRLF | ||
| 60 | brne 1f ; | ||
| 61 | ldi r24, 13 ; | ||
| 62 | rcall 1f ; | ||
| 63 | ldi r24, 10 ;/ | ||
| 64 | 1: | ||
| 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 | ||
| 73 | 2: 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 | ||
| 88 | xputs: | ||
| 89 | _MOVW ZH,ZL, r25,r24 ; Z = pointer to rom string | ||
| 90 | 1: _LPMI r24 | ||
| 91 | cpi r24, 0 | ||
| 92 | breq 2f | ||
| 93 | rcall xputc | ||
| 94 | rjmp 1b | ||
| 95 | 2: 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 | ||
| 109 | xitoa: | ||
| 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 ;/ | ||
| 128 | 0: 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 | ||
| 133 | 1: ldi r21, 32 ;r26 = r25:r22 % r20 | ||
| 134 | clr r26 ;r25:r22 /= r20 | ||
| 135 | 2: 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 ; | ||
| 144 | 3: dec r21 ; | ||
| 145 | brne 2b ;/ | ||
| 146 | cpi r26, 10 ;r26 is a numeral digit '0'-'F' | ||
| 147 | brcs 4f ; | ||
| 148 | subi r26, -7 ; | ||
| 149 | 4: 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 ;/ | ||
| 162 | 5: cp r31, r18 ;Filler | ||
| 163 | brcc 6f ; | ||
| 164 | push r19 ; | ||
| 165 | inc r31 ; | ||
| 166 | rjmp 5b ;/ | ||
| 167 | |||
| 168 | 6: 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 | ||
| 190 | xvprintf: | ||
| 191 | ld ZL, Y+ ;Z = pointer to format string | ||
| 192 | ld ZH, Y+ ;/ | ||
| 193 | |||
| 194 | 0: _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 ;/ | ||
| 199 | 1: rcall xputc ;Put a normal character | ||
| 200 | rjmp 0b ;/ | ||
| 201 | 90: ret | ||
| 202 | |||
| 203 | 20: 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 ;/ | ||
| 211 | 22: _LPMI r21 ;Get width | ||
| 212 | 23: 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 | |||
| 224 | 24: brtc 25f ;get value (low word) | ||
| 225 | neg r18 ; | ||
| 226 | 25: 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 ;/ | ||
| 244 | 26: 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 ;/ | ||
| 253 | 27: 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 | ||
| 263 | 40: push ZH ;Output the value | ||
| 264 | push ZL ; | ||
| 265 | rcall xitoa ; | ||
| 266 | 42: pop ZL ; | ||
| 267 | pop ZH ; | ||
| 268 | rjmp 0b ;/ | ||
| 269 | |||
| 270 | 50: push ZH ;Put a string on the RAM | ||
| 271 | push ZL | ||
| 272 | _MOVW ZH,ZL, r25,r24 | ||
| 273 | 51: ld r24, Z+ | ||
| 274 | cpi r24, 0 | ||
| 275 | breq 42b | ||
| 276 | rcall xputc | ||
| 277 | rjmp 51b | ||
| 278 | |||
| 279 | 60: 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 | ||
| 308 | putram: | ||
| 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 | ||
| 402 | xatoi: | ||
| 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 ;/ | ||
| 415 | 40: adiw ZL, 1 ;Z++; | ||
| 416 | 41: 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 ;} | ||
| 424 | 42: 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 ;} | ||
| 438 | 43: cpi r22, 'x' ;if(r22 != 'x') error; | ||
| 439 | brne 51f ;/ | ||
| 440 | ldi r25, 16 ;r25 = 16; | ||
| 441 | |||
| 442 | 50: adiw ZL, 1 ;Z++; | ||
| 443 | ld r22, Z ;r22 = *Z; | ||
| 444 | 51: 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 ;/ | ||
| 449 | 52: 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 ;} | ||
| 456 | 53: cp r22, r25 ;if(r22 >= r25) error; | ||
| 457 | brcc 70f ;/ | ||
| 458 | 60: ldi r24, 33 ;r21:r18 *= r25; | ||
| 459 | sub r23, r23 ; | ||
| 460 | 61: brcc 62f ; | ||
| 461 | add r23, r25 ; | ||
| 462 | 62: 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 | |||
| 475 | 70: ldi r24, 0 | ||
| 476 | rjmp 81f | ||
| 477 | 80: ldi r24, 1 | ||
| 478 | 81: 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 | ||
| 488 | 82: 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 | ||
| 12 | extern "C" { | ||
| 13 | #endif | ||
| 14 | |||
| 15 | extern 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 | |||
| 22 | void 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 | /*-----------------------------------------------------------------------------*/ | ||
| 30 | void xputs(const char *string_p); | ||
| 31 | |||
| 32 | /* The string placed in the ROM is forwarded to xputc() directly. | ||
| 33 | */ | ||
| 34 | |||
| 35 | |||
| 36 | /*-----------------------------------------------------------------------------*/ | ||
| 37 | void 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 | |||
| 58 | void __xprintf(const char *format_p, ...); /* Send formatted string to the registered device */ | ||
| 59 | void __xsprintf(char*, const char *format_p, ...); /* Put formatted string to the memory */ | ||
| 60 | void __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 | /*-----------------------------------------------------------------------------*/ | ||
| 89 | char 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 | /* | ||
| 2 | Copyright 2013 Mathias Andersson <wraul@dbox.se> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include "backlight.h" | ||
| 19 | #include "eeconfig.h" | ||
| 20 | #include "debug.h" | ||
| 21 | |||
| 22 | backlight_config_t backlight_config; | ||
| 23 | |||
| 24 | void 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 | |||
| 34 | void 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 | |||
| 46 | void 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 | |||
| 58 | void 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 | |||
| 66 | void 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 | |||
| 79 | void 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 | /* | ||
| 2 | Copyright 2013 Mathias Andersson <wraul@dbox.se> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef BACKLIGHT_H | ||
| 19 | #define BACKLIGHT_H | ||
| 20 | |||
| 21 | #include <stdint.h> | ||
| 22 | #include <stdbool.h> | ||
| 23 | |||
| 24 | typedef union { | ||
| 25 | uint8_t raw; | ||
| 26 | struct { | ||
| 27 | bool enable :1; | ||
| 28 | uint8_t level :7; | ||
| 29 | }; | ||
| 30 | } backlight_config_t; | ||
| 31 | |||
| 32 | void backlight_init(void); | ||
| 33 | void backlight_increase(void); | ||
| 34 | void backlight_decrease(void); | ||
| 35 | void backlight_toggle(void); | ||
| 36 | void backlight_step(void); | ||
| 37 | void backlight_set(uint8_t level); | ||
| 38 | void 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef BOOTLOADER_H | ||
| 19 | #define BOOTLOADER_H | ||
| 20 | |||
| 21 | |||
| 22 | /* give code for your bootloader to come up if needed */ | ||
| 23 | void 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 | |||
| 14 | void 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 | |||
| 108 | static 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 | |||
| 123 | bool 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 | |||
| 97 | void bootmagic(void); | ||
| 98 | bool 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | |||
| 53 | static bool command_common(uint8_t code); | ||
| 54 | static void command_common_help(void); | ||
| 55 | static bool command_console(uint8_t code); | ||
| 56 | static void command_console_help(void); | ||
| 57 | #ifdef MOUSEKEY_ENABLE | ||
| 58 | static bool mousekey_console(uint8_t code); | ||
| 59 | static void mousekey_console_help(void); | ||
| 60 | #endif | ||
| 61 | |||
| 62 | static uint8_t numkey2num(uint8_t code); | ||
| 63 | static void switch_default_layer(uint8_t layer); | ||
| 64 | |||
| 65 | |||
| 66 | command_state_t command_state = ONESHOT; | ||
| 67 | |||
| 68 | |||
| 69 | bool 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. */ | ||
| 97 | bool command_extra(uint8_t code) __attribute__ ((weak)); | ||
| 98 | bool command_extra(uint8_t code) | ||
| 99 | { | ||
| 100 | return false; | ||
| 101 | } | ||
| 102 | |||
| 103 | bool command_console_extra(uint8_t code) __attribute__ ((weak)); | ||
| 104 | bool command_console_extra(uint8_t code) | ||
| 105 | { | ||
| 106 | return false; | ||
| 107 | } | ||
| 108 | |||
| 109 | |||
| 110 | /*********************************************************** | ||
| 111 | * Command common | ||
| 112 | ***********************************************************/ | ||
| 113 | static 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 | ||
| 142 | static 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 | |||
| 176 | static 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 | ***********************************************************/ | ||
| 383 | static 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 | |||
| 392 | static 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 | ***********************************************************/ | ||
| 425 | static uint8_t mousekey_param = 0; | ||
| 426 | |||
| 427 | static 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"); | ||
| 439 | static 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 | |||
| 487 | static 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 | |||
| 535 | static 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 | |||
| 557 | static 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 | ***********************************************************/ | ||
| 621 | static 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 | |||
| 638 | static 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef COMMAND_H | ||
| 19 | #define COMMAND | ||
| 20 | |||
| 21 | /* TODO: Refactoring */ | ||
| 22 | typedef enum { ONESHOT, CONSOLE, MOUSEKEY } command_state_t; | ||
| 23 | extern command_state_t command_state; | ||
| 24 | |||
| 25 | /* This allows to extend commands. Return false when command is not processed. */ | ||
| 26 | bool command_extra(uint8_t code); | ||
| 27 | bool command_console_extra(uint8_t code); | ||
| 28 | |||
| 29 | #ifdef COMMAND_ENABLE | ||
| 30 | bool 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 | |||
| 6 | debug_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef DEBUG_H | ||
| 19 | #define DEBUG_H 1 | ||
| 20 | |||
| 21 | #include <stdbool.h> | ||
| 22 | #include "print.h" | ||
| 23 | |||
| 24 | |||
| 25 | #ifdef __cplusplus | ||
| 26 | extern "C" { | ||
| 27 | #endif | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Debug output control | ||
| 31 | */ | ||
| 32 | typedef 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 | |||
| 43 | extern 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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 | |||
| 53 | bool eeconfig_is_enabled(void); | ||
| 54 | |||
| 55 | void eeconfig_init(void); | ||
| 56 | |||
| 57 | void eeconfig_enable(void); | ||
| 58 | |||
| 59 | void eeconfig_disable(void); | ||
| 60 | |||
| 61 | uint8_t eeconfig_read_debug(void); | ||
| 62 | void eeconfig_write_debug(uint8_t val); | ||
| 63 | |||
| 64 | uint8_t eeconfig_read_default_layer(void); | ||
| 65 | void eeconfig_write_default_layer(uint8_t val); | ||
| 66 | |||
| 67 | uint8_t eeconfig_read_keymap(void); | ||
| 68 | void eeconfig_write_keymap(uint8_t val); | ||
| 69 | |||
| 70 | #ifdef BACKLIGHT_ENABLE | ||
| 71 | uint8_t eeconfig_read_backlight(void); | ||
| 72 | void 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 | /* | ||
| 2 | Copyright 2011,2012 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <stdint.h> | ||
| 19 | //#include <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 | ||
| 27 | bool keyboard_nkro = true; | ||
| 28 | #endif | ||
| 29 | |||
| 30 | static host_driver_t *driver; | ||
| 31 | static uint16_t last_system_report = 0; | ||
| 32 | static uint16_t last_consumer_report = 0; | ||
| 33 | |||
| 34 | |||
| 35 | void host_set_driver(host_driver_t *d) | ||
| 36 | { | ||
| 37 | driver = d; | ||
| 38 | } | ||
| 39 | |||
| 40 | host_driver_t *host_get_driver(void) | ||
| 41 | { | ||
| 42 | return driver; | ||
| 43 | } | ||
| 44 | |||
| 45 | uint8_t host_keyboard_leds(void) | ||
| 46 | { | ||
| 47 | if (!driver) return 0; | ||
| 48 | return (*driver->keyboard_leds)(); | ||
| 49 | } | ||
| 50 | /* send report */ | ||
| 51 | void 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 | |||
| 65 | void host_mouse_send(report_mouse_t *report) | ||
| 66 | { | ||
| 67 | if (!driver) return; | ||
| 68 | (*driver->send_mouse)(report); | ||
| 69 | } | ||
| 70 | |||
| 71 | void 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 | |||
| 80 | void 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 | |||
| 89 | uint16_t host_last_sysytem_report(void) | ||
| 90 | { | ||
| 91 | return last_system_report; | ||
| 92 | } | ||
| 93 | |||
| 94 | uint16_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 | ||
| 28 | extern "C" { | ||
| 29 | #endif | ||
| 30 | |||
| 31 | #ifdef NKRO_ENABLE | ||
| 32 | extern bool keyboard_nkro; | ||
| 33 | #endif | ||
| 34 | |||
| 35 | extern uint8_t keyboard_idle; | ||
| 36 | extern uint8_t keyboard_protocol; | ||
| 37 | |||
| 38 | |||
| 39 | /* host driver */ | ||
| 40 | void host_set_driver(host_driver_t *driver); | ||
| 41 | host_driver_t *host_get_driver(void); | ||
| 42 | |||
| 43 | /* host driver interface */ | ||
| 44 | uint8_t host_keyboard_leds(void); | ||
| 45 | void host_keyboard_send(report_keyboard_t *report); | ||
| 46 | void host_mouse_send(report_mouse_t *report); | ||
| 47 | void host_system_send(uint16_t data); | ||
| 48 | void host_consumer_send(uint16_t data); | ||
| 49 | |||
| 50 | uint16_t host_last_sysytem_report(void); | ||
| 51 | uint16_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef HOST_DRIVER_H | ||
| 19 | #define HOST_DRIVER_H | ||
| 20 | |||
| 21 | #include <stdint.h> | ||
| 22 | #include "report.h" | ||
| 23 | |||
| 24 | |||
| 25 | typedef 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 | /* | ||
| 2 | Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | ||
| 45 | static 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 | |||
| 62 | void 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 | */ | ||
| 87 | void 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 | |||
| 124 | MATRIX_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 | |||
| 146 | void 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 | /* | ||
| 2 | Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef KEYBOARD_H | ||
| 19 | #define KEYBOARD_H | ||
| 20 | |||
| 21 | #include <stdbool.h> | ||
| 22 | #include <stdint.h> | ||
| 23 | |||
| 24 | |||
| 25 | #ifdef __cplusplus | ||
| 26 | extern "C" { | ||
| 27 | #endif | ||
| 28 | |||
| 29 | /* key matrix position */ | ||
| 30 | typedef struct { | ||
| 31 | uint8_t col; | ||
| 32 | uint8_t row; | ||
| 33 | } keypos_t; | ||
| 34 | |||
| 35 | /* key event */ | ||
| 36 | typedef 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 | */ | ||
| 49 | static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); } | ||
| 50 | static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); } | ||
| 51 | static 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 | |||
| 61 | void keyboard_init(void); | ||
| 62 | void keyboard_task(void); | ||
| 63 | void 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 | /* | ||
| 2 | Copyright 2011,2012 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* | ||
| 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) */ | ||
| 166 | enum 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 */ | ||
| 400 | enum 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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #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 | |||
| 26 | static action_t keycode_to_action(uint8_t keycode); | ||
| 27 | |||
| 28 | |||
| 29 | /* converts key to action */ | ||
| 30 | action_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)) | ||
| 109 | const 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)) | ||
| 116 | void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) | ||
| 117 | { | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | |||
| 122 | /* translates keycode to action */ | ||
| 123 | static 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)) | ||
| 158 | uint8_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)) | ||
| 166 | action_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 */ | ||
| 28 | typedef 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; | ||
| 41 | keymap_config_t keymap_config; | ||
| 42 | #endif | ||
| 43 | |||
| 44 | |||
| 45 | /* translates key to keycode */ | ||
| 46 | uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key); | ||
| 47 | |||
| 48 | /* translates Fn keycode to action */ | ||
| 49 | action_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)) | ||
| 60 | uint8_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)) | ||
| 64 | uint8_t keymap_fn_layer(uint8_t fn_bits); | ||
| 65 | |||
| 66 | /* keycode to send when release Fn key without using */ | ||
| 67 | __attribute__ ((deprecated)) | ||
| 68 | uint8_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 | |||
| 31 | void 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef MATRIX_H | ||
| 19 | #define MATRIX_H | ||
| 20 | |||
| 21 | #include <stdint.h> | ||
| 22 | #include <stdbool.h> | ||
| 23 | |||
| 24 | |||
| 25 | #if (MATRIX_COLS <= 8) | ||
| 26 | typedef uint8_t matrix_row_t; | ||
| 27 | #elif (MATRIX_COLS <= 16) | ||
| 28 | typedef uint16_t matrix_row_t; | ||
| 29 | #elif (MATRIX_COLS <= 32) | ||
| 30 | typedef 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 | ||
| 39 | extern "C" { | ||
| 40 | #endif | ||
| 41 | |||
| 42 | /* number of matrix rows */ | ||
| 43 | uint8_t matrix_rows(void); | ||
| 44 | /* number of matrix columns */ | ||
| 45 | uint8_t matrix_cols(void); | ||
| 46 | /* intialize matrix for scaning. should be called once. */ | ||
| 47 | void matrix_init(void); | ||
| 48 | /* scan all key states on matrix */ | ||
| 49 | uint8_t matrix_scan(void); | ||
| 50 | /* whether modified from previous scan. used after matrix_scan. */ | ||
| 51 | bool matrix_is_modified(void) __attribute__ ((deprecated)); | ||
| 52 | /* whether a swtich is on */ | ||
| 53 | bool matrix_is_on(uint8_t row, uint8_t col); | ||
| 54 | /* matrix state on row */ | ||
| 55 | matrix_row_t matrix_get_row(uint8_t row); | ||
| 56 | /* print matrix for debug */ | ||
| 57 | void matrix_print(void); | ||
| 58 | |||
| 59 | |||
| 60 | /* power control */ | ||
| 61 | void matrix_power_up(void); | ||
| 62 | void 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 | |||
| 4 | void 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 | |||
| 4 | void suspend_power_down(void) {} | ||
| 5 | bool suspend_wakeup_condition(void) { return true; } | ||
| 6 | void 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 */ | ||
| 5 | volatile uint32_t timer_count = 0; | ||
| 6 | |||
| 7 | /* Timer interrupt handler */ | ||
| 8 | void SysTick_Handler(void) { | ||
| 9 | timer_count++; | ||
| 10 | } | ||
| 11 | |||
| 12 | void timer_init(void) | ||
| 13 | { | ||
| 14 | timer_count = 0; | ||
| 15 | SysTick_Config(SystemCoreClock / 1000); /* 1ms tick */ | ||
| 16 | } | ||
| 17 | |||
| 18 | void timer_clear(void) | ||
| 19 | { | ||
| 20 | timer_count = 0; | ||
| 21 | } | ||
| 22 | |||
| 23 | uint16_t timer_read(void) | ||
| 24 | { | ||
| 25 | return (uint16_t)(timer_count & 0xFFFF); | ||
| 26 | } | ||
| 27 | |||
| 28 | uint32_t timer_read32(void) | ||
| 29 | { | ||
| 30 | return timer_count; | ||
| 31 | } | ||
| 32 | |||
| 33 | uint16_t timer_elapsed(uint16_t last) | ||
| 34 | { | ||
| 35 | return TIMER_DIFF_16(timer_read(), last); | ||
| 36 | } | ||
| 37 | |||
| 38 | uint32_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 | ||
| 10 | int xprintf(const char* format, ...) { return 0; } | ||
| 11 | |||
| 12 | #if 0 | ||
| 13 | /* mbed Serial */ | ||
| 14 | Serial ser(UART_TX, UART_RX); | ||
| 15 | |||
| 16 | /* TODO: Need small implementation for embedded */ | ||
| 17 | int 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 | ||
| 7 | extern "C" { | ||
| 8 | #endif | ||
| 9 | |||
| 10 | int 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <stdint.h> | ||
| 19 | #include "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 | |||
| 28 | static report_mouse_t mouse_report = {}; | ||
| 29 | static uint8_t mousekey_repeat = 0; | ||
| 30 | static uint8_t mousekey_accel = 0; | ||
| 31 | |||
| 32 | static 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) */ | ||
| 42 | uint8_t mk_delay = MOUSEKEY_DELAY/10; | ||
| 43 | /* milliseconds between repeated motion events (0-255) */ | ||
| 44 | uint8_t mk_interval = MOUSEKEY_INTERVAL; | ||
| 45 | /* steady speed (in action_delta units) applied each event (0-255) */ | ||
| 46 | uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED; | ||
| 47 | /* number of events (count) accelerating to steady speed (0-255) */ | ||
| 48 | uint8_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 */ | ||
| 52 | uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED; | ||
| 53 | uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; | ||
| 54 | |||
| 55 | |||
| 56 | static uint16_t last_timer = 0; | ||
| 57 | |||
| 58 | |||
| 59 | static 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 | |||
| 78 | static 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 | |||
| 97 | void 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 | |||
| 128 | void 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 | |||
| 148 | void 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 | |||
| 171 | void mousekey_send(void) | ||
| 172 | { | ||
| 173 | mousekey_debug(); | ||
| 174 | host_mouse_send(&mouse_report); | ||
| 175 | last_timer = timer_read(); | ||
| 176 | } | ||
| 177 | |||
| 178 | void mousekey_clear(void) | ||
| 179 | { | ||
| 180 | mouse_report = (report_mouse_t){}; | ||
| 181 | mousekey_repeat = 0; | ||
| 182 | mousekey_accel = 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | static 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 | ||
| 56 | extern "C" { | ||
| 57 | #endif | ||
| 58 | |||
| 59 | extern uint8_t mk_delay; | ||
| 60 | extern uint8_t mk_interval; | ||
| 61 | extern uint8_t mk_max_speed; | ||
| 62 | extern uint8_t mk_time_to_max; | ||
| 63 | extern uint8_t mk_wheel_max_speed; | ||
| 64 | extern uint8_t mk_wheel_time_to_max; | ||
| 65 | |||
| 66 | |||
| 67 | void mousekey_task(void); | ||
| 68 | void mousekey_on(uint8_t code); | ||
| 69 | void mousekey_off(uint8_t code); | ||
| 70 | void mousekey_clear(void); | ||
| 71 | void 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 | /* | ||
| 2 | Copyright 2013 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 | |||
| 36 | void 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 | ||
| 45 | extern "C" | ||
| 46 | #endif | ||
| 47 | /* function pointer of sendchar to be used by print utility */ | ||
| 48 | void 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 | /* | ||
| 2 | Copyright 2011,2012 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 | ||
| 95 | extern "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 | */ | ||
| 118 | typedef 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 | /* | ||
| 133 | typedef struct { | ||
| 134 | uint8_t mods; | ||
| 135 | uint8_t reserved; | ||
| 136 | uint8_t keys[REPORT_KEYS]; | ||
| 137 | } __attribute__ ((packed)) report_keyboard_t; | ||
| 138 | */ | ||
| 139 | |||
| 140 | typedef 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef SENDCHAR_H | ||
| 19 | #define SENDCHAR_H | ||
| 20 | |||
| 21 | #include <stdint.h> | ||
| 22 | |||
| 23 | |||
| 24 | #ifdef __cplusplus | ||
| 25 | extern "C" { | ||
| 26 | #endif | ||
| 27 | |||
| 28 | /* transmit a character. return 0 on success, -1 on error. */ | ||
| 29 | int8_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #include "sendchar.h" | ||
| 18 | |||
| 19 | |||
| 20 | int8_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #include "uart.h" | ||
| 18 | #include "sendchar.h" | ||
| 19 | |||
| 20 | |||
| 21 | int8_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 | |||
| 21 | void 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 | |||
| 36 | void sleep_led_enable(void) | ||
| 37 | { | ||
| 38 | /* Enable Compare Match Interrupt */ | ||
| 39 | TIMSK1 |= _BV(OCIE1A); | ||
| 40 | } | ||
| 41 | |||
| 42 | void sleep_led_disable(void) | ||
| 43 | { | ||
| 44 | /* Disable Compare Match Interrupt */ | ||
| 45 | TIMSK1 &= ~_BV(OCIE1A); | ||
| 46 | } | ||
| 47 | |||
| 48 | void 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 | */ | ||
| 61 | static const uint8_t breathing_table[64] PROGMEM = { | ||
| 62 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, | ||
| 63 | 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, | ||
| 64 | 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, | ||
| 65 | 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 66 | }; | ||
| 67 | |||
| 68 | ISR(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 | |||
| 7 | void sleep_led_init(void); | ||
| 8 | void sleep_led_enable(void); | ||
| 9 | void sleep_led_disable(void); | ||
| 10 | void 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 | |||
| 8 | void suspend_idle(uint8_t timeout); | ||
| 9 | void suspend_power_down(void); | ||
| 10 | bool suspend_wakeup_condition(void); | ||
| 11 | void 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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 | ||
| 36 | extern "C" { | ||
| 37 | #endif | ||
| 38 | |||
| 39 | extern volatile uint32_t timer_count; | ||
| 40 | |||
| 41 | |||
| 42 | void timer_init(void); | ||
| 43 | void timer_clear(void); | ||
| 44 | uint16_t timer_read(void); | ||
| 45 | uint32_t timer_read32(void); | ||
| 46 | uint16_t timer_elapsed(uint16_t last); | ||
| 47 | uint32_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 | |||
| 39 | static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; | ||
| 40 | static volatile uint8_t tx_buffer_head; | ||
| 41 | static volatile uint8_t tx_buffer_tail; | ||
| 42 | static volatile uint8_t rx_buffer[RX_BUFFER_SIZE]; | ||
| 43 | static volatile uint8_t rx_buffer_head; | ||
| 44 | static volatile uint8_t rx_buffer_tail; | ||
| 45 | |||
| 46 | // Initialize the UART | ||
| 47 | void 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 | ||
| 60 | void 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 | ||
| 75 | uint8_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. | ||
| 90 | uint8_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 | ||
| 101 | ISR(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 | ||
| 117 | ISR(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 | |||
| 6 | void uart_init(uint32_t baud); | ||
| 7 | void uart_putchar(uint8_t c); | ||
| 8 | uint8_t uart_getchar(void); | ||
| 9 | uint8_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include "util.h" | ||
| 19 | |||
| 20 | // bit population - return number of on-bit | ||
| 21 | uint8_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 | |||
| 33 | uint8_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 | |||
| 41 | uint8_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 | ||
| 51 | uint8_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 | |||
| 60 | uint8_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 | |||
| 70 | uint8_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 | |||
| 83 | uint8_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 | |||
| 91 | uint16_t bitrev16(uint16_t bits) | ||
| 92 | { | ||
| 93 | bits = bitrev(bits & 0x00ff)<<8 | bitrev((bits & 0xff00)>>8); | ||
| 94 | return bits; | ||
| 95 | } | ||
| 96 | |||
| 97 | uint32_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 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #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 | |||
| 31 | uint8_t bitpop(uint8_t bits); | ||
| 32 | uint8_t bitpop16(uint16_t bits); | ||
| 33 | uint8_t bitpop32(uint32_t bits); | ||
| 34 | |||
| 35 | uint8_t biton(uint8_t bits); | ||
| 36 | uint8_t biton16(uint16_t bits); | ||
| 37 | uint8_t biton32(uint32_t bits); | ||
| 38 | |||
| 39 | uint8_t bitrev(uint8_t bits); | ||
| 40 | uint16_t bitrev16(uint16_t bits); | ||
| 41 | uint32_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 | ||
| 5 | extern "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 | ||
