1 // this is the style you want to emulate.
2 // This is the canonical layout file for the Quantum project. If you want to add another keyboard,
4 #include QMK_KEYBOARD_H
6 // Each layer gets a name for readability, which is then used in the keymap matrix below.
7 // The underscores don't mean anything - you can have a layer called STUFF or any other name.
8 // Layer names don't all need to be of the same length, obviously, and you can also skip them
9 // entirely and just use numbers.
10 enum dichotomy_layers {
18 #define LONGPRESS_COUNT 4
20 enum dichotomy_keycodes
25 CK_TE, //these 4 CK_XXXX keys are special "alternate long-press" keys controlled with unique timers. Make sure you understand them before you mess with them.
36 #define CUSTOM_LONGPRESS 150
37 #define CUSTOM_TOGGLE_TIME 300
39 #define RED_BRIGHTNESS 3
40 #define GREEN_BRIGHTNESS 2
41 #define BLUE_BRIGHTNESS 2
43 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
44 [_BS] = LAYOUT( /* Base layout, nearly qwerty but with modifications because it's not a full keyboard. Obviously. */
45 CK_TE, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,
46 NUMKEY, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, CK_QE,
47 SFTKEY, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, MOUKEY,
48 KC_LCTL, KC_LALT, KC_LGUI, KC_RGUI, KC_RALT, KC_RCTL,
49 MS_BTN3, KC_LBRC, KC_LPRN, KC_SPC, KC_SPC, KC_RPRN, KC_RBRC, MS_BTN3
52 [_SF] = LAYOUT( /* Shifted layout, small changes (because angle brackets have been moved to thumb cluster buttons) */
53 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
54 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
55 _______, _______, _______, _______, _______, _______, _______, _______, NS_HYPH, KC_UNDS, _______, _______,
56 _______, _______, _______, _______, _______, _______,
57 _______, _______, KC_LABK, _______, _______, KC_RABK, _______, _______
60 [_NM] = LAYOUT( /* Number layout, basically the main function layer */
61 _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, _______,
62 _______, CK_1G, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, CK_BSPE,
63 _______, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, _______,
64 _______, _______, _______, _______, _______, _______,
65 _______, _______, _______, _______, _______, _______, _______, _______
68 [_NS] = LAYOUT( /* Shifted number/function layout, for per-key control. Only active when shift is held, and number is toggled or held */
69 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
70 _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PLUS, NS_EQU, _______,
71 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
72 _______, _______, _______, _______, _______, _______,
73 _______, _______, _______, _______, _______, _______, _______, _______
76 [_MS] = LAYOUT( /* Mouse layer, including buttons for clicking. */
77 _______, _______, _______, _______, _______, _______, KC_VOLU, KC_HOME, KC_PGUP, _______, _______, _______,
78 _______, _______, _______, _______, _______, _______, _______, MS_BTN1, MS_BTN2, _______, _______, _______,
79 _______, _______, _______, _______, _______, _______, KC_VOLD, KC_END, KC_PGDN, _______, _______, _______,
80 _______, _______, _______, _______, KC_UP, _______,
81 _______, _______, _______, _______, KC_LEFT, KC_DOWN, KC_RGHT, _______
86 static uint16_t special_timers[LONGPRESS_COUNT] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF};
87 static bool special_key_states[LONGPRESS_COUNT] = {0,0,0,0};
88 static bool special_key_pressed[LONGPRESS_COUNT] = {0,0,0,0};
90 static uint16_t shift_timer;
91 static uint16_t num_timer;
92 static uint16_t mouse_timer;
94 static uint8_t red_timer;
95 static uint8_t green_timer;
96 static uint8_t blue_timer;
98 static bool shift_singular_key = false;
99 static bool number_singular_key = false;
100 static bool mouse_singular_key = false;
101 static bool capsLED = false;
102 static bool shiftLED = false;
103 static bool numLED = false;
104 static bool mouseLED = false;
106 static bool shift_held = false;
107 static bool shift_suspended = false;
108 report_mouse_t currentReport = {};
110 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
112 //layer = biton32(layer_state); // get the current layer //Or don't, I didn't use it.
113 bool returnVal = true; //this is to determine if more key processing is needed.
115 //custom layer handling for tri_layer,
118 if (record->event.pressed) {
119 num_timer = timer_read();
120 number_singular_key = true;
124 if (timer_elapsed(num_timer) < CUSTOM_TOGGLE_TIME && number_singular_key) {
125 //do nothing, the layer has already been inverted
131 update_tri_layer(_NM, _SF, _NS);
134 //SHIFT is handled as LSHIFT in the general case - 'toggle' shoudl activate caps, while the layer is only active when shift is held.
136 if (record->event.pressed) {
139 shift_suspended = false;
140 shift_timer = timer_read();
141 shift_singular_key = true;
143 register_code(KC_LSFT);
147 if (timer_elapsed(shift_timer) < CUSTOM_TOGGLE_TIME && shift_singular_key) {
148 //this was basically a toggle, so activate/deactivate caps lock.
149 SEND_STRING(SS_TAP(X_CAPSLOCK));
153 unregister_code(KC_LSFT);
155 update_tri_layer(_NM, _SF, _NS);
158 //MOUSE layer needs to be handled the same way as NUMKEY, but differently from shift
160 if (record->event.pressed) {
161 mouse_timer = timer_read();
162 mouse_singular_key = true;
164 mouseLED = !mouseLED;
166 if (timer_elapsed(mouse_timer) < CUSTOM_TOGGLE_TIME && mouse_singular_key){
167 //do nothing, it was a toggle (and it's already been toggled)
170 mouseLED = !mouseLED;
175 //Custom macros for strange keys with different long-tap behavior
177 if (shift_held && shift_suspended){
178 register_code(KC_LSFT);
179 shift_suspended = false;
181 if (record->event.pressed) {
182 special_timers[CK_1G-SAFE_RANGE] = timer_read();
183 special_key_pressed[CK_1G-SAFE_RANGE] = 1;
185 if (special_key_states[CK_1G-SAFE_RANGE]){
186 //key was activated after custom_longpress, need to close those keycodes
187 special_key_states[CK_1G-SAFE_RANGE] = 0;
188 unregister_code(KC_GRAVE);
190 if (special_key_pressed[CK_1G-SAFE_RANGE]){
191 //key was not activated, return macro activating proper, pre-long-tap key
192 SEND_STRING(SS_TAP(X_1));
193 special_key_pressed[CK_1G-SAFE_RANGE] = 0;
195 //the short key was already sent, because another key was pressed.
204 if (shift_held && shift_suspended){
205 register_code(KC_LSFT);
206 shift_suspended = false;
208 if (record->event.pressed) {
209 special_timers[CK_BSPE-SAFE_RANGE] = timer_read();
210 special_key_pressed[CK_BSPE-SAFE_RANGE] = 1;
212 if (special_key_states[CK_BSPE-SAFE_RANGE]){
213 //key was activated after custom_longpress, need to close those keycodes
214 special_key_states[CK_BSPE-SAFE_RANGE] = 0;
215 unregister_code(KC_ENTER);
217 if (special_key_pressed[CK_BSPE-SAFE_RANGE]){
218 //key was not activated, return macro activating proper, pre-long-tap key
219 SEND_STRING(SS_TAP(X_BSLASH));
220 special_key_pressed[CK_BSPE-SAFE_RANGE] = 0;
222 //the short key was already sent, because another key was pressed.
230 if (shift_held && shift_suspended){
231 register_code(KC_LSFT);
232 shift_suspended = false;
234 if (record->event.pressed) {
235 special_timers[CK_QE-SAFE_RANGE] = timer_read();
236 special_key_pressed[CK_QE-SAFE_RANGE] = 1;
238 if (special_key_states[CK_QE-SAFE_RANGE]){
239 //key was activated after custom_longpress, need to close those keycodes
240 special_key_states[CK_QE-SAFE_RANGE] = 0;
241 unregister_code(KC_ENTER);
243 if (special_key_pressed[CK_QE-SAFE_RANGE]){
244 //the long-press key was not activated, return macro activating proper, pre-long-tap key
245 SEND_STRING(SS_TAP(X_QUOTE));
246 special_key_pressed[CK_QE-SAFE_RANGE] = 0;
248 //the short key was already sent, because another key was pressed.
256 if (shift_held && shift_suspended){
257 register_code(KC_LSFT);
258 shift_suspended = false;
260 if (record->event.pressed) {
261 special_timers[CK_TE-SAFE_RANGE] = timer_read();
262 special_key_pressed[CK_TE-SAFE_RANGE] = 1;
264 if (special_key_states[CK_TE-SAFE_RANGE]){
265 //key was activated after custom_longpress, need to close those keycodes
266 special_key_states[CK_TE-SAFE_RANGE] = 0;
267 unregister_code(KC_ESCAPE);
269 if (special_key_pressed[CK_TE-SAFE_RANGE]){
270 //the long-press key was not activated, return macro activating proper, pre-long-tap key
271 SEND_STRING(SS_TAP(X_TAB));
272 special_key_pressed[CK_TE-SAFE_RANGE] = 0;
274 //the short key was already sent, because another key was pressed.
281 //No-shift keys, they unregister the KC_LSFT code so they can send
282 //unshifted values - but they don't change the bool. if any other
283 //key is pressed and the bool is set, KC_LSFT is registered again.
285 if (record->event.pressed) {
286 shift_suspended = true;
287 unregister_code(KC_LSFT);
288 register_code(KC_MINS);
290 unregister_code(KC_MINS);
291 if (shift_held && shift_suspended){
292 register_code(KC_LSFT);
293 shift_suspended = false;
299 if (record->event.pressed) {
300 shift_suspended = true;
301 unregister_code(KC_LSFT);
302 register_code(KC_EQUAL);
304 unregister_code(KC_EQUAL);
305 if (shift_held && shift_suspended){
306 register_code(KC_LSFT);
307 shift_suspended = false;
313 //mouse buttons, for 1-3, to update the mouse report:
315 currentReport = pointing_device_get_report();
316 if (record->event.pressed) {
317 if (shift_held && shift_suspended){
318 register_code(KC_LSFT);
319 shift_suspended = false;
321 //update mouse report here
322 currentReport.buttons |= MOUSE_BTN1; //MOUSE_BTN1 is a const defined in report.h
324 //update mouse report here
325 currentReport.buttons &= ~MOUSE_BTN1;
327 pointing_device_set_report(currentReport);
331 currentReport = pointing_device_get_report();
332 if (record->event.pressed) {
333 if (shift_held && shift_suspended){
334 register_code(KC_LSFT);
335 shift_suspended = false;
337 //update mouse report here
338 currentReport.buttons |= MOUSE_BTN2; //MOUSE_BTN2 is a const defined in report.h
340 //update mouse report here
341 currentReport.buttons &= ~MOUSE_BTN2;
343 pointing_device_set_report(currentReport);
347 currentReport = pointing_device_get_report();
348 if (record->event.pressed) {
349 if (shift_held && shift_suspended){
350 register_code(KC_LSFT);
351 shift_suspended = false;
353 //update mouse report here
354 currentReport.buttons |= MOUSE_BTN3; //MOUSE_BTN3 is a const defined in report.h
356 //update mouse report here
357 currentReport.buttons &= ~MOUSE_BTN3;
359 pointing_device_set_report(currentReport);
362 //Additionally, if NS_ keys are in use, then shift may be held (but is
363 //disabled for the unshifted keycodes to be send. Check the bool and
364 //register shift as necessary.
367 register_code(KC_LSFT);
377 //don't want to reset single key variables
380 //If any other key was pressed during the layer mod hold period,
381 //then the layer mod was used momentarily, and should block latching
382 shift_singular_key = false;
383 number_singular_key = false;
384 mouse_singular_key = false;
406 //Do nothing, don't want to trigger the timer key rollover
409 //Now we're checking to see if any of the special timer keys are pressed
410 //if so, we need to activate their short-press features
411 if (record->event.pressed) {
412 for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
413 if ((!special_key_states[i]) && special_key_pressed[i]){
414 switch (i + SAFE_RANGE){
416 SEND_STRING(SS_TAP(X_1));
419 SEND_STRING(SS_TAP(X_BSLASH));
422 SEND_STRING(SS_TAP(X_QUOTE));
425 SEND_STRING(SS_TAP(X_TAB));
428 special_key_pressed[i] = 0;
432 //do nothing, we don't want to trigger short presses on key releases.
439 void matrix_scan_user(void) {
440 //uint8_t layer = biton32(layer_state);
441 for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
442 if ((timer_elapsed(special_timers[i]) >= CUSTOM_LONGPRESS) && (!special_key_states[i]) && special_key_pressed[i]){
443 switch (i + SAFE_RANGE){
445 register_code(KC_GRAVE);
448 register_code(KC_ENTER);
451 register_code(KC_ENTER);
454 register_code(KC_ESCAPE);
457 special_key_pressed[i] = 0;
458 special_key_states[i] = 1;
461 if (shiftLED || capsLED){
463 if (red_timer < RED_BRIGHTNESS){
475 if (green_timer < GREEN_BRIGHTNESS){
487 if (blue_timer < BLUE_BRIGHTNESS){