diff --git a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/autocorrect.txt b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/autocorrect.txt new file mode 100644 index 000000000000..c6885bbcc4b9 --- /dev/null +++ b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/autocorrect.txt @@ -0,0 +1,472 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# This is a larger example typo dictionary containing 400 entries. It builds to +# a table of about 6000 bytes, so you'll need a keyboard with a generous +# amount of free firmware space to use the full dictionary. Alternatively, pick +# out a subset of entries to a separate file, then build a table from that. +# +# Dictionary syntax: +# Each line of this file defines one typo correction entry with the syntax +# "typo -> correction". Typos and corrections are case insensitive, and any +# whitespace before or after the typo and correction is ignored. The typo must be +# only the letters a-z, or the special character : representing a word break. +# +# For documentation about how to use this dictionary, see +# https://getreuer.info/posts/keyboards/autocorrection +# +# Further resources: +# * Wikipedia has a large list of common typos at +# https://en.wikipedia.org/wiki/Wikipedia:Lists_of_common_misspellings/For_machines +# +# * EmacsWiki has another list of typos at +# https://www.emacswiki.org/emacs/autocorrection_abbrev_defs +# +# * You can find data on English word frequencies at +# https://www.wordfrequency.info/samples.asp + + +## 10 most common words. +# The words "there", "about", "their", "would", "people", "which", "could", +# "think", "other", and "because" are among the most common words in English +# that are 5 letters or longer. (We don't include entries for words shorter than +# that to avoid false triggering.) +:htere -> there +abbout -> about +abotu -> about +baout -> about +:theri -> their +:thier -> their +:owudl -> would +woudl -> would +peaple -> people +peolpe -> people +peopel -> people +poeple -> people +poeople -> people +:hwihc -> which +whcih -> which +whihc -> which +whlch -> which +wihch -> which +coudl -> could +:htikn -> think +:htink -> think +thikn -> think +thiunk -> think +tihkn -> think +:olther -> other +:otehr -> other +baceause -> because +beacuse -> because +becasue -> because +beccause -> because +becouse -> because +becuase -> because + +## Common words, 11-20. +theese -> these +:goign -> going +:gonig -> going +:yaers -> years +:yeasr -> years +:thsoe -> those +shoudl -> should +raelly -> really +realy -> really +relaly -> really +bedore -> before +befoer -> before +littel -> little +beeing -> being +:hwile -> while + +## Common words, 21-30. +aroud -> around +arround -> around +arund -> around +thign -> thing +thigsn -> things +thnigs -> things +anohter -> another +beteen -> between +beween -> between +bewteen -> between +:eveyr -> every +:graet -> great +:agian -> again +:sicne -> since +alwasy -> always +alwyas -> always +throught -> thought + + +## Words especially susceptible to skipping or transposing a letter. +# These entries are for words that are easy enough to spell, but not necessarily +# easy to press the keys in the right order. +# Catch misspellings of "achieves", "achieving", etc. +:acheiv -> achiev +almsot -> almost +alomst -> almost +chnage -> change +chekc -> check +childen -> children +claer -> clear +comapny -> company +contian -> contain +elasped -> elapsed +feild -> field +fitler -> filter +firts -> first +follwo -> follow +:foudn -> found +frequecy -> frequency +firend -> friend +freind -> friend +heigth -> height +iamge -> image +inital -> initial +intput -> input +laguage -> language +lenght -> length +levle -> level +libary -> library +:moeny -> money +mysefl -> myself +ouptut -> output +ouput -> output +probaly -> probably +probelm -> problem +recrod -> record +reponse -> response +reprot -> report +singel -> single +stregth -> strength +strengh -> strength +tkaes -> takes +therfore -> therefore +todya -> today +toghether -> together +unkown -> unknown +unqiue -> unique +widht -> width + + +## Words with tricky spelling. +# If you are a good speller, you could drop this section. +aberation -> aberration +accross -> across +adviced -> advised +aledge -> allege +alledge -> allege +amature -> amateur +anomolous -> anomalous +anomoly -> anomaly +aparent -> apparent +aparrent -> apparent +apparant -> apparent +apparrent -> apparent +asthetic -> aesthetic +auxilary -> auxiliary +auxillary -> auxiliary +auxilliary -> auxiliary +bankrupcy -> bankruptcy +busness -> business +bussiness -> business +calander -> calendar +commitee -> committee +comittee -> committee +competance -> competence +competant -> competent +concensus -> consensus +cognizent -> cognizant +copywrite: -> copyright +choosen -> chosen +collegue -> colleague +excercise -> exercise +:grammer -> grammar +:guage -> gauge +govement -> government +govenment -> government +goverment -> government +governmnet -> government +govorment -> government +govornment -> government +guaratee -> guarantee +garantee -> guarantee +gaurantee -> guarantee +heirarchy -> hierarchy +hygeine -> hygiene +hypocracy -> hypocrisy +hypocrasy -> hypocrisy +hypocricy -> hypocrisy +hypocrit: -> hypocrite +looses: -> loses +maintence -> maintenance +morgage -> mortgage +neccesary -> necessary +necesary -> necessary +pallete -> palette +paralel -> parallel +parralel -> parallel +parrallel -> parallel +priviledge -> privilege +probablly -> probably +prominant -> prominent +propogate -> propagate +proove -> prove +psuedo -> pseudo +reciept -> receipt +# Catch misspellings of "receives", "receiving", etc. +receiev -> receiv +reciev -> receiv +recepient -> recipient +recipiant -> recipient +relevent -> relevant +repitition -> repetition +safty -> safety +saftey -> safety +# Catch misspellings of "separate", "separating", etc. +seperat -> separat +spectogram -> spectrogram +symetric -> symmetric +tolerence -> tolerance + + +## Words particularly for coding. +# Entries for common code keywords ("const") and terminology ("lookup"). +cacheing -> caching +complier -> compiler +doulbe -> double +dyanmic -> dynamic +# As in "execute", "executable", "executing", ... +excecut -> execut +failse -> false +fales -> false +fasle -> false +flase -> false +indeces -> indices +indecies -> indices +indicies -> indices +interator -> iterator +looup -> lookup +namesapce -> namespace +namespcae -> namespace +nulltpr -> nullptr +operaotr -> operator +overide -> override +ovveride -> override +poitner -> pointer +:rference -> reference +referece -> reference +singed -> signed +stirng -> string +strign -> string +swithc -> switch +swtich -> switch +teamplate -> template +tempalte -> template +:ture -> true +retrun -> return +retun -> return +reutrn -> return +cosnt -> const +virutal -> virtual +vitual -> virtual +yeild -> yield + + +## Catch skipped spaces between common words. +:alot: -> a lot +:andteh -> and the +:andthe -> and the +:asthe -> as the +:atthe -> at the +abouta -> about a +aboutit -> about it +aboutthe -> about the +:tothe -> to the +didnot -> did not +fromthe -> from the + + +## Various additional entries. +:agred -> agreed +:ajust -> adjust +:anual -> annual +:asign -> assign +:aslo: -> also +:casue -> cause +:choses -> chooses +:gaurd -> guard +:haev -> have +:hapen -> happen +:idaes -> ideas +:jsut: -> just +:jstu: -> just +:knwo -> know +:konw -> know +:kwno -> know +:ocuntry -> country +:ocur -> occur +:socre -> score +:szie -> size +:the:the: -> the +:turth -> truth +:uesd: -> used +:usally -> usually +abilties -> abilities +abilty -> ability +abvove -> above +accesories -> accessories +accomodate -> accommodate +acommodate -> accommodate +acomplish -> accomplish +actualy -> actually +acurate -> accurate +acutally -> actually +addtion -> addition +againnst -> against +aganist -> against +aggreed -> agreed +agianst -> against +ahppn -> happen +allign -> align +anytying -> anything +aquire -> acquire +availabe -> available +availaible -> available +availalbe -> available +availble -> available +availiable -> available +avalable -> available +avaliable -> available +avilable -> available +bandwith -> bandwidth +begginer -> beginner +beleif -> belief +beleive -> believe +belive -> believe +breif -> brief +burried -> buried +caluclate -> calculate +caluculate -> calculate +calulate -> calculate +catagory -> category +cauhgt -> caught +ceratin -> certain +certian -> certain +cheif -> chief +cieling -> ceiling +circut -> circuit +clasic -> classic +cmoputer -> computer +coform -> conform +comming: -> coming +considerd -> considered +dervied -> derived +desicion -> decision +diferent -> different +diferrent -> different +differnt -> different +diffrent -> different +divison -> division +effecient -> efficient +eligable -> eligible +elpased -> elapsed +embarass -> embarrass +embeded -> embedded +encypt -> encrypt +finaly -> finally +foriegn -> foreign +foward -> forward +fraciton -> fraction +fucntion -> function +fufill -> fulfill +fullfill -> fulfill +futher -> further +ganerate -> generate +generaly -> generally +greatful -> grateful +heigher -> higher +higest -> highest +howver -> however +hydogen -> hydrogen +importamt -> important +inclued -> include +insted -> instead +intrest -> interest +invliad -> invalid +largst -> largest +learnign -> learning +liasion -> liaison +likly -> likely +lisense -> license +listner -> listener +macthing -> matching +manefist -> manifest +mesage -> message +naturual -> natural +occassion -> occasion +occured -> occurred +particualr -> particular +paticular -> particular +peice -> piece +perhasp -> perhaps +perheaps -> perhaps +perhpas -> perhaps +perphas -> perhaps +persue -> pursue +posess -> possess +postion -> position +preiod -> period +primarly -> primarily +privte -> private +proccess -> process +proeprty -> property +propery -> property +realtion -> relation +reasearch -> research +recuring -> recurring +refered -> referred +regluar -> regular +releated -> related +resutl -> result +reuslt -> result +reveiw -> review +satisifed -> satisfied +scheduel -> schedule +sequnce -> sequence +similiar -> similar +simmilar -> similar +slighly -> slightly +somehwat -> somewhat +statment -> statement +sucess -> success +succsess -> success +sugest -> suggest +sumary -> summary +supress -> suppress +surpress -> suppress +thresold -> threshold +tongiht -> tonight +tranpose -> transpose +typcial -> typical +udpate -> update +ususally -> usually +verticies -> vertices +whereever -> wherever +wherre -> where +wierd -> weird diff --git a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/config.h b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/config.h index 4a0effa6b71b..f0d4ded58630 100644 --- a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/config.h +++ b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/config.h @@ -1,10 +1,2 @@ -//optimisations -#define NO_MUSIC_MODE -#undef LOCKING_SUPPORT_ENABLE -#undef LOCKING_RESYNC_ENABLE -#define LAYER_STATE_8BIT - #define DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD -/*TODO -add snap tap and configire once implementation is ready -*/ + diff --git a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/sentence_case.c b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/sentence_case.c index 60dbb9f4f466..623c6b3655f2 100644 --- a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/sentence_case.c +++ b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/sentence_case.c @@ -1,4 +1,4 @@ -// Copyright 2022-2023 Google LLC +// Copyright 2022-2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -62,14 +62,14 @@ static uint8_t sentence_state = STATE_INIT; // Sets the current state to `new_state`. static void set_sentence_state(uint8_t new_state) { -#ifndef NO_DEBUG +#if !defined(NO_DEBUG) && defined(SENTENCE_CASE_DEBUG) if (debug_enable && sentence_state != new_state) { static const char* state_names[] = { "INIT", "WORD", "ABBREV", "ENDING", "PRIMED", "DISABLED", }; dprintf("Sentence case: %s\n", state_names[new_state]); } -#endif // NO_DEBUG +#endif // !NO_DEBUG && SENTENCE_CASE_DEBUG const bool primed = (new_state == STATE_PRIMED); if (primed != (sentence_state == STATE_PRIMED)) { @@ -144,6 +144,20 @@ bool process_sentence_case(uint16_t keycode, keyrecord_t* record) { #endif // SENTENCE_CASE_TIMEOUT > 0 switch (keycode) { + case KC_LCTL ... KC_RGUI: // Ignore mod keys. + case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: // Ignore one-shot mod. + // Ignore MO, TO, TG, TT, OSL, TL layer switch keys. + case QK_MOMENTARY ... QK_MOMENTARY_MAX: + case QK_TO ... QK_TO_MAX: + case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: + case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX: + case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: // Ignore one-shot layer. +#ifdef TRI_LAYER_ENABLE // Ignore Tri Layer keys. + case QK_TRI_LAYER_LOWER: + case QK_TRI_LAYER_UPPER: +#endif // TRI_LAYER_ENABLE + return true; + #ifndef NO_ACTION_TAPPING case QK_MOD_TAP ... QK_MOD_TAP_MAX: if (record->tap.count == 0) { @@ -153,12 +167,12 @@ bool process_sentence_case(uint16_t keycode, keyrecord_t* record) { break; #ifndef NO_ACTION_LAYER case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: -#endif // NO_ACTION_LAYER if (record->tap.count == 0) { return true; } keycode = QK_LAYER_TAP_GET_TAP_KEYCODE(keycode); break; +#endif // NO_ACTION_LAYER #endif // NO_ACTION_TAPPING #ifdef SWAP_HANDS_ENABLE @@ -200,7 +214,9 @@ bool process_sentence_case(uint16_t keycode, keyrecord_t* record) { // ENDING | ABBREV INIT PRIMED ENDING // PRIMED | match! INIT PRIMED PRIMED char code = sentence_case_press_user(keycode, record, mods); +#if defined SENTENCE_CASE_DEBUG dprintf("Sentence Case: code = '%c' (%d)\n", code, (int)code); +#endif // SENTENCE_CASE_DEBUG switch (code) { case '\0': // Current key should be ignored. return true; @@ -269,7 +285,9 @@ bool process_sentence_case(uint16_t keycode, keyrecord_t* record) { #if SENTENCE_CASE_BUFFER_SIZE > 1 key_buffer[SENTENCE_CASE_BUFFER_SIZE - 1] = keycode; if (new_state == STATE_ENDING && !sentence_case_check_ending(key_buffer)) { +#if defined SENTENCE_CASE_DEBUG dprintf("Not a real ending.\n"); +#endif // SENTENCE_CASE_DEBUG new_state = STATE_INIT; } #endif // SENTENCE_CASE_BUFFER_SIZE > 1 @@ -311,9 +329,6 @@ __attribute__((weak)) char sentence_case_press_user(uint16_t keycode, if ((mods & ~(MOD_MASK_SHIFT | MOD_BIT(KC_RALT))) == 0) { const bool shifted = mods & MOD_MASK_SHIFT; switch (keycode) { - case KC_LCTL ... KC_RGUI: // Mod keys. - return '\0'; // These keys are ignored. - case KC_A ... KC_Z: return 'a'; // Letter key. @@ -322,8 +337,13 @@ __attribute__((weak)) char sentence_case_press_user(uint16_t keycode, case KC_1: case KC_SLSH: return shifted ? '.' : '#'; + case KC_EXLM: + case KC_QUES: + return '.'; case KC_2 ... KC_0: // 2 3 4 5 6 7 8 9 0 - case KC_MINS ... KC_SCLN: // - = [ ] ; backslash + case KC_AT ... KC_RPRN: // @ # $ % ^ & * ( ) + case KC_MINS ... KC_SCLN: // - = [ ] backslash ; + case KC_UNDS ... KC_COLN: // _ + { } | : case KC_GRV: case KC_COMM: return '#'; // Symbol key. diff --git a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/sentence_case.h b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/sentence_case.h index 5b1ebbcc0980..4694e94a9800 100644 --- a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/sentence_case.h +++ b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/sentence_case.h @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2022, 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -157,7 +157,7 @@ bool sentence_case_just_typed_P(const uint16_t* buffer, const uint16_t* pattern, * '.' Key is sentence-ending punctuation. Default: . ? ! * * '#' Key types a backspaceable character that isn't part of a word. - * Default: - = [ ] ; ' ` , < > / digits backslash + * Default includes - = [ ] ; ' , < > / _ + @ # $ % ^ & * ( ) { } digits * * ' ' Key is a space. Default: KC_SPC * @@ -177,9 +177,6 @@ bool sentence_case_just_typed_P(const uint16_t* buffer, const uint16_t* pattern, * if ((mods & ~(MOD_MASK_SHIFT | MOD_BIT(KC_RALT))) == 0) { * const bool shifted = mods & MOD_MASK_SHIFT; * switch (keycode) { - * case KC_LCTL ... KC_RGUI: // Mod keys. - * return '\0'; // These keys are ignored. - * * case KC_A ... KC_Z: * return 'a'; // Letter key. * @@ -188,8 +185,13 @@ bool sentence_case_just_typed_P(const uint16_t* buffer, const uint16_t* pattern, * case KC_1: * case KC_SLSH: * return shifted ? '.' : '#'; + * case KC_EXLM: + * case KC_QUES: + * return '.'; * case KC_2 ... KC_0: // 2 3 4 5 6 7 8 9 0 - * case KC_MINS ... KC_SCLN: // - = [ ] ; backslash + * case KC_AT ... KC_RPRN: // @ # $ % ^ & * ( ) + * case KC_MINS ... KC_SCLN: // - = [ ] backslash ; + * case KC_UNDS ... KC_COLN: // _ + { } | : * case KC_GRV: * case KC_COMM: * return '#'; // Symbol key. diff --git a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/socd_cleaner.c b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/socd_cleaner.c new file mode 100644 index 000000000000..546efb7f668b --- /dev/null +++ b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/socd_cleaner.c @@ -0,0 +1,82 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file socd_cleaner.c + * @brief SOCD Cleaner implementation + * + * For full documentation, see + * + */ + +#include "socd_cleaner.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool socd_cleaner_enabled = true; + +static void update_key(uint8_t keycode, bool press) { + if (press) { + add_key(keycode); + } else { + del_key(keycode); + } +} + +bool process_socd_cleaner(uint16_t keycode, keyrecord_t* record, + socd_cleaner_t* state) { + if (!socd_cleaner_enabled || !state->resolution || + (keycode != state->keys[0] && keycode != state->keys[1])) { + return true; // Quick return when disabled or on unrelated events. + } + // The current event corresponds to index `i`, 0 or 1, in the SOCD key pair. + const uint8_t i = (keycode == state->keys[1]); + const uint8_t opposing = i ^ 1; // Index of the opposing key. + + // Track which keys are physically held (vs. keys in the report). + state->held[i] = record->event.pressed; + + // Perform SOCD resolution for events where the opposing key is held. + if (state->held[opposing]) { + switch (state->resolution) { + case SOCD_CLEANER_LAST: // Last input priority with reactivation. + // If the current event is a press, then release the opposing key. + // Otherwise if this is a release, then press the opposing key. + update_key(state->keys[opposing], !state->held[i]); + break; + + case SOCD_CLEANER_NEUTRAL: // Neutral resolution. + // Same logic as SOCD_CLEANER_LAST, but skip default handling so that + // the current key has no effect while the opposing key is held. + update_key(state->keys[opposing], !state->held[i]); + // Send updated report (normally, default handling would do this). + send_keyboard_report(); + return false; // Skip default handling. + + case SOCD_CLEANER_0_WINS: // Key 0 wins. + case SOCD_CLEANER_1_WINS: // Key 1 wins. + if (opposing == (state->resolution - SOCD_CLEANER_0_WINS)) { + // The opposing key is the winner. The current key has no effect. + return false; // Skip default handling. + } else { + // The current key is the winner. Update logic is same as above. + update_key(state->keys[opposing], !state->held[i]); + } + break; + } + } + return true; // Continue default handling to press/release current key. +} diff --git a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/socd_cleaner.h b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/socd_cleaner.h new file mode 100644 index 000000000000..bb37d72a9ccc --- /dev/null +++ b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/features/socd_cleaner.h @@ -0,0 +1,141 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file socd_cleaner.h + * @brief SOCD Cleaner - enhance WASD for fast inputs for gaming + * + * Overview + * -------- + * + * SOCD Cleaner is a QMK library for Simultaneous Opposing Cardinal Directions + * (SOCD) filtering, which is popular for fast inputs on the WASD keys in + * gaming. When two keys of opposing direction are physically held at the same + * time, a rule is applied to decide which key is sent to the computer. + * + * + * Add it to your keymap + * --------------------- + * + * In rules.mk, add `SRC += features/socd_cleaner.c`. Then in keymap.c, add + * + * #include "features/socd_cleaner.h" + * + * socd_cleaner_t socd_v = {{KC_W, KC_S}, SOCD_CLEANER_LAST}; + * socd_cleaner_t socd_h = {{KC_A, KC_D}, SOCD_CLEANER_LAST}; + * + * bool process_record_user(uint16_t keycode, keyrecord_t* record) { + * if (!process_socd_cleaner(keycode, record, &socd_v)) { return false; } + * if (!process_socd_cleaner(keycode, record, &socd_h)) { return false; } + * // Your macros... + * return true; + * } + * + * Each `socd_cleaner_t` instance defines a pair of opposing keys and an SOCD + * resolution strategy (explained below). In `process_record_user()`, handler + * `process_socd_cleaner()` is called with each `socd_cleaner_t` instance. + * + * NOTE: The keys don't have to be WASD. But they must be basic keycodes + * (https://docs.qmk.fm/keycodes_basic). + * + * + * Enabling / disabling + * -------------------- + * + * SOCD filtering is enabled/disabled globally by assigning to variable + * `socd_cleaner_enabled`. For instance, to enable only on a GAME layer: + * + * layer_state_t layer_state_set_user(layer_state_t state) { + * socd_cleaner_enabled = IS_LAYER_ON_STATE(state, GAME); + * return state; + * } + * + * Or filtering can be disabled per `socd_cleaner_t` instance by setting its + * resolution to SOCD_CLEANER_OFF. + * + * + * Resolution strategies + * --------------------- + * + * As controls vary across games, there are multiple possible SOCD resolution + * strategies. SOCD Cleaner implements the following resolutions: + * + * - SOCD_CLEANER_LAST: (Recommended) Last input priority with reactivation. + * The last key pressed wins. Rapid alternating inputs can be made. + * Repeatedly tapping the D key while A is held sends "ADADADAD." + * + * - SOCD_CLEANER_NEUTRAL: Neutral resolution. When both keys are pressed, they + * cancel and neither is sent. + * + * - SOCD_CLEANER_0_WINS: Key 0 always wins, the first key listed in defining + * the `socd_cleaner_t`. For example, the W key always wins in + * + * socd_cleaner_t socd_ud = {{KC_W, KC_S}, SOCD_CLEANER_0_WINS}; + * + * - SOCD_CLEANER_1_WINS: Key 1 always wins, the second key listed. + * + * If you don't know what to pick, SOCD_CLEANER_LAST is recommended. The + * resolution strategy on a `socd_cleaner_t` may be changed at run time by + * assigning to `.resolution`. + * + * + * For full documentation, see + * + */ + +#pragma once + +#include "quantum.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum socd_cleaner_resolution { + // Disable SOCD filtering for this key pair. + SOCD_CLEANER_OFF, + // Last input priority with reactivation. + SOCD_CLEANER_LAST, + // Neutral resolution. When both keys are pressed, they cancel. + SOCD_CLEANER_NEUTRAL, + // Key 0 always wins. + SOCD_CLEANER_0_WINS, + // Key 1 always wins. + SOCD_CLEANER_1_WINS, + // Sentinel to count the number of resolution strategies. + SOCD_CLEANER_NUM_RESOLUTIONS, +}; + +typedef struct { + uint8_t keys[2]; // Basic keycodes for the two opposing keys. + uint8_t resolution; // Resolution strategy. + bool held[2]; // Tracks which keys are physically held. +} socd_cleaner_t; + +/** + * Handler function for SOCD cleaner. + * + * This function should be called from process_record_user(). The function may + * be called multiple times with different socd_cleaner_t instances to filter + * more than one SOCD key pair. + */ +bool process_socd_cleaner(uint16_t keycode, keyrecord_t* record, + socd_cleaner_t* state); + +/** Determines globally whether SOCD cleaner is enabled. */ +extern bool socd_cleaner_enabled; + +#ifdef __cplusplus +} +#endif diff --git a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/keymap.c b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/keymap.c index 2a24a7d4b531..dea1ad4ed9a6 100644 --- a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/keymap.c +++ b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/keymap.c @@ -3,7 +3,7 @@ #include QMK_KEYBOARD_H #include "framework.h" - +#include "features/socd_cleaner.h" #include "features/sentence_case.h" // clang-format off @@ -14,6 +14,14 @@ enum _layers { _FM }; +// Changes from regular layout +// - Capslock => Map as ctrl and escape +// - FN+Backtick => Sleep + + +// Control when held and combined, Escape when tapped +#define KC_ECPS CTL_T(KC_ESC) + const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* * ┌─────┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬────┐ @@ -23,7 +31,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬────┤ * 14 keys │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │ \ │ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴────┤ - * 13 keys │ Caps │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ Enter │ + * 13 keys │ECaps │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ Enter │ * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───────┤ * 12 keys │ Shift │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │ Shift │ * ├────┬───┼───┼───┼───┴───┴───┴───┴───┼───┼───┼───┴┬───┬────┤ @@ -37,7 +45,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 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_DEL, 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_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_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_ECPS, 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_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_LCTL, MO(_FN), KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RCTL, KC_LEFT, KC_UP, KC_DOWN, KC_RGHT ), @@ -46,7 +54,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * ┌─────┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬────┐ * 14 keys │FN lk│Mut│vDn│vUp│Prv│Ply│Nxt│bDn│bUp│Scn│Air│Prt│App│Ins │ * ├───┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────┤ - * 14 keys │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ + * 14 keys │SLP│ │ │ │ │ │ │ │ │ │ │ │ │ │ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬────┤ * 14 keys │ │ │RGB│Nxt│Hue│Sat│Spd│Brt│ │ │Pau│ │ │ │ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴────┤ @@ -62,8 +70,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { */ [_FN] = LAYOUT( FN_LOCK, KC_MUTE, KC_VOLD, KC_VOLU, KC_MPRV, KC_MPLY, KC_MNXT, KC_BRID, KC_BRIU, G(KC_P), KC_AIRP, KC_PSCR, KC_MSEL, KC_INS, - QK_BOOT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - EE_CLR, _______, RGB_TOG, RGB_MOD, RGB_HUI, RGB_SAI, RGB_SPI, RGB_VAI, _______, _______, KC_PAUS, _______, _______, _______, + KC_SLEP, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, RGB_TOG, RGB_MOD, RGB_HUI, RGB_SAI, RGB_SPI, RGB_VAI, _______, _______, KC_PAUS, _______, _______, _______, _______, _______, KC_SYRQ, RGB_RMOD,RGB_HUD, RGB_SAD, RGB_SPD, RGB_VAD, KC_SCRL, _______, _______, _______, _______, _______, _______, _______, BL_BRTG, _______, KC_BRK, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, BL_STEP, _______, _______, KC_HOME, KC_PGUP, KC_PGDN, KC_END @@ -73,8 +81,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [_FN_LOCK] = LAYOUT( _______, KC_MUTE, KC_VOLD, KC_VOLU, KC_MPRV, KC_MPLY, KC_MNXT, KC_BRID, KC_BRIU, G(KC_P), KC_AIRP, KC_PSCR, KC_MSEL, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + QK_BOOT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + EE_CLR, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, MO(_FM), _______, _______, _______, _______, _______, _______, _______, _______, _______ ), @@ -90,9 +98,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { // clang-format on +socd_cleaner_t socd_v = {{KC_W, KC_S}, SOCD_CLEANER_LAST}; +socd_cleaner_t socd_h = {{KC_A, KC_D}, SOCD_CLEANER_LAST}; + // Make sure to keep FN Lock even after reset -bool process_record_user(uint16_t keycode, keyrecord_t *record) { + +bool process_record_user(uint16_t keycode, keyrecord_t* record) { if (!process_sentence_case(keycode, record)) { return false; } + if (!process_socd_cleaner(keycode, record, &socd_v)) { return false; } + if (!process_socd_cleaner(keycode, record, &socd_h)) { return false; } switch (keycode) { case FN_LOCK: if (record->event.pressed) { @@ -111,13 +125,11 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { return true; } +void caps_word_set_user(bool active) { + writePin(GP24, active); +} -// shows when sentence case is active -void sentence_case_primed(bool primed) { - // Change B0 to the pin for the LED to use. - writePin(LED_CAPS_LOCK_PIN, primed); -}; -//shows when caps word is active -void caps_word_set_user(bool primed) { - writePin(LED_CAPS_LOCK_PIN, primed); -}; + +void sentence_case_primed(bool active) { + writePin(GP24, active); +} diff --git a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/rules.mk b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/rules.mk index f8aa223cb7c2..ae32cb0d9011 100644 --- a/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/rules.mk +++ b/keyboards/framework/laptop16/ansi/keymaps/dialgatrainer02/rules.mk @@ -1,14 +1,7 @@ +SRC += features/socd_cleaner.c +SRC += features/sentence_case.c + LTO_ENABLE = yes CONSOLE_ENABLE = no -COMMAND_ENABLE = no -MOUSEKEY_ENABLE = no -EXTRAKEY_ENABLE = yes -SPACE_CADET_ENABLE = no -GRAVE_ESC_ENABLE = no CAPS_WORD_ENABLE = yes -VIA_ENABLE = yes -KEY_LOCK_ENABLE = yes -BOOTMAGIC_ENABLE = yes - -SRC += features/sentence_case.c