Format code according to conventions (#15193)
This commit is contained in:
		
							parent
							
								
									b06740c933
								
							
						
					
					
						commit
						2c5d66987d
					
				
					 35 changed files with 576 additions and 516 deletions
				
			
		| 
						 | 
				
			
			@ -782,9 +782,10 @@ void register_code(uint8_t code) {
 | 
			
		|||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    else if IS_KEY (code) {
 | 
			
		||||
        // TODO: should push command_proc out of this block?
 | 
			
		||||
        if (command_proc(code)) return;
 | 
			
		||||
    else if
 | 
			
		||||
        IS_KEY(code) {
 | 
			
		||||
            // TODO: should push command_proc out of this block?
 | 
			
		||||
            if (command_proc(code)) return;
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
/* TODO: remove
 | 
			
		||||
| 
						 | 
				
			
			@ -801,33 +802,35 @@ void register_code(uint8_t code) {
 | 
			
		|||
        } else
 | 
			
		||||
*/
 | 
			
		||||
#endif
 | 
			
		||||
        {
 | 
			
		||||
            // Force a new key press if the key is already pressed
 | 
			
		||||
            // without this, keys with the same keycode, but different
 | 
			
		||||
            // modifiers will be reported incorrectly, see issue #1708
 | 
			
		||||
            if (is_key_pressed(keyboard_report, code)) {
 | 
			
		||||
                del_key(code);
 | 
			
		||||
            {
 | 
			
		||||
                // Force a new key press if the key is already pressed
 | 
			
		||||
                // without this, keys with the same keycode, but different
 | 
			
		||||
                // modifiers will be reported incorrectly, see issue #1708
 | 
			
		||||
                if (is_key_pressed(keyboard_report, code)) {
 | 
			
		||||
                    del_key(code);
 | 
			
		||||
                    send_keyboard_report();
 | 
			
		||||
                }
 | 
			
		||||
                add_key(code);
 | 
			
		||||
                send_keyboard_report();
 | 
			
		||||
            }
 | 
			
		||||
            add_key(code);
 | 
			
		||||
        }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_MOD(code) {
 | 
			
		||||
            add_mods(MOD_BIT(code));
 | 
			
		||||
            send_keyboard_report();
 | 
			
		||||
        }
 | 
			
		||||
    } else if IS_MOD (code) {
 | 
			
		||||
        add_mods(MOD_BIT(code));
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
    else if IS_SYSTEM (code) {
 | 
			
		||||
        host_system_send(KEYCODE2SYSTEM(code));
 | 
			
		||||
    } else if IS_CONSUMER (code) {
 | 
			
		||||
        host_consumer_send(KEYCODE2CONSUMER(code));
 | 
			
		||||
    }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_SYSTEM(code) { host_system_send(KEYCODE2SYSTEM(code)); }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_CONSUMER(code) { host_consumer_send(KEYCODE2CONSUMER(code)); }
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    else if IS_MOUSEKEY (code) {
 | 
			
		||||
        mousekey_on(code);
 | 
			
		||||
        mousekey_send();
 | 
			
		||||
    }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_MOUSEKEY(code) {
 | 
			
		||||
            mousekey_on(code);
 | 
			
		||||
            mousekey_send();
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -872,22 +875,26 @@ void unregister_code(uint8_t code) {
 | 
			
		|||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    else if IS_KEY (code) {
 | 
			
		||||
        del_key(code);
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    } else if IS_MOD (code) {
 | 
			
		||||
        del_mods(MOD_BIT(code));
 | 
			
		||||
        send_keyboard_report();
 | 
			
		||||
    } else if IS_SYSTEM (code) {
 | 
			
		||||
        host_system_send(0);
 | 
			
		||||
    } else if IS_CONSUMER (code) {
 | 
			
		||||
        host_consumer_send(0);
 | 
			
		||||
    }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_KEY(code) {
 | 
			
		||||
            del_key(code);
 | 
			
		||||
            send_keyboard_report();
 | 
			
		||||
        }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_MOD(code) {
 | 
			
		||||
            del_mods(MOD_BIT(code));
 | 
			
		||||
            send_keyboard_report();
 | 
			
		||||
        }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_SYSTEM(code) { host_system_send(0); }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_CONSUMER(code) { host_consumer_send(0); }
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    else if IS_MOUSEKEY (code) {
 | 
			
		||||
        mousekey_off(code);
 | 
			
		||||
        mousekey_send();
 | 
			
		||||
    }
 | 
			
		||||
    else if
 | 
			
		||||
        IS_MOUSEKEY(code) {
 | 
			
		||||
            mousekey_off(code);
 | 
			
		||||
            mousekey_send();
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ extern bool disable_action_cache;
 | 
			
		|||
 | 
			
		||||
/* Code for handling one-handed key modifiers. */
 | 
			
		||||
#ifdef SWAP_HANDS_ENABLE
 | 
			
		||||
extern bool                   swap_hands;
 | 
			
		||||
extern bool           swap_hands;
 | 
			
		||||
extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS];
 | 
			
		||||
#    if (MATRIX_COLS <= 8)
 | 
			
		||||
typedef uint8_t swap_state_row_t;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,11 +18,11 @@
 | 
			
		|||
#    define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
 | 
			
		||||
#    define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
 | 
			
		||||
#    define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
 | 
			
		||||
#ifndef COMBO_ENABLE
 | 
			
		||||
#    define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)))
 | 
			
		||||
#else
 | 
			
		||||
#    define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
 | 
			
		||||
#endif
 | 
			
		||||
#    ifndef COMBO_ENABLE
 | 
			
		||||
#        define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)))
 | 
			
		||||
#    else
 | 
			
		||||
#        define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -212,11 +212,15 @@ bool process_tapping(keyrecord_t *keyp) {
 | 
			
		|||
                    if (tapping_key.tap.count > 1) {
 | 
			
		||||
                        debug("Tapping: Start new tap with releasing last tap(>1).\n");
 | 
			
		||||
                        // unregister key
 | 
			
		||||
                        process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false,
 | 
			
		||||
#ifdef COMBO_ENABLE
 | 
			
		||||
                                .keycode = tapping_key.keycode,
 | 
			
		||||
#endif
 | 
			
		||||
                                });
 | 
			
		||||
                        process_record(&(keyrecord_t){
 | 
			
		||||
                            .tap           = tapping_key.tap,
 | 
			
		||||
                            .event.key     = tapping_key.event.key,
 | 
			
		||||
                            .event.time    = event.time,
 | 
			
		||||
                            .event.pressed = false,
 | 
			
		||||
#    ifdef COMBO_ENABLE
 | 
			
		||||
                            .keycode = tapping_key.keycode,
 | 
			
		||||
#    endif
 | 
			
		||||
                        });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        debug("Tapping: Start while last tap(1).\n");
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -254,11 +258,15 @@ bool process_tapping(keyrecord_t *keyp) {
 | 
			
		|||
                    if (tapping_key.tap.count > 1) {
 | 
			
		||||
                        debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
 | 
			
		||||
                        // unregister key
 | 
			
		||||
                        process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false,
 | 
			
		||||
#ifdef COMBO_ENABLE
 | 
			
		||||
                                .keycode = tapping_key.keycode,
 | 
			
		||||
#endif
 | 
			
		||||
                                });
 | 
			
		||||
                        process_record(&(keyrecord_t){
 | 
			
		||||
                            .tap           = tapping_key.tap,
 | 
			
		||||
                            .event.key     = tapping_key.event.key,
 | 
			
		||||
                            .event.time    = event.time,
 | 
			
		||||
                            .event.pressed = false,
 | 
			
		||||
#    ifdef COMBO_ENABLE
 | 
			
		||||
                            .keycode = tapping_key.keycode,
 | 
			
		||||
#    endif
 | 
			
		||||
                        });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        debug("Tapping: Start while last timeout tap(1).\n");
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,17 +46,17 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
 | 
			
		|||
#define ROW_SHIFTER ((matrix_row_t)1)
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    bool pressed : 1;
 | 
			
		||||
    bool    pressed : 1;
 | 
			
		||||
    uint8_t time : 7;
 | 
			
		||||
} debounce_counter_t;
 | 
			
		||||
 | 
			
		||||
#if DEBOUNCE > 0
 | 
			
		||||
static debounce_counter_t *debounce_counters;
 | 
			
		||||
static fast_timer_t last_time;
 | 
			
		||||
static bool counters_need_update;
 | 
			
		||||
static bool matrix_need_update;
 | 
			
		||||
static fast_timer_t        last_time;
 | 
			
		||||
static bool                counters_need_update;
 | 
			
		||||
static bool                matrix_need_update;
 | 
			
		||||
 | 
			
		||||
#define DEBOUNCE_ELAPSED 0
 | 
			
		||||
#    define DEBOUNCE_ELAPSED 0
 | 
			
		||||
 | 
			
		||||
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
 | 
			
		||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
 | 
			
		|||
// we use num_rows rather than MATRIX_ROWS to support split keyboards
 | 
			
		||||
void debounce_init(uint8_t num_rows) {
 | 
			
		||||
    debounce_counters = malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t));
 | 
			
		||||
    int i = 0;
 | 
			
		||||
    int i             = 0;
 | 
			
		||||
    for (uint8_t r = 0; r < num_rows; r++) {
 | 
			
		||||
        for (uint8_t c = 0; c < MATRIX_COLS; c++) {
 | 
			
		||||
            debounce_counters[i++].time = DEBOUNCE_ELAPSED;
 | 
			
		||||
| 
						 | 
				
			
			@ -81,10 +81,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
 | 
			
		|||
    bool updated_last = false;
 | 
			
		||||
 | 
			
		||||
    if (counters_need_update) {
 | 
			
		||||
        fast_timer_t now = timer_read_fast();
 | 
			
		||||
        fast_timer_t now          = timer_read_fast();
 | 
			
		||||
        fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
 | 
			
		||||
 | 
			
		||||
        last_time = now;
 | 
			
		||||
        last_time    = now;
 | 
			
		||||
        updated_last = true;
 | 
			
		||||
        if (elapsed_time > UINT8_MAX) {
 | 
			
		||||
            elapsed_time = UINT8_MAX;
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +108,7 @@ static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[],
 | 
			
		|||
    debounce_counter_t *debounce_pointer = debounce_counters;
 | 
			
		||||
 | 
			
		||||
    counters_need_update = false;
 | 
			
		||||
    matrix_need_update = false;
 | 
			
		||||
    matrix_need_update   = false;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t row = 0; row < num_rows; row++) {
 | 
			
		||||
        for (uint8_t col = 0; col < MATRIX_COLS; col++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -146,8 +146,8 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
 | 
			
		|||
            if (delta & col_mask) {
 | 
			
		||||
                if (debounce_pointer->time == DEBOUNCE_ELAPSED) {
 | 
			
		||||
                    debounce_pointer->pressed = (raw[row] & col_mask);
 | 
			
		||||
                    debounce_pointer->time = DEBOUNCE;
 | 
			
		||||
                    counters_need_update = true;
 | 
			
		||||
                    debounce_pointer->time    = DEBOUNCE;
 | 
			
		||||
                    counters_need_update      = true;
 | 
			
		||||
 | 
			
		||||
                    if (debounce_pointer->pressed) {
 | 
			
		||||
                        // key-down: eager
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#if DEBOUNCE > 0
 | 
			
		||||
static bool debouncing = false;
 | 
			
		||||
static bool         debouncing = false;
 | 
			
		||||
static fast_timer_t debouncing_time;
 | 
			
		||||
 | 
			
		||||
void debounce_init(uint8_t num_rows) {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,7 +49,7 @@ static debounce_counter_t *debounce_counters;
 | 
			
		|||
static fast_timer_t        last_time;
 | 
			
		||||
static bool                counters_need_update;
 | 
			
		||||
 | 
			
		||||
#define DEBOUNCE_ELAPSED 0
 | 
			
		||||
#    define DEBOUNCE_ELAPSED 0
 | 
			
		||||
 | 
			
		||||
static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t elapsed_time);
 | 
			
		||||
static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
 | 
			
		||||
| 
						 | 
				
			
			@ -74,10 +74,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
 | 
			
		|||
    bool updated_last = false;
 | 
			
		||||
 | 
			
		||||
    if (counters_need_update) {
 | 
			
		||||
        fast_timer_t now = timer_read_fast();
 | 
			
		||||
        fast_timer_t now          = timer_read_fast();
 | 
			
		||||
        fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
 | 
			
		||||
 | 
			
		||||
        last_time = now;
 | 
			
		||||
        last_time    = now;
 | 
			
		||||
        updated_last = true;
 | 
			
		||||
        if (elapsed_time > UINT8_MAX) {
 | 
			
		||||
            elapsed_time = UINT8_MAX;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ static fast_timer_t        last_time;
 | 
			
		|||
static bool                counters_need_update;
 | 
			
		||||
static bool                matrix_need_update;
 | 
			
		||||
 | 
			
		||||
#define DEBOUNCE_ELAPSED 0
 | 
			
		||||
#    define DEBOUNCE_ELAPSED 0
 | 
			
		||||
 | 
			
		||||
static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
 | 
			
		||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
 | 
			
		||||
| 
						 | 
				
			
			@ -75,10 +75,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
 | 
			
		|||
    bool updated_last = false;
 | 
			
		||||
 | 
			
		||||
    if (counters_need_update) {
 | 
			
		||||
        fast_timer_t now = timer_read_fast();
 | 
			
		||||
        fast_timer_t now          = timer_read_fast();
 | 
			
		||||
        fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
 | 
			
		||||
 | 
			
		||||
        last_time = now;
 | 
			
		||||
        last_time    = now;
 | 
			
		||||
        updated_last = true;
 | 
			
		||||
        if (elapsed_time > UINT8_MAX) {
 | 
			
		||||
            elapsed_time = UINT8_MAX;
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +107,7 @@ static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
 | 
			
		|||
        for (uint8_t col = 0; col < MATRIX_COLS; col++) {
 | 
			
		||||
            if (*debounce_pointer != DEBOUNCE_ELAPSED) {
 | 
			
		||||
                if (*debounce_pointer <= elapsed_time) {
 | 
			
		||||
                    *debounce_pointer = DEBOUNCE_ELAPSED;
 | 
			
		||||
                    *debounce_pointer  = DEBOUNCE_ELAPSED;
 | 
			
		||||
                    matrix_need_update = true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    *debounce_pointer -= elapsed_time;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,7 +49,7 @@ static debounce_counter_t *debounce_counters;
 | 
			
		|||
static fast_timer_t        last_time;
 | 
			
		||||
static bool                counters_need_update;
 | 
			
		||||
 | 
			
		||||
#define DEBOUNCE_ELAPSED 0
 | 
			
		||||
#    define DEBOUNCE_ELAPSED 0
 | 
			
		||||
 | 
			
		||||
static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time);
 | 
			
		||||
static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows);
 | 
			
		||||
| 
						 | 
				
			
			@ -71,10 +71,10 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
 | 
			
		|||
    bool updated_last = false;
 | 
			
		||||
 | 
			
		||||
    if (counters_need_update) {
 | 
			
		||||
        fast_timer_t now = timer_read_fast();
 | 
			
		||||
        fast_timer_t now          = timer_read_fast();
 | 
			
		||||
        fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time);
 | 
			
		||||
 | 
			
		||||
        last_time = now;
 | 
			
		||||
        last_time    = now;
 | 
			
		||||
        updated_last = true;
 | 
			
		||||
        if (elapsed_time > UINT8_MAX) {
 | 
			
		||||
            elapsed_time = UINT8_MAX;
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +102,7 @@ static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {
 | 
			
		|||
    for (uint8_t row = 0; row < num_rows; row++) {
 | 
			
		||||
        if (*debounce_pointer != DEBOUNCE_ELAPSED) {
 | 
			
		||||
            if (*debounce_pointer <= elapsed_time) {
 | 
			
		||||
                *debounce_pointer = DEBOUNCE_ELAPSED;
 | 
			
		||||
                *debounce_pointer  = DEBOUNCE_ELAPSED;
 | 
			
		||||
                matrix_need_update = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                *debounce_pointer -= elapsed_time;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,8 @@
 | 
			
		|||
#include "debounce_test_common.h"
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Release key after 1ms delay */
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +44,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Release key after 2ms delay */
 | 
			
		||||
        {2, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +60,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Release key after 3ms delay */
 | 
			
		||||
        {3, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +76,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort4) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Release key after 4ms delay */
 | 
			
		||||
        {4, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +92,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort5) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Release key after 5ms delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +107,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort6) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Release key after 6ms delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -116,7 +122,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort7) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Release key after 7ms delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +137,8 @@ TEST_F(DebounceTest, OneKeyShort7) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort8) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Release key after 1ms delay */
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +153,8 @@ TEST_F(DebounceTest, OneKeyShort8) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort9) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Release key after 1ms delay */
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -159,7 +168,8 @@ TEST_F(DebounceTest, OneKeyShort9) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
        {2, {{0, 1, DOWN}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +195,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Change twice in the same time period */
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +228,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        {25, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +248,8 @@ TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysShort) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
 | 
			
		||||
        /* Release key after 2ms delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -249,14 +262,14 @@ TEST_F(DebounceTest, TwoKeysShort) {
 | 
			
		|||
        {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
 | 
			
		||||
        /* Press key again after 1ms delay */
 | 
			
		||||
        {11, {{0, 1, DOWN}}, {{0, 1, DOWN}, {0, 2, UP}}}, /* 5ms+5ms after DOWN at time 0 */
 | 
			
		||||
        {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */
 | 
			
		||||
        {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}},             /* 5ms+5ms after DOWN at time 0 */
 | 
			
		||||
    });
 | 
			
		||||
    runEvents();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late, immediately release key */
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +282,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late, immediately release key */
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +297,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late */
 | 
			
		||||
| 
						 | 
				
			
			@ -298,7 +313,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan4) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late */
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +330,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan5) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        {5, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -329,7 +346,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan6) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        {5, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -345,7 +363,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan6) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan7) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        {5, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -358,7 +377,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan7) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan8) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is a bit late */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,9 +31,7 @@ void set_time(uint32_t t);
 | 
			
		|||
void advance_time(uint32_t ms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) {
 | 
			
		||||
    events_.insert(events_.end(), events.begin(), events.end());
 | 
			
		||||
}
 | 
			
		||||
void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) { events_.insert(events_.end(), events.begin(), events.end()); }
 | 
			
		||||
 | 
			
		||||
void DebounceTest::runEvents() {
 | 
			
		||||
    /* Run the test multiple times, from 1kHz to 10kHz scan rate */
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +52,7 @@ void DebounceTest::runEvents() {
 | 
			
		|||
 | 
			
		||||
void DebounceTest::runEventsInternal() {
 | 
			
		||||
    fast_timer_t previous = 0;
 | 
			
		||||
    bool first = true;
 | 
			
		||||
    bool         first    = true;
 | 
			
		||||
 | 
			
		||||
    /* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */
 | 
			
		||||
    debounce_init(MATRIX_ROWS);
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +78,7 @@ void DebounceTest::runEventsInternal() {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        first = false;
 | 
			
		||||
        first    = false;
 | 
			
		||||
        previous = event.time_;
 | 
			
		||||
 | 
			
		||||
        /* Prepare input matrix */
 | 
			
		||||
| 
						 | 
				
			
			@ -98,12 +96,7 @@ void DebounceTest::runEventsInternal() {
 | 
			
		|||
 | 
			
		||||
        /* Check output matrix has expected change events */
 | 
			
		||||
        for (auto &output : event.outputs_) {
 | 
			
		||||
            EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_))
 | 
			
		||||
                    << "Missing event at " << strTime()
 | 
			
		||||
                    << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_)
 | 
			
		||||
                    << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_)
 | 
			
		||||
                    << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
 | 
			
		||||
                    << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
 | 
			
		||||
            EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_)) << "Missing event at " << strTime() << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_) << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_) << "\nexpected_matrix:\n" << strMatrix(output_matrix_) << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Check output matrix has no other changes */
 | 
			
		||||
| 
						 | 
				
			
			@ -133,27 +126,20 @@ void DebounceTest::runDebounce(bool changed) {
 | 
			
		|||
    debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
 | 
			
		||||
 | 
			
		||||
    if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) {
 | 
			
		||||
        FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime()
 | 
			
		||||
            << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
 | 
			
		||||
            << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
 | 
			
		||||
        FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime() << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) {
 | 
			
		||||
    if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) {
 | 
			
		||||
        FAIL() << "Unexpected event: " << error_message << " at " << strTime()
 | 
			
		||||
            << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
 | 
			
		||||
            << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
 | 
			
		||||
            << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
 | 
			
		||||
        FAIL() << "Unexpected event: " << error_message << " at " << strTime() << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_) << "\nexpected_matrix:\n" << strMatrix(output_matrix_) << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string DebounceTest::strTime() {
 | 
			
		||||
    std::stringstream text;
 | 
			
		||||
 | 
			
		||||
    text << "time " << (timer_read_fast() - time_offset_)
 | 
			
		||||
        << " (extra_iterations=" << extra_iterations_
 | 
			
		||||
        << ", auto_advance_time=" << auto_advance_time_ << ")";
 | 
			
		||||
    text << "time " << (timer_read_fast() - time_offset_) << " (extra_iterations=" << extra_iterations_ << ", auto_advance_time=" << auto_advance_time_ << ")";
 | 
			
		||||
 | 
			
		||||
    return text.str();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -181,49 +167,39 @@ std::string DebounceTest::strMatrix(matrix_row_t matrix[]) {
 | 
			
		|||
 | 
			
		||||
bool DebounceTest::directionValue(Direction direction) {
 | 
			
		||||
    switch (direction) {
 | 
			
		||||
    case DOWN:
 | 
			
		||||
        return true;
 | 
			
		||||
        case DOWN:
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
    case UP:
 | 
			
		||||
        return false;
 | 
			
		||||
        case UP:
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string DebounceTest::directionLabel(Direction direction) {
 | 
			
		||||
    switch (direction) {
 | 
			
		||||
    case DOWN:
 | 
			
		||||
        return "DOWN";
 | 
			
		||||
        case DOWN:
 | 
			
		||||
            return "DOWN";
 | 
			
		||||
 | 
			
		||||
    case UP:
 | 
			
		||||
        return "UP";
 | 
			
		||||
        case UP:
 | 
			
		||||
            return "UP";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Modify a matrix and verify that events always specify a change */
 | 
			
		||||
void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) {
 | 
			
		||||
    ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_))
 | 
			
		||||
        << "Test " << name << " at " << strTime()
 | 
			
		||||
        << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_)
 | 
			
		||||
        << " but it is already " << directionLabel(event.direction_)
 | 
			
		||||
        << "\n" << name << "_matrix:\n" << strMatrix(matrix);
 | 
			
		||||
    ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_)) << "Test " << name << " at " << strTime() << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_) << " but it is already " << directionLabel(event.direction_) << "\n" << name << "_matrix:\n" << strMatrix(matrix);
 | 
			
		||||
 | 
			
		||||
    switch (event.direction_) {
 | 
			
		||||
    case DOWN:
 | 
			
		||||
        matrix[event.row_] |= (1U << event.col_);
 | 
			
		||||
        break;
 | 
			
		||||
        case DOWN:
 | 
			
		||||
            matrix[event.row_] |= (1U << event.col_);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
    case UP:
 | 
			
		||||
        matrix[event.row_] &= ~(1U << event.col_);
 | 
			
		||||
        break;
 | 
			
		||||
        case UP:
 | 
			
		||||
            matrix[event.row_] &= ~(1U << event.col_);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DebounceTestEvent::DebounceTestEvent(fast_timer_t time,
 | 
			
		||||
        std::initializer_list<MatrixTestEvent> inputs,
 | 
			
		||||
        std::initializer_list<MatrixTestEvent> outputs)
 | 
			
		||||
        : time_(time), inputs_(inputs), outputs_(outputs) {
 | 
			
		||||
}
 | 
			
		||||
DebounceTestEvent::DebounceTestEvent(fast_timer_t time, std::initializer_list<MatrixTestEvent> inputs, std::initializer_list<MatrixTestEvent> outputs) : time_(time), inputs_(inputs), outputs_(outputs) {}
 | 
			
		||||
 | 
			
		||||
MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction)
 | 
			
		||||
        : row_(row), col_(col), direction_(direction) {
 | 
			
		||||
}
 | 
			
		||||
MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction) : row_(row), col_(col), direction_(direction) {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,36 +31,34 @@ enum Direction {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
class MatrixTestEvent {
 | 
			
		||||
public:
 | 
			
		||||
   public:
 | 
			
		||||
    MatrixTestEvent(int row, int col, Direction direction);
 | 
			
		||||
 | 
			
		||||
    const int row_;
 | 
			
		||||
    const int col_;
 | 
			
		||||
    const int       row_;
 | 
			
		||||
    const int       col_;
 | 
			
		||||
    const Direction direction_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DebounceTestEvent {
 | 
			
		||||
public:
 | 
			
		||||
   public:
 | 
			
		||||
    // 0, {{0, 1, DOWN}}, {{0, 1, DOWN}})
 | 
			
		||||
    DebounceTestEvent(fast_timer_t time,
 | 
			
		||||
        std::initializer_list<MatrixTestEvent> inputs,
 | 
			
		||||
        std::initializer_list<MatrixTestEvent> outputs);
 | 
			
		||||
    DebounceTestEvent(fast_timer_t time, std::initializer_list<MatrixTestEvent> inputs, std::initializer_list<MatrixTestEvent> outputs);
 | 
			
		||||
 | 
			
		||||
    const fast_timer_t time_;
 | 
			
		||||
    const fast_timer_t               time_;
 | 
			
		||||
    const std::list<MatrixTestEvent> inputs_;
 | 
			
		||||
    const std::list<MatrixTestEvent> outputs_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DebounceTest : public ::testing::Test {
 | 
			
		||||
protected:
 | 
			
		||||
   protected:
 | 
			
		||||
    void addEvents(std::initializer_list<DebounceTestEvent> events);
 | 
			
		||||
    void runEvents();
 | 
			
		||||
 | 
			
		||||
    fast_timer_t time_offset_ = 7777;
 | 
			
		||||
    bool time_jumps_ = false;
 | 
			
		||||
    bool         time_jumps_  = false;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static bool directionValue(Direction direction);
 | 
			
		||||
   private:
 | 
			
		||||
    static bool        directionValue(Direction direction);
 | 
			
		||||
    static std::string directionLabel(Direction direction);
 | 
			
		||||
 | 
			
		||||
    void runEventsInternal();
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +76,6 @@ private:
 | 
			
		|||
    matrix_row_t cooked_matrix_[MATRIX_ROWS];
 | 
			
		||||
    matrix_row_t output_matrix_[MATRIX_ROWS];
 | 
			
		||||
 | 
			
		||||
    int extra_iterations_;
 | 
			
		||||
    int  extra_iterations_;
 | 
			
		||||
    bool auto_advance_time_;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,8 @@
 | 
			
		|||
#include "debounce_test_common.h"
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyTooQuick1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        /* Release key exactly on the debounce time */
 | 
			
		||||
        {5, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +71,8 @@ TEST_F(DebounceTest, OneKeyTooQuick1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyTooQuick2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +85,8 @@ TEST_F(DebounceTest, OneKeyTooQuick2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
        {2, {{0, 1, DOWN}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +100,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
        {6, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +115,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +133,8 @@ TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysShort) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        {1, {{0, 2, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +149,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +162,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        {1, {{0, 2, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +178,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late */
 | 
			
		||||
| 
						 | 
				
			
			@ -182,7 +194,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late */
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +210,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        /* Release key before debounce expires */
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +222,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan4) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is a bit late */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,8 @@
 | 
			
		|||
#include "debounce_test_common.h"
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyTooQuick1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        /* Release key exactly on the debounce time */
 | 
			
		||||
        {5, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +71,8 @@ TEST_F(DebounceTest, OneKeyTooQuick1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyTooQuick2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +85,8 @@ TEST_F(DebounceTest, OneKeyTooQuick2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
        {2, {{0, 1, DOWN}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +100,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
        {6, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +115,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +133,8 @@ TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysShort) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        {1, {{0, 2, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +151,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +164,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
        {1, {{0, 2, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +180,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late */
 | 
			
		||||
| 
						 | 
				
			
			@ -184,7 +196,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late */
 | 
			
		||||
| 
						 | 
				
			
			@ -199,7 +212,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        /* Release key before debounce expires */
 | 
			
		||||
| 
						 | 
				
			
			@ -210,7 +224,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan4) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is a bit late */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,8 @@
 | 
			
		|||
#include "debounce_test_common.h"
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort4) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +75,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort5) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +88,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort6) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +101,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
        {2, {{0, 1, DOWN}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +117,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Change twice in the same time period */
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +143,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        {25, {{0, 1, UP}}, {{0, 1, UP}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +155,8 @@ TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysShort) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
        {2, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +177,8 @@ TEST_F(DebounceTest, TwoKeysShort) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted */
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +189,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted even with a 1 scan delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -190,7 +202,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted even with a 1ms delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +215,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan4) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is a bit late but the change will now be accepted */
 | 
			
		||||
| 
						 | 
				
			
			@ -213,7 +227,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan5) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted even with a 1 scan delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -225,7 +240,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan6) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted even with a 1ms delay */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,8 @@
 | 
			
		|||
#include "debounce_test_common.h"
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +33,8 @@ TEST_F(DebounceTest, OneKeyShort1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +47,8 @@ TEST_F(DebounceTest, OneKeyShort2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +61,8 @@ TEST_F(DebounceTest, OneKeyShort3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort4) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +75,8 @@ TEST_F(DebounceTest, OneKeyShort4) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort5) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +88,8 @@ TEST_F(DebounceTest, OneKeyShort5) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyShort6) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +101,8 @@ TEST_F(DebounceTest, OneKeyShort6) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
        {2, {{0, 1, DOWN}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +117,8 @@ TEST_F(DebounceTest, OneKeyBouncing1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        /* Change twice in the same time period */
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +143,8 @@ TEST_F(DebounceTest, OneKeyBouncing2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        {25, {{0, 1, UP}}, {{0, 1, UP}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +155,8 @@ TEST_F(DebounceTest, OneKeyLong) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoRowsShort) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
        {2, {{2, 0, DOWN}}, {{2, 0, DOWN}}},
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +177,8 @@ TEST_F(DebounceTest, TwoRowsShort) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysOverlap) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
        {1, {{0, 1, UP}}, {}},
 | 
			
		||||
        /* Press a second key during the first debounce */
 | 
			
		||||
| 
						 | 
				
			
			@ -190,7 +201,8 @@ TEST_F(DebounceTest, TwoKeysOverlap) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
 | 
			
		||||
        {20, {{0, 1, UP}}, {{0, 1, UP}}},
 | 
			
		||||
        {21, {{0, 2, UP}}, {}},
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +214,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
 | 
			
		||||
        {20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}},
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			@ -210,7 +223,8 @@ TEST_F(DebounceTest, TwoKeysSimultaneous2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted */
 | 
			
		||||
| 
						 | 
				
			
			@ -221,7 +235,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan1) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted even with a 1 scan delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -233,7 +248,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted even with a 1ms delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +261,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan3) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan4) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is a bit late but the change will now be accepted */
 | 
			
		||||
| 
						 | 
				
			
			@ -256,7 +273,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan4) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan5) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted even with a 1 scan delay */
 | 
			
		||||
| 
						 | 
				
			
			@ -268,7 +286,8 @@ TEST_F(DebounceTest, OneKeyDelayedScan5) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(DebounceTest, OneKeyDelayedScan6) {
 | 
			
		||||
    addEvents({ /* Time, Inputs, Outputs */
 | 
			
		||||
    addEvents({
 | 
			
		||||
        /* Time, Inputs, Outputs */
 | 
			
		||||
        {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
 | 
			
		||||
 | 
			
		||||
        /* Processing is very late but the change will now be accepted even with a 1ms delay */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,8 +74,7 @@ enum steno_keycodes {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
#ifdef STENO_COMBINEDMAP
 | 
			
		||||
enum steno_combined_keycodes
 | 
			
		||||
{
 | 
			
		||||
enum steno_combined_keycodes {
 | 
			
		||||
    STN_S3 = QK_STENO_COMB,
 | 
			
		||||
    STN_TKL,
 | 
			
		||||
    STN_PWL,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,10 +18,9 @@
 | 
			
		|||
#include "process_combo.h"
 | 
			
		||||
#include "action_tapping.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef COMBO_COUNT
 | 
			
		||||
__attribute__((weak)) combo_t  key_combos[COMBO_COUNT];
 | 
			
		||||
uint16_t COMBO_LEN = COMBO_COUNT;
 | 
			
		||||
__attribute__((weak)) combo_t key_combos[COMBO_COUNT];
 | 
			
		||||
uint16_t                      COMBO_LEN = COMBO_COUNT;
 | 
			
		||||
#else
 | 
			
		||||
extern combo_t  key_combos[];
 | 
			
		||||
extern uint16_t COMBO_LEN;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,64 +45,86 @@ __attribute__((weak)) bool process_combo_key_release(uint16_t combo_index, combo
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef COMBO_NO_TIMER
 | 
			
		||||
static uint16_t timer                 = 0;
 | 
			
		||||
static uint16_t timer = 0;
 | 
			
		||||
#endif
 | 
			
		||||
static bool     b_combo_enable        = true;  // defaults to enabled
 | 
			
		||||
static uint16_t longest_term          = 0;
 | 
			
		||||
static bool     b_combo_enable = true;  // defaults to enabled
 | 
			
		||||
static uint16_t longest_term   = 0;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    keyrecord_t record;
 | 
			
		||||
    uint16_t combo_index;
 | 
			
		||||
    uint16_t keycode;
 | 
			
		||||
    uint16_t    combo_index;
 | 
			
		||||
    uint16_t    keycode;
 | 
			
		||||
} queued_record_t;
 | 
			
		||||
static uint8_t key_buffer_size = 0;
 | 
			
		||||
static uint8_t         key_buffer_size = 0;
 | 
			
		||||
static queued_record_t key_buffer[COMBO_KEY_BUFFER_LENGTH];
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint16_t combo_index;
 | 
			
		||||
} queued_combo_t;
 | 
			
		||||
static uint8_t combo_buffer_write= 0;
 | 
			
		||||
static uint8_t combo_buffer_read = 0;
 | 
			
		||||
static uint8_t        combo_buffer_write = 0;
 | 
			
		||||
static uint8_t        combo_buffer_read  = 0;
 | 
			
		||||
static queued_combo_t combo_buffer[COMBO_BUFFER_LENGTH];
 | 
			
		||||
 | 
			
		||||
#define INCREMENT_MOD(i) i = (i + 1) % COMBO_BUFFER_LENGTH
 | 
			
		||||
 | 
			
		||||
#define COMBO_KEY_POS ((keypos_t){.col=254, .row=254})
 | 
			
		||||
 | 
			
		||||
#define COMBO_KEY_POS ((keypos_t){.col = 254, .row = 254})
 | 
			
		||||
 | 
			
		||||
#ifndef EXTRA_SHORT_COMBOS
 | 
			
		||||
/* flags are their own elements in combo_t struct. */
 | 
			
		||||
#    define COMBO_ACTIVE(combo)   (combo->active)
 | 
			
		||||
#    define COMBO_ACTIVE(combo) (combo->active)
 | 
			
		||||
#    define COMBO_DISABLED(combo) (combo->disabled)
 | 
			
		||||
#    define COMBO_STATE(combo)    (combo->state)
 | 
			
		||||
#    define COMBO_STATE(combo) (combo->state)
 | 
			
		||||
 | 
			
		||||
#    define ACTIVATE_COMBO(combo)    do {combo->active = true;}while(0)
 | 
			
		||||
#    define DEACTIVATE_COMBO(combo)  do {combo->active = false;}while(0)
 | 
			
		||||
#    define DISABLE_COMBO(combo)     do {combo->disabled = true;}while(0)
 | 
			
		||||
#    define RESET_COMBO_STATE(combo) do { \
 | 
			
		||||
    combo->disabled = false; \
 | 
			
		||||
    combo->state = 0; \
 | 
			
		||||
}while(0)
 | 
			
		||||
#    define ACTIVATE_COMBO(combo) \
 | 
			
		||||
        do {                      \
 | 
			
		||||
            combo->active = true; \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#    define DEACTIVATE_COMBO(combo) \
 | 
			
		||||
        do {                        \
 | 
			
		||||
            combo->active = false;  \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#    define DISABLE_COMBO(combo)    \
 | 
			
		||||
        do {                        \
 | 
			
		||||
            combo->disabled = true; \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#    define RESET_COMBO_STATE(combo) \
 | 
			
		||||
        do {                         \
 | 
			
		||||
            combo->disabled = false; \
 | 
			
		||||
            combo->state    = 0;     \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#else
 | 
			
		||||
/* flags are at the two high bits of state. */
 | 
			
		||||
#    define COMBO_ACTIVE(combo)   (combo->state & 0x80)
 | 
			
		||||
#    define COMBO_ACTIVE(combo) (combo->state & 0x80)
 | 
			
		||||
#    define COMBO_DISABLED(combo) (combo->state & 0x40)
 | 
			
		||||
#    define COMBO_STATE(combo)    (combo->state & 0x3F)
 | 
			
		||||
#    define COMBO_STATE(combo) (combo->state & 0x3F)
 | 
			
		||||
 | 
			
		||||
#    define ACTIVATE_COMBO(combo)    do {combo->state |= 0x80;}while(0)
 | 
			
		||||
#    define DEACTIVATE_COMBO(combo)  do {combo->state &= ~0x80;}while(0)
 | 
			
		||||
#    define DISABLE_COMBO(combo)     do {combo->state |= 0x40;}while(0)
 | 
			
		||||
#    define RESET_COMBO_STATE(combo) do {combo->state &= ~0x7F;}while(0)
 | 
			
		||||
#    define ACTIVATE_COMBO(combo) \
 | 
			
		||||
        do {                      \
 | 
			
		||||
            combo->state |= 0x80; \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#    define DEACTIVATE_COMBO(combo) \
 | 
			
		||||
        do {                        \
 | 
			
		||||
            combo->state &= ~0x80;  \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#    define DISABLE_COMBO(combo)  \
 | 
			
		||||
        do {                      \
 | 
			
		||||
            combo->state |= 0x40; \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#    define RESET_COMBO_STATE(combo) \
 | 
			
		||||
        do {                         \
 | 
			
		||||
            combo->state &= ~0x7F;   \
 | 
			
		||||
        } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline void release_combo(uint16_t combo_index, combo_t *combo) {
 | 
			
		||||
    if (combo->keycode) {
 | 
			
		||||
        keyrecord_t record = {
 | 
			
		||||
            .event = {
 | 
			
		||||
                .key = COMBO_KEY_POS,
 | 
			
		||||
                .time = timer_read()|1,
 | 
			
		||||
                .pressed = false,
 | 
			
		||||
            },
 | 
			
		||||
            .event =
 | 
			
		||||
                {
 | 
			
		||||
                    .key     = COMBO_KEY_POS,
 | 
			
		||||
                    .time    = timer_read() | 1,
 | 
			
		||||
                    .pressed = false,
 | 
			
		||||
                },
 | 
			
		||||
            .keycode = combo->keycode,
 | 
			
		||||
        };
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
| 
						 | 
				
			
			@ -123,18 +144,17 @@ static inline bool _get_combo_must_hold(uint16_t combo_index, combo_t *combo) {
 | 
			
		|||
#elif defined(COMBO_MUST_HOLD_PER_COMBO)
 | 
			
		||||
    return get_combo_must_hold(combo_index, combo);
 | 
			
		||||
#elif defined(COMBO_MUST_HOLD_MODS)
 | 
			
		||||
    return (KEYCODE_IS_MOD(combo->keycode) ||
 | 
			
		||||
            (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX));
 | 
			
		||||
    return (KEYCODE_IS_MOD(combo->keycode) || (combo->keycode >= QK_MOMENTARY && combo->keycode <= QK_MOMENTARY_MAX));
 | 
			
		||||
#endif
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) {
 | 
			
		||||
static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo) {
 | 
			
		||||
    if (_get_combo_must_hold(combo_index, combo)
 | 
			
		||||
#ifdef COMBO_MUST_TAP_PER_COMBO
 | 
			
		||||
            || get_combo_must_tap(combo_index, combo)
 | 
			
		||||
        || get_combo_must_tap(combo_index, combo)
 | 
			
		||||
#endif
 | 
			
		||||
       ) {
 | 
			
		||||
    ) {
 | 
			
		||||
        if (longest_term < COMBO_HOLD_TERM) {
 | 
			
		||||
            return COMBO_HOLD_TERM;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -144,9 +164,8 @@ static inline uint16_t _get_wait_time(uint16_t combo_index, combo_t *combo ) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) {
 | 
			
		||||
 | 
			
		||||
#if defined(COMBO_TERM_PER_COMBO)
 | 
			
		||||
        return get_combo_term(combo_index, combo);
 | 
			
		||||
    return get_combo_term(combo_index, combo);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return COMBO_TERM;
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +173,7 @@ static inline uint16_t _get_combo_term(uint16_t combo_index, combo_t *combo) {
 | 
			
		|||
 | 
			
		||||
void clear_combos(void) {
 | 
			
		||||
    uint16_t index = 0;
 | 
			
		||||
    longest_term = 0;
 | 
			
		||||
    longest_term   = 0;
 | 
			
		||||
    for (index = 0; index < COMBO_LEN; ++index) {
 | 
			
		||||
        combo_t *combo = &key_combos[index];
 | 
			
		||||
        if (!COMBO_ACTIVE(combo)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -175,7 +194,7 @@ static inline void dump_key_buffer(void) {
 | 
			
		|||
        key_buffer_next = key_buffer_i + 1;
 | 
			
		||||
 | 
			
		||||
        queued_record_t *qrecord = &key_buffer[key_buffer_i];
 | 
			
		||||
        keyrecord_t *record = &qrecord->record;
 | 
			
		||||
        keyrecord_t *    record  = &qrecord->record;
 | 
			
		||||
 | 
			
		||||
        if (IS_NOEVENT(record->event)) {
 | 
			
		||||
            continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -185,9 +204,9 @@ static inline void dump_key_buffer(void) {
 | 
			
		|||
            process_combo_event(qrecord->combo_index, true);
 | 
			
		||||
        } else {
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
        action_tapping_process(*record);
 | 
			
		||||
            action_tapping_process(*record);
 | 
			
		||||
#else
 | 
			
		||||
        process_record(record);
 | 
			
		||||
            process_record(record);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
        record->event.time = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -242,7 +261,9 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
 | 
			
		|||
    /* Apply combo's result keycode to the last chord key of the combo and
 | 
			
		||||
     * disable the other keys. */
 | 
			
		||||
 | 
			
		||||
    if (COMBO_DISABLED(combo)) { return; }
 | 
			
		||||
    if (COMBO_DISABLED(combo)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // state to check against so we find the last key of the combo from the buffer
 | 
			
		||||
#if defined(EXTRA_EXTRA_LONG_COMBOS)
 | 
			
		||||
| 
						 | 
				
			
			@ -254,12 +275,11 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
    for (uint8_t key_buffer_i = 0; key_buffer_i < key_buffer_size; key_buffer_i++) {
 | 
			
		||||
 | 
			
		||||
        queued_record_t *qrecord = &key_buffer[key_buffer_i];
 | 
			
		||||
        keyrecord_t *record = &qrecord->record;
 | 
			
		||||
        uint16_t keycode = qrecord->keycode;
 | 
			
		||||
        keyrecord_t *    record  = &qrecord->record;
 | 
			
		||||
        uint16_t         keycode = qrecord->keycode;
 | 
			
		||||
 | 
			
		||||
        uint8_t key_count = 0;
 | 
			
		||||
        uint8_t  key_count = 0;
 | 
			
		||||
        uint16_t key_index = -1;
 | 
			
		||||
        _find_key_index_and_count(combo->keys, keycode, &key_index, &key_count);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -271,7 +291,7 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
 | 
			
		|||
        KEY_STATE_DOWN(state, key_index);
 | 
			
		||||
        if (ALL_COMBO_KEYS_ARE_DOWN(state, key_count)) {
 | 
			
		||||
            // this in the end executes the combo when the key_buffer is dumped.
 | 
			
		||||
            record->keycode = combo->keycode;
 | 
			
		||||
            record->keycode   = combo->keycode;
 | 
			
		||||
            record->event.key = COMBO_KEY_POS;
 | 
			
		||||
 | 
			
		||||
            qrecord->combo_index = combo_index;
 | 
			
		||||
| 
						 | 
				
			
			@ -283,19 +303,15 @@ void apply_combo(uint16_t combo_index, combo_t *combo) {
 | 
			
		|||
            // by making it a TICK event.
 | 
			
		||||
            record->event.time = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    drop_combo_from_buffer(combo_index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void apply_combos(void) {
 | 
			
		||||
    // Apply all buffered normal combos.
 | 
			
		||||
    for (uint8_t i = combo_buffer_read;
 | 
			
		||||
            i != combo_buffer_write;
 | 
			
		||||
            INCREMENT_MOD(i)) {
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = combo_buffer_read; i != combo_buffer_write; INCREMENT_MOD(i)) {
 | 
			
		||||
        queued_combo_t *buffered_combo = &combo_buffer[i];
 | 
			
		||||
        combo_t *combo = &key_combos[buffered_combo->combo_index];
 | 
			
		||||
        combo_t *       combo          = &key_combos[buffered_combo->combo_index];
 | 
			
		||||
 | 
			
		||||
#ifdef COMBO_MUST_TAP_PER_COMBO
 | 
			
		||||
        if (get_combo_must_tap(buffered_combo->combo_index, combo)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -310,15 +326,15 @@ static inline void apply_combos(void) {
 | 
			
		|||
    clear_combos();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
combo_t* overlaps(combo_t *combo1, combo_t *combo2) {
 | 
			
		||||
combo_t *overlaps(combo_t *combo1, combo_t *combo2) {
 | 
			
		||||
    /* Checks if the combos overlap and returns the combo that should be
 | 
			
		||||
     * dropped from the combo buffer.
 | 
			
		||||
     * The combo that has less keys will be dropped. If they have the same
 | 
			
		||||
     * amount of keys, drop combo1. */
 | 
			
		||||
 | 
			
		||||
    uint8_t idx1 = 0, idx2 = 0;
 | 
			
		||||
    uint8_t  idx1 = 0, idx2 = 0;
 | 
			
		||||
    uint16_t key1, key2;
 | 
			
		||||
    bool overlaps = false;
 | 
			
		||||
    bool     overlaps = false;
 | 
			
		||||
 | 
			
		||||
    while ((key1 = pgm_read_word(&combo1->keys[idx1])) != COMBO_END) {
 | 
			
		||||
        idx2 = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -335,7 +351,7 @@ combo_t* overlaps(combo_t *combo1, combo_t *combo2) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record, uint16_t combo_index) {
 | 
			
		||||
    uint8_t key_count = 0;
 | 
			
		||||
    uint8_t  key_count = 0;
 | 
			
		||||
    uint16_t key_index = -1;
 | 
			
		||||
    _find_key_index_and_count(combo->keys, keycode, &key_index, &key_count);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -369,12 +385,9 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
 | 
			
		|||
 | 
			
		||||
                // disable readied combos that overlap with this combo
 | 
			
		||||
                combo_t *drop = NULL;
 | 
			
		||||
                for (uint8_t combo_buffer_i = combo_buffer_read;
 | 
			
		||||
                        combo_buffer_i != combo_buffer_write;
 | 
			
		||||
                        INCREMENT_MOD(combo_buffer_i)) {
 | 
			
		||||
 | 
			
		||||
                    queued_combo_t *qcombo = &combo_buffer[combo_buffer_i];
 | 
			
		||||
                    combo_t *buffered_combo = &key_combos[qcombo->combo_index];
 | 
			
		||||
                for (uint8_t combo_buffer_i = combo_buffer_read; combo_buffer_i != combo_buffer_write; INCREMENT_MOD(combo_buffer_i)) {
 | 
			
		||||
                    queued_combo_t *qcombo         = &combo_buffer[combo_buffer_i];
 | 
			
		||||
                    combo_t *       buffered_combo = &key_combos[qcombo->combo_index];
 | 
			
		||||
 | 
			
		||||
                    if ((drop = overlaps(buffered_combo, combo))) {
 | 
			
		||||
                        DISABLE_COMBO(drop);
 | 
			
		||||
| 
						 | 
				
			
			@ -387,21 +400,19 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
 | 
			
		|||
                            INCREMENT_MOD(combo_buffer_read);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (drop != combo) {
 | 
			
		||||
                    // save this combo to buffer
 | 
			
		||||
                    combo_buffer[combo_buffer_write] = (queued_combo_t){
 | 
			
		||||
                        .combo_index=combo_index,
 | 
			
		||||
                        .combo_index = combo_index,
 | 
			
		||||
                    };
 | 
			
		||||
                    INCREMENT_MOD(combo_buffer_write);
 | 
			
		||||
 | 
			
		||||
                    // get possible longer waiting time for tap-/hold-only combos.
 | 
			
		||||
                    longest_term = _get_wait_time(combo_index, combo);
 | 
			
		||||
                }
 | 
			
		||||
            } // if timer elapsed end
 | 
			
		||||
 | 
			
		||||
            }  // if timer elapsed end
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // chord releases
 | 
			
		||||
| 
						 | 
				
			
			@ -416,7 +427,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
 | 
			
		|||
            else if (get_combo_must_tap(combo_index, combo)) {
 | 
			
		||||
                // immediately apply tap-only combo
 | 
			
		||||
                apply_combo(combo_index, combo);
 | 
			
		||||
                apply_combos(); // also apply other prepared combos and dump key buffer
 | 
			
		||||
                apply_combos();  // also apply other prepared combos and dump key buffer
 | 
			
		||||
#    ifdef COMBO_PROCESS_KEY_RELEASE
 | 
			
		||||
                if (process_combo_key_release(combo_index, combo, key_index, keycode)) {
 | 
			
		||||
                    release_combo(combo_index, combo);
 | 
			
		||||
| 
						 | 
				
			
			@ -424,10 +435,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
 | 
			
		|||
#    endif
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
        } else if (COMBO_ACTIVE(combo)
 | 
			
		||||
                && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo))
 | 
			
		||||
                && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)
 | 
			
		||||
                ) {
 | 
			
		||||
        } else if (COMBO_ACTIVE(combo) && ONLY_ONE_KEY_IS_DOWN(COMBO_STATE(combo)) && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)) {
 | 
			
		||||
            /* last key released */
 | 
			
		||||
            release_combo(combo_index, combo);
 | 
			
		||||
            key_is_part_of_combo = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -435,9 +443,7 @@ static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *
 | 
			
		|||
#ifdef COMBO_PROCESS_KEY_RELEASE
 | 
			
		||||
            process_combo_key_release(combo_index, combo, key_index, keycode);
 | 
			
		||||
#endif
 | 
			
		||||
        } else if (COMBO_ACTIVE(combo)
 | 
			
		||||
                && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)
 | 
			
		||||
                ) {
 | 
			
		||||
        } else if (COMBO_ACTIVE(combo) && KEY_NOT_YET_RELEASED(COMBO_STATE(combo), key_index)) {
 | 
			
		||||
            /* first or middle key released */
 | 
			
		||||
            key_is_part_of_combo = true;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -489,21 +495,21 @@ bool process_combo(uint16_t keycode, keyrecord_t *record) {
 | 
			
		|||
 | 
			
		||||
    if (record->event.pressed && is_combo_key) {
 | 
			
		||||
#ifndef COMBO_NO_TIMER
 | 
			
		||||
#   ifdef COMBO_STRICT_TIMER
 | 
			
		||||
#    ifdef COMBO_STRICT_TIMER
 | 
			
		||||
        if (!timer) {
 | 
			
		||||
            // timer is set only on the first key
 | 
			
		||||
            timer = timer_read();
 | 
			
		||||
        }
 | 
			
		||||
#   else
 | 
			
		||||
#    else
 | 
			
		||||
        timer = timer_read();
 | 
			
		||||
#   endif
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        if (key_buffer_size < COMBO_KEY_BUFFER_LENGTH) {
 | 
			
		||||
            key_buffer[key_buffer_size++] = (queued_record_t){
 | 
			
		||||
                .record = *record,
 | 
			
		||||
                .keycode = keycode,
 | 
			
		||||
                .combo_index = -1, // this will be set when applying combos
 | 
			
		||||
                .record      = *record,
 | 
			
		||||
                .keycode     = keycode,
 | 
			
		||||
                .combo_index = -1,  // this will be set when applying combos
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -532,7 +538,7 @@ void combo_task(void) {
 | 
			
		|||
        if (combo_buffer_read != combo_buffer_write) {
 | 
			
		||||
            apply_combos();
 | 
			
		||||
            longest_term = 0;
 | 
			
		||||
            timer = 0;
 | 
			
		||||
            timer        = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            dump_key_buffer();
 | 
			
		||||
            timer = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -546,9 +552,9 @@ void combo_enable(void) { b_combo_enable = true; }
 | 
			
		|||
 | 
			
		||||
void combo_disable(void) {
 | 
			
		||||
#ifndef COMBO_NO_TIMER
 | 
			
		||||
    timer                      = 0;
 | 
			
		||||
    timer = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    b_combo_enable = false;
 | 
			
		||||
    b_combo_enable    = false;
 | 
			
		||||
    combo_buffer_read = combo_buffer_write;
 | 
			
		||||
    clear_combos();
 | 
			
		||||
    dump_key_buffer();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,8 +43,8 @@ typedef struct {
 | 
			
		|||
#ifdef EXTRA_SHORT_COMBOS
 | 
			
		||||
    uint8_t state;
 | 
			
		||||
#else
 | 
			
		||||
    bool disabled;
 | 
			
		||||
    bool active;
 | 
			
		||||
    bool     disabled;
 | 
			
		||||
    bool     active;
 | 
			
		||||
#    if defined(EXTRA_EXTRA_LONG_COMBOS)
 | 
			
		||||
    uint32_t state;
 | 
			
		||||
#    elif defined(EXTRA_LONG_COMBOS)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM,
 | 
			
		|||
 | 
			
		||||
#ifdef STENO_COMBINEDMAP
 | 
			
		||||
/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */
 | 
			
		||||
static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
 | 
			
		||||
static const uint16_t combinedmap_first[] PROGMEM  = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E};
 | 
			
		||||
static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -174,11 +174,10 @@ bool process_steno(uint16_t keycode, keyrecord_t *record) {
 | 
			
		|||
            return false;
 | 
			
		||||
 | 
			
		||||
#ifdef STENO_COMBINEDMAP
 | 
			
		||||
        case QK_STENO_COMB ... QK_STENO_COMB_MAX:
 | 
			
		||||
        {
 | 
			
		||||
        case QK_STENO_COMB ... QK_STENO_COMB_MAX: {
 | 
			
		||||
            uint8_t result;
 | 
			
		||||
            result = process_steno(combinedmap_first[keycode-QK_STENO_COMB], record);
 | 
			
		||||
            result &= process_steno(combinedmap_second[keycode-QK_STENO_COMB], record);
 | 
			
		||||
            result = process_steno(combinedmap_first[keycode - QK_STENO_COMB], record);
 | 
			
		||||
            result &= process_steno(combinedmap_second[keycode - QK_STENO_COMB], record);
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -145,12 +145,13 @@ void reset_keyboard(void) {
 | 
			
		|||
/* Convert record into usable keycode via the contained event. */
 | 
			
		||||
uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) {
 | 
			
		||||
#ifdef COMBO_ENABLE
 | 
			
		||||
    if (record->keycode) { return record->keycode; }
 | 
			
		||||
    if (record->keycode) {
 | 
			
		||||
        return record->keycode;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    return get_event_keycode(record->event, update_layer_cache);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Convert event into usable keycode. Checks the layer cache to ensure that it
 | 
			
		||||
 * retains the correct keycode after a layer change, if the key is still pressed.
 | 
			
		||||
 * "update_layer_cache" is to ensure that it only updates the layer cache when
 | 
			
		||||
| 
						 | 
				
			
			@ -179,12 +180,12 @@ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) {
 | 
			
		|||
bool pre_process_record_quantum(keyrecord_t *record) {
 | 
			
		||||
    if (!(
 | 
			
		||||
#ifdef COMBO_ENABLE
 | 
			
		||||
        process_combo(get_record_keycode(record, true), record) &&
 | 
			
		||||
            process_combo(get_record_keycode(record, true), record) &&
 | 
			
		||||
#endif
 | 
			
		||||
        true)) {
 | 
			
		||||
            true)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true; // continue processing
 | 
			
		||||
    return true;  // continue processing
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get keycode, and then call keyboard function */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -775,12 +775,12 @@ enum quantum_keycodes {
 | 
			
		|||
#define CMD_T(kc) LCMD_T(kc)
 | 
			
		||||
#define WIN_T(kc) LWIN_T(kc)
 | 
			
		||||
 | 
			
		||||
#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc)  // Left Control + Shift e.g. for gnome-terminal
 | 
			
		||||
#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc)  // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
 | 
			
		||||
#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc)  // Left Control + Alt + GUI
 | 
			
		||||
#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc)  // Right Control + Alt + GUI
 | 
			
		||||
#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc)                         // Left Control + Shift e.g. for gnome-terminal
 | 
			
		||||
#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc)              // Meh is a less hyper version of the Hyper key -- doesn't include GUI, so just Left Control + Shift + Alt
 | 
			
		||||
#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc)             // Left Control + Alt + GUI
 | 
			
		||||
#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc)             // Right Control + Alt + GUI
 | 
			
		||||
#define HYPR_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc)  // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
 | 
			
		||||
#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc)  // Left Shift + GUI
 | 
			
		||||
#define LSG_T(kc) MT(MOD_LSFT | MOD_LGUI, kc)                         // Left Shift + GUI
 | 
			
		||||
#define SGUI_T(kc) LSG_T(kc)
 | 
			
		||||
#define SCMD_T(kc) LSG_T(kc)
 | 
			
		||||
#define SWIN_T(kc) LSG_T(kc)
 | 
			
		||||
| 
						 | 
				
			
			@ -811,7 +811,7 @@ enum quantum_keycodes {
 | 
			
		|||
 | 
			
		||||
#define UC_M_MA UNICODE_MODE_MAC
 | 
			
		||||
#define UNICODE_MODE_OSX UNICODE_MODE_MAC  // Deprecated alias
 | 
			
		||||
#define UC_M_OS UNICODE_MODE_MAC  // Deprecated alias
 | 
			
		||||
#define UC_M_OS UNICODE_MODE_MAC           // Deprecated alias
 | 
			
		||||
#define UC_M_LN UNICODE_MODE_LNX
 | 
			
		||||
#define UC_M_WI UNICODE_MODE_WIN
 | 
			
		||||
#define UC_M_BS UNICODE_MODE_BSD
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,8 +42,8 @@
 | 
			
		|||
    { &dummy, 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb }
 | 
			
		||||
#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL)
 | 
			
		||||
 | 
			
		||||
#define transport_write(id, data, length)          transport_execute_transaction(id, data, length, NULL, 0)
 | 
			
		||||
#define transport_read(id, data, length)           transport_execute_transaction(id, NULL, 0, data, length)
 | 
			
		||||
#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
 | 
			
		||||
#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
 | 
			
		||||
 | 
			
		||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
 | 
			
		||||
// Forward-declare the RPC callback handlers
 | 
			
		||||
| 
						 | 
				
			
			@ -157,8 +157,8 @@ static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_ro
 | 
			
		|||
    memcpy(master_matrix, split_shmem->mmatrix.matrix, sizeof(split_shmem->mmatrix.matrix));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_MASTER_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(master_matrix)
 | 
			
		||||
#    define TRANSACTIONS_MASTER_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(master_matrix)
 | 
			
		||||
#    define TRANSACTIONS_MASTER_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(master_matrix)
 | 
			
		||||
#    define TRANSACTIONS_MASTER_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(master_matrix)
 | 
			
		||||
#    define TRANSACTIONS_MASTER_MATRIX_REGISTRATIONS [PUT_MASTER_MATRIX] = trans_initiator2target_initializer(mmatrix.matrix),
 | 
			
		||||
 | 
			
		||||
#else  // SPLIT_TRANSPORT_MIRROR
 | 
			
		||||
| 
						 | 
				
			
			@ -235,8 +235,8 @@ static void sync_timer_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_SYNC_TIMER_MASTER()      TRANSACTION_HANDLER_MASTER(sync_timer)
 | 
			
		||||
#    define TRANSACTIONS_SYNC_TIMER_SLAVE()       TRANSACTION_HANDLER_SLAVE(sync_timer)
 | 
			
		||||
#    define TRANSACTIONS_SYNC_TIMER_MASTER() TRANSACTION_HANDLER_MASTER(sync_timer)
 | 
			
		||||
#    define TRANSACTIONS_SYNC_TIMER_SLAVE() TRANSACTION_HANDLER_SLAVE(sync_timer)
 | 
			
		||||
#    define TRANSACTIONS_SYNC_TIMER_REGISTRATIONS [PUT_SYNC_TIMER] = trans_initiator2target_initializer(sync_timer),
 | 
			
		||||
 | 
			
		||||
#else  // DISABLE_SYNC_TIMER
 | 
			
		||||
| 
						 | 
				
			
			@ -300,8 +300,8 @@ static void led_state_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
 | 
			
		|||
    set_split_host_keyboard_leds(split_shmem->led_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_LED_STATE_MASTER()      TRANSACTION_HANDLER_MASTER(led_state)
 | 
			
		||||
#    define TRANSACTIONS_LED_STATE_SLAVE()       TRANSACTION_HANDLER_SLAVE(led_state)
 | 
			
		||||
#    define TRANSACTIONS_LED_STATE_MASTER() TRANSACTION_HANDLER_MASTER(led_state)
 | 
			
		||||
#    define TRANSACTIONS_LED_STATE_SLAVE() TRANSACTION_HANDLER_SLAVE(led_state)
 | 
			
		||||
#    define TRANSACTIONS_LED_STATE_REGISTRATIONS [PUT_LED_STATE] = trans_initiator2target_initializer(led_state),
 | 
			
		||||
 | 
			
		||||
#else  // SPLIT_LED_STATE_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -357,8 +357,8 @@ static void mods_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave
 | 
			
		|||
#    endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_MODS_MASTER()      TRANSACTION_HANDLER_MASTER(mods)
 | 
			
		||||
#    define TRANSACTIONS_MODS_SLAVE()       TRANSACTION_HANDLER_SLAVE(mods)
 | 
			
		||||
#    define TRANSACTIONS_MODS_MASTER() TRANSACTION_HANDLER_MASTER(mods)
 | 
			
		||||
#    define TRANSACTIONS_MODS_SLAVE() TRANSACTION_HANDLER_SLAVE(mods)
 | 
			
		||||
#    define TRANSACTIONS_MODS_REGISTRATIONS [PUT_MODS] = trans_initiator2target_initializer(mods),
 | 
			
		||||
 | 
			
		||||
#else  // SPLIT_MODS_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -382,8 +382,8 @@ static bool backlight_handlers_master(matrix_row_t master_matrix[], matrix_row_t
 | 
			
		|||
 | 
			
		||||
static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { backlight_set(split_shmem->backlight_level); }
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_BACKLIGHT_MASTER()      TRANSACTION_HANDLER_MASTER(backlight)
 | 
			
		||||
#    define TRANSACTIONS_BACKLIGHT_SLAVE()       TRANSACTION_HANDLER_SLAVE(backlight)
 | 
			
		||||
#    define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight)
 | 
			
		||||
#    define TRANSACTIONS_BACKLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(backlight)
 | 
			
		||||
#    define TRANSACTIONS_BACKLIGHT_REGISTRATIONS [PUT_BACKLIGHT] = trans_initiator2target_initializer(backlight_level),
 | 
			
		||||
 | 
			
		||||
#else  // BACKLIGHT_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -419,8 +419,8 @@ static void rgblight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_RGBLIGHT_MASTER()      TRANSACTION_HANDLER_MASTER(rgblight)
 | 
			
		||||
#    define TRANSACTIONS_RGBLIGHT_SLAVE()       TRANSACTION_HANDLER_SLAVE(rgblight)
 | 
			
		||||
#    define TRANSACTIONS_RGBLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(rgblight)
 | 
			
		||||
#    define TRANSACTIONS_RGBLIGHT_SLAVE() TRANSACTION_HANDLER_SLAVE(rgblight)
 | 
			
		||||
#    define TRANSACTIONS_RGBLIGHT_REGISTRATIONS [PUT_RGBLIGHT] = trans_initiator2target_initializer(rgblight_sync),
 | 
			
		||||
 | 
			
		||||
#else  // defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
 | 
			
		||||
| 
						 | 
				
			
			@ -449,8 +449,8 @@ static void led_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
 | 
			
		|||
    led_matrix_set_suspend_state(split_shmem->led_matrix_sync.led_suspend_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_LED_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(led_matrix)
 | 
			
		||||
#    define TRANSACTIONS_LED_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(led_matrix)
 | 
			
		||||
#    define TRANSACTIONS_LED_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(led_matrix)
 | 
			
		||||
#    define TRANSACTIONS_LED_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(led_matrix)
 | 
			
		||||
#    define TRANSACTIONS_LED_MATRIX_REGISTRATIONS [PUT_LED_MATRIX] = trans_initiator2target_initializer(led_matrix_sync),
 | 
			
		||||
 | 
			
		||||
#else  // defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
 | 
			
		||||
| 
						 | 
				
			
			@ -479,8 +479,8 @@ static void rgb_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_row_t
 | 
			
		|||
    rgb_matrix_set_suspend_state(split_shmem->rgb_matrix_sync.rgb_suspend_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_RGB_MATRIX_MASTER()      TRANSACTION_HANDLER_MASTER(rgb_matrix)
 | 
			
		||||
#    define TRANSACTIONS_RGB_MATRIX_SLAVE()       TRANSACTION_HANDLER_SLAVE(rgb_matrix)
 | 
			
		||||
#    define TRANSACTIONS_RGB_MATRIX_MASTER() TRANSACTION_HANDLER_MASTER(rgb_matrix)
 | 
			
		||||
#    define TRANSACTIONS_RGB_MATRIX_SLAVE() TRANSACTION_HANDLER_SLAVE(rgb_matrix)
 | 
			
		||||
#    define TRANSACTIONS_RGB_MATRIX_REGISTRATIONS [PUT_RGB_MATRIX] = trans_initiator2target_initializer(rgb_matrix_sync),
 | 
			
		||||
 | 
			
		||||
#else  // defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
 | 
			
		||||
| 
						 | 
				
			
			@ -504,8 +504,8 @@ static bool wpm_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave
 | 
			
		|||
 | 
			
		||||
static void wpm_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { set_current_wpm(split_shmem->current_wpm); }
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_WPM_MASTER()      TRANSACTION_HANDLER_MASTER(wpm)
 | 
			
		||||
#    define TRANSACTIONS_WPM_SLAVE()       TRANSACTION_HANDLER_SLAVE(wpm)
 | 
			
		||||
#    define TRANSACTIONS_WPM_MASTER() TRANSACTION_HANDLER_MASTER(wpm)
 | 
			
		||||
#    define TRANSACTIONS_WPM_SLAVE() TRANSACTION_HANDLER_SLAVE(wpm)
 | 
			
		||||
#    define TRANSACTIONS_WPM_REGISTRATIONS [PUT_WPM] = trans_initiator2target_initializer(current_wpm),
 | 
			
		||||
 | 
			
		||||
#else  // defined(WPM_ENABLE) && defined(SPLIT_WPM_ENABLE)
 | 
			
		||||
| 
						 | 
				
			
			@ -535,8 +535,8 @@ static void oled_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_OLED_MASTER()      TRANSACTION_HANDLER_MASTER(oled)
 | 
			
		||||
#    define TRANSACTIONS_OLED_SLAVE()       TRANSACTION_HANDLER_SLAVE(oled)
 | 
			
		||||
#    define TRANSACTIONS_OLED_MASTER() TRANSACTION_HANDLER_MASTER(oled)
 | 
			
		||||
#    define TRANSACTIONS_OLED_SLAVE() TRANSACTION_HANDLER_SLAVE(oled)
 | 
			
		||||
#    define TRANSACTIONS_OLED_REGISTRATIONS [PUT_OLED] = trans_initiator2target_initializer(current_oled_state),
 | 
			
		||||
 | 
			
		||||
#else  // defined(OLED_ENABLE) && defined(SPLIT_OLED_ENABLE)
 | 
			
		||||
| 
						 | 
				
			
			@ -566,8 +566,8 @@ static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    define TRANSACTIONS_ST7565_MASTER()      TRANSACTION_HANDLER_MASTER(st7565)
 | 
			
		||||
#    define TRANSACTIONS_ST7565_SLAVE()       TRANSACTION_HANDLER_SLAVE(st7565)
 | 
			
		||||
#    define TRANSACTIONS_ST7565_MASTER() TRANSACTION_HANDLER_MASTER(st7565)
 | 
			
		||||
#    define TRANSACTIONS_ST7565_SLAVE() TRANSACTION_HANDLER_SLAVE(st7565)
 | 
			
		||||
#    define TRANSACTIONS_ST7565_REGISTRATIONS [PUT_ST7565] = trans_initiator2target_initializer(current_st7565_state),
 | 
			
		||||
 | 
			
		||||
#else  // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue