diff --git a/src/main.c b/src/main.c index 0ab0c44..6dcac39 100644 --- a/src/main.c +++ b/src/main.c @@ -29,7 +29,6 @@ typedef enum StickyState { StickyNone, StickyOnceDown, StickyOnceUp, - StickyLock, } StickyState; typedef u8 keycode; @@ -78,9 +77,8 @@ static layer layers_top = 0; // ---------------------------------------------------------------------------- -int main(void) { - kb_init(); // does controller initialization too - +int main() { + kb_init(); usb_init(); while (!usb_configured()); @@ -103,16 +101,9 @@ void main_key_loop() { kb_update_matrix(*kb_is_pressed); - // this loop is responsible to - // - "execute" keys when they change state + // - execute key functions when their key changes state // - keep track of which layers the keys were on when they were pressed // (so they can be released using the function from that layer) - // - // note - // - everything else is the key function's responsibility - // - see the keyboard layout file ("keyboard/layout/*.c") for - // which key is assigned which function (per layer) - // - see "lib/key-functions/public/*.c" for the function definitions for (u8 row=0; row 0 && l < KB_LAYERS; l--) { if (layers_active[l]) { return l; } @@ -187,6 +195,7 @@ StickyState layer_sticky(layer l) { // enable a layer void layer_enable(layer l, StickyState sticky) { + // FIXME split off sticky part if (l >= KB_LAYERS) { return; } layers_active[l] = true; @@ -210,7 +219,7 @@ void layer_disable(layer l) { layers_sticky[l] = StickyNone; if (l == layers_top) { - layers_top = _highest_active_layer(1); + layers_top = highest_active_layer(1); } } @@ -221,58 +230,63 @@ void layer_disable_top() { // return layer offset elements below the top layer layer_peek(layer offset) { - return _highest_active_layer(offset); + return highest_active_layer(offset); } -// execute the keypress or keyrelease function (if it exists) of the key at the current possition -void exec_key(void) { - void (*key_function)(void) = - ( (current_is_pressed) - ? kb_layout_press_get(current_layer, current_row, current_col) - : kb_layout_release_get(current_layer, current_row, current_col) ); - - if (key_function) { - (*key_function)(); +bool is_layer_enable(keyfunc f) { + if (f == &kbfun_layer_enable || f == &kbfun_layer_sticky) { + return true; } + return false; +} - // If the current layer is in the sticky once up state and a key defined - // for this layer (a non-transparent key) was pressed, pop the layer - if (layer_top_sticky() == StickyOnceUp && non_trans_key_pressed) { - layer_disable_top(); +bool is_layer_disable(keyfunc f) { + if (f == &kbfun_layer_disable || f == &kbfun_layer_sticky) { + return true; + } + return false; +} + +void layer_enable_upto(layer max_layer) { + // FIXME clean this up + + // pressing a key implicitly activates all lower layers as well + for (layer l=0; l <= KB_LAYERS; l++) { + void (*key_function)(void) = kb_keyfunc_press(l, current_row, current_col); + + if (is_layer_enable(key_function)) { + layer enable_layer = (layer) kb_keycode(l, current_row, current_col); + if (enable_layer <= max_layer) { + layer_enable(enable_layer, StickyNone); + } + } } } +// ---------------------------------------------------------------------------- +// layout info // ---------------------------------------------------------------------------- -keycode kb_layout_get(layer l, u8 row, u8 col) { - return (keycode) pgm_read_byte(&(_kb_layout[l][row][col] )); +keycode kb_keycode(layer l, u8 row, u8 col) { + return (keycode) pgm_read_byte(&(_kb_layout[l][row][col])); } -keyfunc kb_layout_press_get(layer l, u8 row, u8 col) { - return (keyfunc) pgm_read_word(&(_kb_layout_press[l][row][col] )); +keyfunc kb_keyfunc_press(layer l, u8 row, u8 col) { + return (keyfunc) pgm_read_word(&(_kb_layout_press[l][row][col])); } -keyfunc kb_layout_release_get(layer l, u8 row, u8 col) { +keyfunc kb_keyfunc_release(layer l, u8 row, u8 col) { return (keyfunc) pgm_read_word(&(_kb_layout_release[l][row][col])); } -/* - * Generate a normal keypress or keyrelease - * - * Arguments - * - press: whether to generate a keypress (true) or keyrelease (false) - * - keycode: the keycode to use - * - * Note - * - Because of the way USB does things, what this actually does is either add - * or remove 'keycode' from the list of currently pressed keys, to be sent at - * the end of the current cycle (see main.c) - */ +// ---------------------------------------------------------------------------- +// keyfunc primitives +// ---------------------------------------------------------------------------- + +// basic keypresses void _kbfun_press_release(bool press, keycode key) { -// no-op - if (key == 0) { - return; - } + // no-op + if (key == 0) { return; } if (press) { _kbfun_press(key); @@ -282,7 +296,7 @@ void _kbfun_press_release(bool press, keycode key) { } void _kbfun_press(keycode key) { -// modifier keys + // modifier keys switch (key) { case KEY_LeftControl: keyboard_modifier_keys |= (1<<0); return; case KEY_LeftShift: keyboard_modifier_keys |= (1<<1); return; @@ -295,7 +309,7 @@ void _kbfun_press(keycode key) { } // all others - for (u8 i=0; i<6; i++) { + for (u8 i=0; i < sizeof(keyboard_keys); i++) { if (keyboard_keys[i] == 0) { keyboard_keys[i] = key; return; @@ -304,7 +318,7 @@ void _kbfun_press(keycode key) { } void _kbfun_release(keycode key) { -// modifier keys + // modifier keys switch (key) { case KEY_LeftControl: keyboard_modifier_keys &= ~(1<<0); return; case KEY_LeftShift: keyboard_modifier_keys &= ~(1<<1); return; @@ -316,8 +330,8 @@ void _kbfun_release(keycode key) { case KEY_RightGUI: keyboard_modifier_keys &= ~(1<<7); return; } -// all others - for (u8 i=0; i<6; i++) { + // all others + for (u8 i=0; i < sizeof(keyboard_keys); i++) { if (keyboard_keys[i] == key) { keyboard_keys[i] = 0; return; @@ -325,27 +339,25 @@ void _kbfun_release(keycode key) { } } -/* - * Is the given keycode pressed? - */ bool _kbfun_is_pressed(keycode key) { -// modifier keys + // modifier keys switch (key) { - case KEY_LeftControl: if (keyboard_modifier_keys & (1<<0)) { return true; } - case KEY_LeftShift: if (keyboard_modifier_keys & (1<<1)) { return true; } - case KEY_LeftAlt: if (keyboard_modifier_keys & (1<<2)) { return true; } - case KEY_LeftGUI: if (keyboard_modifier_keys & (1<<3)) { return true; } - case KEY_RightControl: if (keyboard_modifier_keys & (1<<4)) { return true; } - case KEY_RightShift: if (keyboard_modifier_keys & (1<<5)) { return true; } - case KEY_RightAlt: if (keyboard_modifier_keys & (1<<6)) { return true; } - case KEY_RightGUI: if (keyboard_modifier_keys & (1<<7)) { return true; } + case KEY_LeftControl: return (keyboard_modifier_keys & (1<<0)); + case KEY_LeftShift: return (keyboard_modifier_keys & (1<<1)); + case KEY_LeftAlt: return (keyboard_modifier_keys & (1<<2)); + case KEY_LeftGUI: return (keyboard_modifier_keys & (1<<3)); + case KEY_RightControl: return (keyboard_modifier_keys & (1<<4)); + case KEY_RightShift: return (keyboard_modifier_keys & (1<<5)); + case KEY_RightAlt: return (keyboard_modifier_keys & (1<<6)); + case KEY_RightGUI: return (keyboard_modifier_keys & (1<<7)); } -// all others - for (u8 i=0; i<6; i++) + // all others + for (u8 i=0; i < sizeof(keyboard_keys); i++) { if (keyboard_keys[i] == key) { return true; } + } return false; } @@ -355,142 +367,64 @@ void _kbfun_mediakey_press_release(bool press, keycode key) { if (press) { consumer_key = media_key; } else { -// Only one key can be pressed at a time so only clear the keypress for -// active key (most recently pressed) + // only one media key can be pressed at a time, so only clear most recent one if (media_key == consumer_key) { consumer_key = 0; } } } -keycode _kbfun_get_keycode() { - return kb_layout_get(current_layer, current_row, current_col); -} // ---------------------------------------------------------------------------- -// basic +// basic keyfuncs // ---------------------------------------------------------------------------- +keycode current_keycode() { return kb_keycode(current_layer, current_row, current_col); } +keyfunc current_keyfunc_press() { return kb_keyfunc_press(current_layer, current_row, current_col); } +keyfunc current_keycode_release() { return kb_keyfunc_release(current_layer, current_row, current_col); } + +// normal key void kbfun_press_release() { if (!trans_key_pressed) { non_trans_key_pressed = true; } - kbfun_press_release_preserve_sticky(); + _kbfun_press_release(current_is_pressed, current_keycode()); } -/* - * Generate a normal keypress or keyrelease - * While basing the sticky key state transition on whether - * kbfun_press_release() was called after kbfun_transparent() generally - * works in practice, it is not always the desired behavior. One of the - * benefits of sticky keys is avoiding key chording, so we want to make sure - * that standard modifiers do not interrupt the sticky key cycle. Use - * kbfun_press_release_preserve_sticky() if you want to define a standard - * modifier key (shift, control, alt, gui) on the sticky layer instead of - * defining the key to be transparent for the layer. - */ -void kbfun_press_release_preserve_sticky() { - keycode key = _kbfun_get_keycode(); - _kbfun_press_release(current_is_pressed, key); +// media key +void kbfun_mediakey_press_release() { + keycode key = current_keycode(); + _kbfun_mediakey_press_release(current_is_pressed, key); } -// ---------------------------------------------------------------------------- -// layer helper functions -// ---------------------------------------------------------------------------- - -static bool is_layer_enable(keyfunc f) { - if (f == &kbfun_layer_enable || f == &kbfun_layer_sticky) { - return true; - } - return false; -} - -static bool is_layer_disable(keyfunc f) { - if (f == &kbfun_layer_disable || f == &kbfun_layer_sticky) { - return true; - } - return false; -} - -static void layer_enable_upto(layer max_layer) { - // FIXME clean this up - - // pressing a key implicitly activates all lower layers as well - for (layer l=0; l <= KB_LAYERS; l++) { - void (*key_function)(void) = kb_layout_press_get(l, current_row, current_col); - - if (is_layer_enable(key_function)) { - layer enable_layer = (layer) kb_layout_get(l, current_row, current_col); - if (enable_layer <= max_layer) { - layer_enable(enable_layer, StickyNone); - } - } - } -} - -// ---------------------------------------------------------------------------- -// layer functions -// ---------------------------------------------------------------------------- - -// enable given layer +// enable layer void kbfun_layer_enable() { - layer l = (layer) _kbfun_get_keycode(); - - // FIXME useful for anything? - // Only the topmost layer on the stack should be in sticky once state, pop - // the top layer if it is in sticky once state - /* StickyState topSticky = layer_top_sticky(); */ - /* if (topSticky == StickyOnceDown || topSticky == StickyOnceUp) { */ - /* layer_disable_top(); */ - /* } */ - + layer l = (layer) current_keycode(); layer_enable_upto(l); } -// disable given layer +// disable layer void kbfun_layer_disable() { - /* layer l = _kbfun_get_keycode(); */ - // FIXME clean this up - // letting go off a key releases *all* layers on that key for (layer l=0; l <= KB_LAYERS; l++) { - void (*key_function)(void) = kb_layout_release_get(l, current_row, current_col); + void (*key_function)(void) = kb_keyfunc_release(l, current_row, current_col); if (is_layer_disable(key_function)) { - layer disable_layer = (layer) kb_layout_get(l, current_row, current_col); + layer disable_layer = (layer) kb_keycode(l, current_row, current_col); layer_disable(disable_layer); } } } -/* - * This function gives similar behavior to sticky keys for modifiers available - * on most operating systems. - * 1) One time down (set on key press) - The layer was not active and the key - * has been pressed but not yet released. The layer is pushed in the one - * time down state. - * 2) One time up (set on key release) - The layer was active when the layer - * sticky key was released. If a key on this layer (not set to - * transparent) was pressed before the key was released, the layer will be - * popped. If a non-transparent key was not pressed, the layer is popped - * and pushed again in the one time up state. - * 3) Locked (set on key press) - The layer was active and in the one time up - * state when the layer sticky key was pressed again. The layer will be - * popped if the function is invoked on a subsequent keypress. - */ +// sticky layer key void kbfun_layer_sticky() { - layer l = (layer) _kbfun_get_keycode(); - StickyState topSticky = layer_top_sticky(); + layer l = (layer) current_keycode(); + StickyState top_sticky = layer_top_sticky(); if (current_is_pressed) { - if (l == layers_top) { - // FIXME - /* if (topSticky == StickyOnceUp) { */ - /* layer_enable(l, StickyLock); */ - /* } */ - } else { + if (l != layers_top) { // only the topmost layer on the stack should be in sticky once state - if (topSticky == StickyOnceDown || topSticky == StickyOnceUp) { + if (top_sticky == StickyOnceDown || top_sticky == StickyOnceUp) { layer_disable_top(); } layer_enable(l, StickyOnceDown); @@ -516,72 +450,63 @@ void kbfun_layer_sticky() { } // ---------------------------------------------------------------------------- -// special +// combo keyfuncs // ---------------------------------------------------------------------------- -/* - * Generate a 'shift' press or release before the normal keypress or release - */ -void kbfun_shift_press_release(void) { +// +shift +void kbfun_shift_press_release() { _kbfun_press_release(current_is_pressed, KEY_LeftShift); kbfun_press_release(); } -/* - * Generate a 'control' press or release before the normal keypress or release - */ -void kbfun_control_press_release(void) { +// +control +void kbfun_control_press_release() { _kbfun_press_release(current_is_pressed, KEY_LeftControl); kbfun_press_release(); } -/* - * When assigned to two keys (e.g. the physical left and right shift keys) - * (in both the press and release matrices), pressing and holding down one of - * the keys will make the second key toggle capslock - * - * If either of the shifts are pressed when the second key is pressed, they - * wil be released so that capslock will register properly when pressed. - * Capslock will then be pressed and released, and the original state of the - * shifts will be restored - */ -void kbfun_2_keys_capslock_press_release(void) { +// +alt +void kbfun_alt_press_release() { + _kbfun_press_release(current_is_pressed, KEY_LeftAlt); + kbfun_press_release(); +} + +// +win +void kbfun_win_press_release() { + _kbfun_press_release(current_is_pressed, KEY_LeftGUI); + kbfun_press_release(); +} + +// capslock +void kbfun_2_keys_capslock_press_release() { static u8 keys_pressed; static bool lshift_pressed; static bool rshift_pressed; - keycode key = _kbfun_get_keycode(); + keycode key = current_keycode(); if (!current_is_pressed) { keys_pressed--; } -// take care of the key that was actually pressed + // take care of the key that was actually pressed _kbfun_press_release(current_is_pressed, key); -// take care of capslock (only on the press of the 2nd key) + // take care of capslock (only on the press of the 2nd key) if (keys_pressed == 1 && current_is_pressed) { -// save the state of left and right shift + // save the state of left and right shift lshift_pressed = _kbfun_is_pressed(KEY_LeftShift); rshift_pressed = _kbfun_is_pressed(KEY_RightShift); -// disable both + // disable both _kbfun_press_release(false, KEY_LeftShift); _kbfun_press_release(false, KEY_RightShift); -// press capslock, then release it + // press capslock, then release it _kbfun_press_release(true, KEY_CapsLock); usb_keyboard_send(); _kbfun_press_release(false, KEY_CapsLock); usb_keyboard_send(); -// restore the state of left and right shift + // restore the state of left and right shift if (lshift_pressed) { _kbfun_press_release(true, KEY_LeftShift); } if (rshift_pressed) { _kbfun_press_release(true, KEY_RightShift); } } if (current_is_pressed) { keys_pressed++; } } - -/* - * Generate a keypress for a media key - */ -void kbfun_mediakey_press_release(void) { - keycode key = _kbfun_get_keycode(); - _kbfun_mediakey_press_release(current_is_pressed, key); -} diff --git a/src/main.h b/src/main.h index 1eceb7a..736c38c 100644 --- a/src/main.h +++ b/src/main.h @@ -1,30 +1,36 @@ /* This file was automatically generated. Do not edit! */ -void kbfun_mediakey_press_release(void); -void kbfun_2_keys_capslock_press_release(void); -void kbfun_control_press_release(void); -void kbfun_shift_press_release(void); -void kbfun_layer_disable(); -void kbfun_layer_sticky(); -void kbfun_layer_enable(); -void kbfun_press_release_preserve_sticky(); +void kbfun_2_keys_capslock_press_release(); +void kbfun_win_press_release(); +void kbfun_alt_press_release(); +void kbfun_control_press_release(); +void kbfun_shift_press_release(); +void kbfun_mediakey_press_release(); void kbfun_press_release(); -keycode _kbfun_get_keycode(); +keyfunc current_keycode_release(); +keyfunc current_keyfunc_press(); +keycode current_keycode(); void _kbfun_mediakey_press_release(bool press,keycode key); bool _kbfun_is_pressed(keycode key); void _kbfun_release(keycode key); void _kbfun_press(keycode key); void _kbfun_press_release(bool press,keycode key); -keycode kb_layout_get(layer l,u8 row,u8 col); -keyfunc kb_layout_release_get(layer l,u8 row,u8 col); -keyfunc kb_layout_press_get(layer l,u8 row,u8 col); +keycode kb_keycode(layer l,u8 row,u8 col); +void layer_enable_upto(layer max_layer); +void kbfun_layer_disable(); +bool is_layer_disable(keyfunc f); +void kbfun_layer_sticky(); +void kbfun_layer_enable(); +bool is_layer_enable(keyfunc f); layer layer_peek(layer offset); -void layer_disable_top(); void layer_disable(layer l); void layer_enable(layer l,StickyState sticky); StickyState layer_sticky(layer l); +layer highest_active_layer(layer offset); +void layer_disable_top(); StickyState layer_top_sticky(); -layer _highest_active_layer(layer offset); +keyfunc kb_keyfunc_release(layer l,u8 row,u8 col); +keyfunc kb_keyfunc_press(layer l,u8 row,u8 col); void exec_key(void); void main_key_loop(); void init_layers(); -int main(void); +int main();