diff options
author | Joel Challis <git@zvecr.com> | 2020-09-27 13:04:27 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-27 13:04:27 +0100 |
commit | 50835bb13875843cac0236995afe86508744e595 (patch) | |
tree | 7945640f00ef64fa445feee156d076a7b514c62a | |
parent | e7acd39b78a7cb81b258044dd190dc5bda55d120 (diff) | |
download | qmk_firmware-50835bb13875843cac0236995afe86508744e595.tar.gz qmk_firmware-50835bb13875843cac0236995afe86508744e595.zip |
[keyboard] Add SP-111 support (#10193)
* Initial sp111 support
* Align with template
-rw-r--r-- | keyboards/sp111/config.h | 83 | ||||
-rw-r--r-- | keyboards/sp111/info.json | 19 | ||||
-rw-r--r-- | keyboards/sp111/keymaps/default/keymap.c | 57 | ||||
-rw-r--r-- | keyboards/sp111/keymaps/via/config.h | 18 | ||||
-rw-r--r-- | keyboards/sp111/keymaps/via/keymap.c | 42 | ||||
-rw-r--r-- | keyboards/sp111/keymaps/via/rules.mk | 1 | ||||
-rw-r--r-- | keyboards/sp111/matrix.c | 178 | ||||
-rw-r--r-- | keyboards/sp111/mcp23018.c | 120 | ||||
-rw-r--r-- | keyboards/sp111/mcp23018.h | 34 | ||||
-rw-r--r-- | keyboards/sp111/readme.md | 21 | ||||
-rw-r--r-- | keyboards/sp111/rules.mk | 30 | ||||
-rw-r--r-- | keyboards/sp111/sp111.c | 42 | ||||
-rw-r--r-- | keyboards/sp111/sp111.h | 41 |
13 files changed, 686 insertions, 0 deletions
diff --git a/keyboards/sp111/config.h b/keyboards/sp111/config.h new file mode 100644 index 000000000..ee765dc8f --- /dev/null +++ b/keyboards/sp111/config.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* Copyright 2020 blindassassin111 | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #pragma once | ||
17 | |||
18 | #include "config_common.h" | ||
19 | |||
20 | /* USB Device descriptor parameter */ | ||
21 | #define VENDOR_ID 0x544B //TK | ||
22 | #define PRODUCT_ID 0x5111 | ||
23 | #define DEVICE_VER 0x0001 | ||
24 | #define MANUFACTURER The Key Company | ||
25 | #define PRODUCT SP111 | ||
26 | |||
27 | /* key matrix size */ | ||
28 | #define MATRIX_ROWS 6*2 | ||
29 | #define MATRIX_COLS 11 | ||
30 | |||
31 | /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ | ||
32 | #define DEBOUNCE 5 | ||
33 | |||
34 | /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ | ||
35 | #define LOCKING_SUPPORT_ENABLE | ||
36 | /* Locking resynchronize hack */ | ||
37 | #define LOCKING_RESYNC_ENABLE | ||
38 | |||
39 | /* If defined, GRAVE_ESC will always act as ESC when CTRL is held. | ||
40 | * This is useful for the Windows task manager shortcut (ctrl+shift+esc). | ||
41 | */ | ||
42 | //#define GRAVE_ESC_CTRL_OVERRIDE | ||
43 | |||
44 | /* | ||
45 | * Force NKRO | ||
46 | * | ||
47 | * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved | ||
48 | * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the | ||
49 | * makefile for this to work.) | ||
50 | * | ||
51 | * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) | ||
52 | * until the next keyboard reset. | ||
53 | * | ||
54 | * NKRO may prevent your keystrokes from being detected in the BIOS, but it is | ||
55 | * fully operational during normal computer usage. | ||
56 | * | ||
57 | * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) | ||
58 | * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by | ||
59 | * bootmagic, NKRO mode will always be enabled until it is toggled again during a | ||
60 | * power-up. | ||
61 | * | ||
62 | */ | ||
63 | //#define FORCE_NKRO | ||
64 | |||
65 | /* | ||
66 | * Feature disable options | ||
67 | * These options are also useful to firmware size reduction. | ||
68 | */ | ||
69 | |||
70 | /* disable debug print */ | ||
71 | //#define NO_DEBUG | ||
72 | |||
73 | /* disable print */ | ||
74 | //#define NO_PRINT | ||
75 | |||
76 | /* disable action features */ | ||
77 | //#define NO_ACTION_LAYER | ||
78 | //#define NO_ACTION_TAPPING | ||
79 | //#define NO_ACTION_ONESHOT | ||
80 | |||
81 | /* disable these deprecated features by default */ | ||
82 | #define NO_ACTION_MACRO | ||
83 | #define NO_ACTION_FUNCTION | ||
diff --git a/keyboards/sp111/info.json b/keyboards/sp111/info.json new file mode 100644 index 000000000..e478a3220 --- /dev/null +++ b/keyboards/sp111/info.json | |||
@@ -0,0 +1,19 @@ | |||
1 | { | ||
2 | "keyboard_name": "SP-111", | ||
3 | "url": "https://thekey.company/products/sp-111", | ||
4 | "maintainer": "blindassassin111", | ||
5 | "width": 22.5, | ||
6 | "height": 6.75, | ||
7 | "layouts": { | ||
8 | "LAYOUT_all": { | ||
9 | "layout": [ | ||
10 | {"label":"F13", "x":0, "y":0}, {"label":"F14", "x":1, "y":0}, {"label":"F15", "x":2, "y":0}, {"label":"F16", "x":3, "y":0}, {"label":"Esc", "x":4.5, "y":0}, {"label":"F1", "x":5.75, "y":0}, {"label":"F2", "x":6.75, "y":0}, {"label":"F3", "x":7.75, "y":0}, {"label":"F4", "x":8.75, "y":0}, {"label":"F5", "x":10, "y":0}, {"label":"F6", "x":11, "y":0}, {"label":"F7", "x":12.75, "y":0}, {"label":"F8", "x":13.75, "y":0}, {"label":"F9", "x":15, "y":0}, {"label":"F10", "x":16, "y":0}, {"label":"F11", "x":17, "y":0}, {"label":"F12", "x":18, "y":0}, {"label":"Prt Scn", "x":19.25, "y":0}, {"label":"Scl Lck", "x":20.5, "y":0}, {"label":"Pause", "x":21.5, "y":0}, | ||
11 | {"label":"Num Lock", "x":0, "y":1.5}, {"label":"/", "x":1, "y":1.5}, {"label":"*", "x":2, "y":1.5}, {"label":"-", "x":3, "y":1.5}, {"label":"~", "x":4.5, "y":1.5}, {"label":"!", "x":5.5, "y":1.5}, {"label":"@", "x":6.5, "y":1.5}, {"label":"#", "x":7.5, "y":1.5}, {"label":"$", "x":8.5, "y":1.5}, {"label":"%", "x":9.5, "y":1.5}, {"label":"^", "x":10.5, "y":1.5}, {"label":"&", "x":12.25, "y":1.5}, {"label":"*", "x":13.25, "y":1.5}, {"label":"(", "x":14.25, "y":1.5}, {"label":")", "x":15.25, "y":1.5}, {"label":"_", "x":16.25, "y":1.5}, {"label":"+", "x":17.25, "y":1.5}, {"label":"Backspace", "x":18.25, "y":1.5}, {"label":"Backspace2", "x":19.25, "y":1.5}, {"label":"Home", "x":20.5, "y":1.5}, {"label":"Insert", "x":21.5, "y":1.5}, | ||
12 | {"label":"7", "x":0, "y":2.5}, {"label":"8", "x":1, "y":2.5}, {"label":"9", "x":2, "y":2.5}, {"label":"+", "x":3, "y":2.5}, {"label":"Tab", "x":4.5, "y":2.5, "w":1.5}, {"label":"Q", "x":6, "y":2.5}, {"label":"W", "x":7, "y":2.5}, {"label":"E", "x":8, "y":2.5}, {"label":"R", "x":9, "y":2.5}, {"label":"T", "x":10, "y":2.5}, {"label":"Y", "x":11.75, "y":2.5}, {"label":"U", "x":12.75, "y":2.5}, {"label":"I", "x":13.75, "y":2.5}, {"label":"O", "x":14.75, "y":2.5}, {"label":"P", "x":15.75, "y":2.5}, {"label":"{", "x":16.75, "y":2.5}, {"label":"}", "x":17.75, "y":2.5}, {"label":"|", "x":18.75, "y":2.5, "w":1.5}, {"label":"End", "x":20.5, "y":2.5}, {"label":"Delete", "x":21.5, "y":2.5}, | ||
13 | {"label":"4", "x":0, "y":3.5}, {"label":"5", "x":1, "y":3.5}, {"label":"6", "x":2, "y":3.5}, {"label":"=", "x":3, "y":3.5}, {"label":"Caps Lock", "x":4.5, "y":3.5, "w":1.75}, {"label":"A", "x":6.25, "y":3.5}, {"label":"S", "x":7.25, "y":3.5}, {"label":"D", "x":8.25, "y":3.5}, {"label":"F", "x":9.25, "y":3.5}, {"label":"G", "x":10.25, "y":3.5}, {"label":"H", "x":12, "y":3.5}, {"label":"J", "x":13, "y":3.5}, {"label":"K", "x":14, "y":3.5}, {"label":"L", "x":15, "y":3.5}, {"label":":", "x":16, "y":3.5}, {"label":"\"", "x":17, "y":3.5}, {"label":"Enter", "x":18, "y":3.5, "w":2.25}, {"label":"PgUp", "x":20.5, "y":3.5}, {"label":"PgDn", "x":21.5, "y":3.5}, | ||
14 | {"label":"1", "x":0, "y":4.5}, {"label":"2", "x":1, "y":4.5}, {"label":"3", "x":2, "y":4.5}, {"label":"Enter", "x":3, "y":4.5}, {"label":"Shift", "x":4.5, "y":4.5, "w":1.25}, {"label":"numbs", "x":5.75, "y":4.5, "w":1}, {"label":"Z", "x":6.75, "y":4.5}, {"label":"X", "x":7.75, "y":4.5}, {"label":"C", "x":8.75, "y":4.5}, {"label":"V", "x":9.75, "y":4.5}, {"label":"B", "x":10.75, "y":4.5}, {"label":"N", "x":12.5, "y":4.5}, {"label":"M", "x":13.5, "y":4.5}, {"label":"<", "x":14.5, "y":4.5}, {"label":">", "x":15.5, "y":4.5}, {"label":"?", "x":16.5, "y":4.5}, {"label":"Shift", "x":17.5, "y":4.5, "w":1.75}, {"label":"Fn", "x":19.25, "y":4.5}, {"label":"\u2191", "x":20.5, "y":4.75}, | ||
15 | {"label":"0", "x":0, "y":5.5}, {"label":"00", "x":1, "y":5.5}, {"label":".", "x":2, "y":5.5}, {"label":"..", "x":3, "y":5.5}, {"label":"Ctrl", "x":4.5, "y":5.5, "w":1.25}, {"label":"Code", "x":5.75, "y":5.5, "w":1.25}, {"label":"Alt", "x":7, "y":5.5, "w":1.25}, {"label":"Fn", "x":8.25, "y":5.5, "w":1}, {"label":"", "x":9.25, "y":5.5, "w":2.25}, {"label":"", "x":12.25, "y":5.5, "w":2.25}, {"label":"", "x":14.5, "y":5.5, "w":1}, {"label":"Alt", "x":15.5, "y":5.5, "w":1.25}, {"label":"Code", "x":16.75, "y":5.5, "w":1.25}, {"label":"Ctrl", "x":18, "y":5.5, "w":1.25}, {"label":"\u2190", "x":19.5, "y":5.75}, {"label":"\u2193", "x":20.5, "y":5.75}, {"label":"\u2192", "x":21.5, "y":5.75} | ||
16 | ] | ||
17 | } | ||
18 | } | ||
19 | } | ||
diff --git a/keyboards/sp111/keymaps/default/keymap.c b/keyboards/sp111/keymaps/default/keymap.c new file mode 100644 index 000000000..0cb29f42a --- /dev/null +++ b/keyboards/sp111/keymaps/default/keymap.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* Copyright 2020 blindassassin111 | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #include QMK_KEYBOARD_H | ||
17 | |||
18 | // Defines names for use in layer keycodes and the keymap | ||
19 | enum layer_names { | ||
20 | _BASE, | ||
21 | _FN | ||
22 | }; | ||
23 | |||
24 | // Defines the keycodes used by our macros in process_record_user | ||
25 | enum custom_keycodes { | ||
26 | KC_P00 = SAFE_RANGE | ||
27 | }; | ||
28 | |||
29 | const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||
30 | [_BASE] = LAYOUT_all( | ||
31 | KC_MUTE, KC_MPRV, KC_MPLY, KC_MNXT, KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS, | ||
32 | KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_HOME, KC_INS, | ||
33 | KC_P7, KC_P8, KC_P9, KC_PPLS, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_END, KC_DEL, | ||
34 | KC_P4, KC_P5, KC_P6, KC_PEQL, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP, KC_PGDN, | ||
35 | KC_P1, KC_P2, KC_P3, KC_PENT, KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(_FN), KC_UP, | ||
36 | KC_P0, KC_P0, KC_P00, KC_PDOT, KC_LCTL, KC_LGUI, KC_LALT, KC_MUTE, KC_SPC, KC_SPC, KC_APP, KC_RALT, KC_RGUI, KC_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT), | ||
37 | |||
38 | [_FN] = LAYOUT_all( | ||
39 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RESET, | ||
40 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
41 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
42 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
43 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
44 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______), | ||
45 | }; | ||
46 | |||
47 | bool process_record_user(uint16_t keycode, keyrecord_t *record) { | ||
48 | if (record->event.pressed) { | ||
49 | switch (keycode) { | ||
50 | case KC_P00: | ||
51 | tap_code(KC_P0); | ||
52 | tap_code(KC_P0); | ||
53 | return false; | ||
54 | } | ||
55 | } | ||
56 | return true; | ||
57 | } | ||
diff --git a/keyboards/sp111/keymaps/via/config.h b/keyboards/sp111/keymaps/via/config.h new file mode 100644 index 000000000..e16379c5d --- /dev/null +++ b/keyboards/sp111/keymaps/via/config.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* Copyright 2020 blindassassin111 | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #pragma once | ||
17 | |||
18 | #define DYNAMIC_KEYMAP_LAYER_COUNT 3 | ||
diff --git a/keyboards/sp111/keymaps/via/keymap.c b/keyboards/sp111/keymaps/via/keymap.c new file mode 100644 index 000000000..1cb4380dd --- /dev/null +++ b/keyboards/sp111/keymaps/via/keymap.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* Copyright 2020 blindassassin111 | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #include QMK_KEYBOARD_H | ||
17 | |||
18 | const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||
19 | [0] = LAYOUT_all( | ||
20 | KC_MUTE, KC_MPRV, KC_MPLY, KC_MNXT, KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS, | ||
21 | KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_HOME, KC_INS, | ||
22 | KC_P7, KC_P8, KC_P9, KC_PPLS, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_END, KC_DEL, | ||
23 | KC_P4, KC_P5, KC_P6, KC_PEQL, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP, KC_PGDN, | ||
24 | KC_P1, KC_P2, KC_P3, KC_PENT, KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(1), KC_UP, | ||
25 | KC_P0, KC_P0, KC_P0, KC_PDOT, KC_LCTL, KC_LGUI, KC_LALT, KC_MUTE, KC_SPC, KC_SPC, KC_APP, KC_RALT, KC_RGUI, KC_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT), | ||
26 | |||
27 | [1] = LAYOUT_all( | ||
28 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RESET, | ||
29 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
30 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
31 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
32 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
33 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______), | ||
34 | |||
35 | [2] = LAYOUT_all( | ||
36 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
37 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
38 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
39 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
40 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||
41 | _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______), | ||
42 | }; | ||
diff --git a/keyboards/sp111/keymaps/via/rules.mk b/keyboards/sp111/keymaps/via/rules.mk new file mode 100644 index 000000000..1e5b99807 --- /dev/null +++ b/keyboards/sp111/keymaps/via/rules.mk | |||
@@ -0,0 +1 @@ | |||
VIA_ENABLE = yes | |||
diff --git a/keyboards/sp111/matrix.c b/keyboards/sp111/matrix.c new file mode 100644 index 000000000..33b232dca --- /dev/null +++ b/keyboards/sp111/matrix.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* Copyright 2020 zvecr<git@zvecr.com> | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #include "mcp23018.h" | ||
17 | #include "quantum.h" | ||
18 | |||
19 | // Optimize scanning code for speed as a slight mitigation for the port expander | ||
20 | #pragma GCC push_options | ||
21 | #pragma GCC optimize("-O3") | ||
22 | |||
23 | #define I2C_ADDR 0x20 | ||
24 | |||
25 | static uint16_t mcp23018_reset_loop = 0; | ||
26 | static uint8_t mcp23018_errors = 0; | ||
27 | |||
28 | static const pin_t row_pins[MATRIX_ROWS / 2] = {B1, D5, D4, D6, D7, B4}; | ||
29 | static const pin_t col_pins[MATRIX_COLS] = {F5, F6, F7, C7, C6, B6, B5, D3, D2, B3, B2}; | ||
30 | |||
31 | //_____REGULAR funcs____________________________________________________________ | ||
32 | |||
33 | static void select_row(uint8_t row) { | ||
34 | setPinOutput(row_pins[row]); | ||
35 | writePinLow(row_pins[row]); | ||
36 | } | ||
37 | |||
38 | static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); } | ||
39 | |||
40 | static void unselect_rows(void) { | ||
41 | for (uint8_t x = 0; x < MATRIX_ROWS / 2; x++) { | ||
42 | setPinInputHigh(row_pins[x]); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | static void init_pins(void) { | ||
47 | unselect_rows(); | ||
48 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
49 | setPinInputHigh(col_pins[x]); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { | ||
54 | // Store last value of row prior to reading | ||
55 | matrix_row_t last_row_value = current_matrix[current_row]; | ||
56 | |||
57 | // Clear data in matrix row | ||
58 | matrix_row_t current_row_value = 0; | ||
59 | |||
60 | // Select row and wait for row selection to stabilize | ||
61 | select_row(current_row); | ||
62 | wait_us(5); | ||
63 | |||
64 | // For each col... | ||
65 | for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { | ||
66 | // Select the col pin to read (active low) | ||
67 | uint8_t pin_state = readPin(col_pins[col_index]); | ||
68 | |||
69 | // Populate the matrix row with the state of the col pin | ||
70 | current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); | ||
71 | } | ||
72 | |||
73 | // Unselect row | ||
74 | unselect_row(current_row); | ||
75 | |||
76 | if (last_row_value == current_row_value) { | ||
77 | return false; | ||
78 | } | ||
79 | |||
80 | current_matrix[current_row] = current_row_value; | ||
81 | return true; | ||
82 | } | ||
83 | |||
84 | //_____MCP23018 funcs___________________________________________________________ | ||
85 | |||
86 | static void init_pins_MCP23018(void) { | ||
87 | mcp23018_errors += !mcp23018_set_config(I2C_ADDR, mcp23018_PORTA, 0b11111111); | ||
88 | mcp23018_errors += !mcp23018_set_config(I2C_ADDR, mcp23018_PORTB, 0b01100000); | ||
89 | } | ||
90 | |||
91 | static void select_row_MCP23018(uint8_t row) { | ||
92 | uint8_t mask = 0; | ||
93 | |||
94 | switch (row) { | ||
95 | case 6: | ||
96 | mask = 0b10000000; | ||
97 | break; | ||
98 | case 7: | ||
99 | mask = 0b00000001; | ||
100 | break; | ||
101 | case 8: | ||
102 | mask = 0b00000010; | ||
103 | break; | ||
104 | case 9: | ||
105 | mask = 0b00000100; | ||
106 | break; | ||
107 | case 10: | ||
108 | mask = 0b00001000; | ||
109 | break; | ||
110 | case 11: | ||
111 | mask = 0b00010000; | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | mcp23018_errors += !mcp23018_set_output(I2C_ADDR, mcp23018_PORTB, ~mask); | ||
116 | } | ||
117 | |||
118 | static uint16_t read_cols_MCP23018(void) { | ||
119 | uint16_t tmp = 0xFFFF; | ||
120 | mcp23018_errors += !mcp23018_readPins_all(I2C_ADDR, &tmp); | ||
121 | |||
122 | uint16_t state = ((tmp & 0b11111111) << 2) | ((tmp & 0b0110000000000000) >> 13); | ||
123 | return (~state) & 0b1111111111; | ||
124 | } | ||
125 | |||
126 | static bool read_cols_on_row_MCP23018(matrix_row_t current_matrix[], uint8_t current_row) { | ||
127 | // Store last value of row prior to reading | ||
128 | matrix_row_t last_row_value = current_matrix[current_row]; | ||
129 | |||
130 | // No need to Clear data in matrix row as we just replace in one go | ||
131 | |||
132 | // Select row and wait for row selection to stabilize | ||
133 | select_row_MCP23018(current_row); | ||
134 | |||
135 | matrix_row_t current_row_value = read_cols_MCP23018(); | ||
136 | |||
137 | // No need to Unselect row as the next `select_row` will blank everything | ||
138 | |||
139 | if (last_row_value == current_row_value) { | ||
140 | return false; | ||
141 | } | ||
142 | |||
143 | current_matrix[current_row] = current_row_value; | ||
144 | return true; | ||
145 | } | ||
146 | |||
147 | //_____CUSTOM MATRIX IMPLEMENTATION____________________________________________________ | ||
148 | |||
149 | void matrix_init_custom(void) { | ||
150 | mcp23018_init(I2C_ADDR); | ||
151 | |||
152 | init_pins(); | ||
153 | init_pins_MCP23018(); | ||
154 | } | ||
155 | |||
156 | bool matrix_scan_custom(matrix_row_t current_matrix[]) { | ||
157 | bool changed = false; | ||
158 | for (uint8_t current_row = 0; current_row < MATRIX_ROWS / 2; current_row++) { | ||
159 | changed |= read_cols_on_row(current_matrix, current_row); | ||
160 | } | ||
161 | |||
162 | if (mcp23018_errors) { | ||
163 | if (++mcp23018_reset_loop > 0x7FFF) { | ||
164 | // tuned to about 5s given the current scan rate | ||
165 | print("trying to reset mcp23018\n"); | ||
166 | mcp23018_reset_loop = 0; | ||
167 | mcp23018_errors = 0; | ||
168 | init_pins_MCP23018(); | ||
169 | } | ||
170 | return changed; | ||
171 | } | ||
172 | |||
173 | for (uint8_t current_row = MATRIX_ROWS / 2; current_row < MATRIX_ROWS; current_row++) { | ||
174 | changed |= read_cols_on_row_MCP23018(current_matrix, current_row); | ||
175 | } | ||
176 | return changed; | ||
177 | } | ||
178 | #pragma GCC pop_options | ||
diff --git a/keyboards/sp111/mcp23018.c b/keyboards/sp111/mcp23018.c new file mode 100644 index 000000000..f1d8e568d --- /dev/null +++ b/keyboards/sp111/mcp23018.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* Copyright 2020 zvecr<git@zvecr.com> | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #include "mcp23018.h" | ||
17 | #include "i2c_master.h" | ||
18 | #include "wait.h" | ||
19 | #include "debug.h" | ||
20 | |||
21 | #define SLAVE_TO_ADDR(n) (n << 1) | ||
22 | #define TIMEOUT 100 | ||
23 | |||
24 | enum { | ||
25 | CMD_IODIRA = 0x00, // i/o direction register | ||
26 | CMD_IODIRB = 0x01, | ||
27 | CMD_GPPUA = 0x0C, // GPIO pull-up resistor register | ||
28 | CMD_GPPUB = 0x0D, | ||
29 | CMD_GPIOA = 0x12, // general purpose i/o port register (write modifies OLAT) | ||
30 | CMD_GPIOB = 0x13, | ||
31 | }; | ||
32 | |||
33 | void mcp23018_init(uint8_t addr) { | ||
34 | static uint8_t s_init = 0; | ||
35 | if (!s_init) { | ||
36 | i2c_init(); | ||
37 | wait_ms(1000); | ||
38 | |||
39 | s_init = 1; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | bool mcp23018_set_config(uint8_t slave_addr, uint8_t port, uint8_t conf) { | ||
44 | uint8_t addr = SLAVE_TO_ADDR(slave_addr); | ||
45 | uint8_t cmdDirection = port ? CMD_IODIRB : CMD_IODIRA; | ||
46 | uint8_t cmdPullup = port ? CMD_GPPUB : CMD_GPPUA; | ||
47 | |||
48 | i2c_status_t ret = i2c_writeReg(addr, cmdDirection, &conf, sizeof(conf), TIMEOUT); | ||
49 | if (ret != I2C_STATUS_SUCCESS) { | ||
50 | dprintf("mcp23018_set_config::directionFAILED::%u\n", ret); | ||
51 | return false; | ||
52 | } | ||
53 | |||
54 | ret = i2c_writeReg(addr, cmdPullup, &conf, sizeof(conf), TIMEOUT); | ||
55 | if (ret != I2C_STATUS_SUCCESS) { | ||
56 | dprintf("mcp23018_set_config::pullupFAILED::%u\n", ret); | ||
57 | return false; | ||
58 | } | ||
59 | |||
60 | return true; | ||
61 | } | ||
62 | |||
63 | bool mcp23018_set_output(uint8_t slave_addr, uint8_t port, uint8_t conf) { | ||
64 | uint8_t addr = SLAVE_TO_ADDR(slave_addr); | ||
65 | uint8_t cmd = port ? CMD_GPIOB : CMD_GPIOA; | ||
66 | |||
67 | i2c_status_t ret = i2c_writeReg(addr, cmd, &conf, sizeof(conf), TIMEOUT); | ||
68 | if (ret != I2C_STATUS_SUCCESS) { | ||
69 | dprintf("mcp23018_set_output::FAILED::%u\n", ret); | ||
70 | return false; | ||
71 | } | ||
72 | |||
73 | return true; | ||
74 | } | ||
75 | |||
76 | bool mcp23018_set_output_all(uint8_t slave_addr, uint8_t confA, uint8_t confB) { | ||
77 | uint8_t addr = SLAVE_TO_ADDR(slave_addr); | ||
78 | uint8_t conf[2] = {confA, confB}; | ||
79 | |||
80 | i2c_status_t ret = i2c_writeReg(addr, CMD_GPIOA, &conf[0], sizeof(conf), TIMEOUT); | ||
81 | if (ret != I2C_STATUS_SUCCESS) { | ||
82 | dprintf("mcp23018_set_output::FAILED::%u\n", ret); | ||
83 | return false; | ||
84 | } | ||
85 | |||
86 | return true; | ||
87 | } | ||
88 | |||
89 | bool mcp23018_readPins(uint8_t slave_addr, uint8_t port, uint8_t* out) { | ||
90 | uint8_t addr = SLAVE_TO_ADDR(slave_addr); | ||
91 | uint8_t cmd = port ? CMD_GPIOB : CMD_GPIOA; | ||
92 | |||
93 | i2c_status_t ret = i2c_readReg(addr, cmd, out, sizeof(uint8_t), TIMEOUT); | ||
94 | if (ret != I2C_STATUS_SUCCESS) { | ||
95 | dprintf("mcp23018_readPins::FAILED::%u\n", ret); | ||
96 | return false; | ||
97 | } | ||
98 | |||
99 | return true; | ||
100 | } | ||
101 | |||
102 | bool mcp23018_readPins_all(uint8_t slave_addr, uint16_t* out) { | ||
103 | uint8_t addr = SLAVE_TO_ADDR(slave_addr); | ||
104 | |||
105 | typedef union { | ||
106 | uint8_t u8[2]; | ||
107 | uint16_t u16; | ||
108 | } data16; | ||
109 | |||
110 | data16 data = {.u16 = 0}; | ||
111 | |||
112 | i2c_status_t ret = i2c_readReg(addr, CMD_GPIOA, &data.u8[0], sizeof(data), TIMEOUT); | ||
113 | if (ret != I2C_STATUS_SUCCESS) { | ||
114 | dprintf("mcp23018_readPins::FAILED::%u\n", ret); | ||
115 | return false; | ||
116 | } | ||
117 | |||
118 | *out = data.u16; | ||
119 | return true; | ||
120 | } | ||
diff --git a/keyboards/sp111/mcp23018.h b/keyboards/sp111/mcp23018.h new file mode 100644 index 000000000..dc2251b72 --- /dev/null +++ b/keyboards/sp111/mcp23018.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* Copyright 2020 zvecr<git@zvecr.com> | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #pragma once | ||
17 | |||
18 | #include <stdint.h> | ||
19 | #include <stdbool.h> | ||
20 | |||
21 | #define mcp23018_PORTA 0 | ||
22 | #define mcp23018_PORTB 1 | ||
23 | |||
24 | #define ALL_OUTPUT 0 | ||
25 | #define ALL_INPUT 0xFF | ||
26 | #define ALL_LOW 0 | ||
27 | #define ALL_HIGH 0xFF | ||
28 | |||
29 | void mcp23018_init(uint8_t addr); | ||
30 | bool mcp23018_set_config(uint8_t slave_addr, uint8_t port, uint8_t conf); | ||
31 | bool mcp23018_set_output(uint8_t slave_addr, uint8_t port, uint8_t conf); | ||
32 | bool mcp23018_set_output_all(uint8_t slave_addr, uint8_t confA, uint8_t confB); | ||
33 | bool mcp23018_readPins(uint8_t slave_addraddr, uint8_t port, uint8_t* ret); | ||
34 | bool mcp23018_readPins_all(uint8_t slave_addr, uint16_t* ret); | ||
diff --git a/keyboards/sp111/readme.md b/keyboards/sp111/readme.md new file mode 100644 index 000000000..b9f8f02e0 --- /dev/null +++ b/keyboards/sp111/readme.md | |||
@@ -0,0 +1,21 @@ | |||
1 | # SP-111 | ||
2 | |||
3 |  | ||
4 | |||
5 | Southpaw (left sided numpad) allows you to use the numpad and mouse at the same time. | ||
6 | Split allows placement in a comfortable manner for long sessions. | ||
7 | Right side layout to maintain the functionality of a full size board in a much more compact manner. | ||
8 | |||
9 | * Keyboard Maintainer: [zvecr](https://github.com/zvecr), blindassassin111 | ||
10 | * Hardware Supported: SP-111 | ||
11 | * Hardware Availability: <https://thekey.company/products/sp-111> | ||
12 | |||
13 | Make example for this keyboard (after setting up your build environment): | ||
14 | |||
15 | make sp111:default | ||
16 | |||
17 | Flashing example for this keyboard: | ||
18 | |||
19 | make sp111:default:flash | ||
20 | |||
21 | See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). | ||
diff --git a/keyboards/sp111/rules.mk b/keyboards/sp111/rules.mk new file mode 100644 index 000000000..6aab68074 --- /dev/null +++ b/keyboards/sp111/rules.mk | |||
@@ -0,0 +1,30 @@ | |||
1 | # MCU name | ||
2 | MCU = atmega32u4 | ||
3 | |||
4 | # Bootloader selection | ||
5 | BOOTLOADER = atmel-dfu | ||
6 | |||
7 | # Build Options | ||
8 | # change yes to no to disable | ||
9 | # | ||
10 | BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration | ||
11 | MOUSEKEY_ENABLE = yes # Mouse keys | ||
12 | EXTRAKEY_ENABLE = yes # Audio control and System control | ||
13 | CONSOLE_ENABLE = no # Console for debug | ||
14 | COMMAND_ENABLE = no # Commands for debug and configuration | ||
15 | # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE | ||
16 | SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend | ||
17 | # if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work | ||
18 | NKRO_ENABLE = yes # USB Nkey Rollover | ||
19 | BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality | ||
20 | RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow | ||
21 | BLUETOOTH_ENABLE = no # Enable Bluetooth | ||
22 | AUDIO_ENABLE = no # Audio output | ||
23 | LTO_ENABLE = yes # Smaller (and slightly faster) firmware | ||
24 | |||
25 | |||
26 | # custom matrix setup | ||
27 | CUSTOM_MATRIX = lite | ||
28 | |||
29 | SRC += mcp23018.c matrix.c | ||
30 | QUANTUM_LIB_SRC += i2c_master.c | ||
diff --git a/keyboards/sp111/sp111.c b/keyboards/sp111/sp111.c new file mode 100644 index 000000000..737334998 --- /dev/null +++ b/keyboards/sp111/sp111.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* Copyright 2020 blindassassin111 | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #include "sp111.h" | ||
17 | |||
18 | void keyboard_pre_init_kb(void) { | ||
19 | // enable built in pullups to avoid timeouts when right hand not connected | ||
20 | setPinInputHigh(D0); | ||
21 | setPinInputHigh(D1); | ||
22 | |||
23 | keyboard_pre_init_user(); | ||
24 | } | ||
25 | |||
26 | void matrix_init_kb(void) { | ||
27 | setPinOutput(F0); | ||
28 | setPinOutput(F1); | ||
29 | setPinOutput(F4); | ||
30 | |||
31 | matrix_init_user(); | ||
32 | } | ||
33 | |||
34 | bool led_update_kb(led_t led_state) { | ||
35 | bool res = led_update_user(led_state); | ||
36 | if (res) { | ||
37 | writePin(F0, led_state.num_lock); | ||
38 | writePin(F1, led_state.caps_lock); | ||
39 | writePin(F4, led_state.scroll_lock); | ||
40 | } | ||
41 | return res; | ||
42 | } | ||
diff --git a/keyboards/sp111/sp111.h b/keyboards/sp111/sp111.h new file mode 100644 index 000000000..fb7e3394a --- /dev/null +++ b/keyboards/sp111/sp111.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* Copyright 2020 blindassassin111 | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation, either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | #pragma once | ||
17 | |||
18 | #include "quantum.h" | ||
19 | #define ___ KC_NO | ||
20 | |||
21 | #define LAYOUT_all( \ | ||
22 | L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A, R01, R02, R03, R04, R05, R06, R07, R08, R09, \ | ||
23 | L10, L11, L12, L13, L14, L15, L16, L17, L18, L19, L0B, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, \ | ||
24 | L20, L21, L22, L23, L24, L25, L26, L27, L28, L29, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, \ | ||
25 | L30, L31, L32, L33, L34, L35, L36, L37, L38, L39, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, \ | ||
26 | L40, L41, L42, L43, L44, L45, L46, L47, L48, L49, R41, R42, R43, R44, R45, R46, R47, R48, \ | ||
27 | L50, L51, L52, L53, L54, L55, L56, L57, L58, R52, R53, R54, R55, R56, R57, R49, R59 \ | ||
28 | ) { \ | ||
29 | { L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A }, \ | ||
30 | { L10, L11, L12, L13, L14, L15, L16, L17, L18, L19, L0B }, \ | ||
31 | { L20, L21, L22, L23, L24, L25, L26, L27, L28, L29, ___ }, \ | ||
32 | { L30, L31, L32, L33, L34, L35, L36, L37, L38, L39, ___ }, \ | ||
33 | { L40, L41, L42, L43, L44, L45, L46, L47, L48, L49, ___ }, \ | ||
34 | { L50, L51, L52, L53, L54, L55, L56, L57, L58, ___, ___ }, \ | ||
35 | { ___, R01, R02, R03, R04, R05, R06, R07, R08, R09, ___ }, \ | ||
36 | { R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, ___ }, \ | ||
37 | { R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, ___ }, \ | ||
38 | { R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, ___ }, \ | ||
39 | { ___, R41, R42, R43, R44, R45, R46, R47, R48, ___, ___ }, \ | ||
40 | { ___, ___, R52, R53, R54, R55, R56, R57, R49, R59, ___ } \ | ||
41 | } | ||