aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keyboards/gray_studio/think65/solder/info.json74
-rw-r--r--keyboards/gray_studio/think65/solder/keymaps/rys/keymap.c271
-rw-r--r--keyboards/gray_studio/think65/solder/keymaps/rys/readme.md11
-rw-r--r--keyboards/gray_studio/think65/solder/solder.h16
4 files changed, 369 insertions, 3 deletions
diff --git a/keyboards/gray_studio/think65/solder/info.json b/keyboards/gray_studio/think65/solder/info.json
index 0be504253..cc87af41b 100644
--- a/keyboards/gray_studio/think65/solder/info.json
+++ b/keyboards/gray_studio/think65/solder/info.json
@@ -77,7 +77,77 @@
77 {"label":"K4F (E6,F6)", "x":15, "y":4} 77 {"label":"K4F (E6,F6)", "x":15, "y":4}
78 ] 78 ]
79 }, 79 },
80 80 "LAYOUT_65_iso_badge": {
81 "key_count": 66,
82 "layout": [
83 {"label":"K00", "x":0, "y":0},
84 {"label":"K01", "x":1, "y":0},
85 {"label":"K02", "x":2, "y":0},
86 {"label":"K03", "x":3, "y":0},
87 {"label":"K04", "x":4, "y":0},
88 {"label":"K05", "x":5, "y":0},
89 {"label":"K06", "x":6, "y":0},
90 {"label":"K07", "x":7, "y":0},
91 {"label":"K08", "x":8, "y":0},
92 {"label":"K09", "x":9, "y":0},
93 {"label":"K0A", "x":10, "y":0},
94 {"label":"K0B", "x":11, "y":0},
95 {"label":"K0C", "x":12, "y":0},
96 {"label":"K0D", "x":13, "y":0, "w":2},
97 {"label":"K0F", "x":15, "y":0},
98 {"label":"K10", "x":0, "y":1, "w":1.5},
99 {"label":"K12", "x":1.5, "y":1},
100 {"label":"K13", "x":2.5, "y":1},
101 {"label":"K14", "x":3.5, "y":1},
102 {"label":"K15", "x":4.5, "y":1},
103 {"label":"K16", "x":5.5, "y":1},
104 {"label":"K17", "x":6.5, "y":1},
105 {"label":"K18", "x":7.5, "y":1},
106 {"label":"K19", "x":8.5, "y":1},
107 {"label":"K1A", "x":9.5, "y":1},
108 {"label":"K1B", "x":10.5, "y":1},
109 {"label":"K1C", "x":11.5, "y":1},
110 {"label":"K1D", "x":12.5, "y":1},
111 {"label":"K1F", "x":15, "y":1},
112 {"label":"K20", "x":0, "y":2, "w":1.75},
113 {"label":"K22", "x":1.75, "y":2},
114 {"label":"K23", "x":2.75, "y":2},
115 {"label":"K24", "x":3.75, "y":2},
116 {"label":"K25", "x":4.75, "y":2},
117 {"label":"K26", "x":5.75, "y":2},
118 {"label":"K27", "x":6.75, "y":2},
119 {"label":"K28", "x":7.75, "y":2},
120 {"label":"K29", "x":8.75, "y":2},
121 {"label":"K2A", "x":9.75, "y":2},
122 {"label":"K2B", "x":10.75, "y":2},
123 {"label":"K2C", "x":11.75, "y":2},
124 {"label":"K1E", "x":12.75, "y":2},
125 {"label":"K2D", "x":13.75, "y":1, "w":1.25, "h":2},
126 {"label":"K30", "x":0, "y":3, "w":1.25},
127 {"label":"K31", "x":1.25, "y":3},
128 {"label":"K32", "x":2.25, "y":3},
129 {"label":"K33", "x":3.25, "y":3},
130 {"label":"K34", "x":4.25, "y":3},
131 {"label":"K35", "x":5.25, "y":3},
132 {"label":"K36", "x":6.25, "y":3},
133 {"label":"K37", "x":7.25, "y":3},
134 {"label":"K38", "x":8.25, "y":3},
135 {"label":"K39", "x":9.25, "y":3},
136 {"label":"K3A", "x":10.25, "y":3},
137 {"label":"K3B", "x":11.25, "y":3},
138 {"label":"K3D", "x":12.25, "y":3, "w":1.75},
139 {"label":"K3E", "x":14, "y":3},
140 {"label":"K40", "x":0, "y":4, "w":1.25},
141 {"label":"K41", "x":1.25, "y":4, "w":1.25},
142 {"label":"K43", "x":2.5, "y":4, "w":1.25},
143 {"label":"K46", "x":3.75, "y":4, "w":6.25},
144 {"label":"K4A", "x":10, "y":4, "w":1.25},
145 {"label":"K4B", "x":11.25, "y":4, "w":1.25},
146 {"label":"K4D", "x":13, "y":4},
147 {"label":"K4E", "x":14, "y":4},
148 {"label":"K4F", "x":15, "y":4}
149 ]
150 },
81 "LAYOUT_all": { 151 "LAYOUT_all": {
82 "key_count": 69, 152 "key_count": 69,
83 "layout": [ 153 "layout": [
@@ -154,4 +224,4 @@
154 } 224 }
155 } 225 }
156 ,"meta": "https://noroadsleft.github.io/kbf_qmk_converter/" 226 ,"meta": "https://noroadsleft.github.io/kbf_qmk_converter/"
157} \ No newline at end of file 227}
diff --git a/keyboards/gray_studio/think65/solder/keymaps/rys/keymap.c b/keyboards/gray_studio/think65/solder/keymaps/rys/keymap.c
new file mode 100644
index 000000000..658798ed6
--- /dev/null
+++ b/keyboards/gray_studio/think65/solder/keymaps/rys/keymap.c
@@ -0,0 +1,271 @@
1/* Copyright 2019 Rys Sommefeldt
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/*
19 * LED ranges
20 * ┌─────────────┬─────────────┬───────────────────────────────────────────┐
21 * │ 00 01 02 03 │ 04 05 06 07 │ 08 09 10 11 12 13 14 15 16 17 18 19 20 21 │
22 * │   escape    │    badge    │              underglow                    │
23 * └─────────────┴─────────────┴───────────────────────────────────────────┘
24 */
25
26// Define the LED ranges start, end
27#define THINK65_LED_RANGE_OFF 0, 0
28#define THINK65_LED_RANGE_ESC 0, 4
29#define THINK65_LED_RANGE_BADGE 4, 8
30#define THINK65_LED_RANGE_UNDERGLOW 8, 22
31#define THINK65_LED_RANGE_ALL 0, 22
32
33// Turn the LEDs off by setting HSV to 0, 0, 0
34#define THINK65_LEDS_OFF 0, 0, 0
35
36// There are 3 ranges, so we can store all combinations in 2^3 values
37// Define all of them to make it easier to write the cycling code
38#define THINK65_LED_STATE_OFF 0x0 // 0b00000000
39#define THINK65_LED_STATE_ESC 0x1 // 0b00000001
40#define THINK65_LED_STATE_BADGE 0x2 // 0b00000010
41#define THINK65_LED_STATE_UNDERGLOW 0x4 // 0b00000100
42#define THINK65_LED_STATE_ESC_AND_BADGE 0x3 // 0b00000011
43#define THINK65_LED_STATE_ESC_AND_UNDERGLOW 0x5 // 0b00000101
44#define THINK65_LED_STATE_BADGE_AND_UNDERGLOW 0x6 // 0b00000110
45#define THINK65_LED_STATE_ON 0x7 // 0b00000111
46
47// Define each LED range as a bit flag
48#define THINK65_LED_ESC_RANGE_BIT 0
49#define THINK65_LED_BADGE_RANGE_BIT 1
50#define THINK65_LED_UNDERGLOW_RANGE_BIT 2
51
52// Setup some keycodes to control cycling and range toggling
53enum rys_keycodes {
54 CYC_LED = SAFE_RANGE,
55 TOG_ESC,
56 TOG_BDG,
57 TOG_UGL
58};
59
60// setup the user EEPROM space we need
61typedef union {
62 uint8_t raw;
63 struct {
64 uint8_t current_led_state:8;
65 };
66} user_config_t;
67
68user_config_t user_config;
69
70// toggle one of the range flag bits
71void toggle_led_state(unsigned int led_range) {
72 if (led_range >= THINK65_LED_ESC_RANGE_BIT && led_range <= THINK65_LED_UNDERGLOW_RANGE_BIT) {
73 user_config.current_led_state ^= 1 << led_range;
74 }
75}
76
77// set one of the range flag bits
78void set_led_state(unsigned int led_range) {
79 if (led_range >= THINK65_LED_ESC_RANGE_BIT && led_range <= THINK65_LED_UNDERGLOW_RANGE_BIT) {
80 user_config.current_led_state |= 1 << led_range;
81 }
82}
83
84// clear one of the range flag bits
85void clear_led_state(unsigned int led_range) {
86 if (led_range >= THINK65_LED_ESC_RANGE_BIT && led_range <= THINK65_LED_UNDERGLOW_RANGE_BIT) {
87 user_config.current_led_state &= ~(1 << led_range);
88 }
89}
90
91// cycle LED states: Off -> Esc -> Badge -> Underglow -> Esc+Badge -> Esc+Underglow -> Badge+Underglow -> All
92void cycle_led_state(void) {
93 switch(user_config.current_led_state) {
94 case THINK65_LED_STATE_OFF:
95 user_config.current_led_state = THINK65_LED_STATE_ESC;
96 break;
97 case THINK65_LED_STATE_ESC:
98 user_config.current_led_state = THINK65_LED_STATE_BADGE;
99 break;
100 case THINK65_LED_STATE_BADGE:
101 user_config.current_led_state = THINK65_LED_STATE_UNDERGLOW;
102 break;
103 case THINK65_LED_STATE_UNDERGLOW:
104 user_config.current_led_state = THINK65_LED_STATE_ESC_AND_BADGE;
105 break;
106 case THINK65_LED_STATE_ESC_AND_BADGE:
107 user_config.current_led_state = THINK65_LED_STATE_ESC_AND_UNDERGLOW;
108 break;
109 case THINK65_LED_STATE_ESC_AND_UNDERGLOW:
110 user_config.current_led_state = THINK65_LED_STATE_BADGE_AND_UNDERGLOW;
111 break;
112 case THINK65_LED_STATE_BADGE_AND_UNDERGLOW:
113 user_config.current_led_state = THINK65_LED_STATE_ON;
114 break;
115 case THINK65_LED_STATE_ON:
116 user_config.current_led_state = THINK65_LED_STATE_OFF;
117 break;
118 default:
119 break;
120 }
121}
122
123void apply_led_state(void) {
124 uint8_t h = rgblight_get_hue();
125 uint8_t s = rgblight_get_sat();
126 uint8_t v = rgblight_get_val();
127
128 // Set the RGB ranges based on the current state
129 switch(user_config.current_led_state) {
130 case THINK65_LED_STATE_OFF:
131 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_ALL);
132 break;
133 case THINK65_LED_STATE_ESC:
134 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_ESC);
135 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_BADGE);
136 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_UNDERGLOW);
137 break;
138 case THINK65_LED_STATE_BADGE:
139 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_ESC);
140 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_BADGE);
141 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_UNDERGLOW);
142 break;
143 case THINK65_LED_STATE_UNDERGLOW:
144 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_ESC);
145 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_BADGE);
146 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_UNDERGLOW);
147 break;
148 case THINK65_LED_STATE_ESC_AND_BADGE:
149 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_ESC);
150 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_BADGE);
151 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_UNDERGLOW);
152 break;
153 case THINK65_LED_STATE_ESC_AND_UNDERGLOW:
154 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_ESC);
155 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_BADGE);
156 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_UNDERGLOW);
157 break;
158 case THINK65_LED_STATE_BADGE_AND_UNDERGLOW:
159 rgblight_sethsv_range(THINK65_LEDS_OFF, THINK65_LED_RANGE_ESC);
160 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_BADGE);
161 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_UNDERGLOW);
162 break;
163 case THINK65_LED_STATE_ON:
164 rgblight_sethsv_range(h, s, v, THINK65_LED_RANGE_ALL);
165 break;
166 default:
167 break;
168 }
169}
170
171void keyboard_post_init_user(void) {
172 user_config.raw = eeconfig_read_user();
173
174 if (user_config.current_led_state >= THINK65_LED_STATE_OFF && user_config.current_led_state <= THINK65_LED_STATE_ON) {
175 // If the current state read from user EEPROM is valid, apply it
176 apply_led_state();
177 } else {
178 // Setup a new default state of off
179 user_config.current_led_state = THINK65_LED_STATE_OFF;
180 apply_led_state();
181 eeconfig_update_user(user_config.raw);
182 }
183}
184
185bool process_record_user(uint16_t keycode, keyrecord_t *record) {
186 switch (keycode) {
187 case CYC_LED:
188 if (record->event.pressed) {
189 cycle_led_state();
190 apply_led_state();
191 eeconfig_update_user(user_config.raw);
192 }
193 break;
194 case TOG_ESC:
195 if (record->event.pressed) {
196 toggle_led_state(THINK65_LED_ESC_RANGE_BIT);
197 apply_led_state();
198 eeconfig_update_user(user_config.raw);
199 }
200 break;
201 case TOG_BDG:
202 if (record->event.pressed) {
203 toggle_led_state(THINK65_LED_BADGE_RANGE_BIT);
204 apply_led_state();
205 eeconfig_update_user(user_config.raw);
206 }
207 break;
208 case TOG_UGL:
209 if (record->event.pressed) {
210 toggle_led_state(THINK65_LED_UNDERGLOW_RANGE_BIT);
211 apply_led_state();
212 eeconfig_update_user(user_config.raw);
213 }
214 break;
215 case KC_CAPS:
216 if (!record->event.pressed) {
217 // connect capslock LED control to the badge LEDs
218 host_keyboard_led_state().caps_lock ? set_led_state(THINK65_LED_BADGE_RANGE_BIT) : clear_led_state(THINK65_LED_BADGE_RANGE_BIT);
219 apply_led_state();
220 eeconfig_update_user(user_config.raw);
221 }
222 break;
223 default:
224 break;
225 }
226 return true;
227}
228
229const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
230 [0] = LAYOUT_65_iso_badge(
231 /*
232 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┬───┐
233 * │Esc│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ Backsp│ ` │
234 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┼───┤
235 * │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │     │Del│
236 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐ Ent├───┤
237 * │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ # │    │   │
238 * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴┬───┤   │
239 * │Shft│ \ │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │ Shift│ ↑ │   │
240 * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬─┬───┼───┼───┤
241 * │Ctrl│LAlt│GUI │      Spaaaaaaace       │RAlt│ L1 │ │ ← │ ↓ │ → │
242 * └────┴────┴────┴────────────────────────┴────┴────┘ └───┴───┴───┘
243 */
244 KC_ESC, 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_GRV,
245 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_DEL,
246 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_NUHS, KC_ENT,
247 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, KC_UP,
248 KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RALT, MO(1), KC_LEFT, KC_DOWN, KC_RGHT
249 ),
250 [1] = LAYOUT_65_iso_badge(
251 /*
252 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┬───┐
253 * │RST│ F1│ F2│ F3│ F4│ F5│ F6│ F7│ F8│ F9│F10│F11│F12│       │   │
254 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┼───┤
255 * │ TOG │PLN│MOD│HU+│HU-│SA+│SA-│VA+│VA-│   │   │   │   │     │   │
256 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    ├───┤
257 * │      │   │   │   │   │   │   │   │   │   │   │   │   │    │   │
258 * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴┬───┤   │
259 * │    │   │   │   │   │   │   │   │   │   │   │   │      │CYC│   │
260 * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬─┬───┼───┼───┤
261 * │    │    │    │                        │    │    │ │ESC│BDG│UGL│
262 * └────┴────┴────┴────────────────────────┴────┴────┘ └───┴───┴───┘
263 */
264 RESET, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______,
265 RGB_TOG, RGB_M_P, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, _______, _______, _______, _______, _______,
266 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
267 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, CYC_LED,
268 _______, _______, _______, _______, _______, _______, TOG_ESC, TOG_BDG, TOG_UGL
269 ),
270
271};
diff --git a/keyboards/gray_studio/think65/solder/keymaps/rys/readme.md b/keyboards/gray_studio/think65/solder/keymaps/rys/readme.md
new file mode 100644
index 000000000..ed73e3064
--- /dev/null
+++ b/keyboards/gray_studio/think65/solder/keymaps/rys/readme.md
@@ -0,0 +1,11 @@
1# Personal keymap for the Think 6.5 with compatible soldered PCB
2
3The layout is UK ISO with some small personal tweaks.
4
5The LED cycling code is based on code posted to the Gray Studio Discord by `MudkipMao` on Nov 22nd 2019. Thanks!
6
7## LED cycling
8
9This map saves and restores your current active LED group choice to user EEPROM and restores it on keyboard init, which you can cycle through all combinations of, or toggle individually.
10
11The cycle is `Off -> Esc -> Badge -> Underglow -> Esc+Badge -> Esc+Underglow -> Badge+Underglow -> All`. Look at the keymap for the controls on layer 1.
diff --git a/keyboards/gray_studio/think65/solder/solder.h b/keyboards/gray_studio/think65/solder/solder.h
index b77cc578b..19ee55125 100644
--- a/keyboards/gray_studio/think65/solder/solder.h
+++ b/keyboards/gray_studio/think65/solder/solder.h
@@ -45,5 +45,19 @@
45 { K40, K41, KC_NO, K43, KC_NO, KC_NO, K46, KC_NO, KC_NO, KC_NO, K4A, K4B, KC_NO, K4D, K4E, K4F }, \ 45 { K40, K41, KC_NO, K43, KC_NO, KC_NO, K46, KC_NO, KC_NO, KC_NO, K4A, K4B, KC_NO, K4D, K4E, K4F }, \
46} 46}
47 47
48#define LAYOUT_65_iso_badge( \
49 K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0F, \
50 K10, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1F, \
51 K20, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K1E, K2D, \
52 K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3D, K3E, \
53 K40, K41, K43, K46, K4A, K4B, K4D, K4E, K4F \
54) { \
55 { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, KC_NO, K0F }, \
56 { K10, KC_NO, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, K1F }, \
57 { K20, KC_NO, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, KC_NO, KC_NO }, \
58 { K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, KC_NO, K3D, K3E, KC_NO }, \
59 { K40, K41, KC_NO, K43, KC_NO, KC_NO, K46, KC_NO, KC_NO, KC_NO, K4A, K4B, KC_NO, K4D, K4E, K4F }, \
60}
61
48// generated by KBFirmware JSON to QMK Parser 62// generated by KBFirmware JSON to QMK Parser
49// https://noroadsleft.github.io/kbf_qmk_converter/ \ No newline at end of file 63// https://noroadsleft.github.io/kbf_qmk_converter/