DennyTom's buttery_engine (#8138)
* Selectively adding pieces * Adding georgi keymap * Adding more files, fixing make * Smaller makefiles * Fixing make rules * README more inline with QMK's guidelines * Turning off buggy assert * Improving documentation based on a user feedback. * Slightly better schema * Resurrected state machine diagram
This commit is contained in:
288
users/dennytom/chording_engine/tests/minunit.h
Normal file
288
users/dennytom/chording_engine/tests/minunit.h
Normal file
@ -0,0 +1,288 @@
|
||||
#define mu_assert(message, test) \
|
||||
do { \
|
||||
if (!(test)) { \
|
||||
return message; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RED "\033[0;31m"
|
||||
#define GREEN "\033[0;32m"
|
||||
#define NC "\033[0m"
|
||||
|
||||
enum ASSERT_TYPES {
|
||||
UINT,
|
||||
INT
|
||||
};
|
||||
|
||||
#define BUFF_SIZE 1024
|
||||
char buffer[BUFF_SIZE];
|
||||
|
||||
#define ASSERT_EQ(type, actual, expected) \
|
||||
do { \
|
||||
if (actual != expected) { \
|
||||
switch (type) { \
|
||||
case UINT: \
|
||||
snprintf(buffer, BUFF_SIZE, "\nline %d\nvar %s\nactual = %u\nexpected = %u\n", __LINE__, #actual, actual, expected); \
|
||||
break; \
|
||||
case INT: \
|
||||
snprintf(buffer, BUFF_SIZE, "\nline %d\nvar %s\nactual = %d\nexpected = %d\n", __LINE__, #actual, actual, expected); \
|
||||
break; \
|
||||
default: \
|
||||
snprintf(buffer, BUFF_SIZE, "\nline %d\nunsupported ASSERT_EQ type\n", __LINE__); \
|
||||
break; \
|
||||
} \
|
||||
printf("%s\n", buffer); \
|
||||
passed = false; \
|
||||
all_passed = false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MATRIX_ROWS 2
|
||||
#define MATRIX_COLS 10
|
||||
#define LAYOUT_test( \
|
||||
k09, k08, k07, k06, k05, k04, k03, k02, k01, k00, \
|
||||
k19, k18, k17, k16, k15, k14, k13, k12, k11, k10 \
|
||||
) { \
|
||||
{ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09}, \
|
||||
{ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19}, \
|
||||
}
|
||||
|
||||
#define PROGMEM
|
||||
#define memcpy_P memcpy
|
||||
const struct Chord* pgm_read_word(const struct Chord* const* chord) {return *chord;}
|
||||
|
||||
typedef struct {
|
||||
uint8_t col;
|
||||
uint8_t row;
|
||||
} keypos_t;
|
||||
|
||||
typedef struct {
|
||||
keypos_t key;
|
||||
bool pressed;
|
||||
uint16_t time;
|
||||
} keyevent_t;
|
||||
|
||||
typedef struct {
|
||||
bool interrupted :1;
|
||||
bool reserved2 :1;
|
||||
bool reserved1 :1;
|
||||
bool reserved0 :1;
|
||||
uint8_t count :4;
|
||||
} tap_t;
|
||||
|
||||
typedef struct {
|
||||
keyevent_t event;
|
||||
tap_t tap;
|
||||
} keyrecord_t;
|
||||
|
||||
keyrecord_t pressed = {{{0,0},true,0}, {0,0,0,0,0}};
|
||||
keyrecord_t depressed = {{{0,0},false,0}, {0,0,0,0,0}};
|
||||
|
||||
enum keycodes {
|
||||
KC_NO,
|
||||
KC_TILDE,
|
||||
KC_GRAVE,
|
||||
KC_EXCLAIM,
|
||||
KC_1,
|
||||
KC_AT,
|
||||
KC_2,
|
||||
KC_HASH,
|
||||
KC_3,
|
||||
KC_DOLLAR,
|
||||
KC_4,
|
||||
KC_PERCENT,
|
||||
KC_5,
|
||||
KC_CIRCUMFLEX,
|
||||
KC_6,
|
||||
KC_AMPERSAND,
|
||||
KC_7,
|
||||
KC_ASTERISK,
|
||||
KC_8,
|
||||
KC_LEFT_PAREN,
|
||||
KC_9,
|
||||
KC_RIGHT_PAREN,
|
||||
KC_0,
|
||||
KC_UNDERSCORE,
|
||||
KC_MINUS,
|
||||
KC_PLUS,
|
||||
KC_EQUAL,
|
||||
KC_LEFT_CURLY_BRACE,
|
||||
KC_LBRACKET,
|
||||
KC_RIGHT_CURLY_BRACE,
|
||||
KC_RBRACKET,
|
||||
KC_PIPE,
|
||||
KC_BSLASH,
|
||||
KC_COLON,
|
||||
KC_SCOLON,
|
||||
KC_DOUBLE_QUOTE,
|
||||
KC_QUOTE,
|
||||
KC_LEFT_ANGLE_BRACKET,
|
||||
KC_COMMA,
|
||||
KC_RIGHT_ANGLE_BRACKET,
|
||||
KC_DOT,
|
||||
KC_QUESTION,
|
||||
KC_SLASH,
|
||||
KC_Q,
|
||||
KC_W,
|
||||
KC_E,
|
||||
KC_R,
|
||||
KC_T,
|
||||
KC_Y,
|
||||
KC_U,
|
||||
KC_I,
|
||||
KC_O,
|
||||
KC_P,
|
||||
KC_A,
|
||||
KC_S,
|
||||
KC_D,
|
||||
KC_F,
|
||||
KC_G,
|
||||
KC_H,
|
||||
KC_J,
|
||||
KC_K,
|
||||
KC_L,
|
||||
KC_Z,
|
||||
KC_X,
|
||||
KC_C,
|
||||
KC_V,
|
||||
KC_B,
|
||||
KC_N,
|
||||
KC_M,
|
||||
KC_ESC,
|
||||
KC_LSFT,
|
||||
KC_LCTL,
|
||||
KC_LGUI,
|
||||
KC_LALT,
|
||||
KC_RALT,
|
||||
KC_RCTL,
|
||||
KC_RGUI,
|
||||
KC_RSFT,
|
||||
KC_TAB,
|
||||
KC_DEL,
|
||||
KC_INS,
|
||||
KC_BSPC,
|
||||
KC_ENTER,
|
||||
KC_SPACE,
|
||||
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_LEFT,
|
||||
KC_DOWN,
|
||||
KC_UP,
|
||||
KC_RIGHT,
|
||||
|
||||
SAFE_RANGE
|
||||
};
|
||||
|
||||
#define HISTORY 20
|
||||
|
||||
int16_t current_time;
|
||||
uint8_t keyboard_history[HISTORY][SAFE_RANGE-1];
|
||||
int16_t time_history[HISTORY];
|
||||
uint8_t history_index;
|
||||
|
||||
void register_code(int16_t keycode) {
|
||||
history_index++;
|
||||
for (int j = 0; j < SAFE_RANGE-1; j++) {
|
||||
keyboard_history[history_index][j] = keyboard_history[history_index-1][j];
|
||||
}
|
||||
keyboard_history[history_index][keycode] = 1;
|
||||
time_history[history_index] = current_time;
|
||||
};
|
||||
void unregister_code(int16_t keycode) {
|
||||
history_index++;
|
||||
for (int j = 0; j < SAFE_RANGE-1; j++) {
|
||||
keyboard_history[history_index][j] = keyboard_history[history_index-1][j];
|
||||
}
|
||||
keyboard_history[history_index][keycode] = 0;
|
||||
time_history[history_index] = current_time;
|
||||
};
|
||||
void send_keyboard_report(void) { /*still don't know what this does*/ };
|
||||
void matrix_scan_user (void);
|
||||
void wait_ms(uint16_t ms) {
|
||||
current_time += ms;
|
||||
};
|
||||
uint16_t timer_read(void) {
|
||||
uint16_t result = current_time;
|
||||
return result;
|
||||
};
|
||||
uint16_t timer_elapsed(uint16_t timer) {
|
||||
uint16_t result = current_time - timer;
|
||||
return result;
|
||||
};
|
||||
void layer_move(int16_t layer) { /*ignoring for now*/ };
|
||||
void clear_keyboard(void) {
|
||||
history_index++;
|
||||
for (int j = 0; j < SAFE_RANGE-1; j++) {
|
||||
keyboard_history[history_index][j] = 0;
|
||||
}
|
||||
time_history[history_index] = current_time;
|
||||
};
|
||||
void reset_keyboard(void) { /*ignoring for now*/ };
|
||||
|
||||
void pause_ms(uint16_t ms) {
|
||||
for (int i = 0; i < ms; i++) {
|
||||
current_time++;
|
||||
matrix_scan_user();
|
||||
}
|
||||
};
|
||||
|
||||
#define TEST(name) \
|
||||
do { \
|
||||
printf("%s\n", name); \
|
||||
passed = true; \
|
||||
do { \
|
||||
uint8_t clear_state = ACTIVATED; \
|
||||
struct Chord clear_chord PROGMEM = {0, QWERTY, &clear_state, NULL, 0, 0, clear}; \
|
||||
clear_chord.function(&clear_chord); \
|
||||
} while (0); \
|
||||
current_time = 0; \
|
||||
history_index = 0; \
|
||||
for (int j = 0; j < SAFE_RANGE-1; j++) { \
|
||||
keyboard_history[0][j] = 0; \
|
||||
} \
|
||||
time_history[0] = 0; \
|
||||
for (int i = 1; i < HISTORY; i++) { \
|
||||
for (int j = 0; j < SAFE_RANGE-1; j++) { \
|
||||
keyboard_history[i][j] = -1; \
|
||||
} \
|
||||
time_history[i] = -1; \
|
||||
}
|
||||
|
||||
#define END_TEST \
|
||||
if (passed) { \
|
||||
printf(GREEN"PASSED"NC"\n"); \
|
||||
} else { \
|
||||
printf(RED"FAILED"NC"\n"); \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
#define MAIN \
|
||||
int main(int argc, char **argv) { \
|
||||
bool passed = true; \
|
||||
bool all_passed = true;
|
||||
|
||||
#define END \
|
||||
printf("\n"); \
|
||||
if (all_passed) { \
|
||||
printf(GREEN"ALL TESTS PASSED"NC"\n"); \
|
||||
} else { \
|
||||
printf(RED"TESTS FAILED"NC"\n"); \
|
||||
} \
|
||||
return 1 - all_passed; \
|
||||
}
|
1259
users/dennytom/chording_engine/tests/test.c
Normal file
1259
users/dennytom/chording_engine/tests/test.c
Normal file
File diff suppressed because it is too large
Load Diff
11
users/dennytom/chording_engine/tests/test_full.sh
Normal file
11
users/dennytom/chording_engine/tests/test_full.sh
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
cd ..
|
||||
python3 parser.py tests/test_keymap_def.json tests/test_keymap.c && \
|
||||
gcc -g tests/test.c -o tests/test && \
|
||||
tests/test && \
|
||||
python3 parser.py ../../../keyboards/butterstick/keymaps/tomas/keymap_def.json ../../../keyboards/butterstick/keymaps/tomas/keymap.c && \
|
||||
python3 parser.py ../../../keyboards/georgi/keymaps/tomas/keymap_def.json ../../../keyboards/georgi/keymaps/tomas/keymap.c && \
|
||||
python3 parser.py ../../../keyboards/georgi/keymaps/buttery/keymap_def.json ../../../keyboards/georgi/keymaps/buttery/keymap.c && \
|
||||
cd ../../../ && \
|
||||
make butterstick && \
|
||||
make georgi
|
145
users/dennytom/chording_engine/tests/test_keymap_def.json
Normal file
145
users/dennytom/chording_engine/tests/test_keymap_def.json
Normal file
@ -0,0 +1,145 @@
|
||||
{
|
||||
"keys": [
|
||||
"TOP1", "TOP2", "TOP3", "TOP4", "TOP5", "TOP6", "TOP7", "TOP8", "TOP9", "TOP0",
|
||||
"BOT1", "BOT2", "BOT3", "BOT4", "BOT5", "BOT6", "BOT7", "BOT8", "BOT9", "BOT0"
|
||||
],
|
||||
"parameters": {
|
||||
"do_not_include_QMK": true,
|
||||
"layout_function_name": "LAYOUT_test",
|
||||
"chord_timeout": 100,
|
||||
"dance_timeout": 200,
|
||||
"leader_timeout": 750,
|
||||
"tap_timeout": 50,
|
||||
"command_max_length": 5,
|
||||
"leader_max_length": 5,
|
||||
"dynamic_macro_max_length": 20,
|
||||
"string_max_length": 16,
|
||||
"long_press_multiplier": 3,
|
||||
"default_pseudolayer": "QWERTY"
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"type": "auto"
|
||||
},
|
||||
{
|
||||
"type": "manual",
|
||||
"keycodes": ["KC_1", "KC_2", "KC_3", "KC_4", "KC_5", "KC_6", "KC_7", "KC_8", "KC_9", "KC_0",
|
||||
"KC_Q", "KC_W", "KC_E", "KC_R", "KC_T", "KC_Y", "KC_U", "KC_I", "KC_O", "KC_P"
|
||||
]
|
||||
}
|
||||
],
|
||||
"chord_sets": [
|
||||
{
|
||||
"name": "rows",
|
||||
"chords": [
|
||||
["TOP1"], ["TOP2"], ["TOP3"], ["TOP4"], ["TOP5"], ["TOP6"], ["TOP7"], ["TOP8"], ["TOP9"], ["TOP0"],
|
||||
["TOP1", "BOT1"], ["TOP2", "BOT2"], ["TOP3", "BOT3"], ["TOP4", "BOT4"], ["TOP5", "BOT5"], ["TOP6", "BOT6"], ["TOP7", "BOT7"], ["TOP8", "BOT8"], ["TOP9", "BOT9"], ["TOP0", "BOT0"],
|
||||
["BOT1"], ["BOT2"], ["BOT3"], ["BOT4"], ["BOT5"], ["BOT6"], ["BOT7"], ["BOT8"], ["BOT9"], ["BOT0"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "cols",
|
||||
"chords": [
|
||||
["TOP1", "TOP2"], ["TOP2", "TOP3"], ["TOP3", "TOP4"], ["TOP4", "TOP5"], ["TOP5", "TOP6"], ["TOP6", "TOP7"], ["TOP7", "TOP8"], ["TOP8", "TOP9"], ["TOP9", "TOP0"],
|
||||
["TOP1", "TOP2", "BOT1", "BOT2"], ["TOP2", "TOP3", "BOT2", "BOT3"], ["TOP3", "TOP4", "BOT3", "BOT4"], ["TOP4", "TOP5", "BOT4", "BOT5"], ["TOP5", "TOP6", "BOT5", "BOT6"], ["TOP6", "TOP7", "BOT6", "BOT7"], ["TOP7", "TOP8", "BOT7", "BOT8"], ["TOP8", "TOP9", "BOT8", "BOT9"], ["TOP9", "TOP0", "BOT9", "BOT0"],
|
||||
["BOT1", "BOT2"], ["BOT2", "BOT3"], ["BOT3", "BOT4"], ["BOT4", "BOT5"], ["BOT5", "BOT6"], ["BOT6", "BOT7"], ["BOT7", "BOT8"], ["BOT8", "BOT9"], ["BOT9", "BOT0"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "asetniop",
|
||||
"chords": [
|
||||
["TOP1"], ["TOP2"], ["TOP3"], ["TOP4"], ["TOP7"], ["TOP8"], ["TOP9"], ["TOP0"],
|
||||
["TOP1", "TOP2"], ["TOP2", "TOP3"], ["TOP3", "TOP4"], ["TOP4", "TOP7"], ["TOP7", "TOP8"], ["TOP8", "TOP9"], ["TOP9", "TOP0"],
|
||||
["TOP1", "TOP3"], ["TOP2", "TOP4"], ["TOP3", "TOP7"], ["TOP4", "TOP8"], ["TOP7", "TOP9"], ["TOP8", "TOP0"],
|
||||
["TOP1", "TOP4"], ["TOP2", "TOP7"], ["TOP3", "TOP8"], ["TOP4", "TOP9"], ["TOP7", "TOP0"],
|
||||
["TOP1", "TOP7"], ["TOP2", "TOP8"], ["TOP3", "TOP9"], ["TOP4", "TOP0"],
|
||||
["TOP1", "TOP8"], ["TOP2", "TOP9"], ["TOP3", "TOP0"],
|
||||
["TOP1", "TOP9"], ["TOP2", "TOP0"],
|
||||
["TOP1", "TOP0"]
|
||||
]
|
||||
}
|
||||
],
|
||||
"pseudolayers": [
|
||||
{
|
||||
"name": "ALWAYS_ON",
|
||||
"chords": [
|
||||
{
|
||||
"type": "visual",
|
||||
"chord": [
|
||||
" ", " ", " ", " ", " ", " ", " ", "X", "X", "X",
|
||||
" ", " ", " ", " ", " ", " ", " ", "X", "X", "X"
|
||||
],
|
||||
"keycode": "MO(FNC, NUM)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "QWERTY",
|
||||
"chords": [
|
||||
{
|
||||
"type": "chord_set",
|
||||
"set": "rows",
|
||||
"keycodes": [
|
||||
"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
|
||||
"A", "S", "D", "F", "G", "H", "J", "K", "L", ";",
|
||||
"AS(Z)", "KK(X, LCTL)", "KL(C, NUM)", "KM(V, LALT)", "B", "N", "M", "COMMA", ".", "M(double_dance, KC_9, KC_0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "chord_set",
|
||||
"set": "cols",
|
||||
"keycodes": [
|
||||
"ESC", "", "", "", "", "", "", "", "",
|
||||
"", "LEAD", "", "", "CMD", "", "", "", "",
|
||||
"LSFT", "O(LSFT)", "", "", "", "O(NUM)", "MO(NUM)", "", "DF(NUM)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "visual",
|
||||
"chord": [
|
||||
"X", "X", " ", " ", " ", " ", " ", " ", " ", " ",
|
||||
"X", "X", " ", " ", " ", " ", " ", " ", " ", " "
|
||||
],
|
||||
"keycode": "LOCK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "NUM",
|
||||
"chords": [
|
||||
{
|
||||
"type": "chord_set",
|
||||
"set": "rows",
|
||||
"keycodes": [
|
||||
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
|
||||
"", "", "", "", "", "", "", "", "", "",
|
||||
"", "KC_LEFT", "D(KC_1, KC_2, KC_3)", "", "", "", "DM_RECORD", "DM_NEXT", "DM_END", "DM_PLAY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "simple",
|
||||
"chord": ["BOT1"],
|
||||
"keycode": "MK(KC_LCTL, KC_LSFT)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FNC",
|
||||
"chords": []
|
||||
}
|
||||
],
|
||||
"leader_sequences": [
|
||||
{
|
||||
"name": "fnc_L1",
|
||||
"function": "void fnc_L1(void) { key_in(KC_A); clear_keyboard(); }",
|
||||
"sequence": ["KC_O", "KC_P"]
|
||||
},
|
||||
{
|
||||
"name": "fnc_L2",
|
||||
"function": "void fnc_L2(void) { key_in(KC_S); clear_keyboard(); }",
|
||||
"sequence": ["KC_P", "KC_O"]
|
||||
}
|
||||
],
|
||||
"extra_code": "void double_dance(const struct Chord* self) {\n switch (*self->state) {\n case ACTIVATED:\n *self->counter = (*self->counter + 1) % 2;\n break;\n case PRESS_FROM_ACTIVE:\n if (*self->counter == 1) {\n key_in(self->value1);\n } else {\n key_in(self->value2);\n }\n *self->state = FINISHED_FROM_ACTIVE;\n break;\n case FINISHED:\n if (*self->counter == 1) {\n tap_key(self->value1);\n } else {\n tap_key(self->value2);\n }\n *self->counter = 0;\n *self->state = IDLE;\n break;\n case RESTART:\n if (*self->counter == 1) {\n key_out(self->value1);\n } else {\n key_out(self->value2);\n }\n *self->counter = 0;\n break;\n default:\n break;\n }\n}\n",
|
||||
"extra_dependencies": []
|
||||
}
|
6
users/dennytom/chording_engine/tests/test_quick.sh
Normal file
6
users/dennytom/chording_engine/tests/test_quick.sh
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd ..
|
||||
python3 parser.py tests/test_keymap_def.json tests/test_keymap.c && \
|
||||
gcc -g tests/test.c -o tests/test && \
|
||||
tests/test
|
Reference in New Issue
Block a user