From 8a9bf1f1653a5029ffd8f1e1171cd0b16bc2bc71 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Sat, 30 Jul 2016 08:37:30 +0200 Subject: Update some obsolete references Some links were still pointing to `/keyboards/ergodox_ez`, while the directory is `/keyboards/erdogox` now. Not all references have been updated, and some of the text here and there may need updating to mention the ErgoDox Infinity too, but that's out of the scope for this quick fix. Signed-off-by: Gergely Nagy --- doc/TMK_README.md | 2 +- doc/VAGRANT_GUIDE.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/TMK_README.md b/doc/TMK_README.md index 6164dacd3..f3d96717a 100644 --- a/doc/TMK_README.md +++ b/doc/TMK_README.md @@ -34,7 +34,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di * [atomic](keyboards/atomic/) - [Atomic] Ortholinear 60% keyboard ### Ergodox EZ -* [ergodox_ez](keyboards/ergodox_ez) - [Ergodox_EZ] Assembled split keyboard +* [ergodox_ez](keyboards/ergodox/ez) - [Ergodox_EZ] Assembled split keyboard ## Other projects diff --git a/doc/VAGRANT_GUIDE.md b/doc/VAGRANT_GUIDE.md index 62044b7f7..c9958e16b 100644 --- a/doc/VAGRANT_GUIDE.md +++ b/doc/VAGRANT_GUIDE.md @@ -20,7 +20,7 @@ See [/doc/keymap.md](/doc/keymap.md). ## Flashing the firmware -The "easy" way to flash the firmware is using a tool from your host OS like the Teensy programming app. [ErgoDox EZ](/keyboards/ergodox_ez/readme.md) gives a great example. +The "easy" way to flash the firmware is using a tool from your host OS like the Teensy programming app. [ErgoDox EZ](/keyboards/ergodox/readme.md) gives a great example. If you want to program via the command line you can uncomment the ['modifyvm'] lines in the Vagrantfile to enable the USB passthrough into Linux and then program using the command line tools like dfu-util/dfu-programmer or you can install the Teensy CLI version. - \ No newline at end of file + -- cgit v1.2.3-70-g09d2 From d9bef1658e062d76f87a752daa30047d865dca0f Mon Sep 17 00:00:00 2001 From: Jiehong Ma Date: Sun, 31 Jul 2016 16:49:31 +0200 Subject: feature: add basic doc about how a keyboard works on USB This comes from the discussion on #520 --- doc/basic_how_keyboards_work.md | 96 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 doc/basic_how_keyboards_work.md (limited to 'doc') diff --git a/doc/basic_how_keyboards_work.md b/doc/basic_how_keyboards_work.md new file mode 100644 index 000000000..73c3f5c5f --- /dev/null +++ b/doc/basic_how_keyboards_work.md @@ -0,0 +1,96 @@ +# How keys are registered, and interpreted by computers + +In this file, you can will learn the concepts of how keyboards work over USB, +and you'll be able to better understand what you can expect from changing your +firmware directly. + +## Schematic view + +Whenever you type on 1 particular key, here is the chain of actions taking +place: + +``` text ++------+ +-----+ +----------+ +----------+ +----+ +| User |-------->| Key |------>| Firmware |----->| USB wire |---->| OS | ++------+ +-----+ +----------+ +----------+ |----+ +``` + +This scheme is a very simple view of what's going on, and more details follow +in the next sections. + +## 1. You Press a Key + +Whenever you press a key, the firmware of your keyboard can register this event. +It can register when the key is pressed, held and released. + +This usually happens with a [periodic scan of key presses with a frequency around 100 hz](https://github.com/benblazak/ergodox-firmware/blob/master/references.md#typical-keyboard-information). +This speed often is limited by the mechanical key response time, the protocol +to transfer those key presses (here USB HID), and by the software it is used in. + +## 2. What the Firmware Sends + +The [HID specification](http://www.usb.org/developers/hidpage/Hut1_12v2.pdf) +tells what a keyboard can actually send through USB to have a chance to be +properly recognised. This includes a pre-defined list of keycodes which are +simple numbers from `0x00` to `0xE7`. The firmware assigns a keycode to each +key of the keyboard. + +The firmware does not send actually letters or characters, but only keycodes. +Thus, by modifying the firmware, you only can modify what keycode is sent over +USB for a given key. + +## 3. What the Operating System Does + +Once the keycode reaches the operating system, a piece of software has to have +it match an actual character thanks to a keyboard layout. For example, if your +layout is set to QWERTY, a sample of the matching table is as follow: + +``` text +| keycode | character | +|---------+-----------| +| 0x04 | a/A | +| 0x05 | b/B | +| 0x06 | c/C | +| ... | ... | +| 0x1C | y/Y | +| 0x1D | z/Z | +| ... | ... | +|---------+-----------| +``` + +## Back to the firmware + +As the layout is generally fixed (unless you create your own), the firmware can +actually call a keycode by its layout name directly to ease things for you. + +This is exactly what is done here with `KC_A` actually representing `0x04` in +QWERTY. The full list can be found in `keycode.txt`. + +## List of Characters You Can Send + +Putting aside shortcuts, having a limited set of keycodes mapped to a limited +layout means that **the list of characters you can assign to a given key only +is the ones present in the layout**. + +For example, this means that if you have a QWERTY US layout, and you want to +assign 1 key to produce `€` (euro currency symbol), you are unable to do so, +because the QWERTY US layout does not have such mapping. You could fix that by +using a QWERTY UK layout, or a QWERTY US International. + +You may wonder why a keyboard layout containing all of Unicode is not devised +then? The limited number of keycode available through USB simply disallow such +a thing. + +## How to (Maybe) Enter Unicode Characters + +You can have the firmware send *sequences of keys* to use the [software Unicode +Input +Method](https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input) of +the target operating system, thus effectively entering characters independently +of the layout defined in the OS. + +Yet, it does come with multiple disadvantages: + + - Tied to a specific OS a a time (need recompilation when changing OS); + - Within a given OS, does not work in all software; + - Limited to a subset of Unicode on some systems. -- cgit v1.2.3-70-g09d2 From f41c2e6863f2ebf55311051cdead743683846a49 Mon Sep 17 00:00:00 2001 From: Felix Uhl Date: Mon, 8 Aug 2016 17:53:08 +0200 Subject: Update TMK_README.md updated link to non-existent build.md file --- doc/TMK_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/TMK_README.md b/doc/TMK_README.md index f3d96717a..0c75a0e27 100644 --- a/doc/TMK_README.md +++ b/doc/TMK_README.md @@ -113,7 +113,7 @@ Third party libraries like LUFA, PJRC and V-USB have their own license respectiv Build Firmware and Program Controller ------------------------------------- -See [doc/build.md](tmk_core/doc/build.md), or the readme in the particular keyboards/* folder. +See [doc/BUILD_GUIDE.md](tmk_core/doc/BUILD_GUIDE.md), or the readme in the particular keyboards/* folder. -- cgit v1.2.3-70-g09d2 From 6975135f545d08955ed26ef046a0333e291af716 Mon Sep 17 00:00:00 2001 From: Felix Uhl Date: Wed, 10 Aug 2016 11:40:51 +0200 Subject: updated reference Build setup links to main readme now. --- doc/TMK_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/TMK_README.md b/doc/TMK_README.md index 0c75a0e27..e3438eda2 100644 --- a/doc/TMK_README.md +++ b/doc/TMK_README.md @@ -113,7 +113,7 @@ Third party libraries like LUFA, PJRC and V-USB have their own license respectiv Build Firmware and Program Controller ------------------------------------- -See [doc/BUILD_GUIDE.md](tmk_core/doc/BUILD_GUIDE.md), or the readme in the particular keyboards/* folder. +See [build environment setup](/readme.md#build-environment-setup), or the readme in the particular keyboards/* folder. -- cgit v1.2.3-70-g09d2 From a41a53baadf14b50d63fc9424aca67e7bde193f3 Mon Sep 17 00:00:00 2001 From: Felix Uhl Date: Thu, 11 Aug 2016 09:13:38 +0200 Subject: Fix dead link in keycode.txt The link to the HID Usage tables was outdated and dead, so I replaced it. --- doc/keycode.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/keycode.txt b/doc/keycode.txt index c1134f9bf..5a42c50bf 100644 --- a/doc/keycode.txt +++ b/doc/keycode.txt @@ -2,7 +2,7 @@ Keycode Symbol Table ==================== Keycodes are defined in `common/keycode.h`. Range of 00-A4 and E0-E7 are identical with HID Usage: - + Virtual keycodes are defined out of above range to support special actions. -- cgit v1.2.3-70-g09d2 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. --- doc/keymap.md | 18 ++++++++++++++++++ tmk_core/common.mk | 4 ++++ tmk_core/common/action.c | 33 +++++++++++++++++++++++++++++++++ tmk_core/common/action.h | 18 ++++++++++++++++++ tmk_core/common/action_code.h | 8 +++++++- 5 files changed, 80 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/keymap.md b/doc/keymap.md index d1985e567..1285ad6cd 100644 --- a/doc/keymap.md +++ b/doc/keymap.md @@ -455,6 +455,24 @@ 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 configuration table is a simple 2-dimensional array to map from column/row to new column/row. Example `hand_swap_config` for Planck: + +``` +const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { + {{11, 0}, {10, 0}, {9, 0}, {8, 0}, {7, 0}, {6, 0}, {5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}}, + {{11, 1}, {10, 1}, {9, 1}, {8, 1}, {7, 1}, {6, 1}, {5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}}, + {{11, 2}, {10, 2}, {9, 2}, {8, 2}, {7, 2}, {6, 2}, {5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}}, + {{11, 3}, {10, 3}, {9, 3}, {8, 3}, {7, 3}, {6, 3}, {5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}}, +}; +``` + +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). + + + ## 3. Layer switching Example There are some ways to switch layer with 'Layer' actions. diff --git a/tmk_core/common.mk b/tmk_core/common.mk index aa05b9491..429c57143 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -85,6 +85,10 @@ ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) OPT_DEFS += -DBLUETOOTH_ENABLE endif +ifeq ($(strip $(ONEHAND_ENABLE)), yes) + OPT_DEFS += -DONEHAND_ENABLE +endif + ifeq ($(strip $(KEYMAP_SECTION_ENABLE)), yes) OPT_DEFS += -DKEYMAP_SECTION_ENABLE diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index be6dea2b7..0413b1a99 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: diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index e8aa12a7c..b9bdfe642 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -65,6 +65,24 @@ bool process_record_quantum(keyrecord_t *record); #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) extern bool disable_action_cache; #endif + +/* Code for handling one-handed key modifiers. */ +#ifdef ONEHAND_ENABLE +extern bool swap_hands; +extern const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS]; +#if (MATRIX_COLS <= 8) +typedef uint8_t swap_state_row_t; +#elif (MATRIX_COLS <= 16) +typedef uint16_t swap_state_row_t; +#elif (MATRIX_COLS <= 32) +typedef uint32_t swap_state_row_t; +#else +#error "MATRIX_COLS: invalid value" +#endif + +void process_hand_swap(keyevent_t *record); +#endif + void process_record_nocache(keyrecord_t *record); void process_record(keyrecord_t *record); void process_action(keyrecord_t *record, action_t action); diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h index ca729aaec..95d2cbf3e 100644 --- a/tmk_core/common/action_code.h +++ b/tmk_core/common/action_code.h @@ -295,6 +295,10 @@ enum backlight_opt { BACKLIGHT_STEP = 3, 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)) @@ -306,7 +310,7 @@ enum backlight_opt { #define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8) #define ACTION_BACKLIGHT_LEVEL(level) ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | (level)) /* Command */ -#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (addr)) +#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (id)) /* Function */ enum function_opts { FUNC_TAP = 0x8, /* indciates function is tappable */ @@ -314,5 +318,7 @@ enum function_opts { #define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id)) #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) #endif /* ACTION_CODE_H */ -- cgit v1.2.3-70-g09d2 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 'doc') diff --git a/doc/keymap.md b/doc/keymap.md index 1285ad6cd..6f2a663fc 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 0413b1a99..08ef22eb9 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 95d2cbf3e..33da35f35 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-70-g09d2