more cleanup

master
Stefan Dorn 2016-06-11 21:42:22 +01:00
parent 0c141072da
commit b4c9342533
7 changed files with 282 additions and 312 deletions

View File

@ -11,7 +11,7 @@
#include <stdint.h>
#include <stddef.h>
#include <avr/pgmspace.h>
#include "../lib/usb-keyboard.h"
#include "../lib/keyboard.h"
#include "../lib/key-functions/public.h"
#include "./matrix.h"
#include "./default--matrix-control.h"

View File

@ -1,183 +0,0 @@
/* ----------------------------------------------------------------------------
* key functions : basic : code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include "./public.h"
/*
* Generate a normal keypress or keyrelease
*/
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 functions
* ------------------------------------------------------------------------- */
// 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);
}
}
}
// actual 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);
}
}
}
}

View File

@ -1,45 +0,0 @@
/* ----------------------------------------------------------------------------
* key functions : device specific : code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include "./public.h"
// ----------------------------------------------------------------------------
// descriptions
// ----------------------------------------------------------------------------
/*
* [name]
* Jump to Bootloader
*
* [description]
* For reflashing the controller
*/
// from PJRC (slightly modified)
// <http://www.pjrc.com/teensy/jump_to_bootloader.html>
void kbfun_jump_to_bootloader(void) {
// --- for all Teensy boards ---
cli();
// disable watchdog, if enabled
// disable all peripherals
UDCON = 1;
USBCON = (1<<FRZCLK); // disable USB
UCSR1B = 0;
_delay_ms(5);
// --- Teensy 2.0 specific ---
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
asm volatile("jmp 0x7E00");
}

View File

@ -125,3 +125,283 @@ void _kbfun_mediakey_press_release(bool press, uint8_t keycode) {
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)
// <http://www.pjrc.com/teensy/jump_to_bootloader.html>
void kbfun_jump_to_bootloader(void) {
// --- for all Teensy boards ---
cli();
// disable watchdog, if enabled
// disable all peripherals
UDCON = 1;
USBCON = (1<<FRZCLK); // disable USB
UCSR1B = 0;
_delay_ms(5);
// --- Teensy 2.0 specific ---
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
asm volatile("jmp 0x7E00");
}
// ----------------------------------------------------------------------------
// special
// ----------------------------------------------------------------------------
/*
* Generate a 'shift' press or release before the normal keypress or release
*/
void kbfun_shift_press_release(void) {
_kbfun_press_release(main_arg_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) {
_kbfun_press_release(main_arg_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) {
static uint8_t keys_pressed;
static bool lshift_pressed;
static bool rshift_pressed;
uint8_t keycode = _kbfun_get_keycode();
if (!main_arg_is_pressed) { keys_pressed--; }
// take care of the key that was actually pressed
_kbfun_press_release(main_arg_is_pressed, keycode);
// take care of capslock (only on the press of the 2nd key)
if (keys_pressed == 1 && main_arg_is_pressed) {
// save the state of left and right shift
lshift_pressed = _kbfun_is_pressed(KEY_LeftShift);
rshift_pressed = _kbfun_is_pressed(KEY_RightShift);
// disable both
_kbfun_press_release(false, KEY_LeftShift);
_kbfun_press_release(false, KEY_RightShift);
// 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
if (lshift_pressed) { _kbfun_press_release(true, KEY_LeftShift); }
if (rshift_pressed) { _kbfun_press_release(true, KEY_RightShift); }
}
if (main_arg_is_pressed) { keys_pressed++; }
}
/*
* Generate a keypress for a media key
*/
void kbfun_mediakey_press_release(void) {
uint8_t keycode = _kbfun_get_keycode();
_kbfun_mediakey_press_release(main_arg_is_pressed, keycode);
}

View File

@ -16,7 +16,7 @@
#include "../../keyboard/layout.h"
#include "../../keyboard/matrix.h"
#include "../../lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "../../lib/usb-keyboard.h"
#include "../../lib/keyboard.h"
// --------------------------------------------------------------------

View File

@ -1,82 +0,0 @@
/* ----------------------------------------------------------------------------
* key functions : special : code
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include "./public.h"
// ----------------------------------------------------------------------------
/*
* Generate a 'shift' press or release before the normal keypress or release
*/
void kbfun_shift_press_release(void) {
_kbfun_press_release(main_arg_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) {
_kbfun_press_release(main_arg_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) {
static uint8_t keys_pressed;
static bool lshift_pressed;
static bool rshift_pressed;
uint8_t keycode = _kbfun_get_keycode();
if (!main_arg_is_pressed) { keys_pressed--; }
// take care of the key that was actually pressed
_kbfun_press_release(main_arg_is_pressed, keycode);
// take care of capslock (only on the press of the 2nd key)
if (keys_pressed == 1 && main_arg_is_pressed) {
// save the state of left and right shift
lshift_pressed = _kbfun_is_pressed(KEY_LeftShift);
rshift_pressed = _kbfun_is_pressed(KEY_RightShift);
// disable both
_kbfun_press_release(false, KEY_LeftShift);
_kbfun_press_release(false, KEY_RightShift);
// 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
if (lshift_pressed) { _kbfun_press_release(true, KEY_LeftShift); }
if (rshift_pressed) { _kbfun_press_release(true, KEY_RightShift); }
}
if (main_arg_is_pressed) { keys_pressed++; }
}
/*
* Generate a keypress for a media key
*/
void kbfun_mediakey_press_release(void) {
uint8_t keycode = _kbfun_get_keycode();
_kbfun_mediakey_press_release(main_arg_is_pressed, keycode);
}
/* ----------------------------------------------------------------------------
* ------------------------------------------------------------------------- */