]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/handwired/hexon38/keymaps/default/keymap.c
Update keyboards/kbdfans/kbd67/readme.md
[qmk_firmware.git] / keyboards / handwired / hexon38 / keymaps / default / keymap.c
1 // see https://github.com/pepaslabs/hexon38
2
3 #include "hexon38.h"
4
5 #define A_ KC_A
6 #define B_ KC_B
7 #define C_ KC_C
8 #define D_ KC_D
9 #define E_ KC_E
10 #define F_ KC_F
11 #define G_ KC_G
12 #define H_ KC_H
13 #define I_ KC_I
14 #define J_ KC_J
15 #define K_ KC_K
16 #define L_ KC_L
17 #define M_ KC_M
18 #define N_ KC_N
19 #define O_ KC_O
20 #define P_ KC_P
21 #define Q_ KC_Q
22 #define R_ KC_R
23 #define S_ KC_S
24 #define T_ KC_T
25 #define U_ KC_U
26 #define V_ KC_V
27 #define W_ KC_W
28 #define X_ KC_X
29 #define Y_ KC_Y
30 #define Z_ KC_Z
31
32 // Dual-role keys: modifier when held, alpha when tapped.
33 #define A_CTL CTL_T(KC_A)
34 #define S_ALT ALT_T(KC_S)
35 #define D_GUI GUI_T(KC_D)
36 #define F_SFT SFT_T(KC_F)
37 #define J_SFT SFT_T(KC_J)
38 #define K_GUI GUI_T(KC_K)
39 #define L_ALT ALT_T(KC_L)
40 #define COLN_CTL CTL_T(KC_SCLN)
41
42 #define ______ KC_TRNS
43 #define LSHIFT KC_LSHIFT
44 #define RSHIFT KC_RSHIFT
45 #define COMMA KC_COMM
46 #define SLASH KC_SLSH
47 #define SPACE KC_SPC
48 #define TAB KC_TAB
49 #define BKSPC KC_BSPC
50 #define ENTER KC_ENT
51 #define PERIOD KC_DOT
52
53 #define BASE_LAYER LAYOUT
54 #define BLANK_LAYER LAYOUT
55
56
57 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
58
59     BASE_LAYER(
60 //                  ,--------+--------+--------+--------.    ,--------+--------+--------+--------.
61                         W_   ,   E_   ,   R_   ,   T_   ,        Y_   ,   U_   ,   I_   ,   O_   ,
62 //|--------+--------+--------+--------+--------+--------|    |--------+--------+--------+--------+--------+--------.
63       Q_   ,  A_CTL ,  S_ALT ,  D_GUI ,  F_SFT ,   G_   ,        H_   ,  J_SFT ,  K_GUI ,  L_ALT ,COLN_CTL,   P_   ,
64 //|--------+--------+--------+--------+--------+--------'    `--------+--------+--------+--------+--------+--------|
65       B_   ,   Z_   ,   X_   ,   C_   ,   V_   ,                          M_   ,  COMMA , PERIOD ,  SLASH ,   N_   ,
66 //`--------+--------+--------+--------+--------'                      `--------+--------+--------+--------+--------'
67
68 //                  ,--------+--------+--------+--------.    ,--------+--------+--------+--------.
69                       LSHIFT ,  SPACE ,   TAB  ,  DEBUG ,       SPACE ,  BKSPC ,  ENTER , RSHIFT
70 //                  `--------+--------+--------+--------'    `--------+--------+--------+--------'
71 ),
72
73     BLANK_LAYER(
74 //                  ,--------+--------+--------+--------.    ,--------+--------+--------+--------.
75                       ______ , ______ , ______ , ______ ,      ______ , ______ , ______ , ______ ,
76 //|--------+--------+--------+--------+--------+--------|    |--------+--------+--------+--------+--------+--------.
77     ______ , ______ , ______ , ______ , ______ , ______ ,      ______ , ______ , ______ , ______ , ______ , ______ ,
78 //|--------+--------+--------+--------+--------+--------'    `--------+--------+--------+--------+--------+--------|
79     ______ , ______ , ______ , ______ , ______ ,                        ______ , ______ , ______ , ______ , ______ ,
80 //`--------+--------+--------+--------+--------'                      `--------+--------+--------+--------+--------'
81
82 //                  ,--------+--------+--------+--------.    ,--------+--------+--------+--------.
83                       ______ , ______ , ______ , ______ ,      ______ , ______ , ______ , ______
84 //                  `--------+--------+--------+--------'    `--------+--------+--------+--------'
85 )
86
87 };
88
89 // a linked list of pending key events (press or release) which we haven't processed yet.
90 struct _pending_key_t {
91     uint16_t keycode;
92     keyrecord_t record;
93     struct _pending_key_t *next;
94 };
95 typedef struct _pending_key_t pending_key_t;
96
97 // worst case is 10 down strokes and 1 up stroke before we can start disambiguating.
98 #define RINGSIZE 11
99
100 // a ring buffer and linked list to store pending key events (presses and releases).
101 // (basically, this is a fixed-allocation linked list.)
102 struct _kring_t {
103     // the actual key events.
104     pending_key_t items[RINGSIZE];
105     // the index of the oldest item, or -1 if no items.
106     int8_t ifirst;
107     // the index of the most recently added item, or -1 if no items.
108     int8_t ilast;
109     // the number of items in the ring.
110     uint8_t count;
111     // the head of the linked list.
112     pending_key_t *head;
113 };
114 typedef struct _kring_t kring_t;
115
116 // safe accessor to the i-th item of the linked list (returns pointer or NULL).
117 pending_key_t* kring_get(kring_t *ring, uint8_t i) {
118     if (i >= ring->count) {
119         return NULL;
120     }
121     uint8_t j = (ring->ifirst + i) % RINGSIZE;
122     return &(ring->items[j]);
123 }
124
125 // return the last key in the list of buffered keys.
126 pending_key_t* kring_last(kring_t *ring) {
127     if (ring->count == 0) {
128         return NULL;
129     }
130     return kring_get(ring, ring->count - 1);
131 }
132
133 // remove the oldest item from the ring (the head of the list).
134 void kring_pop(kring_t *ring) {
135     if (ring->count > 0) {
136         ring->ifirst += 1;
137         ring->ifirst %= RINGSIZE;
138         ring->head = ring->head->next;
139         ring->count -= 1;
140     }
141 }
142
143 // add an item to the ring (append to the list).
144 void kring_append(kring_t *ring, uint16_t keycode, keyrecord_t *record) {
145     if (ring->count >= RINGSIZE) {
146         // uh oh, we overflowed the capacity of our buffer :(
147         return;
148     }
149
150     // if the ring is empty, insert at index 0.
151     if (ring->count == 0) {
152         ring->count += 1;
153         ring->ifirst = 0;
154         ring->ilast = 0;
155         ring->head = &(ring->items[0]);
156     }
157     // else, append it onto the end.
158     else {
159         ring->count += 1;
160         ring->ilast += 1;
161         ring->ilast %= RINGSIZE;
162     }
163
164     // the index at which we should insert this item.
165     int8_t i = ring->ilast;
166
167     // insert the item.
168     ring->items[i].keycode = keycode;
169     ring->items[i].record.event = record->event;
170 #ifndef NO_ACTION_TAPPING
171     ring->items[i].record.tap = record->tap;
172 #endif
173     ring->items[i].next = NULL;
174
175     // update the previous item to point to this item.
176     if (ring->count > 1) {
177         kring_get(ring, ring->count - 2)->next = &(ring->items[i]);
178     }
179 }
180
181 kring_t g_pending;
182
183 void matrix_init_user(void) {
184     g_pending.ifirst = -1;
185     g_pending.ilast = -1;
186     g_pending.count = 0;
187     g_pending.head = NULL;
188 }
189
190 void matrix_scan_user(void) {}
191
192 /*
193 a_ a-: emit a
194 a_ b_ b- a-: emit SHIFT+b
195 a_ b_ a- b-: emit a, b
196 dual1down, dual1up -> norm1down, norm1up
197 dual1down, norm2down, norm2up -> mod1down, norm2down, norm2up
198 dual1down, norm2down, dual1up -> norm1down, norm2down, norm1up
199 dual1down, dual2down, norm3down, norm3up -> mod1down, mod2down, norm3down, norm3up
200 so, a dual key can't be disambiguated until the next keyup of a keydown (not including keyups from keys before it).
201 */
202
203 bool is_ambiguous_kc(uint16_t kc) {
204     // See the MT() define: https://github.com/qmk/qmk_firmware/blob/master/quantum/quantum_keycodes.h#L642
205     // See the QK_MOD_TAP case: https://github.com/qmk/qmk_firmware/blob/master/quantum/keymap_common.c#L134
206     uint8_t mod = mod_config((kc >> 0x8) & 0x1F);
207     return mod != 0;
208 }
209
210 bool is_down(pending_key_t *k) {
211     return k->record.event.pressed;
212 }
213
214 bool is_up(pending_key_t *k) {
215     return !is_down(k);
216 }
217
218 bool keys_match(pending_key_t *a, pending_key_t *b) {
219     return a->record.event.key.col == b->record.event.key.col
220         && a->record.event.key.row == b->record.event.key.row;
221 }
222
223 // both the down and corresponding upstroke of a keypress.
224 struct _pending_pair_t {
225     pending_key_t *down;
226     pending_key_t *up;
227 };
228 typedef struct _pending_pair_t pending_pair_t;
229
230 // returns true if this keydown event has a corresponding keyup event in the
231 // list of buffered keys.  also fills out 'p'.
232 bool is_downup_pair(pending_key_t *k, pending_pair_t *p) {
233     // first, make sure this event is keydown.
234     if (!is_down(k)) {
235         return false;
236     }
237     // now find its matching keyup.
238     pending_key_t *next = k->next;
239     while (next != NULL) {
240         if (keys_match(k, next) && is_up(next)) {
241             // found it.
242             if (p != NULL) {
243                 p->down = k;
244                 p->up = next;
245             }
246             return true;
247         }
248         next = next->next;
249     }
250     // didn't find it.
251     return false;
252 }
253
254 // given a QK_MOD_TAP keycode, return the KC_* version of the modifier keycode.
255 uint16_t get_mod_kc(uint16_t keycode) {
256     uint8_t mod = mod_config((keycode >> 0x8) & 0x1F);
257     switch (mod) {
258     case MOD_LCTL:
259         return KC_LCTL;
260     case MOD_RCTL:
261         return KC_RCTL;
262     case MOD_LSFT:
263         return KC_LSFT;
264     case MOD_RSFT:
265         return KC_RSFT;
266     case MOD_LALT:
267         return KC_LALT;
268     case MOD_RALT:
269         return KC_RALT;
270     case MOD_LGUI:
271         return KC_LGUI;
272     case MOD_RGUI:
273         return KC_RGUI;
274     default:
275         // shrug?  this shouldn't happen.
276         return keycode;
277     }
278 }
279
280 bool is_mod_kc(uint16_t keycode) {
281     switch (keycode) {
282     case QK_MODS ... QK_MODS_MAX:
283         return true;
284     default:
285         return false;
286     }
287 }
288
289 void interpret_as_mod(pending_pair_t *p) {
290     // see https://github.com/qmk/qmk_firmware/issues/1503
291     pending_key_t *k;
292     k = p->down;
293     if (k != NULL) {
294         k->keycode = get_mod_kc(k->keycode);
295     }
296     k = p->up;
297     if (k != NULL) {
298         k->keycode = get_mod_kc(k->keycode);
299     }
300 }
301
302 void interpret_as_normal(pending_pair_t *p) {
303     pending_key_t *k;
304     k = p->down;
305     if (k != NULL) {
306         k->keycode = k->keycode & 0xFF;
307     }
308     k = p->up;
309     if (k != NULL) {
310         k->keycode = k->keycode & 0xFF;
311     }
312 }
313
314 void execute_head_and_pop(kring_t *ring) {
315     pending_key_t *head = kring_get(ring, 0);
316     uint16_t kc = head->keycode;
317     if (is_mod_kc(kc)) {
318         if (is_down(head)) {
319             dprintf("  %s: mod down 0x%04X\n", __func__, kc);
320             set_mods(get_mods() | MOD_BIT(kc));
321         } else {
322             dprintf("  %s: mod up 0x%04X\n", __func__, kc);
323             set_mods(get_mods() & ~MOD_BIT(kc));
324         }
325     } else {
326         if (is_down(head)) {
327             dprintf("  %s: key down 0x%04X\n", __func__, kc);
328             register_code16(kc);
329         } else {
330             dprintf("  %s: key up 0x%04X\n", __func__, kc);
331             unregister_code16(kc);
332         }
333     }
334     kring_pop(ring);
335 }
336
337 // try to figure out what the next pending keypress means.
338 bool parse_next(kring_t *pending) {
339     pending_pair_t p;
340     pending_key_t *first = kring_get(pending, 0);
341     if (!is_ambiguous_kc(first->keycode)) {
342         // this pending key isn't ambiguous, so execute it.
343         dprintf(" %s: found unambiguous key\n", __func__);
344         execute_head_and_pop(pending);
345         return true;
346     } else if (is_ambiguous_kc(first->keycode) && is_up(first)) {
347         dprintf(" %s: interpreting keyup as mod\n", __func__);
348         p.down = NULL;
349         p.up = first;
350         interpret_as_mod(&p);
351         execute_head_and_pop(pending);
352         return true;
353     } else if (is_downup_pair(first, &p)) {
354         // 'first' was released before any other pressed key, so treat this as
355         // a rolling series of normal key taps.
356         dprintf(" %s: found down-up pair, interpreting as normal key\n", __func__);
357         interpret_as_normal(&p);
358         execute_head_and_pop(pending);
359         return true;
360     } else {
361         // if another key was pressed and released while 'first' was held, then we
362         // should treat it like a modifier.
363         pending_key_t *next = first->next;
364         while (next != NULL) {
365             if (is_downup_pair(next, NULL)) {
366                 dprintf(" %s: found subsequent downup pair, interpreting head as mod\n", __func__);
367                 p.down = first;
368                 p.up = NULL;
369                 interpret_as_mod(&p);
370                 execute_head_and_pop(pending);
371                 return true;
372             }
373             next = next->next;
374         }
375
376         // we can't disambiguate 'first' yet.  wait for another keypress.
377         dprintf(" %s: can't disambiguate (yet)\n", __func__);
378         return false;
379     }
380 }
381
382 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
383     if (keycode == DEBUG) {
384         return true;
385     }
386
387     if (g_pending.count == 0 && !is_ambiguous_kc(keycode)) {
388         // we have no pending keys and this key isn't ambiguous, so we should
389         // just let QMK take care of it.
390         dprintf("%s: handled by qmk\n", __func__);
391         return true;
392     } else {
393         dprintf("%s: got dual-role key\n", __func__);
394         // append the keypress and then try parsing all pending keypresses.
395         kring_append(&g_pending, keycode, record);
396         while (g_pending.count > 0) {
397             dprintf("%s: looping through %d keys...\n", __func__, g_pending.count);
398             if (!parse_next(&g_pending)) {
399                 // one of our keypresses is ambiguous and we can't proceed until
400                 // we get further keypresses to disambiguate it.
401                 dprintf("%s: %d pending keys are ambiguous\n", __func__, g_pending.count);
402                 break;
403             }
404         }
405         return false;
406     }
407 }