Skip to content

Instantly share code, notes, and snippets.

@cellularmitosis
Created December 21, 2018 00:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cellularmitosis/a320bd33214622585b15ff95b0e35548 to your computer and use it in GitHub Desktop.
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
// 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