|
@@ -212,6 +212,12 @@ static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+#else
|
|
|
+
|
|
|
+static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) {
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
#endif
|
|
|
|
|
|
/** \brief matrix_setup
|
|
@@ -426,64 +432,74 @@ void switch_events(uint8_t row, uint8_t col, bool pressed) {
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-/** \brief Perform scan of keyboard matrix
|
|
|
+/**
|
|
|
+ * @brief Generates a tick event at a maximum rate of 1KHz that drives the
|
|
|
+ * internal QMK state machine.
|
|
|
+ */
|
|
|
+static inline void generate_tick_event(void) {
|
|
|
+ static uint16_t last_tick = 0;
|
|
|
+ const uint16_t now = timer_read();
|
|
|
+ if (TIMER_DIFF_16(now, last_tick) != 0) {
|
|
|
+ action_exec(TICK_EVENT);
|
|
|
+ last_tick = now;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief This task scans the keyboards matrix and processes any key presses
|
|
|
+ * that occur.
|
|
|
*
|
|
|
- * Any detected changes in state are sent out as part of the processing
|
|
|
+ * @return true Matrix did change
|
|
|
+ * @return false Matrix didn't change
|
|
|
*/
|
|
|
-bool matrix_scan_task(void) {
|
|
|
- static matrix_row_t matrix_prev[MATRIX_ROWS];
|
|
|
- matrix_row_t matrix_row = 0;
|
|
|
- matrix_row_t matrix_change = 0;
|
|
|
-#ifdef QMK_KEYS_PER_SCAN
|
|
|
- uint8_t keys_processed = 0;
|
|
|
-#endif
|
|
|
+static bool matrix_task(void) {
|
|
|
+ static matrix_row_t matrix_previous[MATRIX_ROWS];
|
|
|
|
|
|
- uint8_t matrix_changed = matrix_scan();
|
|
|
- if (matrix_changed) last_matrix_activity_trigger();
|
|
|
+ matrix_scan();
|
|
|
|
|
|
- for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
|
|
- matrix_row = matrix_get_row(r);
|
|
|
- matrix_change = matrix_row ^ matrix_prev[r];
|
|
|
- if (matrix_change) {
|
|
|
-#ifdef MATRIX_HAS_GHOST
|
|
|
- if (has_ghost_in_row(r, matrix_row)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-#endif
|
|
|
- if (debug_matrix) matrix_print();
|
|
|
- matrix_row_t col_mask = 1;
|
|
|
- for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
|
|
|
- if (matrix_change & col_mask) {
|
|
|
- if (should_process_keypress()) {
|
|
|
- action_exec((keyevent_t){
|
|
|
- .key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */
|
|
|
- });
|
|
|
- }
|
|
|
- // record a processed key
|
|
|
- matrix_prev[r] ^= col_mask;
|
|
|
-
|
|
|
- switch_events(r, c, (matrix_row & col_mask));
|
|
|
-
|
|
|
-#ifdef QMK_KEYS_PER_SCAN
|
|
|
- // only jump out if we have processed "enough" keys.
|
|
|
- if (++keys_processed >= QMK_KEYS_PER_SCAN)
|
|
|
-#endif
|
|
|
- // process a key per task call
|
|
|
- goto MATRIX_LOOP_END;
|
|
|
+ bool matrix_changed = false;
|
|
|
+ for (uint8_t row = 0; row < MATRIX_ROWS && !matrix_changed; row++) {
|
|
|
+ matrix_changed |= matrix_previous[row] ^ matrix_get_row(row);
|
|
|
+ }
|
|
|
+
|
|
|
+ matrix_scan_perf_task();
|
|
|
+
|
|
|
+ // Short-circuit the complete matrix processing if it is not necessary
|
|
|
+ if (!matrix_changed) {
|
|
|
+ generate_tick_event();
|
|
|
+ return matrix_changed;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (debug_config.matrix) {
|
|
|
+ matrix_print();
|
|
|
+ }
|
|
|
+
|
|
|
+ const bool process_keypress = should_process_keypress();
|
|
|
+
|
|
|
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
|
|
+ const matrix_row_t current_row = matrix_get_row(row);
|
|
|
+ const matrix_row_t row_changes = current_row ^ matrix_previous[row];
|
|
|
+
|
|
|
+ if (!row_changes || has_ghost_in_row(row, current_row)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ matrix_row_t col_mask = 1;
|
|
|
+ for (uint8_t col = 0; col < MATRIX_COLS; col++, col_mask <<= 1) {
|
|
|
+ if (row_changes & col_mask) {
|
|
|
+ const bool key_pressed = current_row & col_mask;
|
|
|
+
|
|
|
+ if (process_keypress) {
|
|
|
+ action_exec(MAKE_KEYEVENT(row, col, key_pressed));
|
|
|
}
|
|
|
+
|
|
|
+ switch_events(row, col, key_pressed);
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- // call with pseudo tick event when no real key event.
|
|
|
-#ifdef QMK_KEYS_PER_SCAN
|
|
|
- // we can get here with some keys processed now.
|
|
|
- if (!keys_processed)
|
|
|
-#endif
|
|
|
- action_exec(TICK_EVENT);
|
|
|
|
|
|
-MATRIX_LOOP_END:
|
|
|
+ matrix_previous[row] = current_row;
|
|
|
+ }
|
|
|
|
|
|
- matrix_scan_perf_task();
|
|
|
return matrix_changed;
|
|
|
}
|
|
|
|
|
@@ -562,20 +578,12 @@ void quantum_task(void) {
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-/** \brief Keyboard task: Do keyboard routine jobs
|
|
|
- *
|
|
|
- * Do routine keyboard jobs:
|
|
|
- *
|
|
|
- * * scan matrix
|
|
|
- * * handle mouse movements
|
|
|
- * * handle midi commands
|
|
|
- * * light LEDs
|
|
|
- *
|
|
|
- * This is repeatedly called as fast as possible.
|
|
|
- */
|
|
|
+/** \brief Main task that is repeatedly called as fast as possible. */
|
|
|
void keyboard_task(void) {
|
|
|
- bool matrix_changed = matrix_scan_task();
|
|
|
- (void)matrix_changed;
|
|
|
+ const bool matrix_changed = matrix_task();
|
|
|
+ if (matrix_changed) {
|
|
|
+ last_matrix_activity_trigger();
|
|
|
+ }
|
|
|
|
|
|
quantum_task();
|
|
|
|
|
@@ -597,8 +605,10 @@ void keyboard_task(void) {
|
|
|
#endif
|
|
|
|
|
|
#ifdef ENCODER_ENABLE
|
|
|
- bool encoders_changed = encoder_read();
|
|
|
- if (encoders_changed) last_encoder_activity_trigger();
|
|
|
+ const bool encoders_changed = encoder_read();
|
|
|
+ if (encoders_changed) {
|
|
|
+ last_encoder_activity_trigger();
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
#ifdef OLED_ENABLE
|