diff options
-rw-r--r-- | common.mk | 1 | ||||
-rw-r--r-- | common/action.c | 127 | ||||
-rw-r--r-- | common/layer_stack.c | 100 | ||||
-rw-r--r-- | common/layer_stack.h | 44 |
4 files changed, 167 insertions, 105 deletions
@@ -3,6 +3,7 @@ SRC += $(COMMON_DIR)/host.c \ $(COMMON_DIR)/keyboard.c \ $(COMMON_DIR)/action.c \ $(COMMON_DIR)/action_macro.c \ + $(COMMON_DIR)/layer_stack.c \ $(COMMON_DIR)/keymap.c \ $(COMMON_DIR)/command.c \ $(COMMON_DIR)/timer.c \ diff --git a/common/action.c b/common/action.c index 38c5933ee..9a8d75596 100644 --- a/common/action.c +++ b/common/action.c @@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "util.h" #include "debug.h" #include "action.h" +#include "layer_stack.h" /* default layer indicates base layer */ @@ -163,85 +164,6 @@ static void oneshot_toggle(void) } -/* - * Layer stack - */ -#define LAYER_STACK_SIZE 8 -typedef struct { - uint8_t layer:4; - uint8_t next:3; - bool used; -} layer_item_t; - -static uint8_t top_layer = 0; -// [0] is sentinel and not used. [0] is null item. -static layer_item_t layer_stack[LAYER_STACK_SIZE] = {}; - -static bool layer_push(uint8_t layer) -{ - for (uint8_t i = 1; i < LAYER_STACK_SIZE; i++) { - if (!layer_stack[i].used) { - layer_stack[i] = (layer_item_t){ .layer = layer, - .next = top_layer, - .used = true }; - top_layer = i; - return true; - } - } - return false; -} -static bool layer_pop(void) -{ - if (layer_stack[top_layer].used) { - uint8_t popped = top_layer; - top_layer = layer_stack[popped].next; - layer_stack[popped] = (layer_item_t){}; - return true; - } - return false; -} -static bool layer_remove(uint8_t layer) -{ - if (layer_stack[top_layer].used && layer_stack[top_layer].layer == layer) { - layer_pop(); - debug("layer_remove: top_layer\n"); - return true; - } - - for (uint8_t i = top_layer; layer_stack[i].used; i = layer_stack[i].next) { - debug("layer_remove: ["); debug_dec(i); debug("]"); - debug_dec(layer_stack[i].layer); debug("\n"); - uint8_t removed = layer_stack[i].next; - if (layer_stack[removed].used && layer_stack[removed].layer == layer) { - layer_stack[i].next = layer_stack[removed].next; - layer_stack[removed] = (layer_item_t){}; - debug("layer_remove: removed.\n"); - return true; - } - } - return false; -} -static bool layer_remove_then_push(uint8_t layer) -{ - layer_remove(layer); - return layer_push(layer); -} -static bool layer_remove_or_push(uint8_t layer) -{ - return (layer_remove(layer)) || layer_push(layer); -} -static void debug_layer_stack(void) -{ - debug("layer_stack: "); - layer_item_t item = layer_stack[top_layer]; - while (item.used) { - debug_dec(item.layer); - debug("["); debug_dec(item.next); debug("]"); - item = layer_stack[item.next]; - } - debug("\n"); -} - void action_exec(keyevent_t event) { @@ -292,14 +214,9 @@ static action_t get_action(key_t key) action.code = ACTION_NO; /* layer stack */ - for (layer_item_t i = layer_stack[top_layer]; i.used; i = layer_stack[i.next]) { - action = action_for_key(i.layer, key); - if (action.code != ACTION_TRANSPARENT) { - debug_layer_stack(); - debug("layer_stack: used. "); debug_dec(i.layer); debug("\n"); - return action; - } - debug("layer_stack: through. "); debug_dec(i.layer); debug("\n"); + action = layer_stack_get_action(key); + if (action.code != ACTION_TRANSPARENT) { + return action; } /* current layer: 0 means default layer */ @@ -618,41 +535,41 @@ static void process_action(keyrecord_t *record) switch (action.layer.code) { case LAYER_MOMENTARY: /* momentary */ if (event.pressed) { - layer_remove_then_push(action.layer.val); - debug_layer_stack(); + layer_stack_remove_then_push(action.layer.val); + layer_stack_debug(); } else { - layer_remove(action.layer.val); - debug_layer_stack(); + layer_stack_remove(action.layer.val); + layer_stack_debug(); } break; case LAYER_ON_PRESS: if (event.pressed) { - layer_remove_or_push(action.layer.val); - debug_layer_stack(); + layer_stack_remove_or_push(action.layer.val); + layer_stack_debug(); } break; case LAYER_ON_RELEASE: if (!event.pressed) { - layer_remove_or_push(action.layer.val); - debug_layer_stack(); + layer_stack_remove_or_push(action.layer.val); + layer_stack_debug(); } break; case LAYER_ON_BOTH: - layer_remove_or_push(action.layer.val); - debug_layer_stack(); + layer_stack_remove_or_push(action.layer.val); + layer_stack_debug(); break; case LAYER_TAP_TOGGLE: /* switch on hold and toggle on several taps */ if (event.pressed) { if (tap_count < TAPPING_TOGGLE) { debug("LAYER_STACK: tap toggle(press).\n"); - layer_remove_or_push(action.layer.val); - debug_layer_stack(); + layer_stack_remove_or_push(action.layer.val); + layer_stack_debug(); } } else { if (tap_count <= TAPPING_TOGGLE) { debug("LAYER_STACK: tap toggle(release).\n"); - layer_remove_or_push(action.layer.val); - debug_layer_stack(); + layer_stack_remove_or_push(action.layer.val); + layer_stack_debug(); } } break; @@ -664,8 +581,8 @@ static void process_action(keyrecord_t *record) register_code(action.layer.code); } else { debug("LAYER_STACK: No tap: layer_stack(on press)\n"); - layer_remove_or_push(action.layer.val); - debug_layer_stack(); + layer_stack_remove_or_push(action.layer.val); + layer_stack_debug(); } } else { if (IS_TAPPING_KEY(event.key) && tap_count > 0) { @@ -673,8 +590,8 @@ static void process_action(keyrecord_t *record) unregister_code(action.layer.code); } else { debug("LAYER_STACK: No tap: layer_stack(on release)\n"); - layer_remove_or_push(action.layer.val); - debug_layer_stack(); + layer_stack_remove_or_push(action.layer.val); + layer_stack_debug(); } } break; diff --git a/common/layer_stack.c b/common/layer_stack.c new file mode 100644 index 000000000..07c84870c --- /dev/null +++ b/common/layer_stack.c @@ -0,0 +1,100 @@ +#include <stdint.h> +#include "keyboard.h" +#include "layer_stack.h" +#include "debug.h" + + +static uint8_t top_layer = 0; + +/* [0] always works as sentinel and not used for store.*/ +static layer_item_t layer_stack[LAYER_STACK_SIZE] = {}; + +bool layer_stack_push(uint8_t layer) +{ + for (uint8_t i = 1; i < LAYER_STACK_SIZE; i++) { + if (!layer_stack[i].used) { + layer_stack[i] = (layer_item_t){ .layer = layer, + .next = top_layer, + .used = true }; + top_layer = i; + return true; + } + } + return false; +} + +bool layer_stack_pop(void) +{ + if (layer_stack[top_layer].used) { + uint8_t popped = top_layer; + top_layer = layer_stack[popped].next; + layer_stack[popped] = (layer_item_t){}; + return true; + } + return false; +} + +bool layer_stack_remove(uint8_t layer) +{ + if (layer_stack[top_layer].used && layer_stack[top_layer].layer == layer) { + layer_stack_pop(); + debug("layer_stack_remove: top_layer\n"); + return true; + } + + for (uint8_t i = top_layer; layer_stack[i].used; i = layer_stack[i].next) { + debug("layer_stack_remove: ["); debug_dec(i); debug("]"); + debug_dec(layer_stack[i].layer); debug("\n"); + uint8_t removed = layer_stack[i].next; + if (layer_stack[removed].used && layer_stack[removed].layer == layer) { + layer_stack[i].next = layer_stack[removed].next; + layer_stack[removed] = (layer_item_t){}; + debug("layer_stack_remove: removed.\n"); + return true; + } + } + return false; +} + +bool layer_stack_remove_then_push(uint8_t layer) +{ + layer_stack_remove(layer); + return layer_stack_push(layer); +} + +bool layer_stack_remove_or_push(uint8_t layer) +{ + return (layer_stack_remove(layer)) || layer_stack_push(layer); +} + +void layer_stack_debug(void) +{ + debug("layer_stack: "); + layer_item_t item = layer_stack[top_layer]; + while (item.used) { + debug_dec(item.layer); + debug("["); debug_dec(item.next); debug("]"); + item = layer_stack[item.next]; + } + debug("\n"); +} + + + +action_t layer_stack_get_action(key_t key) +{ + action_t action; + action.code = ACTION_TRANSPARENT; + + /* layer stack */ + for (layer_item_t i = layer_stack[top_layer]; i.used; i = layer_stack[i.next]) { + action = action_for_key(i.layer, key); + if (action.code != ACTION_TRANSPARENT) { + layer_stack_debug(); + debug("layer_stack: used. "); debug_dec(i.layer); debug("\n"); + return action; + } + debug("layer_stack: through. "); debug_dec(i.layer); debug("\n"); + } + return action; +} diff --git a/common/layer_stack.h b/common/layer_stack.h new file mode 100644 index 000000000..c88eaffc4 --- /dev/null +++ b/common/layer_stack.h @@ -0,0 +1,44 @@ +/* +Copyright 2013 Jun Wako <wakojun@gmail.com> + +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 <http://www.gnu.org/licenses/>. +*/ +#ifndef LAYER_STACK_H +#define LAYER_STACK_H + +#include <stdint.h> +#include "action.h" + + +/* + * Layer stack + */ +#define LAYER_STACK_SIZE 8 +typedef struct { + uint8_t layer:4; + uint8_t next:3; + bool used; +} layer_item_t; + + +bool layer_stack_push(uint8_t layer); +bool layer_stack_pop(void); +bool layer_stack_remove(uint8_t layer); +bool layer_stack_remove_then_push(uint8_t layer); +bool layer_stack_remove_or_push(uint8_t layer); +void layer_stack_debug(void); +action_t layer_stack_get_action(key_t key); + +#endif + |