Created
December 21, 2018 00:36
-
-
Save cellularmitosis/a320bd33214622585b15ff95b0e35548 to your computer and use it in GitHub Desktop.
A ring buffer / linked list for buffering ambiguous keys in QMK's config.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// a linked list of pending key events (press or release) which we haven't processed yet. | |
typedef struct _pending_key_t { | |
uint16_t keycode; | |
keyrecord_t record; | |
struct _pending_key_t *next; | |
} pending_key_t; | |
// worst case is 10 down strokes and 1 up stroke before we can start disambiguating. | |
#define RINGSIZE 11 | |
// a ring buffer and linked list to store pending key events (presses and releases). | |
// (basically, this is a fixed-allocation linked list.) | |
typedef { | |
// the actual key events. | |
pending_key_t items[RINGSIZE]; | |
// the index of the oldest item, or -1 if no items. | |
int8_t ifirst = -1; | |
// the index of the most recently added item, or -1 if no items. | |
int8_t ilast = -1; | |
// the number of items in the ring. | |
uint8_t count = 0; | |
// the head of the linked list. | |
pending_key_t *head = NULL; | |
} kring_t; | |
// safe accessor to the i-th item of the linked list (returns pointer or NULL). | |
pending_key_t* kr_get(kring_t *ring, uint8_t i) { | |
if (i >= ring->count) { | |
return NULL; | |
} | |
uint8_t j = (ring->ifirst + i) % RINGSIZE; | |
return &(ring->items[j]); | |
} | |
// remove the oldest item from the ring (the head of the list). | |
void kr_pop(kring_t *ring) { | |
if (ring->count > 0) { | |
ring->ifirst += 1; | |
ring->head = ring->head->next; | |
ring->count -= 1; | |
} | |
} | |
// add an item to the ring (append to the list). | |
void kr_append(kring_t *ring, uint16_t keycode, keyrecord_t *record) { | |
if (ring->count >= RINGSIZE) { | |
// uh oh, we overflowed the capacity of our buffer :( | |
return; | |
} | |
// if the ring is empty, insert at index 0. | |
if (ring->count == 0) { | |
ring->count += 1; | |
ring->first = 0; | |
ring->last = 0; | |
ring->head = &(ring->items[0]); | |
} | |
// else, append it onto the end. | |
else { | |
ring->count += 1; | |
ring->last += 1; | |
ring->last %= RINGSIZE; | |
} | |
// the index at which we should insert this item. | |
int8_t i = ring->ilast; | |
// insert the item. | |
ring->items[i].keycode = keycode; | |
ring->items[i].record.event = record->event; | |
#ifndef NO_ACTION_TAPPING | |
ring->items[i].record.tap = record->tap; | |
#endif | |
ring->items[i].next = NULL; | |
// update the previous item to point to this item. | |
if (ring->count > 1) { | |
kr_get(ring, ring->count-2)->next = kr_get(ring, ring->count-1); | |
} | |
} | |
kring_t pending; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment