diff --git a/src/lib/keyboard.h b/src/keyboard/keyboard.h similarity index 94% rename from src/lib/keyboard.h rename to src/keyboard/keyboard.h index 9e2a686..68581f4 100644 --- a/src/lib/keyboard.h +++ b/src/keyboard/keyboard.h @@ -324,3 +324,31 @@ #define SYSTEM_POWER_DOWN 0x0081 #define SYSTEM_SLEEP 0x0082 #define SYSTEM_WAKE_UP 0x0083 + +/* + * MediaCodeLookupTable is used to translate from enumeration in keyboard.h to + * consumer key scan code in usb_keyboard.h + */ +static const uint16_t _media_code_lookup_table[] = { + AUDIO_MUTE, // MEDIAKEY_AUDIO_MUTE + AUDIO_VOL_UP, // MEDIAKEY_AUDIO_VOL_UP + AUDIO_VOL_DOWN, // MEDIAKEY_AUDIO_VOL_DOWN + TRANSPORT_NEXT_TRACK, // MEDIAKEY_NEXT_TRACK + TRANSPORT_PREV_TRACK, // MEDIAKEY_PREV_TRACK + TRANSPORT_STOP, // MEDIAKEY_STOP + TRANSPORT_PLAY_PAUSE, // MEDIAKEY_PLAY_PAUSE + TRANSPORT_RECORD, // MEDIAKEY_RECORD + TRANSPORT_REWIND, // MEDIAKEY_REWIND + TRANSPORT_EJECT, // MEDIAKEY_EJECT + AL_CC_CONFIG, // MEDIAKEY_CC_CONFIG + AL_EMAIL, // MEDIAKEY_EMAIL + AL_CALCULATOR, // MEDIAKEY_CALCULATOR + AL_LOCAL_BROWSER, // MEDIAKEY_LOCAL_BROWSER + AC_SEARCH, // MEDIAKEY_BROWSER_SEARCH + AC_HOME, // MEDIAKEY_BROWSER_HOME + AC_BACK, // MEDIAKEY_BROWSER_BACK + AC_FORWARD, // MEDIAKEY_BROWSER_FORWARD + AC_STOP, // MEDIAKEY_BROWSER_STOP + AC_REFRESH, // MEDIAKEY_BROWSER_REFRESH + AC_BOOKMARKS, // MEDIAKEY_BROWSER_BOOKMARKS +}; diff --git a/src/keyboard/layout.h b/src/keyboard/layout.h index 6e86f0a..6a39620 100644 --- a/src/keyboard/layout.h +++ b/src/keyboard/layout.h @@ -11,8 +11,6 @@ #include #include #include -#include "../lib/keyboard.h" -#include "../lib/keyfunctions.h" typedef void (*void_funptr_t)(void); @@ -22,6 +20,43 @@ typedef void (*void_funptr_t)(void); #define KB_COLUMNS 14 // must match real life #define KB_LAYERS 10 +// -------------------------------------------------------------------- +uint8_t main_layers_top_layer (void); +uint8_t main_layers_top_sticky (void); +uint8_t main_layers_sticky (uint8_t layer); +void main_layers_enable (uint8_t layer, uint8_t sticky); +void main_layers_disable (uint8_t layer); +void main_layers_disable_top (void); + +// basic +void kbfun_press_release (void); +void kbfun_press_release_preserve_sticky (void); +void kbfun_toggle (void); +void kbfun_transparent (void); + +// layer functions +void kbfun_layer_enable (void); +void kbfun_layer_sticky (void); +void kbfun_layer_disable (void); + +// device +void kbfun_jump_to_bootloader (void); + +// special +void kbfun_shift_press_release (void); +void kbfun_control_press_release (void); +void kbfun_2_keys_capslock_press_release (void); +void kbfun_mediakey_press_release (void); + +// private +void _kbfun_press_release (bool press, uint8_t keycode); +bool _kbfun_is_pressed (uint8_t keycode); +void _kbfun_mediakey_press_release (bool press, uint8_t keycode); +uint8_t _kbfun_get_keycode (void); + +// device +void kbfun_jump_to_bootloader(void); + // -------------------------------------------------------------------- /* diff --git a/src/lib/keyfunctions.c b/src/lib/keyfunctions.c deleted file mode 100644 index 84d619b..0000000 --- a/src/lib/keyfunctions.c +++ /dev/null @@ -1,407 +0,0 @@ -/* ---------------------------------------------------------------------------- - * key functions : private : code - * ---------------------------------------------------------------------------- - * Copyright (c) 2012 Ben Blazak - * Released under The MIT License (MIT) (see "license.md") - * Project located at - * ------------------------------------------------------------------------- */ - -#include "./keyfunctions.h" - -/* - * MediaCodeLookupTable is used to translate from enumeration in keyboard.h to - * consumer key scan code in usb_keyboard.h - */ -static const uint16_t _media_code_lookup_table[] = { - AUDIO_MUTE, // MEDIAKEY_AUDIO_MUTE - AUDIO_VOL_UP, // MEDIAKEY_AUDIO_VOL_UP - AUDIO_VOL_DOWN, // MEDIAKEY_AUDIO_VOL_DOWN - TRANSPORT_NEXT_TRACK, // MEDIAKEY_NEXT_TRACK - TRANSPORT_PREV_TRACK, // MEDIAKEY_PREV_TRACK - TRANSPORT_STOP, // MEDIAKEY_STOP - TRANSPORT_PLAY_PAUSE, // MEDIAKEY_PLAY_PAUSE - TRANSPORT_RECORD, // MEDIAKEY_RECORD - TRANSPORT_REWIND, // MEDIAKEY_REWIND - TRANSPORT_EJECT, // MEDIAKEY_EJECT - AL_CC_CONFIG, // MEDIAKEY_CC_CONFIG - AL_EMAIL, // MEDIAKEY_EMAIL - AL_CALCULATOR, // MEDIAKEY_CALCULATOR - AL_LOCAL_BROWSER, // MEDIAKEY_LOCAL_BROWSER - AC_SEARCH, // MEDIAKEY_BROWSER_SEARCH - AC_HOME, // MEDIAKEY_BROWSER_HOME - AC_BACK, // MEDIAKEY_BROWSER_BACK - AC_FORWARD, // MEDIAKEY_BROWSER_FORWARD - AC_STOP, // MEDIAKEY_BROWSER_STOP - AC_REFRESH, // MEDIAKEY_BROWSER_REFRESH - AC_BOOKMARKS, // MEDIAKEY_BROWSER_BOOKMARKS -}; - -// ---------------------------------------------------------------------------- - -/* - * 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) - */ -void _kbfun_press_release(bool press, uint8_t keycode) { -// no-op - if (keycode == 0) { - return; - } - -// modifier keys - switch (keycode) { - case KEY_LeftControl: (press) ? (keyboard_modifier_keys |= (1<<0)) : (keyboard_modifier_keys &= ~(1<<0)); return; - case KEY_LeftShift: (press) ? (keyboard_modifier_keys |= (1<<1)) : (keyboard_modifier_keys &= ~(1<<1)); return; - case KEY_LeftAlt: (press) ? (keyboard_modifier_keys |= (1<<2)) : (keyboard_modifier_keys &= ~(1<<2)); return; - case KEY_LeftGUI: (press) ? (keyboard_modifier_keys |= (1<<3)) : (keyboard_modifier_keys &= ~(1<<3)); return; - case KEY_RightControl: (press) ? (keyboard_modifier_keys |= (1<<4)) : (keyboard_modifier_keys &= ~(1<<4)); return; - case KEY_RightShift: (press) ? (keyboard_modifier_keys |= (1<<5)) : (keyboard_modifier_keys &= ~(1<<5)); return; - case KEY_RightAlt: (press) ? (keyboard_modifier_keys |= (1<<6)) : (keyboard_modifier_keys &= ~(1<<6)); return; - case KEY_RightGUI: (press) ? (keyboard_modifier_keys |= (1<<7)) : (keyboard_modifier_keys &= ~(1<<7)); return; - } - -// all others - for (uint8_t i=0; i<6; i++) { - if (press) { - if (keyboard_keys[i] == 0) { - keyboard_keys[i] = keycode; - return; - } - } else { - if (keyboard_keys[i] == keycode) { - keyboard_keys[i] = 0; - return; - } - } - } -} - -/* - * Is the given keycode pressed? - */ -bool _kbfun_is_pressed(uint8_t keycode) { -// modifier keys - switch (keycode) { - 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; } - } - -// all others - for (uint8_t i=0; i<6; i++) - if (keyboard_keys[i] == keycode) { - return true; - } - - return false; -} - -void _kbfun_mediakey_press_release(bool press, uint8_t keycode) { - uint16_t mediakey_code = _media_code_lookup_table[keycode]; - if (press) { - consumer_key = mediakey_code; - } else { -// Only one key can be pressed at a time so only clear the keypress for -// active key (most recently pressed) - if (mediakey_code == consumer_key) { - consumer_key = 0; - } - } -} - -uint8_t _kbfun_get_keycode() { - return kb_layout_get(main_arg_layer, main_arg_row, main_arg_col); -} - -// ---------------------------------------------------------------------------- -// basic -// ---------------------------------------------------------------------------- - -void kbfun_press_release() { - if (!main_arg_trans_key_pressed) { - main_arg_any_non_trans_key_pressed = true; - } - kbfun_press_release_preserve_sticky(); -} - -/* - * 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() { - uint8_t keycode = _kbfun_get_keycode(); - _kbfun_press_release(main_arg_is_pressed, keycode); -} - -/* - * Toggle the key pressed or unpressed - */ -void kbfun_toggle(void) { - uint8_t keycode = _kbfun_get_keycode(); - bool is_pressed = _kbfun_is_pressed(keycode); - _kbfun_press_release(!is_pressed, keycode); -} - -/* - * Execute the key that would have been executed if the current layer was not - * active - */ -void kbfun_transparent(void) { - // TODO maybe re-implement this cleaner? - main_arg_trans_key_pressed = true; - main_arg_layer_offset++; - main_arg_layer = main_layers_peek(main_arg_layer_offset); - main_layers_pressed[main_arg_row][main_arg_col] = main_arg_layer; - main_exec_key(); -} - - -// ---------------------------------------------------------------------------- -// layer helper functions -// ---------------------------------------------------------------------------- - -static bool is_layer_enable(void_funptr_t f) { - if (f == &kbfun_layer_enable || f == &kbfun_layer_sticky) { - return true; - } - return false; -} - -static bool is_layer_disable(void_funptr_t f) { - if (f == &kbfun_layer_disable || f == &kbfun_layer_sticky) { - return true; - } - return false; -} - -static void layer_enable_upto(uint8_t max_layer) { - // FIXME clean this up - - // pressing a key implicitly activates all lower layers as well - for (uint8_t layer=0; layer <= KB_LAYERS; layer++) { - void (*key_function)(void) = kb_layout_press_get(layer, main_arg_row, main_arg_col); - - if (is_layer_enable(key_function)) { - uint8_t enable_layer = kb_layout_get(layer, main_arg_row, main_arg_col); - if (enable_layer <= max_layer) { - main_layers_enable(enable_layer, eStickyNone); - } - } - } -} - -static void layer_disable_all() { - // FIXME clean this up - - // letting go off a key releases *all* layers on that key - for (uint8_t layer=0; layer <= KB_LAYERS; layer++) { - void (*key_function)(void) = kb_layout_release_get(layer, main_arg_row, main_arg_col); - - if (is_layer_disable(key_function)) { - uint8_t disable_layer = kb_layout_get(layer, main_arg_row, main_arg_col); - main_layers_disable(disable_layer); - } - } -} - -// ---------------------------------------------------------------------------- -// layer functions -// ---------------------------------------------------------------------------- - -// enable given layer -void kbfun_layer_enable() { - uint8_t 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 - /* uint8_t topSticky = main_layers_top_sticky(); */ - /* if (topSticky == eStickyOnceDown || topSticky == eStickyOnceUp) { */ - /* main_layers_disable_top(); */ - /* } */ - - layer_enable_upto(layer); -} - -// disable given layer -void kbfun_layer_disable() { - /* uint8_t layer = _kbfun_get_keycode(); */ - layer_disable_all(); -} - -/* - * 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. - */ -void kbfun_layer_sticky() { - uint8_t layer = _kbfun_get_keycode(); - uint8_t topLayer = main_layers_top_layer(); - uint8_t topSticky = main_layers_top_sticky(); - - if (main_arg_is_pressed) { - if (topLayer == layer) { - // FIXME - /* if (topSticky == eStickyOnceUp) { */ - /* main_layers_enable(layer, eStickyLock); */ - /* } */ - } else { - // only the topmost layer on the stack should be in sticky once state - if (topSticky == eStickyOnceDown || topSticky == eStickyOnceUp) { - main_layers_disable_top(); - } - main_layers_enable(layer, eStickyOnceDown); - - // this should be the only place we care about this flag being cleared - main_arg_any_non_trans_key_pressed = false; - } - } else { - if (main_layers_sticky(layer) == eStickyOnceDown) { - // When releasing this sticky key, pop the layer always - main_layers_disable(layer); - - if (!main_arg_any_non_trans_key_pressed) { - // If no key defined for this layer (a non-transparent key) - // was pressed, push the layer again, but in the - // StickyOnceUp state - main_layers_enable(layer, eStickyOnceUp); - } - } - } -} - -// ---------------------------------------------------------------------------- -// device -// ---------------------------------------------------------------------------- - -/* - * [name] - * Jump to Bootloader - * - * [description] - * For reflashing the controller - */ - -// from PJRC (slightly modified) -// -void kbfun_jump_to_bootloader(void) { - // --- for all Teensy boards --- - - cli(); - - // disable watchdog, if enabled - // disable all peripherals - UDCON = 1; - USBCON = (1< - * Released under The MIT License (MIT) (see "license.md") - * Project located at - * ------------------------------------------------------------------------- */ - -#pragma once - -#include -#include -#include -#include -#include "../main.h" -#include "../keyboard/layout.h" -#include "../lib/keyboard.h" - -// -------------------------------------------------------------------- - -// basic -void kbfun_press_release (void); -void kbfun_press_release_preserve_sticky (void); -void kbfun_toggle (void); -void kbfun_transparent (void); - -// layer functions -void kbfun_layer_enable (void); -void kbfun_layer_sticky (void); -void kbfun_layer_disable (void); - -// device -void kbfun_jump_to_bootloader (void); - -// special -void kbfun_shift_press_release (void); -void kbfun_control_press_release (void); -void kbfun_2_keys_capslock_press_release (void); -void kbfun_mediakey_press_release (void); - -// private -void _kbfun_press_release (bool press, uint8_t keycode); -bool _kbfun_is_pressed (uint8_t keycode); -void _kbfun_mediakey_press_release (bool press, uint8_t keycode); -uint8_t _kbfun_get_keycode (void); - -// device -void kbfun_jump_to_bootloader(void); diff --git a/src/main.c b/src/main.c index 13ecfa2..cbe1a24 100644 --- a/src/main.c +++ b/src/main.c @@ -7,11 +7,23 @@ * ------------------------------------------------------------------------- */ -#include "./main.h" +#include +#include +#include +#include +#include +#include +#include +#include "./keyboard/controller.h" +#include "./keyboard/keyboard.h" #include "./keyboard/layout_gen.h" // ---------------------------------------------------------------------------- +#define KB_ROWS 6 // must match real life +#define KB_COLUMNS 14 // must match real life +#define KB_LAYERS 10 + static bool _main_kb_is_pressed[KB_ROWS][KB_COLUMNS]; bool (*main_kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_main_kb_is_pressed; @@ -31,6 +43,16 @@ bool main_arg_was_pressed; bool main_arg_any_non_trans_key_pressed; bool main_arg_trans_key_pressed; +// -------------------------------------------------------------------- + +typedef enum StickyState +{ + eStickyNone, + eStickyOnceDown, + eStickyOnceUp, + eStickyLock +} StickyState; + // layer data struct layer { bool active; @@ -198,3 +220,373 @@ void main_exec_key(void) { main_layers_disable_top(); } } + +// ---------------------------------------------------------------------------- + +/* + * 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) + */ +void _kbfun_press_release(bool press, uint8_t keycode) { +// no-op + if (keycode == 0) { + return; + } + +// modifier keys + switch (keycode) { + case KEY_LeftControl: (press) ? (keyboard_modifier_keys |= (1<<0)) : (keyboard_modifier_keys &= ~(1<<0)); return; + case KEY_LeftShift: (press) ? (keyboard_modifier_keys |= (1<<1)) : (keyboard_modifier_keys &= ~(1<<1)); return; + case KEY_LeftAlt: (press) ? (keyboard_modifier_keys |= (1<<2)) : (keyboard_modifier_keys &= ~(1<<2)); return; + case KEY_LeftGUI: (press) ? (keyboard_modifier_keys |= (1<<3)) : (keyboard_modifier_keys &= ~(1<<3)); return; + case KEY_RightControl: (press) ? (keyboard_modifier_keys |= (1<<4)) : (keyboard_modifier_keys &= ~(1<<4)); return; + case KEY_RightShift: (press) ? (keyboard_modifier_keys |= (1<<5)) : (keyboard_modifier_keys &= ~(1<<5)); return; + case KEY_RightAlt: (press) ? (keyboard_modifier_keys |= (1<<6)) : (keyboard_modifier_keys &= ~(1<<6)); return; + case KEY_RightGUI: (press) ? (keyboard_modifier_keys |= (1<<7)) : (keyboard_modifier_keys &= ~(1<<7)); return; + } + +// all others + for (uint8_t i=0; i<6; i++) { + if (press) { + if (keyboard_keys[i] == 0) { + keyboard_keys[i] = keycode; + return; + } + } else { + if (keyboard_keys[i] == keycode) { + keyboard_keys[i] = 0; + return; + } + } + } +} + +/* + * Is the given keycode pressed? + */ +bool _kbfun_is_pressed(uint8_t keycode) { +// modifier keys + switch (keycode) { + 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; } + } + +// all others + for (uint8_t i=0; i<6; i++) + if (keyboard_keys[i] == keycode) { + return true; + } + + return false; +} + +void _kbfun_mediakey_press_release(bool press, uint8_t keycode) { + uint16_t mediakey_code = _media_code_lookup_table[keycode]; + if (press) { + consumer_key = mediakey_code; + } else { +// Only one key can be pressed at a time so only clear the keypress for +// active key (most recently pressed) + if (mediakey_code == consumer_key) { + consumer_key = 0; + } + } +} + +uint8_t _kbfun_get_keycode() { + return kb_layout_get(main_arg_layer, main_arg_row, main_arg_col); +} + +// ---------------------------------------------------------------------------- +// basic +// ---------------------------------------------------------------------------- + +void kbfun_press_release() { + if (!main_arg_trans_key_pressed) { + main_arg_any_non_trans_key_pressed = true; + } + kbfun_press_release_preserve_sticky(); +} + +/* + * 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() { + uint8_t keycode = _kbfun_get_keycode(); + _kbfun_press_release(main_arg_is_pressed, keycode); +} + +/* + * Toggle the key pressed or unpressed + */ +void kbfun_toggle(void) { + uint8_t keycode = _kbfun_get_keycode(); + bool is_pressed = _kbfun_is_pressed(keycode); + _kbfun_press_release(!is_pressed, keycode); +} + +/* + * Execute the key that would have been executed if the current layer was not + * active + */ +void kbfun_transparent(void) { + // TODO maybe re-implement this cleaner? + main_arg_trans_key_pressed = true; + main_arg_layer_offset++; + main_arg_layer = main_layers_peek(main_arg_layer_offset); + main_layers_pressed[main_arg_row][main_arg_col] = main_arg_layer; + main_exec_key(); +} + + +// ---------------------------------------------------------------------------- +// layer helper functions +// ---------------------------------------------------------------------------- + +static bool is_layer_enable(void_funptr_t f) { + if (f == &kbfun_layer_enable || f == &kbfun_layer_sticky) { + return true; + } + return false; +} + +static bool is_layer_disable(void_funptr_t f) { + if (f == &kbfun_layer_disable || f == &kbfun_layer_sticky) { + return true; + } + return false; +} + +static void layer_enable_upto(uint8_t max_layer) { + // FIXME clean this up + + // pressing a key implicitly activates all lower layers as well + for (uint8_t layer=0; layer <= KB_LAYERS; layer++) { + void (*key_function)(void) = kb_layout_press_get(layer, main_arg_row, main_arg_col); + + if (is_layer_enable(key_function)) { + uint8_t enable_layer = kb_layout_get(layer, main_arg_row, main_arg_col); + if (enable_layer <= max_layer) { + main_layers_enable(enable_layer, eStickyNone); + } + } + } +} + +static void layer_disable_all() { + // FIXME clean this up + + // letting go off a key releases *all* layers on that key + for (uint8_t layer=0; layer <= KB_LAYERS; layer++) { + void (*key_function)(void) = kb_layout_release_get(layer, main_arg_row, main_arg_col); + + if (is_layer_disable(key_function)) { + uint8_t disable_layer = kb_layout_get(layer, main_arg_row, main_arg_col); + main_layers_disable(disable_layer); + } + } +} + +// ---------------------------------------------------------------------------- +// layer functions +// ---------------------------------------------------------------------------- + +// enable given layer +void kbfun_layer_enable() { + uint8_t 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 + /* uint8_t topSticky = main_layers_top_sticky(); */ + /* if (topSticky == eStickyOnceDown || topSticky == eStickyOnceUp) { */ + /* main_layers_disable_top(); */ + /* } */ + + layer_enable_upto(layer); +} + +// disable given layer +void kbfun_layer_disable() { + /* uint8_t layer = _kbfun_get_keycode(); */ + layer_disable_all(); +} + +/* + * 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. + */ +void kbfun_layer_sticky() { + uint8_t layer = _kbfun_get_keycode(); + uint8_t topLayer = main_layers_top_layer(); + uint8_t topSticky = main_layers_top_sticky(); + + if (main_arg_is_pressed) { + if (topLayer == layer) { + // FIXME + /* if (topSticky == eStickyOnceUp) { */ + /* main_layers_enable(layer, eStickyLock); */ + /* } */ + } else { + // only the topmost layer on the stack should be in sticky once state + if (topSticky == eStickyOnceDown || topSticky == eStickyOnceUp) { + main_layers_disable_top(); + } + main_layers_enable(layer, eStickyOnceDown); + + // this should be the only place we care about this flag being cleared + main_arg_any_non_trans_key_pressed = false; + } + } else { + if (main_layers_sticky(layer) == eStickyOnceDown) { + // When releasing this sticky key, pop the layer always + main_layers_disable(layer); + + if (!main_arg_any_non_trans_key_pressed) { + // If no key defined for this layer (a non-transparent key) + // was pressed, push the layer again, but in the + // StickyOnceUp state + main_layers_enable(layer, eStickyOnceUp); + } + } + } +} + +// ---------------------------------------------------------------------------- +// device +// ---------------------------------------------------------------------------- + +/* + * [name] + * Jump to Bootloader + * + * [description] + * For reflashing the controller + */ + +// from PJRC (slightly modified) +// +void kbfun_jump_to_bootloader(void) { + // --- for all Teensy boards --- + + cli(); + + // disable watchdog, if enabled + // disable all peripherals + UDCON = 1; + USBCON = (1< - * Released under The MIT License (MIT) (see "license.md") - * Project located at - * ------------------------------------------------------------------------- */ - -#pragma once - -#include -#include -#include -#include "./lib/keyfunctions.h" -#include "./keyboard/controller.h" -#include "./keyboard/layout.h" - -// -------------------------------------------------------------------- - -typedef enum StickyState -{ - eStickyNone, - eStickyOnceDown, - eStickyOnceUp, - eStickyLock -} StickyState; - -extern bool (*main_kb_is_pressed)[KB_ROWS][KB_COLUMNS]; -extern bool (*main_kb_was_pressed)[KB_ROWS][KB_COLUMNS]; -extern uint8_t main_layers_pressed[KB_ROWS][KB_COLUMNS]; -extern uint8_t main_arg_layer; -extern uint8_t main_arg_layer_offset; -extern uint8_t main_arg_row; -extern uint8_t main_arg_col; -extern bool main_arg_is_pressed; -extern bool main_arg_was_pressed; -extern bool main_arg_any_non_trans_key_pressed; -extern bool main_arg_trans_key_pressed; - -// -------------------------------------------------------------------- - -void main_exec_key (void); - -uint8_t main_layers_top_layer (void); -uint8_t main_layers_top_sticky (void); -uint8_t main_layers_sticky (uint8_t layer); -void main_layers_enable (uint8_t layer, uint8_t sticky); -void main_layers_disable (uint8_t layer); -void main_layers_disable_top (void); diff --git a/src/lib/teensy-2-0.md b/src/teensy-2-0.md similarity index 100% rename from src/lib/teensy-2-0.md rename to src/teensy-2-0.md diff --git a/src/lib/teensy-readme.md b/src/teensy-readme.md similarity index 100% rename from src/lib/teensy-readme.md rename to src/teensy-readme.md