]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/dichotomy/keymaps/default/keymap.c
Keyboard: Fixing spelling, updating code, finalizing keymap for Dichotomy (#4539)
[qmk_firmware.git] / keyboards / dichotomy / keymaps / default / keymap.c
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,
3
4 #include "dichotomy.h"
5
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 {
11         _BS,
12         _SF,
13         _NM,
14         _NS,
15         _MS
16 };
17
18 #define LONGPRESS_COUNT 4
19
20 enum dichotomy_keycodes
21 {
22   CK_1G = SAFE_RANGE,
23   CK_BSPE,
24   CK_QE,
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.
26   NS_HYPH,
27   NS_EQU,
28   NUMKEY,
29   SFTKEY,
30   MOUKEY,
31   MS_BTN1,
32   MS_BTN2,
33   MS_BTN3
34 };
35
36 #define CUSTOM_LONGPRESS 150
37 #define CUSTOM_TOGGLE_TIME 300
38
39 #define RED_BRIGHTNESS 3
40 #define GREEN_BRIGHTNESS 2
41 #define BLUE_BRIGHTNESS 2
42
43 // Fillers to make layering more clear
44 #define _______ KC_TRNS
45 #define XXXXXXX KC_NO
46
47 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
48 [_BS] = LAYOUT( /* Base layout, nearly qwerty but with modifications because it's not a full keyboard. Obviously. */
49   CK_TE,   KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,           KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_BSPC,
50   NUMKEY,  KC_A,    KC_S,    KC_D,    KC_F,    KC_G,           KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, CK_QE,
51   SFTKEY,  KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,           KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, MOUKEY,
52                              KC_LCTL, KC_LALT, KC_LGUI,        KC_RGUI, KC_RALT, KC_RCTL,
53                     MS_BTN3, KC_LBRC, KC_LPRN, KC_SPC,         KC_SPC,  KC_RPRN, KC_RBRC, MS_BTN3
54 ),
55
56 [_SF] = LAYOUT( /* Shifted layout, small changes (because angle brackets have been moved to thumb cluster buttons) */
57   _______, _______, _______, _______, _______, _______,        _______, _______, _______, _______, _______, _______,
58   _______, _______, _______, _______, _______, _______,        _______, _______, _______, _______, _______, _______,
59   _______, _______, _______, _______, _______, _______,        _______, _______, NS_HYPH, KC_UNDS, _______, _______,
60                              _______, _______, _______,        _______, _______, _______,
61                     _______, _______, KC_LABK, _______,        _______, KC_RABK, _______, _______
62 ),
63
64 [_NM] = LAYOUT( /* Number layout, basically the main function layer */
65   _______, KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,          KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  _______,
66   _______, CK_1G,   KC_2,    KC_3,    KC_4,    KC_5,           KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    CK_BSPE,
67   _______, KC_F11,  KC_F12,  KC_F13,  KC_F14,  KC_F15,         KC_F16,  KC_F17,  KC_F18,  KC_F19,  KC_F20,  _______,
68                              _______, _______, _______,        _______, _______, _______,
69                     _______, _______, _______, _______,        _______, _______, _______, _______
70 ),
71
72 [_NS] = LAYOUT( /* Shifted number/function layout, for per-key control.  Only active when shift is held, and number is toggled or held */
73   _______, _______, _______, _______, _______, _______,        _______, _______, _______, _______, _______, _______,
74   _______, _______, _______, _______, _______, _______,        _______, _______, _______, KC_PLUS, NS_EQU,  _______,
75   _______, _______, _______, _______, _______, _______,        _______, _______, _______, _______, _______, _______,
76                                                          _______, _______, _______,        _______, _______, _______,
77                                         _______, _______, _______, _______,        _______, _______, _______, _______
78 ),
79
80 [_MS] = LAYOUT( /* Mouse layer, including buttons for clicking. */
81   _______, _______, _______, _______, _______, _______,        KC_VOLU, KC_HOME, KC_PGUP, _______, _______, _______,
82   _______, _______, _______, _______, _______, _______,        _______, MS_BTN1, MS_BTN2, _______, _______, _______,
83   _______, _______, _______, _______, _______, _______,        KC_VOLD, KC_END,  KC_PGDN, _______, _______, _______,
84                                                          _______, _______, _______,        _______, KC_UP,   _______,
85                                         _______, _______, _______, _______,        KC_LEFT, KC_DOWN, KC_RGHT, _______
86 )
87
88 };
89
90
91 const uint16_t PROGMEM fn_actions[] = {
92
93 };
94
95 static uint16_t special_timers[LONGPRESS_COUNT] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF};
96 static bool special_key_states[LONGPRESS_COUNT] = {0,0,0,0};
97 static bool special_key_pressed[LONGPRESS_COUNT] = {0,0,0,0};
98
99 static uint16_t shift_timer;
100 static uint16_t num_timer;
101 static uint16_t mouse_timer;
102
103 static uint8_t red_timer;
104 static uint8_t green_timer;
105 static uint8_t blue_timer;
106
107 static bool shift_singular_key = false;
108 static bool number_singular_key = false;
109 static bool mouse_singular_key = false;
110 static bool capsLED = false;
111 static bool shiftLED = false;
112 static bool numLED = false;
113 static bool mouseLED = false;
114
115 static bool shift_held = false;
116 static bool shift_suspended = false;
117 report_mouse_t currentReport = {};
118
119 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
120         //uint8_t layer;
121         //layer = biton32(layer_state);  // get the current layer  //Or don't, I didn't use it.
122         bool returnVal = true; //this is to determine if more key processing is needed.
123
124          //custom layer handling for tri_layer,
125         switch (keycode) {
126                 case NUMKEY:
127                         if (record->event.pressed) {
128                                 num_timer = timer_read();
129                                 number_singular_key = true;
130                                 layer_invert(_NM);
131                                 numLED = !numLED;
132                         } else {
133                                 if (timer_elapsed(num_timer) < CUSTOM_TOGGLE_TIME && number_singular_key) {
134                                         //do nothing, the layer has already been inverted
135                                 } else {
136                                         layer_invert(_NM);
137                                         numLED = !numLED;
138                                 }
139                         }
140                         update_tri_layer(_NM, _SF, _NS);
141                         returnVal = false;
142                 break;
143                 //SHIFT is handled as LSHIFT in the general case - 'toggle' shoudl activate caps, while the layer is only active when shift is held.
144                 case SFTKEY:
145                         if (record->event.pressed) {
146                                 shift_held = true;
147                                 shiftLED = true;
148                                 shift_suspended = false;
149                                 shift_timer = timer_read();
150                                 shift_singular_key = true;
151                                 layer_on(_SF);
152                                 register_code(KC_LSFT);
153                         } else {
154                                 shift_held = false;
155                                 shiftLED = false;
156                                 if (timer_elapsed(shift_timer) < CUSTOM_TOGGLE_TIME && shift_singular_key) {
157                                         //this was basically a toggle, so activate/deactivate caps lock.
158                                         SEND_STRING(SS_TAP(X_CAPSLOCK));
159                                         capsLED = !capsLED;
160                                 }
161                                 layer_off(_SF);
162                                 unregister_code(KC_LSFT);
163                         }
164                         update_tri_layer(_NM, _SF, _NS);
165                         returnVal = false;
166                 break;
167                 //MOUSE layer needs to be handled the same way as NUMKEY, but differently from shift
168                 case MOUKEY:
169                         if (record->event.pressed) {
170                                 mouse_timer = timer_read();
171                                 mouse_singular_key = true;
172                                 layer_invert(_MS);
173                                 mouseLED = !mouseLED;
174                         } else {
175                                 if (timer_elapsed(mouse_timer) < CUSTOM_TOGGLE_TIME && mouse_singular_key){
176                                         //do nothing, it was a toggle (and it's already been toggled)
177                                 } else {
178                                         layer_invert(_MS);
179                                         mouseLED = !mouseLED;
180                                 }
181                         }
182                         returnVal = false;
183                 break;
184                 //Custom macros for strange keys with different long-tap behavior
185                 case CK_1G:
186                         if (shift_held && shift_suspended){
187                                 register_code(KC_LSFT);
188                                 shift_suspended = false;
189                         }
190                         if (record->event.pressed) {
191                                 special_timers[CK_1G-SAFE_RANGE] = timer_read();
192                                 special_key_pressed[CK_1G-SAFE_RANGE] = 1;
193                         } else {
194                                 if (special_key_states[CK_1G-SAFE_RANGE]){
195                                         //key was activated after custom_longpress, need to close those keycodes
196                                         special_key_states[CK_1G-SAFE_RANGE] = 0;
197                                         unregister_code(KC_GRAVE);
198                                 } else {
199                                         if (special_key_pressed[CK_1G-SAFE_RANGE]){
200                                                 //key was not activated, return macro activating proper, pre-long-tap key
201                                                 SEND_STRING(SS_TAP(X_1));
202                                                 special_key_pressed[CK_1G-SAFE_RANGE] = 0;
203                                         } else {
204                                                 //the short key was already sent, because another key was pressed.
205                                                 //Do nothing.
206                                         }
207
208                                 }
209                         }
210                         returnVal = false;
211                 break;
212                 case CK_BSPE:
213                         if (shift_held && shift_suspended){
214                                 register_code(KC_LSFT);
215                                 shift_suspended = false;
216                         }
217                         if (record->event.pressed) {
218                                 special_timers[CK_BSPE-SAFE_RANGE] = timer_read();
219                                 special_key_pressed[CK_BSPE-SAFE_RANGE] = 1;
220                         } else {
221                                 if (special_key_states[CK_BSPE-SAFE_RANGE]){
222                                         //key was activated after custom_longpress, need to close those keycodes
223                                         special_key_states[CK_BSPE-SAFE_RANGE] = 0;
224                                         unregister_code(KC_ENTER);
225                                 } else {
226                                         if (special_key_pressed[CK_BSPE-SAFE_RANGE]){
227                                                 //key was not activated, return macro activating proper, pre-long-tap key
228                                                 SEND_STRING(SS_TAP(X_BSLASH));
229                                                 special_key_pressed[CK_BSPE-SAFE_RANGE] = 0;
230                                         } else {
231                                                 //the short key was already sent, because another key was pressed.
232                                                 //Do nothing.
233                                         }
234                                 }
235                         }
236                         returnVal = false;
237                 break;
238                 case CK_QE:
239                         if (shift_held && shift_suspended){
240                                 register_code(KC_LSFT);
241                                 shift_suspended = false;
242                         }
243                         if (record->event.pressed) {
244                                 special_timers[CK_QE-SAFE_RANGE] = timer_read();
245                                 special_key_pressed[CK_QE-SAFE_RANGE] = 1;
246                         } else {
247                                 if (special_key_states[CK_QE-SAFE_RANGE]){
248                                         //key was activated after custom_longpress, need to close those keycodes
249                                         special_key_states[CK_QE-SAFE_RANGE] = 0;
250                                         unregister_code(KC_ENTER);
251                                 } else {
252                                         if (special_key_pressed[CK_QE-SAFE_RANGE]){
253                                                 //the long-press key was not activated, return macro activating proper, pre-long-tap key
254                                                 SEND_STRING(SS_TAP(X_QUOTE));
255                                                 special_key_pressed[CK_QE-SAFE_RANGE] = 0;
256                                         } else {
257                                                 //the short key was already sent, because another key was pressed.
258                                                 //Do nothing.
259                                         }
260                                 }
261                         }
262                         returnVal = false;
263                 break;
264                 case CK_TE:
265                         if (shift_held && shift_suspended){
266                                 register_code(KC_LSFT);
267                                 shift_suspended = false;
268                         }
269                         if (record->event.pressed) {
270                                 special_timers[CK_TE-SAFE_RANGE] = timer_read();
271                                 special_key_pressed[CK_TE-SAFE_RANGE] = 1;
272                         } else {
273                                 if (special_key_states[CK_TE-SAFE_RANGE]){
274                                         //key was activated after custom_longpress, need to close those keycodes
275                                         special_key_states[CK_TE-SAFE_RANGE] = 0;
276                                         unregister_code(KC_ESCAPE);
277                                 } else {
278                                         if (special_key_pressed[CK_TE-SAFE_RANGE]){
279                                                 //the long-press key was not activated, return macro activating proper, pre-long-tap key
280                                                 SEND_STRING(SS_TAP(X_TAB));
281                                                 special_key_pressed[CK_TE-SAFE_RANGE] = 0;
282                                         } else {
283                                                 //the short key was already sent, because another key was pressed.
284                                                 //Do nothing.
285                                         }
286                                 }
287                         }
288                         returnVal = false;
289                 break;
290                 //No-shift keys, they unregister the KC_LSFT code so they can send
291                 //unshifted values - but they don't change the bool. if any other
292                 //key is pressed and the bool is set, KC_LSFT is registered again.
293                 case NS_HYPH:
294                         if (record->event.pressed) {
295                                 shift_suspended = true;
296                                 unregister_code(KC_LSFT);
297                                 register_code(KC_MINS);
298                         } else {
299                                 unregister_code(KC_MINS);
300                                 if (shift_held && shift_suspended){
301                                         register_code(KC_LSFT);
302                                         shift_suspended = false;
303                                 }
304                         }
305                         returnVal = false;
306                 break;
307                 case NS_EQU:
308                         if (record->event.pressed) {
309                                 shift_suspended = true;
310                                 unregister_code(KC_LSFT);
311                                 register_code(KC_EQUAL);
312                         } else {
313                                 unregister_code(KC_EQUAL);
314                                 if (shift_held && shift_suspended){
315                                         register_code(KC_LSFT);
316                                         shift_suspended = false;
317                                 }
318                         }
319                         returnVal = false;
320                 break;
321
322                 //mouse buttons, for 1-3, to update the mouse report:
323                 case MS_BTN1:
324                         currentReport = pointing_device_get_report();
325                         if (record->event.pressed) {
326                                 if (shift_held && shift_suspended){
327                                         register_code(KC_LSFT);
328                                         shift_suspended = false;
329                                 }
330                                 //update mouse report here
331                                 currentReport.buttons |= MOUSE_BTN1; //MOUSE_BTN1 is a const defined in report.h
332                         } else {
333                                 //update mouse report here
334                                 currentReport.buttons &= ~MOUSE_BTN1;
335                         }
336                         pointing_device_set_report(currentReport);
337                         returnVal = false;
338                 break;
339                 case MS_BTN2:
340                         currentReport = pointing_device_get_report();
341                         if (record->event.pressed) {
342                                 if (shift_held && shift_suspended){
343                                         register_code(KC_LSFT);
344                                         shift_suspended = false;
345                                 }
346                                 //update mouse report here
347                                 currentReport.buttons |= MOUSE_BTN2; //MOUSE_BTN2 is a const defined in report.h
348                         } else {
349                                 //update mouse report here
350                                 currentReport.buttons &= ~MOUSE_BTN2;
351                         }
352                         pointing_device_set_report(currentReport);
353                         returnVal = false;
354                 break;
355                 case MS_BTN3:
356                         currentReport = pointing_device_get_report();
357                         if (record->event.pressed) {
358                                 if (shift_held && shift_suspended){
359                                         register_code(KC_LSFT);
360                                         shift_suspended = false;
361                                 }
362                                 //update mouse report here
363                                 currentReport.buttons |= MOUSE_BTN3; //MOUSE_BTN3 is a const defined in report.h
364                         } else {
365                                 //update mouse report here
366                                 currentReport.buttons &= ~MOUSE_BTN3;
367                         }
368                         pointing_device_set_report(currentReport);
369                         returnVal = false;
370                 break;
371                 //Additionally, if NS_ keys are in use, then shift may be held (but is
372                 //disabled for the unshifted keycodes to be send.  Check the bool and
373                 //register shift as necessary.
374                 default:
375                         if (shift_held){
376                                 register_code(KC_LSFT);
377                         }
378                 break;
379         }
380         switch (keycode){
381                 case KC_BSPC:
382                 case KC_NO:
383                 case NUMKEY:
384                 case SFTKEY:
385                 case MOUKEY:
386                         //don't want to reset single key variables
387                 break;
388                 default:
389                         //If any other key was pressed during the layer mod hold period,
390                         //then the layer mod was used momentarily, and should block latching
391                         shift_singular_key = false;
392                         number_singular_key = false;
393                         mouse_singular_key = false;
394                 break;
395         }
396         switch (keycode){
397                 case KC_BSPC:
398                 case KC_NO:
399                 case NUMKEY:
400                 case SFTKEY:
401                 case MOUKEY:
402                 case MOUSE_BTN1:
403                 case MOUSE_BTN2:
404                 case MOUSE_BTN3:
405                 case KC_LCTL:
406                 case KC_LALT:
407                 case KC_LGUI:
408                 case KC_RCTL:
409                 case KC_RALT:
410                 case KC_RGUI:
411                 case CK_1G:
412                 case CK_BSPE:
413                 case CK_QE:
414                 case CK_TE:
415                         //Do nothing, don't want to trigger the timer key rollover
416                 break;
417                 default:
418                         //Now we're checking to see if any of the special timer keys are pressed
419                         //if so, we need to activate their short-press features
420                         if (record->event.pressed) {
421                                 for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
422                                         if ((!special_key_states[i]) && special_key_pressed[i]){
423                                                 switch (i + SAFE_RANGE){
424                                                         case CK_1G:
425                                                                 SEND_STRING(SS_TAP(X_1));
426                                                         break;
427                                                         case CK_BSPE:
428                                                                 SEND_STRING(SS_TAP(X_BSLASH));
429                                                         break;
430                                                         case CK_QE:
431                                                                 SEND_STRING(SS_TAP(X_QUOTE));
432                                                         break;
433                                                         case CK_TE:
434                                                                 SEND_STRING(SS_TAP(X_TAB));
435                                                         break;
436                                                 }
437                                                 special_key_pressed[i] = 0;
438                                         }
439                                 }
440                         } else {
441                                 //do nothing, we don't want to trigger short presses on key releases.
442                         }
443                 break;
444         }
445         return returnVal;
446 };
447
448 void matrix_scan_user(void) {
449         //uint8_t layer = biton32(layer_state);
450         for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
451                 if ((timer_elapsed(special_timers[i]) >= CUSTOM_LONGPRESS) && (!special_key_states[i]) && special_key_pressed[i]){
452                         switch (i + SAFE_RANGE){
453                                 case CK_1G:
454                                         register_code(KC_GRAVE);
455                                 break;
456                                 case CK_BSPE:
457                                         register_code(KC_ENTER);
458                                 break;
459                                 case CK_QE:
460                                         register_code(KC_ENTER);
461                                 break;
462                                 case CK_TE:
463                                         register_code(KC_ESCAPE);
464                                 break;
465                         }
466                         special_key_pressed[i] = 0;
467                         special_key_states[i] = 1;
468                 }
469         }
470     if (shiftLED || capsLED){
471                 red_timer++;
472                 if (red_timer < RED_BRIGHTNESS){
473                         red_led_on();
474                 } else {
475                         red_timer = 0;
476                         red_led_off();
477                 }
478     } else {
479                 red_timer = 0;
480                 red_led_off();
481     }
482     if (numLED){
483                 green_timer++;
484                 if (green_timer < GREEN_BRIGHTNESS){
485                         grn_led_on();
486                 } else {
487                         green_timer = 0;
488                         grn_led_off();
489                 }
490     } else {
491                 green_timer = 0;
492                 grn_led_off();
493     }
494     if (mouseLED){
495                 blue_timer++;
496                 if (blue_timer < BLUE_BRIGHTNESS){
497                         blu_led_on();
498                 } else {
499                         blue_timer = 0;
500                         blu_led_off();
501                 }
502     } else {
503                 blue_timer = 0;
504                 blu_led_off();
505     }
506 };