qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

keymap.c (15842B)


      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 QMK_KEYBOARD_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   CK_MSE1,
     32   CK_MSE2,
     33   CK_MSE3
     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 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                     CK_MSE3, KC_LBRC, KC_LPRN, KC_SPC,         KC_SPC,  KC_RPRN, KC_RBRC, CK_MSE3
     50 ),
     51 
     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, _______, _______
     58 ),
     59 
     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                     _______, _______, _______, _______,        _______, _______, _______, _______
     66 ),
     67 
     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 					_______, _______, _______, _______,        _______, _______, _______, _______
     74 ),
     75 
     76 [_MS] = LAYOUT( /* Mouse layer, including buttons for clicking. */
     77   _______, _______, _______, _______, _______, _______,        KC_VOLU, KC_HOME, KC_PGUP, _______, _______, _______,
     78   _______, _______, _______, _______, _______, _______,        _______, CK_MSE1, CK_MSE2, _______, _______, _______,
     79   _______, _______, _______, _______, _______, _______,        KC_VOLD, KC_END,  KC_PGDN, _______, _______, _______,
     80   							 _______, _______, _______,        _______, KC_UP,   _______,
     81 					_______, _______, _______, _______,        KC_LEFT, KC_DOWN, KC_RGHT, _______
     82 )
     83 
     84 };
     85 
     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};
     89 
     90 static uint16_t shift_timer;
     91 static uint16_t num_timer;
     92 static uint16_t mouse_timer;
     93 
     94 static uint8_t red_timer;
     95 static uint8_t green_timer;
     96 static uint8_t blue_timer;
     97 
     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;
    105 
    106 static bool shift_held = false;
    107 static bool shift_suspended = false;
    108 report_mouse_t currentReport = {};
    109 
    110 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    111 	//uint8_t layer;
    112 	//layer = get_highest_layer(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.
    114 
    115 	 //custom layer handling for tri_layer,
    116 	switch (keycode) {
    117 		case NUMKEY:
    118 			if (record->event.pressed) {
    119 				num_timer = timer_read();
    120 				number_singular_key = true;
    121 				layer_invert(_NM);
    122 				numLED = !numLED;
    123 			} else {
    124 				if (timer_elapsed(num_timer) < CUSTOM_TOGGLE_TIME && number_singular_key) {
    125 					//do nothing, the layer has already been inverted
    126 				} else {
    127 					layer_invert(_NM);
    128 					numLED = !numLED;
    129 				}
    130 			}
    131 			update_tri_layer(_NM, _SF, _NS);
    132 			returnVal = false;
    133 		break;
    134 		//SHIFT is handled as LSHIFT in the general case - 'toggle' shoudl activate caps, while the layer is only active when shift is held.
    135 		case SFTKEY:
    136 			if (record->event.pressed) {
    137 				shift_held = true;
    138 				shiftLED = true;
    139 				shift_suspended = false;
    140 				shift_timer = timer_read();
    141 				shift_singular_key = true;
    142 				layer_on(_SF);
    143 				register_code(KC_LSFT);
    144 			} else {
    145 				shift_held = false;
    146 				shiftLED = false;
    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_CAPS_LOCK));
    150 					capsLED = !capsLED;
    151 				}
    152 				layer_off(_SF);
    153 				unregister_code(KC_LSFT);
    154 			}
    155 			update_tri_layer(_NM, _SF, _NS);
    156 			returnVal = false;
    157 		break;
    158 		//MOUSE layer needs to be handled the same way as NUMKEY, but differently from shift
    159 		case MOUKEY:
    160 			if (record->event.pressed) {
    161 				mouse_timer = timer_read();
    162 				mouse_singular_key = true;
    163 				layer_invert(_MS);
    164 				mouseLED = !mouseLED;
    165 			} else {
    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)
    168 				} else {
    169 					layer_invert(_MS);
    170 					mouseLED = !mouseLED;
    171 				}
    172 			}
    173 			returnVal = false;
    174 		break;
    175 		//Custom macros for strange keys with different long-tap behavior
    176 		case CK_1G:
    177 			if (shift_held && shift_suspended){
    178 				register_code(KC_LSFT);
    179 				shift_suspended = false;
    180 			}
    181 			if (record->event.pressed) {
    182 				special_timers[CK_1G-SAFE_RANGE] = timer_read();
    183 				special_key_pressed[CK_1G-SAFE_RANGE] = 1;
    184 			} else {
    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);
    189 				} else {
    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;
    194 					} else {
    195 						//the short key was already sent, because another key was pressed.
    196 						//Do nothing.
    197 					}
    198 
    199 				}
    200 			}
    201 			returnVal = false;
    202 		break;
    203 		case CK_BSPE:
    204 			if (shift_held && shift_suspended){
    205 				register_code(KC_LSFT);
    206 				shift_suspended = false;
    207 			}
    208 			if (record->event.pressed) {
    209 				special_timers[CK_BSPE-SAFE_RANGE] = timer_read();
    210 				special_key_pressed[CK_BSPE-SAFE_RANGE] = 1;
    211 			} else {
    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);
    216 				} else {
    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_BACKSLASH));
    220 						special_key_pressed[CK_BSPE-SAFE_RANGE] = 0;
    221 					} else {
    222 						//the short key was already sent, because another key was pressed.
    223 						//Do nothing.
    224 					}
    225 				}
    226 			}
    227 			returnVal = false;
    228 		break;
    229 		case CK_QE:
    230 			if (shift_held && shift_suspended){
    231 				register_code(KC_LSFT);
    232 				shift_suspended = false;
    233 			}
    234 			if (record->event.pressed) {
    235 				special_timers[CK_QE-SAFE_RANGE] = timer_read();
    236 				special_key_pressed[CK_QE-SAFE_RANGE] = 1;
    237 			} else {
    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);
    242 				} else {
    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;
    247 					} else {
    248 						//the short key was already sent, because another key was pressed.
    249 						//Do nothing.
    250 					}
    251 				}
    252 			}
    253 			returnVal = false;
    254 		break;
    255 		case CK_TE:
    256 			if (shift_held && shift_suspended){
    257 				register_code(KC_LSFT);
    258 				shift_suspended = false;
    259 			}
    260 			if (record->event.pressed) {
    261 				special_timers[CK_TE-SAFE_RANGE] = timer_read();
    262 				special_key_pressed[CK_TE-SAFE_RANGE] = 1;
    263 			} else {
    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);
    268 				} else {
    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;
    273 					} else {
    274 						//the short key was already sent, because another key was pressed.
    275 						//Do nothing.
    276 					}
    277 				}
    278 			}
    279 			returnVal = false;
    280 		break;
    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.
    284 		case NS_HYPH:
    285 			if (record->event.pressed) {
    286 				shift_suspended = true;
    287 				unregister_code(KC_LSFT);
    288 				register_code(KC_MINS);
    289 			} else {
    290 				unregister_code(KC_MINS);
    291 				if (shift_held && shift_suspended){
    292 					register_code(KC_LSFT);
    293 					shift_suspended = false;
    294 				}
    295 			}
    296 			returnVal = false;
    297 		break;
    298 		case NS_EQU:
    299 			if (record->event.pressed) {
    300 				shift_suspended = true;
    301 				unregister_code(KC_LSFT);
    302 				register_code(KC_EQUAL);
    303 			} else {
    304 				unregister_code(KC_EQUAL);
    305 				if (shift_held && shift_suspended){
    306 					register_code(KC_LSFT);
    307 					shift_suspended = false;
    308 				}
    309 			}
    310 			returnVal = false;
    311 		break;
    312 
    313 		//mouse buttons, for 1-3, to update the mouse report:
    314 		case CK_MSE1:
    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;
    320 				}
    321 				//update mouse report here
    322 				currentReport.buttons |= MOUSE_BTN1; //MOUSE_BTN1 is a const defined in report.h
    323 			} else {
    324 				//update mouse report here
    325 				currentReport.buttons &= ~MOUSE_BTN1;
    326 			}
    327 			pointing_device_set_report(currentReport);
    328 			returnVal = false;
    329 		break;
    330 		case CK_MSE2:
    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;
    336 				}
    337 				//update mouse report here
    338 				currentReport.buttons |= MOUSE_BTN2; //MOUSE_BTN2 is a const defined in report.h
    339 			} else {
    340 				//update mouse report here
    341 				currentReport.buttons &= ~MOUSE_BTN2;
    342 			}
    343 			pointing_device_set_report(currentReport);
    344 			returnVal = false;
    345 		break;
    346 		case CK_MSE3:
    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;
    352 				}
    353 				//update mouse report here
    354 				currentReport.buttons |= MOUSE_BTN3; //MOUSE_BTN3 is a const defined in report.h
    355 			} else {
    356 				//update mouse report here
    357 				currentReport.buttons &= ~MOUSE_BTN3;
    358 			}
    359 			pointing_device_set_report(currentReport);
    360 			returnVal = false;
    361 		break;
    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.
    365 		default:
    366 			if (shift_held){
    367 				register_code(KC_LSFT);
    368 			}
    369 		break;
    370 	}
    371 	switch (keycode){
    372 		case KC_BSPC:
    373 		case KC_NO:
    374 		case NUMKEY:
    375 		case SFTKEY:
    376 		case MOUKEY:
    377 			//don't want to reset single key variables
    378 		break;
    379 		default:
    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;
    385 		break;
    386 	}
    387 	switch (keycode){
    388 		case KC_BSPC:
    389 		case KC_NO:
    390 		case NUMKEY:
    391 		case SFTKEY:
    392 		case MOUKEY:
    393 		case MOUSE_BTN1:
    394 		case MOUSE_BTN2:
    395 		case MOUSE_BTN3:
    396 		case KC_LCTL:
    397 		case KC_LALT:
    398 		case KC_LGUI:
    399 		case KC_RCTL:
    400 		case KC_RALT:
    401 		case KC_RGUI:
    402 		case CK_1G:
    403 		case CK_BSPE:
    404 		case CK_QE:
    405 		case CK_TE:
    406 			//Do nothing, don't want to trigger the timer key rollover
    407 		break;
    408 		default:
    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){
    415 							case CK_1G:
    416 								SEND_STRING(SS_TAP(X_1));
    417 							break;
    418 							case CK_BSPE:
    419 								SEND_STRING(SS_TAP(X_BACKSLASH));
    420 							break;
    421 							case CK_QE:
    422 								SEND_STRING(SS_TAP(X_QUOTE));
    423 							break;
    424 							case CK_TE:
    425 								SEND_STRING(SS_TAP(X_TAB));
    426 							break;
    427 						}
    428 						special_key_pressed[i] = 0;
    429 					}
    430 				}
    431 			} else {
    432 				//do nothing, we don't want to trigger short presses on key releases.
    433 			}
    434 		break;
    435 	}
    436 	return returnVal;
    437 };
    438 
    439 void matrix_scan_user(void) {
    440 	//uint8_t layer = get_highest_layer(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){
    444 				case CK_1G:
    445 					register_code(KC_GRAVE);
    446 				break;
    447 				case CK_BSPE:
    448 					register_code(KC_ENTER);
    449 				break;
    450 				case CK_QE:
    451 					register_code(KC_ENTER);
    452 				break;
    453 				case CK_TE:
    454 					register_code(KC_ESCAPE);
    455 				break;
    456 			}
    457 			special_key_pressed[i] = 0;
    458 			special_key_states[i] = 1;
    459 		}
    460 	}
    461     if (shiftLED || capsLED){
    462 		red_timer++;
    463 		if (red_timer < RED_BRIGHTNESS){
    464 			red_led_on();
    465 		} else {
    466 			red_timer = 0;
    467 			red_led_off();
    468 		}
    469     } else {
    470 		red_timer = 0;
    471 		red_led_off();
    472     }
    473     if (numLED){
    474 		green_timer++;
    475 		if (green_timer < GREEN_BRIGHTNESS){
    476 			grn_led_on();
    477 		} else {
    478 			green_timer = 0;
    479 			grn_led_off();
    480 		}
    481     } else {
    482 		green_timer = 0;
    483 		grn_led_off();
    484     }
    485     if (mouseLED){
    486 		blue_timer++;
    487 		if (blue_timer < BLUE_BRIGHTNESS){
    488 			blu_led_on();
    489 		} else {
    490 			blue_timer = 0;
    491 			blu_led_off();
    492 		}
    493     } else {
    494 		blue_timer = 0;
    495 		blu_led_off();
    496     }
    497 };