summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2017-05-25 22:46:01 +0100
committerTomasz Kramkowski <tk@the-tk.com>2017-05-25 22:46:01 +0100
commitde1f8661e0900c6794279e758a141e31d8b506ae (patch)
tree8c46ba4248950e0fac7a2c51c827c2da9b31061a
parent11779f9588d2f3f954558d80ab30e187451129b0 (diff)
downloadfmk-de1f8661e0900c6794279e758a141e31d8b506ae.tar.gz
fmk-de1f8661e0900c6794279e758a141e31d8b506ae.tar.xz
fmk-de1f8661e0900c6794279e758a141e31d8b506ae.zip
Implement support for keyboard layers
-rw-r--r--pit.c61
-rw-r--r--usb/keycodes.h2
2 files changed, 50 insertions, 13 deletions
diff --git a/pit.c b/pit.c
index 1241766..58359b7 100644
--- a/pit.c
+++ b/pit.c
@@ -71,17 +71,33 @@ static const struct gpio rows[] = {
};
/* COL AND ROW SWAPPED!!! */
-static enum keycode keymap[ARRLEN(rows)][ARRLEN(cols)] = {
- { /* S01 */ KEY_ESCAPE, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, },
- { /* S10 */ KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_NONE, KEY_BACKSPACE, KEY_GRAVE, KEY_TAB, KEY_Q, },
- { /* S19 */ KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, },
- { /* S28 */ KEY_LSQUARE, KEY_RSQUARE, KEY_NONE, KEY_DELETE, KEY_CAPSLK, KEY_A, KEY_S, KEY_D, KEY_F, },
- { /* S37 */ KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_QUOTE, KEY_BACKSLASH, KEY_ENTER, },
- { /* S46 */ KEY_PGUP, KEY_LSHIFT, KEY_NU_BACKSLASH, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, },
- { /* S55 */ KEY_M, KEY_COMMA, KEY_PERIOD, KEY_SLASH, KEY_RSHIFT, KEY_UP, KEY_PGDN, KEY_LCTRL, KEY_LGUI, },
- { /* S64 */ KEY_LALT, KEY_SPACE, KEY_RALT, KEY_NONE, KEY_RCTRL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_NONE, },
+static enum keycode keymap[2][ARRLEN(rows)][ARRLEN(cols)] = {
+ {
+ { /* S01 */ KEY_ESCAPE, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, },
+ { /* S10 */ KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_NONE, KEY_BACKSPACE, KEY_GRAVE, KEY_TAB, KEY_Q, },
+ { /* S19 */ KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, },
+ { /* S28 */ KEY_LSQUARE,KEY_RSQUARE, KEY_NONE, KEY_DELETE, KEY_CAPSLK, KEY_A, KEY_S, KEY_D, KEY_F, },
+ { /* S37 */ KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_QUOTE, KEY_BACKSLASH, KEY_ENTER, },
+ { /* S46 */ KEY_PGUP, KEY_LSHIFT, KEY_NU_BACKSLASH,KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, },
+ { /* S55 */ KEY_M, KEY_COMMA, KEY_PERIOD, KEY_SLASH, KEY_RSHIFT, KEY_UP, KEY_PGDN, KEY_LCTRL, KEY_LGUI, },
+ { /* S64 */ KEY_LALT, KEY_SPACE, KEY_RALT, KEY_LAYER1, KEY_RCTRL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_NONE, },
+ }, {
+ { /* S01 */ KEY_ESCAPE, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, },
+ { /* S10 */ KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_NONE, KEY_BACKSPACE, KEY_GRAVE, KEY_TAB, KEY_Q, },
+ { /* S19 */ KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, },
+ { /* S28 */ KEY_LSQUARE, KEY_RSQUARE, KEY_NONE, KEY_INSERT, KEY_CAPSLK, KEY_A, KEY_S, KEY_D, KEY_F, },
+ { /* S37 */ KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_QUOTE, KEY_BACKSLASH, KEY_ENTER, },
+ { /* S46 */ KEY_HOME, KEY_LSHIFT, KEY_NU_BACKSLASH,KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, },
+ { /* S55 */ KEY_M, KEY_COMMA, KEY_PERIOD, KEY_SLASH, KEY_RSHIFT, KEY_UP, KEY_END, KEY_LCTRL, KEY_LGUI, },
+ { /* S64 */ KEY_LALT, KEY_SPACE, KEY_APPLICATION,KEY_NONE, KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_NONE, },
+ }
};
+static enum keycode keydown[ARRLEN(cols)][ARRLEN(rows)];
+
+static unsigned char prevlayer;
+static unsigned char layer;
+
void pit_setup(void)
{
/* Set up ports (could be done with GPC registers */
@@ -121,13 +137,32 @@ static uint8_t kstates[ARRLEN(cols)][ARRLEN(rows)] = { 0 };
static void key_state(int col, int row, bool state)
{
uint8_t kstate;
+ enum keycode keycode;
kstate = kstates[col][row] = kstates[col][row] << 1 | state;
- if (kstate == 0x7f)
- usb_endpt1_setkey(keymap[row][col], true);
- else if (kstate == 0x80)
- usb_endpt1_setkey(keymap[row][col], false);
+ if (kstate == 0x7f) {
+ keycode = keymap[layer][row][col];
+ keydown[col][row] = keycode;
+ if (keycode < KEY_LAYER0) {
+ usb_endpt1_setkey(keycode, true);
+ return;
+ }
+ prevlayer = layer;
+ layer = keycode - KEY_LAYER0;
+ } else if (kstate == 0x80) {
+ keycode = keydown[col][row];
+ if (keycode < KEY_LAYER0) {
+ usb_endpt1_setkey(keycode, false);
+ return;
+ }
+ /*
+ * TODO: This will actually break with more than 2 layers
+ * needs a layer stack and also some special handling for letting go of
+ * previous layer keys mid-press.
+ */
+ layer = prevlayer;
+ }
}
void pit0_isr(void)
diff --git a/usb/keycodes.h b/usb/keycodes.h
index b1eec72..e43ae26 100644
--- a/usb/keycodes.h
+++ b/usb/keycodes.h
@@ -218,6 +218,8 @@ enum keycode {
KEY_RSHIFT,
KEY_RALT,
KEY_RGUI,
+ KEY_LAYER0 = 0xf00,
+ KEY_LAYER1,
};
_Static_assert(KEY_EXSEL == 0xa4, "Keycodes enum is broken");
_Static_assert(KEY_KP_HEX == 0xdd, "Keycodes enum is broken");