diff options
author | Tomasz Kramkowski <tk@the-tk.com> | 2017-05-25 22:46:01 +0100 |
---|---|---|
committer | Tomasz Kramkowski <tk@the-tk.com> | 2017-05-25 22:46:01 +0100 |
commit | de1f8661e0900c6794279e758a141e31d8b506ae (patch) | |
tree | 8c46ba4248950e0fac7a2c51c827c2da9b31061a | |
parent | 11779f9588d2f3f954558d80ab30e187451129b0 (diff) | |
download | fmk-de1f8661e0900c6794279e758a141e31d8b506ae.tar.gz fmk-de1f8661e0900c6794279e758a141e31d8b506ae.tar.xz fmk-de1f8661e0900c6794279e758a141e31d8b506ae.zip |
Implement support for keyboard layers
-rw-r--r-- | pit.c | 61 | ||||
-rw-r--r-- | usb/keycodes.h | 2 |
2 files changed, 50 insertions, 13 deletions
@@ -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"); |