2012-04-10 10:44:27 +02:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
* key functions: code
|
2012-04-25 08:22:20 +02:00
|
|
|
*
|
|
|
|
* These functions may do.. pretty much anything rational that thay like. If
|
|
|
|
* they want keycodes to be sent to the host in an aggrate report, they're
|
|
|
|
* responsible for modifying the appropriate report variables.
|
2012-04-10 10:44:27 +02:00
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
* 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>
|
|
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
2012-04-29 08:40:00 +02:00
|
|
|
#include "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
|
|
|
#include "lib/data-types.h"
|
2012-05-14 03:06:17 +02:00
|
|
|
#include "lib/usb/usage-page/keyboard.h"
|
2012-04-10 10:44:27 +02:00
|
|
|
#include "keyboard.h"
|
|
|
|
|
2012-06-15 07:02:57 +02:00
|
|
|
#include "key-functions.h" // includes the appropriate keyboard 'matrix.h'
|
|
|
|
#include "key-functions--private.h"
|
2012-04-28 00:39:26 +02:00
|
|
|
|
2012-06-15 07:02:57 +02:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// private functions
|
2012-06-15 01:01:34 +02:00
|
|
|
// ----------------------------------------------------------------------------
|
2012-04-12 06:05:45 +02:00
|
|
|
|
2012-06-15 01:01:34 +02:00
|
|
|
/*
|
|
|
|
* Generate a normal keypress or keyrelease
|
|
|
|
*
|
|
|
|
* Arguments
|
|
|
|
* - keycode: the keycode to use
|
|
|
|
* - pressed: whether to generate a keypress (true) or keyrelease (false)
|
|
|
|
*
|
|
|
|
* Note
|
|
|
|
* - Because of the way USB does things, what this actually does is either add
|
2012-06-15 07:02:57 +02:00
|
|
|
* or remove 'keycode' from the list of currently pressed keys, to be sent at
|
|
|
|
* the end of the current cycle (see main.c)
|
2012-06-15 01:01:34 +02:00
|
|
|
*/
|
2012-06-15 07:02:57 +02:00
|
|
|
void _press_release(uint8_t keycode, bool pressed) {
|
2012-04-25 08:49:17 +02:00
|
|
|
// no-op
|
2012-06-15 01:01:34 +02:00
|
|
|
if (keycode == 0)
|
2012-04-25 08:49:17 +02:00
|
|
|
return;
|
|
|
|
|
2012-04-25 08:22:20 +02:00
|
|
|
// modifier keys
|
2012-06-15 01:01:34 +02:00
|
|
|
switch (keycode) {
|
|
|
|
case KEY_LeftControl: (pressed)
|
|
|
|
? (keyboard_modifier_keys |= (1<<0))
|
|
|
|
: (keyboard_modifier_keys &= ~(1<<0));
|
2012-04-25 08:22:20 +02:00
|
|
|
return;
|
2012-06-15 01:01:34 +02:00
|
|
|
case KEY_LeftShift: (pressed)
|
|
|
|
? (keyboard_modifier_keys |= (1<<1))
|
|
|
|
: (keyboard_modifier_keys &= ~(1<<1));
|
2012-04-25 08:22:20 +02:00
|
|
|
return;
|
2012-06-15 01:01:34 +02:00
|
|
|
case KEY_LeftAlt: (pressed)
|
|
|
|
? (keyboard_modifier_keys |= (1<<2))
|
|
|
|
: (keyboard_modifier_keys &= ~(1<<2));
|
2012-04-25 08:22:20 +02:00
|
|
|
return;
|
2012-06-15 01:01:34 +02:00
|
|
|
case KEY_LeftGUI: (pressed)
|
|
|
|
? (keyboard_modifier_keys |= (1<<3))
|
|
|
|
: (keyboard_modifier_keys &= ~(1<<3));
|
2012-04-25 08:22:20 +02:00
|
|
|
return;
|
2012-06-15 01:01:34 +02:00
|
|
|
case KEY_RightControl: (pressed)
|
|
|
|
? (keyboard_modifier_keys |= (1<<4))
|
|
|
|
: (keyboard_modifier_keys &= ~(1<<4));
|
2012-04-25 08:22:20 +02:00
|
|
|
return;
|
2012-06-15 01:01:34 +02:00
|
|
|
case KEY_RightShift: (pressed)
|
|
|
|
? (keyboard_modifier_keys |= (1<<5))
|
|
|
|
: (keyboard_modifier_keys &= ~(1<<5));
|
2012-04-25 08:22:20 +02:00
|
|
|
return;
|
2012-06-15 01:01:34 +02:00
|
|
|
case KEY_RightAlt: (pressed)
|
|
|
|
? (keyboard_modifier_keys |= (1<<6))
|
|
|
|
: (keyboard_modifier_keys &= ~(1<<6));
|
2012-04-25 08:22:20 +02:00
|
|
|
return;
|
2012-06-15 01:01:34 +02:00
|
|
|
case KEY_RightGUI: (pressed)
|
|
|
|
? (keyboard_modifier_keys |= (1<<7))
|
|
|
|
: (keyboard_modifier_keys &= ~(1<<7));
|
2012-04-25 08:22:20 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// all others
|
2012-06-15 01:01:34 +02:00
|
|
|
for (uint8_t i=0; i<6; i++) {
|
|
|
|
if (pressed) {
|
|
|
|
if (keyboard_keys[i] == 0) {
|
|
|
|
keyboard_keys[i] = keycode;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (keyboard_keys[i] == keycode) {
|
|
|
|
keyboard_keys[i] = 0;
|
|
|
|
return;
|
|
|
|
}
|
2012-04-11 03:58:26 +02:00
|
|
|
}
|
2012-06-15 01:01:34 +02:00
|
|
|
}
|
2012-04-10 10:44:27 +02:00
|
|
|
}
|
|
|
|
|
2012-06-15 07:02:57 +02:00
|
|
|
/*
|
|
|
|
* Set current layer
|
|
|
|
* - Sets any keys currently set to the overall current layer to the new layer,
|
|
|
|
* and then sets the overall current layer
|
|
|
|
*
|
|
|
|
* Arguments
|
|
|
|
* - value: the new layer value
|
|
|
|
* - current_layer: (a pointer to) the overall current layer (see main.c)
|
2012-06-15 23:36:50 +02:00
|
|
|
* - current_layers: (a pointer to a matrix of) the current layer for each key
|
2012-06-15 07:02:57 +02:00
|
|
|
* (see main.c and lib/key-functions.h)
|
|
|
|
*
|
|
|
|
* Note
|
|
|
|
* - Leaving all non-current layer values alone allows changing layers while
|
|
|
|
* maintaining a possibly enabled layer mask (as might be used to implement
|
|
|
|
* firmware enabled numlock)
|
|
|
|
*/
|
|
|
|
void _layer_set_current(
|
|
|
|
uint8_t value,
|
|
|
|
uint8_t * current_layer,
|
2012-06-15 23:36:50 +02:00
|
|
|
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
|
2012-06-15 07:02:57 +02:00
|
|
|
|
|
|
|
// don't switch to out-of-bounds layers
|
2012-06-15 23:36:50 +02:00
|
|
|
if ( value < 0 || value >= KB_LAYERS )
|
2012-06-15 07:02:57 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
for (uint8_t row=0; row<KB_ROWS; row++)
|
|
|
|
for (uint8_t col=0; col<KB_COLUMNS; col++)
|
2012-06-15 23:36:50 +02:00
|
|
|
// if a key is set to a non-current layer, let it be
|
|
|
|
if ((*current_layers)[row][col] == *current_layer)
|
|
|
|
(*current_layers)[row][col] = value;
|
2012-06-15 07:02:57 +02:00
|
|
|
|
|
|
|
(*current_layer) = value;
|
|
|
|
}
|
|
|
|
|
2012-06-15 23:36:50 +02:00
|
|
|
/*
|
|
|
|
* Is the given keycode pressed?
|
|
|
|
*/
|
|
|
|
bool _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;
|
|
|
|
}
|
|
|
|
|
2012-06-15 07:02:57 +02:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// public functions
|
2012-06-15 01:01:34 +02:00
|
|
|
// ----------------------------------------------------------------------------
|
2012-04-25 08:49:17 +02:00
|
|
|
|
2012-06-15 01:01:34 +02:00
|
|
|
/*
|
2012-06-15 23:36:50 +02:00
|
|
|
* Press
|
|
|
|
* - Generate a normal keypress
|
2012-06-15 01:01:34 +02:00
|
|
|
*/
|
|
|
|
void kbfun_press( KBFUN_FUNCTION_ARGS ) {
|
|
|
|
_press_release(keycode_, true);
|
|
|
|
}
|
2012-04-25 08:22:20 +02:00
|
|
|
|
2012-06-15 01:01:34 +02:00
|
|
|
/*
|
2012-06-15 23:36:50 +02:00
|
|
|
* Release
|
|
|
|
* - Generate a normal keyrelease
|
2012-06-15 01:01:34 +02:00
|
|
|
*/
|
|
|
|
void kbfun_release( KBFUN_FUNCTION_ARGS ) {
|
|
|
|
_press_release(keycode_, false);
|
2012-04-10 10:44:27 +02:00
|
|
|
}
|
|
|
|
|
2012-06-15 07:02:57 +02:00
|
|
|
/*
|
2012-06-15 23:36:50 +02:00
|
|
|
* Set layer
|
|
|
|
* - Set layer to the value specified in the keymap (using the value as a
|
|
|
|
* number instead of a keycode)
|
2012-06-15 07:02:57 +02:00
|
|
|
*/
|
|
|
|
void kbfun_layer_set( KBFUN_FUNCTION_ARGS ) {
|
|
|
|
_layer_set_current( keycode_, current_layer_, current_layers_ );
|
|
|
|
}
|
2012-06-11 05:48:24 +02:00
|
|
|
|
2012-06-15 01:01:34 +02:00
|
|
|
/*
|
2012-06-15 23:36:50 +02:00
|
|
|
* Increase layer
|
|
|
|
* - Increment layer by the value specified in the keymap (for all non-masked
|
|
|
|
* keys)
|
2012-06-15 01:01:34 +02:00
|
|
|
*/
|
bugfix (mostly): changed the way layers are handled
before, if you pressed a key, then shifted layers, then released it, the
first layer's press() would be called, and the 2nd layer's release()
would be called, causing keys to stick, and probably other errors. now,
the layer that the key was on when it was pressed is kept track of, and
the proper release() is called.
also, layers can be shifted per key now, instead of just for the whole
board at once
i also changed how keyboard-private includes are handled. "private"
stuff is now in its own file, instead of being nested in an extra
`#ifdef`.
and i think that's it. i'm pretty tired right now, so there may be
errors, but it seemed to work all right with cursory tests.
2012-06-11 12:27:34 +02:00
|
|
|
void kbfun_layer_inc( KBFUN_FUNCTION_ARGS ) {
|
2012-06-15 07:02:57 +02:00
|
|
|
_layer_set_current(
|
2012-06-15 23:36:50 +02:00
|
|
|
(*current_layer_) + keycode_,
|
2012-06-15 07:02:57 +02:00
|
|
|
current_layer_,
|
|
|
|
current_layers_ );
|
2012-06-04 08:46:21 +02:00
|
|
|
}
|
|
|
|
|
2012-06-15 01:01:34 +02:00
|
|
|
/*
|
2012-06-15 23:36:50 +02:00
|
|
|
* Decrease layer
|
|
|
|
* - Decrement layer by the value specified in the keymap (for all non-masked
|
|
|
|
* keys)
|
2012-06-15 01:01:34 +02:00
|
|
|
*/
|
bugfix (mostly): changed the way layers are handled
before, if you pressed a key, then shifted layers, then released it, the
first layer's press() would be called, and the 2nd layer's release()
would be called, causing keys to stick, and probably other errors. now,
the layer that the key was on when it was pressed is kept track of, and
the proper release() is called.
also, layers can be shifted per key now, instead of just for the whole
board at once
i also changed how keyboard-private includes are handled. "private"
stuff is now in its own file, instead of being nested in an extra
`#ifdef`.
and i think that's it. i'm pretty tired right now, so there may be
errors, but it seemed to work all right with cursory tests.
2012-06-11 12:27:34 +02:00
|
|
|
void kbfun_layer_dec( KBFUN_FUNCTION_ARGS ) {
|
2012-06-15 07:02:57 +02:00
|
|
|
_layer_set_current(
|
2012-06-15 23:36:50 +02:00
|
|
|
(*current_layer_) - keycode_,
|
2012-06-15 07:02:57 +02:00
|
|
|
current_layer_,
|
|
|
|
current_layers_ );
|
2012-06-04 08:46:21 +02:00
|
|
|
}
|
|
|
|
|
2012-06-15 01:01:34 +02:00
|
|
|
/*
|
2012-06-15 23:36:50 +02:00
|
|
|
* Two keys => capslock
|
|
|
|
* - 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 toggle capslock
|
|
|
|
*
|
|
|
|
* Note
|
|
|
|
* - 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
|
2012-06-15 01:01:34 +02:00
|
|
|
*/
|
2012-06-15 23:36:50 +02:00
|
|
|
#include "../lib/usb/usage-page/keyboard.h"
|
2012-06-15 01:01:34 +02:00
|
|
|
void kbfun_2_keys_capslock_press_release( KBFUN_FUNCTION_ARGS ) {
|
2012-06-15 23:36:50 +02:00
|
|
|
static uint8_t keys_pressed;
|
|
|
|
static bool lshift_pressed;
|
|
|
|
static bool rshift_pressed;
|
2012-06-15 01:01:34 +02:00
|
|
|
|
|
|
|
if (!pressed_) keys_pressed--;
|
|
|
|
|
2012-06-15 23:36:50 +02:00
|
|
|
// take care of the key that was actually pressed
|
2012-06-15 01:01:34 +02:00
|
|
|
_press_release(keycode_, pressed_);
|
2012-06-15 23:36:50 +02:00
|
|
|
|
|
|
|
// take care of capslock (only on the press of the 2nd key)
|
|
|
|
if (keys_pressed == 1 && pressed_) {
|
|
|
|
// save the state of left and right shift
|
|
|
|
lshift_pressed = _is_pressed(KEY_LeftShift);
|
|
|
|
rshift_pressed = _is_pressed(KEY_RightShift);
|
|
|
|
// disable both
|
|
|
|
_press_release(KEY_LeftShift, false);
|
|
|
|
_press_release(KEY_RightShift, false);
|
|
|
|
|
|
|
|
// press capslock, then release it
|
|
|
|
_press_release(KEY_CapsLock, true);
|
|
|
|
usb_keyboard_send();
|
|
|
|
_press_release(KEY_CapsLock, false);
|
|
|
|
usb_keyboard_send();
|
|
|
|
|
|
|
|
// restore the state of left and right shift
|
|
|
|
if (lshift_pressed)
|
|
|
|
_press_release(KEY_LeftShift, true);
|
|
|
|
if (rshift_pressed)
|
|
|
|
_press_release(KEY_RightShift, true);
|
|
|
|
}
|
2012-06-15 01:01:34 +02:00
|
|
|
|
|
|
|
if (pressed_) keys_pressed++;
|
|
|
|
}
|
|
|
|
|