624 lines
22 KiB
C
624 lines
22 KiB
C
/* ----------------------------------------------------------------------------
|
|
* main()
|
|
* ----------------------------------------------------------------------------
|
|
* 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 <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
// --------------------------------------------------------------------
|
|
// types and forward declarations
|
|
// --------------------------------------------------------------------
|
|
|
|
typedef int8_t i8;
|
|
typedef uint8_t u8;
|
|
typedef int16_t i16;
|
|
typedef uint16_t u16;
|
|
typedef uint32_t u32;
|
|
|
|
typedef u8 keycode;
|
|
typedef u16 media_keycode;
|
|
typedef u8 layer;
|
|
typedef u32 millis; // wraps every 50 days, but that's fine for our logic
|
|
|
|
typedef void (*keyfunc)(keycode, bool);
|
|
|
|
#include "./main.h"
|
|
|
|
// --------------------------------------------------------------------
|
|
// hardware
|
|
// --------------------------------------------------------------------
|
|
|
|
// comment out this define to disable the debug interface completely
|
|
// however, just not using the functions gets rid of most of the firmware bloat already
|
|
#define KBD_DEBUG
|
|
#include "./keyboard/controller.c"
|
|
#include "./keyboard/keyboard.h"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// layout data
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include "./keyboard/layout.c"
|
|
// defines:
|
|
// #define KB_LAYERS #{Layers.size}
|
|
// static const keycode PROGMEM _kb_layout_code[KB_ROWS][KB_COLUMNS][KB_LAYERS];
|
|
// static const keyfunc PROGMEM _kb_layout_func[KB_ROWS][KB_COLUMNS][KB_LAYERS];
|
|
|
|
/* static u8 layers[KB_LAYERS] = {0, 1, 1+2, 3, 4, 2+3+4}; */
|
|
|
|
#if KB_LAYERS > 8
|
|
#error "can only handle 8 layers for now"
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// globals
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// state of key presses
|
|
static bool _kb_is_pressed[KB_ROWS][KB_COLUMNS];
|
|
static bool (*kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_is_pressed;
|
|
|
|
static bool _kb_was_pressed[KB_ROWS][KB_COLUMNS];
|
|
static bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_was_pressed;
|
|
|
|
static layer layers_pressed[KB_ROWS][KB_COLUMNS];
|
|
|
|
// layer state
|
|
static i8 layers_active[KB_LAYERS];
|
|
static layer layers_top;
|
|
|
|
// sticky states
|
|
static bool layer_sticky_on;
|
|
static bool layer_sticky[KB_LAYERS];
|
|
static bool layer_sticky_done;
|
|
static u8 mod_sticky;
|
|
static bool mod_sticky_done;
|
|
|
|
// key repeat config
|
|
static const millis repeat_delay = 300; // ms before key repeat kicks in
|
|
static const millis repeat_rate = 13; // send 1 / RATE key press
|
|
|
|
// key repeat state
|
|
static millis time_pressed[KB_ROWS][KB_COLUMNS];
|
|
static bool repeating[KB_ROWS][KB_COLUMNS];
|
|
|
|
// TODO this only exists as a workaround until we handle our own key repeats
|
|
static const keyfunc _kb_layer_funcs[] = {
|
|
&kbfun_layer_press_release,
|
|
&kbfun_layer_sticky,
|
|
&kbfun_shift_layer_press_release,
|
|
&kbfun_control_layer_press_release,
|
|
&kbfun_alt_layer_press_release,
|
|
&kbfun_win_layer_press_release,
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// utilities
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#define array_length(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
#define set_bit(x, i) (x) |= (1u << (i))
|
|
#define unset_bit(x, i) (x) &= ~(1u << (i))
|
|
#define toggle_bit(x, i) (x) ^= (1u << (i))
|
|
#define is_set(x, i) (((x) >> (i)) & 1u)
|
|
#define is_unset(x, i) !is_set((x), (i))
|
|
|
|
#define set_layer(x, layer) set_bit((x), (layer) - 1)
|
|
#define unset_layer(x, layer) unset_bit((x), (layer) - 1)
|
|
#define toggle_layer(x, layer) toggle_bit((x), (layer) - 1)
|
|
|
|
millis now() { return timer0_ms; }
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// main
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int main() {
|
|
// initialize
|
|
init_hw();
|
|
init_layers();
|
|
init_sticky();
|
|
init_timer();
|
|
|
|
// never return
|
|
main_key_loop();
|
|
return 0;
|
|
}
|
|
|
|
void main_key_loop() {
|
|
for (;;) {
|
|
// swap `kb_is_pressed` and `kb_was_pressed`, then update
|
|
bool (*temp)[KB_ROWS][KB_COLUMNS] = kb_was_pressed;
|
|
kb_was_pressed = kb_is_pressed;
|
|
kb_is_pressed = temp;
|
|
|
|
kb_update_matrix(*kb_is_pressed);
|
|
|
|
// - 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)
|
|
for (u8 row=0; row<KB_ROWS; row++) {
|
|
for (u8 col=0; col<KB_COLUMNS; col++) {
|
|
bool is_pressed = (*kb_is_pressed)[row][col];
|
|
bool was_pressed = (*kb_was_pressed)[row][col];
|
|
|
|
if (is_pressed) {
|
|
if (!was_pressed) { main_key_down_new(row, col); }
|
|
else { main_key_down_repeat(row, col); }
|
|
} else {
|
|
if (!was_pressed) { continue; } // no change
|
|
else { main_key_up(row, col); }
|
|
}
|
|
}
|
|
}
|
|
|
|
// send the USB report (even if nothing's changed)
|
|
usb_keyboard_send();
|
|
usb_extra_consumer_send();
|
|
|
|
// unset sticky keys if necessary
|
|
if (layer_sticky_on && layer_sticky_done) {
|
|
for (layer l=1; l < KB_LAYERS; l++) {
|
|
if (layer_sticky[l]) {
|
|
layer_disable(l);
|
|
layer_sticky[l] = false;
|
|
}
|
|
}
|
|
layer_sticky_on = false;
|
|
layer_sticky_done = false;
|
|
}
|
|
|
|
if (mod_sticky && mod_sticky_done) {
|
|
keyboard_modifier_keys &= ~mod_sticky;
|
|
usb_keyboard_send();
|
|
mod_sticky = 0;
|
|
mod_sticky_done = false;
|
|
}
|
|
|
|
// debounce in ms; see keyswitch spec for necessary value
|
|
_delay_ms(5);
|
|
}
|
|
}
|
|
|
|
void main_key_up(u8 row, u8 col) {
|
|
layer layer = layers_pressed[row][col];
|
|
layers_pressed[row][col] = 0;
|
|
|
|
// stop key repeat
|
|
if (repeating[row][col]) {
|
|
repeating[row][col] = false;
|
|
/* debug_printf("stop: %lu\n", now() - time_pressed[row][col]); */
|
|
}
|
|
|
|
exec_key(layer, row, col, false);
|
|
}
|
|
|
|
void main_key_down_new(u8 row, u8 col) {
|
|
layer layer = layers_top;
|
|
layers_pressed[row][col] = layer;
|
|
|
|
time_pressed[row][col] = now();
|
|
/* debug_printf("down: %lu\n", time_pressed[row][col]); */
|
|
|
|
exec_key(layer, row, col, true);
|
|
}
|
|
|
|
void main_key_down_repeat(u8 row, u8 col) {
|
|
millis t = now(); // consistency!
|
|
millis diff = t - time_pressed[row][col];
|
|
|
|
if (!repeating[row][col] && diff >= repeat_delay) { // start repeat
|
|
repeating[row][col] = true;
|
|
time_pressed[row][col] = t;
|
|
|
|
/* debug_printf("start: %lu\n", diff); */
|
|
} else if (repeating[row][col] && diff >= repeat_rate) { // continue repeat
|
|
time_pressed[row][col] = t;
|
|
|
|
/* debug_printf("cont: %lu\n", diff); */
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// init functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void init_hw() {
|
|
kb_init();
|
|
usb_init();
|
|
while (!usb_configured());
|
|
}
|
|
|
|
void init_sticky() {
|
|
for (layer l=1; l < KB_LAYERS; l++) {
|
|
layer_sticky[l] = false;
|
|
}
|
|
layer_sticky_on = false;
|
|
mod_sticky = 0;
|
|
layer_sticky_done = false;
|
|
mod_sticky_done = false;
|
|
}
|
|
|
|
void init_layers() {
|
|
for (layer l=0; l < KB_LAYERS; l++) {
|
|
layers_active[l] = 0;
|
|
}
|
|
layers_active[0] = 1;
|
|
layers_top = 0;
|
|
|
|
for (u8 row=0; row<KB_ROWS; row++) {
|
|
for (u8 col=0; col<KB_COLUMNS; col++) {
|
|
layers_pressed[row][col] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void init_timer() {
|
|
for (u8 row=0; row<KB_ROWS; row++) {
|
|
for (u8 col=0; col<KB_COLUMNS; col++) {
|
|
time_pressed[row][col] = 0;
|
|
repeating[row][col] = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// layer functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// find highest active layer
|
|
layer highest_active_layer() {
|
|
for (layer l = KB_LAYERS - 1; l > 0; l--) {
|
|
if (layers_active[l] > 0) { return l; }
|
|
}
|
|
|
|
// the base layer is always active
|
|
return 0;
|
|
}
|
|
|
|
// enable a layer
|
|
void layer_enable(layer l) {
|
|
if (l >= KB_LAYERS || l == 0) { return; }
|
|
|
|
layers_active[l] += 1;
|
|
|
|
if (l > layers_top) {
|
|
layers_top = l;
|
|
}
|
|
}
|
|
|
|
// disable a layer
|
|
void layer_disable(layer l) {
|
|
// base layer stays always on
|
|
if (l >= KB_LAYERS || l == 0) { return; }
|
|
|
|
if (layers_active[l] > 0) {
|
|
layers_active[l] -= 1;
|
|
}
|
|
|
|
if (l == layers_top) {
|
|
layers_top = highest_active_layer();
|
|
}
|
|
|
|
// re-press affected keys
|
|
for (u8 row=0; row<KB_ROWS; row++) {
|
|
for (u8 col=0; col<KB_COLUMNS; col++) {
|
|
if (layers_pressed[row][col] == l) {
|
|
keyfunc func = (kb_keyfunc(l, row, col));
|
|
// FIXME don't re-send normal keys until we have key repeats
|
|
if (is_layer_keyfunc(func)) {
|
|
// FIXME this kinda shouldn't be here and it privileges layer 0 even more
|
|
layers_pressed[row][col] = 0;
|
|
exec_key(l, row, col, false);
|
|
|
|
layers_pressed[row][col] = layers_top;
|
|
exec_key(layers_top, row, col, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool is_layer_keyfunc(keyfunc f) {
|
|
for (int i=0; i<array_length(_kb_layer_funcs); i++) {
|
|
if (f == _kb_layer_funcs[i]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// layout info
|
|
// ----------------------------------------------------------------------------
|
|
|
|
keycode kb_keycode (layer l, u8 row, u8 col) { return (keycode) pgm_read_byte(&(_kb_layout_code[row][col][l])); }
|
|
keyfunc kb_keyfunc (layer l, u8 row, u8 col) { return (keyfunc) pgm_read_word(&(_kb_layout_func[row][col][l])); }
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// keyfunc primitives
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// basic keypresses
|
|
void _kbfun_normal_press_release(keycode key, bool is_pressed) {
|
|
if (key == 0) { return; } // noop
|
|
|
|
if (is_pressed) { _kbfun_normal_swap(0, key); }
|
|
else { _kbfun_normal_swap(key, 0); }
|
|
}
|
|
|
|
void _kbfun_mediakey_press_release(keycode key, bool is_pressed) {
|
|
media_keycode media_key = _media_code_lookup(key);
|
|
if (is_pressed) {
|
|
consumer_key = media_key;
|
|
} else {
|
|
// only one media key can be pressed at a time, so only clear most recent one
|
|
if (media_key == consumer_key) {
|
|
consumer_key = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void _kbfun_modifier_press_release(keycode key, bool is_pressed) {
|
|
if (is_pressed) {
|
|
set_bit(keyboard_modifier_keys, key);
|
|
} else {
|
|
unset_bit(keyboard_modifier_keys, key);
|
|
}
|
|
}
|
|
|
|
void _kbfun_normal_swap(keycode from, keycode to) {
|
|
for (u8 i=0; i < sizeof(keyboard_keys); i++) {
|
|
if (keyboard_keys[i] == from) {
|
|
keyboard_keys[i] = to;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool _kbfun_normal_is_pressed(keycode key) {
|
|
for (u8 i=0; i < sizeof(keyboard_keys); i++) {
|
|
if (keyboard_keys[i] == key) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool _kbfun_mediakey_is_pressed(keycode key) {
|
|
return (consumer_key != 0);
|
|
}
|
|
|
|
bool _kbfun_modifier_is_pressed(keycode key) {
|
|
return is_set(keyboard_modifier_keys, key);
|
|
}
|
|
|
|
void _kbfun_normal_sticky_done() {
|
|
layer_sticky_done = true;
|
|
mod_sticky_done = true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// basic keyfuncs
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// execute the keypress or keyrelease function (if it exists) of the key at the current possition
|
|
void exec_key(layer layer, u8 row, u8 col, bool is_pressed) {
|
|
keycode key = kb_keycode(layer, row, col);
|
|
void (*key_function)(keycode, bool) = kb_keyfunc(layer, row, col);
|
|
|
|
if (key_function) { (*key_function)(key, is_pressed); }
|
|
}
|
|
|
|
// normal key
|
|
void kbfun_normal_press_release(keycode key, bool is_pressed) {
|
|
_kbfun_normal_sticky_done();
|
|
_kbfun_normal_press_release(key, is_pressed);
|
|
}
|
|
|
|
// media key
|
|
void kbfun_mediakey_press_release(keycode key, bool is_pressed) {
|
|
_kbfun_normal_sticky_done();
|
|
_kbfun_mediakey_press_release(key, is_pressed);
|
|
}
|
|
|
|
// modifier
|
|
void kbfun_modifier_press_release(keycode key, bool is_pressed) {
|
|
layer_sticky_done = true;
|
|
_kbfun_modifier_press_release(key, is_pressed);
|
|
}
|
|
|
|
// layer key
|
|
void kbfun_layer_press_release(keycode key, bool is_pressed) {
|
|
layer_sticky_done = true; // don't disable sticky mods!
|
|
|
|
layer l = (layer) key;
|
|
if (is_pressed) {
|
|
layer_enable(l);
|
|
} else {
|
|
layer_disable(l);
|
|
}
|
|
}
|
|
|
|
// sticky layer key
|
|
void kbfun_layer_sticky(keycode key, bool is_pressed) {
|
|
layer l = (layer) key;
|
|
|
|
if (is_pressed) {
|
|
if (! layer_sticky[l]) {
|
|
layer_enable(l);
|
|
layer_sticky_done = false;
|
|
}
|
|
} else {
|
|
if (layer_sticky_done) {
|
|
layer_disable(l);
|
|
} else {
|
|
layer_sticky[l] = true;
|
|
layer_sticky_on = true;
|
|
layer_sticky_done = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// sticky modifier key
|
|
void kbfun_modifier_sticky(keycode key, bool is_pressed) {
|
|
// TODO handle: sticky, then same modifier
|
|
keycode mod = key;
|
|
|
|
if (is_pressed) {
|
|
kbfun_modifier_press_release(key, true);
|
|
mod_sticky_done = false;
|
|
} else {
|
|
if (mod_sticky_done) {
|
|
kbfun_modifier_press_release(key, false);
|
|
} else {
|
|
set_bit(mod_sticky, mod);
|
|
mod_sticky_done = false;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// combo keyfuncs
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
void _kbfun_combo_normal_press_release(keycode combo_key, keycode key, bool is_pressed) {
|
|
_kbfun_modifier_press_release(combo_key, is_pressed);
|
|
kbfun_normal_press_release(key, is_pressed);
|
|
}
|
|
|
|
void _kbfun_combo_normal_press_release_once(keycode combo_key, keycode key, bool is_pressed) {
|
|
// FIXME this should be cleaner when we have actual key repeats
|
|
|
|
if (is_pressed) {
|
|
// avoid messing with independently pressed modifiers
|
|
bool mod_already_pressed = _kbfun_modifier_is_pressed(combo_key);
|
|
|
|
if (!mod_already_pressed) {
|
|
_kbfun_modifier_press_release(combo_key, true);
|
|
}
|
|
|
|
kbfun_normal_press_release(key, true);
|
|
|
|
if (!mod_already_pressed) {
|
|
// we force a keyboard send to prevent the modifier from bleeding into the next key press
|
|
usb_keyboard_send();
|
|
_kbfun_modifier_press_release(combo_key, false);
|
|
}
|
|
} else {
|
|
kbfun_normal_press_release(key, false);
|
|
}
|
|
}
|
|
|
|
void _kbfun_combo_layer_press_release(keycode combo_key, keycode key, bool is_pressed) {
|
|
kbfun_layer_press_release(key, is_pressed);
|
|
_kbfun_modifier_press_release(combo_key, is_pressed);
|
|
}
|
|
|
|
void kbfun_shift_press_release(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release(MOD_KEY_LeftShift, key, is_pressed); } // +shift
|
|
void kbfun_control_press_release(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release(MOD_KEY_LeftControl, key, is_pressed); } // +control
|
|
void kbfun_alt_press_release(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release(MOD_KEY_LeftAlt, key, is_pressed); } // +alt
|
|
void kbfun_win_press_release(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release(MOD_KEY_LeftGUI, key, is_pressed); } // +win
|
|
//
|
|
void kbfun_shift_press_release_once(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release_once(MOD_KEY_LeftShift, key, is_pressed); } // +shift once
|
|
void kbfun_control_press_release_once(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release_once(MOD_KEY_LeftControl, key, is_pressed); } // +control once
|
|
void kbfun_alt_press_release_once(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release_once(MOD_KEY_LeftAlt, key, is_pressed); } // +alt once
|
|
void kbfun_win_press_release_once(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release_once(MOD_KEY_LeftGUI, key, is_pressed); } // +win once
|
|
//
|
|
void kbfun_shift_layer_press_release(keycode key, bool is_pressed) { _kbfun_combo_layer_press_release(MOD_KEY_LeftShift, key, is_pressed); } // +shift + layer
|
|
void kbfun_control_layer_press_release(keycode key, bool is_pressed) { _kbfun_combo_layer_press_release(MOD_KEY_LeftControl, key, is_pressed); } // +control + layer
|
|
void kbfun_alt_layer_press_release(keycode key, bool is_pressed) { _kbfun_combo_layer_press_release(MOD_KEY_LeftAlt, key, is_pressed); } // +alt + layer
|
|
void kbfun_win_layer_press_release(keycode key, bool is_pressed) { _kbfun_combo_layer_press_release(MOD_KEY_LeftGUI, key, is_pressed); } // +win + layer
|
|
|
|
// multi-combos
|
|
|
|
// TODO lol
|
|
|
|
void _kbfun_combo_normal_press_release2(keycode combo_key1, keycode combo_key2, keycode key, bool is_pressed) {
|
|
_kbfun_modifier_press_release(combo_key1, is_pressed);
|
|
_kbfun_modifier_press_release(combo_key2, is_pressed);
|
|
kbfun_normal_press_release(key, is_pressed);
|
|
}
|
|
|
|
void _kbfun_combo_normal_press_release3(keycode combo_key1, keycode combo_key2, keycode combo_key3, keycode key, bool is_pressed) {
|
|
_kbfun_modifier_press_release(combo_key1, is_pressed);
|
|
_kbfun_modifier_press_release(combo_key2, is_pressed);
|
|
_kbfun_modifier_press_release(combo_key3, is_pressed);
|
|
kbfun_normal_press_release(key, is_pressed);
|
|
}
|
|
|
|
void _kbfun_combo_normal_press_release4(keycode combo_key1, keycode combo_key2, keycode combo_key3, keycode combo_key4, keycode key, bool is_pressed) {
|
|
_kbfun_modifier_press_release(combo_key1, is_pressed);
|
|
_kbfun_modifier_press_release(combo_key2, is_pressed);
|
|
_kbfun_modifier_press_release(combo_key3, is_pressed);
|
|
_kbfun_modifier_press_release(combo_key4, is_pressed);
|
|
kbfun_normal_press_release(key, is_pressed);
|
|
}
|
|
|
|
#define COMBO2(x1, x2) _kbfun_combo_normal_press_release2(x1, x2, key, is_pressed)
|
|
#define COMBO3(x1, x2, x3) _kbfun_combo_normal_press_release3(x1, x2, x3, key, is_pressed)
|
|
#define COMBO4(x1, x2, x3, x4) _kbfun_combo_normal_press_release4(x1, x2, x3, x4, key, is_pressed)
|
|
|
|
void kbfun_shift_control_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftShift, MOD_KEY_LeftControl); }
|
|
void kbfun_shift_alt_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftShift, MOD_KEY_LeftAlt); }
|
|
void kbfun_shift_win_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftShift, MOD_KEY_LeftGUI); }
|
|
void kbfun_control_alt_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftControl, MOD_KEY_LeftAlt); }
|
|
void kbfun_control_win_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftControl, MOD_KEY_LeftGUI); }
|
|
void kbfun_alt_win_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftAlt, MOD_KEY_LeftGUI); }
|
|
|
|
void kbfun_shift_control_alt_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftControl, MOD_KEY_LeftAlt); }
|
|
void kbfun_shift_control_win_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftControl, MOD_KEY_LeftGUI); }
|
|
void kbfun_shift_alt_control_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftAlt, MOD_KEY_LeftControl); }
|
|
void kbfun_shift_alt_win_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftAlt, MOD_KEY_LeftGUI); }
|
|
void kbfun_shift_win_control_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftGUI, MOD_KEY_LeftControl); }
|
|
void kbfun_shift_win_alt_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftGUI, MOD_KEY_LeftAlt); }
|
|
void kbfun_control_alt_shift_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftControl, MOD_KEY_LeftAlt, MOD_KEY_LeftShift); }
|
|
void kbfun_control_alt_win_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftControl, MOD_KEY_LeftAlt, MOD_KEY_LeftGUI); }
|
|
void kbfun_control_win_shift_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftControl, MOD_KEY_LeftGUI, MOD_KEY_LeftShift); }
|
|
void kbfun_control_win_alt_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftControl, MOD_KEY_LeftGUI, MOD_KEY_LeftAlt); }
|
|
void kbfun_alt_win_shift_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftAlt, MOD_KEY_LeftGUI, MOD_KEY_LeftShift); }
|
|
void kbfun_alt_win_control_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftAlt, MOD_KEY_LeftGUI, MOD_KEY_LeftControl); }
|
|
|
|
void kbfun_shift_control_alt_win_press_release(keycode key, bool is_pressed) { COMBO4(MOD_KEY_LeftShift, MOD_KEY_LeftControl, MOD_KEY_LeftAlt, MOD_KEY_LeftGUI); }
|
|
|
|
// capslock
|
|
void kbfun_capslock_press_release(keycode key, bool is_pressed) {
|
|
static u8 keys_pressed;
|
|
static bool lshift_pressed;
|
|
static bool rshift_pressed;
|
|
|
|
if (!is_pressed) { keys_pressed--; }
|
|
|
|
// take care of the key that was actually pressed
|
|
_kbfun_modifier_press_release(key, is_pressed);
|
|
|
|
// take care of capslock (only on the press of the 2nd key)
|
|
if (keys_pressed == 1 && is_pressed) {
|
|
// save the state of left and right shift
|
|
lshift_pressed = _kbfun_modifier_is_pressed(MOD_KEY_LeftShift);
|
|
rshift_pressed = _kbfun_modifier_is_pressed(MOD_KEY_RightShift);
|
|
// disable both
|
|
_kbfun_modifier_press_release(MOD_KEY_LeftShift, false);
|
|
_kbfun_modifier_press_release(MOD_KEY_RightShift, false);
|
|
|
|
// press capslock, then release it
|
|
_kbfun_normal_press_release(KEY_CapsLock, true); usb_keyboard_send();
|
|
_kbfun_normal_press_release(KEY_CapsLock, false); usb_keyboard_send();
|
|
|
|
// restore the state of left and right shift
|
|
if (lshift_pressed) { _kbfun_modifier_press_release(MOD_KEY_LeftShift, true); }
|
|
if (rshift_pressed) { _kbfun_modifier_press_release(MOD_KEY_RightShift, true); }
|
|
}
|
|
|
|
if (is_pressed) { keys_pressed++; }
|
|
}
|