From dd378601608849679ead6e2cccb74f7f29c131dc Mon Sep 17 00:00:00 2001 From: Joe Wasson Date: Wed, 27 Jul 2016 08:43:02 -0700 Subject: Add one-hand support. This adds an action, `ACTION_SWAP_HANDS`, that swaps the the keys on the keyboard across a keymap-defined hemisphere in order to support one-hand typing without requiring a separate one-handed layer. See updated `doc/keymap.md` for more information. --- tmk_core/common/action.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'tmk_core/common/action.c') diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index be6dea2b79..0413b1a997 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -41,6 +41,12 @@ void action_exec(keyevent_t event) dprint("EVENT: "); debug_event(event); dprintln(); } +#ifdef ONEHAND_ENABLE + if (!IS_NOEVENT(event)) { + process_hand_swap(&event); + } +#endif + keyrecord_t record = { .event = event }; #ifndef NO_ACTION_TAPPING @@ -53,6 +59,26 @@ void action_exec(keyevent_t event) #endif } +#ifdef ONEHAND_ENABLE +bool swap_hands = false; + +void process_hand_swap(keyevent_t *event) { + static swap_state_row_t swap_state[MATRIX_ROWS]; + + keypos_t pos = event->key; + swap_state_row_t col_bit = (swap_state_row_t)1<pressed ? swap_hands : + swap_state[pos.row] & (col_bit); + + if (do_swap) { + event->key = hand_swap_config[pos.row][pos.col]; + swap_state[pos.row] |= col_bit; + } else { + swap_state[pos.row] &= ~(col_bit); + } +} +#endif + #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) bool disable_action_cache = false; @@ -439,6 +465,13 @@ void process_action(keyrecord_t *record, action_t action) break; #endif case ACT_COMMAND: + switch (action.command.id) { +#ifdef ONEHAND_ENABLE + case CMD_SWAP_HANDS: + swap_hands = event.pressed; + break; +#endif + } break; #ifndef NO_ACTION_FUNCTION case ACT_FUNCTION: -- cgit v1.2.3 From 8090f6b499fd87ddeb7a191f7bc3dace9d03be23 Mon Sep 17 00:00:00 2001 From: Joe Wasson Date: Thu, 28 Jul 2016 01:24:06 -0700 Subject: Improve one-hand support by adding more actions and tap keys. --- doc/keymap.md | 13 +++++++++- tmk_core/common/action.c | 57 ++++++++++++++++++++++++++++++++++++++++--- tmk_core/common/action_code.h | 28 ++++++++++++++++++--- 3 files changed, 89 insertions(+), 9 deletions(-) (limited to 'tmk_core/common/action.c') diff --git a/doc/keymap.md b/doc/keymap.md index 1285ad6cd1..6f2a663fc8 100644 --- a/doc/keymap.md +++ b/doc/keymap.md @@ -456,8 +456,9 @@ Turn the backlight on and off without changing level. ### 2.6 Swap-Hands Action -The swap-hands action allows support for one-handed keyboards without requiring a separate layer. Set `ONEHAND_ENABLE` in the Makefile and define a `hand_swap_config` entry in your keymap. Now whenever the `ACTION_SWAP_HANDS` command is executed the keyboard is mirrored. For instance, to type "Hello, World" on QWERTY you would type `^Ge^s^s^w^c W^wr^sd` +The swap-hands action allows support for one-handed keyboards without requiring a separate layer. Set `ONEHAND_ENABLE` in the Makefile and define a `hand_swap_config` entry in your keymap. Now whenever the `ACTION_SWAP_HANDS` command key is pressed the keyboard is mirrored. For instance, to type "Hello, World" on QWERTY you would type `^Ge^s^s^w^c W^wr^sd` +### 2.6.1 Configuration The configuration table is a simple 2-dimensional array to map from column/row to new column/row. Example `hand_swap_config` for Planck: ``` @@ -471,6 +472,16 @@ const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { Note that the array indices are reversed same as the matrix and the values are of type `keypos_t` which is `{col, row}` and all values are zero-based. In the example above, `hand_swap_config[2][4]` (third row, fifth column) would return {7, 2} (third row, eighth column). +### 2.6.2 Advanced Swap Commands +- **`ACTION_SWAP_HANDS()`** Swaps hands when pressed, returns to normal when released (momentary). +- **`ACTION_SWAP_HANDS_TOGGLE()`** Toggles swap on and off with every keypress. +- **`ACTION_SWAP_HANDS_TAP_TOGGLE()`** Toggles with a tap; momentary when held. +- **`ACTION_SWAP_HANDS_TAP_KEY(key)`** Sends `key` with a tap; momentary swap when held. +- **`ACTION_SWAP_HANDS_ON_OFF()`** Alias for `ACTION_SWAP_HANDS()` +- **`ACTION_SWAP_HANDS_OFF_ON()`** Momentarily turns off swap. +- **`ACTION_SWAP_HANDS_ON()`** Turns on swapping and leaves it on. +- **`ACTION_SWAP_HANDS_OFF()`** Turn off swapping and leaves it off. Good for returning to a known state. + ## 3. Layer switching Example diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index 0413b1a997..08ef22eb97 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -465,14 +465,55 @@ void process_action(keyrecord_t *record, action_t action) break; #endif case ACT_COMMAND: - switch (action.command.id) { + break; #ifdef ONEHAND_ENABLE - case CMD_SWAP_HANDS: + case ACT_SWAP_HANDS: + switch (action.swap.code) { + case OP_SH_TOGGLE: + if (event.pressed) { + swap_hands = !swap_hands; + } + break; + case OP_SH_ON_OFF: swap_hands = event.pressed; break; -#endif + case OP_SH_OFF_ON: + swap_hands = !event.pressed; + break; + case OP_SH_ON: + if (!event.pressed) { + swap_hands = true; + } + break; + case OP_SH_OFF: + if (!event.pressed) { + swap_hands = false; + } + break; + #ifndef NO_ACTION_TAPPING + case OP_SH_TAP_TOGGLE: + /* tap toggle */ + if (tap_count > 0) { + if (!event.pressed) { + swap_hands = !swap_hands; + } + } else { + swap_hands = event.pressed; + } + break; + default: + if (tap_count > 0) { + if (event.pressed) { + register_code(action.swap.code); + } else { + unregister_code(action.swap.code); + } + } else { + swap_hands = event.pressed; + } + #endif } - break; +#endif #ifndef NO_ACTION_FUNCTION case ACT_FUNCTION: action_function(record, action.func.id, action.func.opt); @@ -685,6 +726,13 @@ bool is_tap_key(keypos_t key) return true; } return false; + case ACT_SWAP_HANDS: + switch (action.swap.code) { + case 0x00 ... 0xdf: + case OP_SH_TAP_TOGGLE: + return true; + } + return false; case ACT_MACRO: case ACT_FUNCTION: if (action.func.opt & FUNC_TAP) { return true; } @@ -725,6 +773,7 @@ void debug_action(action_t action) case ACT_MACRO: dprint("ACT_MACRO"); break; case ACT_COMMAND: dprint("ACT_COMMAND"); break; case ACT_FUNCTION: dprint("ACT_FUNCTION"); break; + case ACT_SWAP_HANDS: dprint("ACT_SWAP_HANDS"); break; default: dprint("UNKNOWN"); break; } dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff); diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h index 95d2cbf3e4..33da35f35f 100644 --- a/tmk_core/common/action_code.h +++ b/tmk_core/common/action_code.h @@ -108,6 +108,8 @@ enum action_kind_id { /* Other Keys */ ACT_USAGE = 0b0100, ACT_MOUSEKEY = 0b0101, + /* One-hand Support */ + ACT_SWAP_HANDS = 0b0110, /* Layer Actions */ ACT_LAYER = 0b1000, ACT_LAYER_TAP = 0b1010, /* Layer 0-15 */ @@ -178,6 +180,11 @@ typedef union { uint8_t opt :4; uint8_t kind :4; } func; + struct action_swap { + uint8_t code :8; + uint8_t opt :4; + uint8_t kind :4; + } swap; } action_t; @@ -296,9 +303,6 @@ enum backlight_opt { BACKLIGHT_LEVEL = 4, }; -enum command_id { - CMD_SWAP_HANDS = 0x14, -}; /* Macro */ #define ACTION_MACRO(id) ACTION(ACT_MACRO, (id)) #define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP<<8 | (id)) @@ -319,6 +323,22 @@ enum function_opts { #define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | (id)) #define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | (id)) /* OneHand Support */ -#define ACTION_SWAP_HANDS() ACTION_COMMAND(CMD_SWAP_HANDS, 0) +enum swap_hands_pram_tap_op { + OP_SH_TOGGLE = 0xF0, + OP_SH_TAP_TOGGLE, + OP_SH_ON_OFF, + OP_SH_OFF_ON, + OP_SH_OFF, + OP_SH_ON, +}; + +#define ACTION_SWAP_HANDS() ACTION_SWAP_HANDS_ON_OFF() +#define ACTION_SWAP_HANDS_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TOGGLE) +#define ACTION_SWAP_HANDS_TAP_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TAP_TOGGLE) +#define ACTION_SWAP_HANDS_TAP_KEY(key) ACTION(ACT_SWAP_HANDS, key) +#define ACTION_SWAP_HANDS_ON_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_ON_OFF) +#define ACTION_SWAP_HANDS_OFF_ON() ACTION(ACT_SWAP_HANDS, OP_SH_OFF_ON) +#define ACTION_SWAP_HANDS_ON() ACTION(ACT_SWAP_HANDS, OP_SH_ON) +#define ACTION_SWAP_HANDS_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_OFF) #endif /* ACTION_CODE_H */ -- cgit v1.2.3 From d4309990472895bbbe82f7ba22ed33c16f928778 Mon Sep 17 00:00:00 2001 From: Didier Loiseau Date: Fri, 23 Sep 2016 00:55:15 +0200 Subject: Fix issue #772 Meh and Hyper not working --- tmk_core/common/action.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tmk_core/common/action.c') diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index 08ef22eb97..d485b46c77 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -155,9 +155,10 @@ void process_action(keyrecord_t *record, action_t action) action.key.mods<<4; if (event.pressed) { if (mods) { - if (IS_MOD(action.key.code)) { + if (IS_MOD(action.key.code) || action.key.code == KC_NO) { // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless. - // this also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT) + // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT). + // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO). add_mods(mods); } else { add_weak_mods(mods); @@ -168,7 +169,7 @@ void process_action(keyrecord_t *record, action_t action) } else { unregister_code(action.key.code); if (mods) { - if (IS_MOD(action.key.code)) { + if (IS_MOD(action.key.code) || action.key.code == KC_NO) { del_mods(mods); } else { del_weak_mods(mods); -- cgit v1.2.3 From 6f44ca7a59d60e20c1d35e8edc916571f5fe40ef Mon Sep 17 00:00:00 2001 From: SjB Date: Sun, 15 Jan 2017 23:12:42 -0500 Subject: oneshot timeout would only timeout after an event. After setting a ONESHOT_TIMEOUT value, the oneshot layer state would not expire without an event being triggered (key pressed). The reason was that in the process_record function we would return priort to execute the process_action function if it detected a NOEVENT cycle. The process_action contained the codes to timeout the oneshot layer state. The codes to clear the oneshot layer state have been move just in front of where we check for the NOEVENT cycle in the process_record function. --- tmk_core/common/action.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'tmk_core/common/action.c') diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index d485b46c77..a77177240b 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -102,6 +102,13 @@ bool process_record_quantum(keyrecord_t *record) { void process_record(keyrecord_t *record) { +#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + if (has_oneshot_layer_timed_out()) { + dprintf("Oneshot layer: timeout\n"); + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + } +#endif + if (IS_NOEVENT(record->event)) { return; } if(!process_record_quantum(record)) @@ -126,13 +133,6 @@ void process_action(keyrecord_t *record, action_t action) uint8_t tap_count = record->tap.count; #endif -#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - if (has_oneshot_layer_timed_out()) { - dprintf("Oneshot layer: timeout\n"); - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } -#endif - if (event.pressed) { // clear the potential weak mods left by previously pressed keys clear_weak_mods(); -- cgit v1.2.3 From 45e0d09414c09c626d2349b6a5036a29fe03b1c6 Mon Sep 17 00:00:00 2001 From: SjB Date: Sun, 29 Jan 2017 12:56:20 -0500 Subject: moved oneshot cancellation code outside of process_record. The oneshot cancellation code do not depend on the action_tapping_process and since process_record get called via the action_tapping_process logic moved the oneshot cancellation code into the action_exec function just before the action_tapping_process call --- tmk_core/common/action.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'tmk_core/common/action.c') diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index a77177240b..f03670a7f7 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -49,6 +49,13 @@ void action_exec(keyevent_t event) keyrecord_t record = { .event = event }; +#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) + if (has_oneshot_layer_timed_out()) { + dprintf("Oneshot layer: timeout\n"); + clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); + } +#endif + #ifndef NO_ACTION_TAPPING action_tapping_process(record); #else @@ -100,15 +107,8 @@ bool process_record_quantum(keyrecord_t *record) { return true; } -void process_record(keyrecord_t *record) +void process_record(keyrecord_t *record) { -#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) - if (has_oneshot_layer_timed_out()) { - dprintf("Oneshot layer: timeout\n"); - clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); - } -#endif - if (IS_NOEVENT(record->event)) { return; } if(!process_record_quantum(record)) -- cgit v1.2.3 From c68e596f32c5d450a714627871408407e9988ef7 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo Date: Mon, 13 Feb 2017 08:03:07 +0700 Subject: Implement faux-clicky feature --- build_keyboard.mk | 5 ++ keyboards/planck/keymaps/priyadi/Makefile | 3 +- keyboards/planck/keymaps/priyadi/keymap.c | 4 +- quantum/fauxclicky.c | 68 ++++++++++++++++++++++++ quantum/fauxclicky.h | 87 +++++++++++++++++++++++++++++++ quantum/template/rules.mk | 1 + tmk_core/common/action.c | 13 +++++ tmk_core/common/keyboard.c | 6 +++ 8 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 quantum/fauxclicky.c create mode 100644 quantum/fauxclicky.h (limited to 'tmk_core/common/action.c') diff --git a/build_keyboard.mk b/build_keyboard.mk index 2c64e93a28..c8e82cf0e5 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -161,6 +161,11 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes) SRC += $(QUANTUM_DIR)/audio/luts.c endif +ifeq ($(strip $(FAUXCLICKY_ENABLE)), yes) + OPT_DEFS += -DFAUXCLICKY_ENABLE + SRC += $(QUANTUM_DIR)/fauxclicky.c +endif + ifeq ($(strip $(UCIS_ENABLE)), yes) OPT_DEFS += -DUCIS_ENABLE UNICODE_ENABLE = yes diff --git a/keyboards/planck/keymaps/priyadi/Makefile b/keyboards/planck/keymaps/priyadi/Makefile index 336608b8cc..27c2638e2f 100644 --- a/keyboards/planck/keymaps/priyadi/Makefile +++ b/keyboards/planck/keymaps/priyadi/Makefile @@ -10,12 +10,13 @@ COMMAND_ENABLE = no # Commands for debug and configuration NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality MIDI_ENABLE = no # MIDI controls -AUDIO_ENABLE = yes # Audio output on port C6 +AUDIO_ENABLE = no # Audio output on port C6 UNICODE_ENABLE = no # Unicode UNICODEMAP_ENABLE = yes # Unicode map BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time. API_SYSEX_ENABLE = no +FAUXCLICKY_ENABLE = yes # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend diff --git a/keyboards/planck/keymaps/priyadi/keymap.c b/keyboards/planck/keymaps/priyadi/keymap.c index 2e979221a9..13668fd106 100644 --- a/keyboards/planck/keymaps/priyadi/keymap.c +++ b/keyboards/planck/keymaps/priyadi/keymap.c @@ -268,8 +268,8 @@ const uint32_t PROGMEM unicode_map[] = { // hybrid right-gui & scroll lock (mapped to Compose in OS) -#undef KC_RCTL -#define KC_RCTL MT(MOD_LCTL, KC_SLCK) +#undef KC_RALT +#define KC_RALT MT(MOD_RALT, KC_SLCK) // keymaps diff --git a/quantum/fauxclicky.c b/quantum/fauxclicky.c new file mode 100644 index 0000000000..13273e7058 --- /dev/null +++ b/quantum/fauxclicky.c @@ -0,0 +1,68 @@ +/* +Copyright 2017 Priyadi Iman Nurcahyo + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include + +__attribute__ ((weak)) +float fauxclicky_pressed_note[2] = MUSICAL_NOTE(_F3, 2); +__attribute__ ((weak)) +float fauxclicky_released_note[2] = MUSICAL_NOTE(_A3, 2); +__attribute__ ((weak)) +float fauxclicky_beep_note[2] = MUSICAL_NOTE(_C3, 2); + +bool fauxclicky_enabled = true; +uint16_t note_start = 0; +bool note_playing = false; +uint16_t note_period = 0; + +void fauxclicky_init() +{ + // Set port PC6 (OC3A and /OC4A) as output + DDRC |= _BV(PORTC6); + + // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers + TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); + TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); +} + +void fauxclicky_stop() +{ + FAUXCLICKY_DISABLE_OUTPUT; + note_playing = false; +} + +void fauxclicky_play(float note[2]) { + if (!fauxclicky_enabled) return; + if (note_playing) fauxclicky_stop(); + FAUXCLICKY_TIMER_PERIOD = (uint16_t)(((float)F_CPU) / (note[0] * FAUXCLICKY_CPU_PRESCALER)); + FAUXCLICKY_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (note[0] * FAUXCLICKY_CPU_PRESCALER)) / 2); + note_playing = true; + note_period = (note[1] / 16) * (60 / (float)FAUXCLICKY_TEMPO) * 100; // check this + note_start = timer_read(); + FAUXCLICKY_ENABLE_OUTPUT; +} + +void fauxclicky_check() { + if (!note_playing) return; + + if (timer_elapsed(note_start) > note_period) { + fauxclicky_stop(); + } +} diff --git a/quantum/fauxclicky.h b/quantum/fauxclicky.h new file mode 100644 index 0000000000..6cfc291c05 --- /dev/null +++ b/quantum/fauxclicky.h @@ -0,0 +1,87 @@ +/* +Copyright 2017 Priyadi Iman Nurcahyo + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifdef AUDIO_ENABLE +#error "AUDIO_ENABLE and FAUXCLICKY_ENABLE cannot be both enabled" +#endif + +#include "musical_notes.h" + +__attribute__ ((weak)) +float fauxclicky_pressed_note[2]; +__attribute__ ((weak)) +float fauxclicky_released_note[2]; +__attribute__ ((weak)) +float fauxclicky_beep_note[2]; + +// +// tempo in BPM +// + +#ifndef FAUXCLICKY_TEMPO +#define FAUXCLICKY_TEMPO TEMPO_DEFAULT +#endif + +// beep on press +#define FAUXCLICKY_ACTION_PRESS fauxclicky_play(fauxclicky_pressed_note) + +// beep on release +#define FAUXCLICKY_ACTION_RELEASE fauxclicky_play(fauxclicky_released_note) + +// general purpose beep +#define FAUXCLICKY_BEEP fauxclicky_play(fauxclicky_beep_note) + +// enable +#define FAUXCLICKY_ON fauxclicky_enabled = true + +// disable +#define FAUXCLICKY_OFF do { \ + fauxclicky_enabled = false; \ + fauxclicky_stop(); \ +} while (0) + +// +// pin configuration +// + +#ifndef FAUXCLICKY_CPU_PRESCALER +#define FAUXCLICKY_CPU_PRESCALER 8 +#endif + +#ifndef FAUXCLICKY_ENABLE_OUTPUT +#define FAUXCLICKY_ENABLE_OUTPUT TCCR3A |= _BV(COM3A1); +#endif + +#ifndef FAUXCLICKY_DISABLE_OUTPUT +#define FAUXCLICKY_DISABLE_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0)); +#endif + +#ifndef FAUXCLICKY_TIMER_PERIOD +#define FAUXCLICKY_TIMER_PERIOD ICR3 +#endif + +#ifndef FAUXCLICKY_DUTY_CYCLE +#define FAUXCLICKY_DUTY_CYCLE OCR3A +#endif + +// +// definitions +// + +void fauxclicky_init(void); +void fauxclicky_stop(void); +void fauxclicky_play(float note[2]); +void fauxclicky_check(void); + diff --git a/quantum/template/rules.mk b/quantum/template/rules.mk index 55898147dd..bad3387bf4 100644 --- a/quantum/template/rules.mk +++ b/quantum/template/rules.mk @@ -65,3 +65,4 @@ MIDI_ENABLE ?= no # MIDI controls UNICODE_ENABLE ?= no # Unicode BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID AUDIO_ENABLE ?= no # Audio output on port C6 +FAUXCLICKY_ENABLE ?= no # Use buzzer to emulate clicky switches diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index f03670a7f7..94de36918d 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -33,6 +33,9 @@ along with this program. If not, see . #include "nodebug.h" #endif +#ifdef FAUXCLICKY_ENABLE +#include +#endif void action_exec(keyevent_t event) { @@ -41,6 +44,16 @@ void action_exec(keyevent_t event) dprint("EVENT: "); debug_event(event); dprintln(); } +#ifdef FAUXCLICKY_ENABLE + if (IS_PRESSED(event)) { + FAUXCLICKY_ACTION_PRESS; + } + if (IS_RELEASED(event)) { + FAUXCLICKY_ACTION_RELEASE; + } + fauxclicky_check(); +#endif + #ifdef ONEHAND_ENABLE if (!IS_NOEVENT(event)) { process_hand_swap(&event); diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 3aa82231b0..eac1f1dd81 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -51,6 +51,9 @@ along with this program. If not, see . #ifdef RGBLIGHT_ENABLE # include "rgblight.h" #endif +#ifdef FAUXCLICKY_ENABLE +# include "fauxclicky.h" +#endif #ifdef SERIAL_LINK_ENABLE # include "serial_link/system/serial_link.h" #endif @@ -108,6 +111,9 @@ void keyboard_init(void) { #ifdef RGBLIGHT_ENABLE rgblight_init(); #endif +#ifdef FAUXCLICKY_ENABLE + fauxclicky_init(); +#endif #if defined(NKRO_ENABLE) && defined(FORCE_NKRO) keymap_config.nkro = 1; #endif -- cgit v1.2.3