浏览代码

Add proper multimatrix support

Fred Sundvik 7 年之前
父节点
当前提交
6c68cccd90
共有 5 个文件被更改,包括 196 次插入98 次删除
  1. 38 49
      drivers/qwiic/qwiic_keyboard.c
  2. 37 12
      tmk_core/common/action_layer.c
  3. 2 0
      tmk_core/common/action_layer.h
  4. 116 37
      tmk_core/common/keyboard.c
  5. 3 0
      tmk_core/common/keyboard.h

+ 38 - 49
drivers/qwiic/qwiic_keyboard.c

@@ -37,15 +37,15 @@
 void qwiic_keyboard_write_keymap(uint8_t * pointer);
 void qwiic_keyboard_read_keymap(uint8_t * pointer);
 
-bool qwiic_keyboard_master = false;
-bool qwiic_keyboard_connected = false;
-uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] = {0};
-uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0};
-twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received;
+static bool qwiic_keyboard_master = false;
+static bool qwiic_keyboard_connected = false;
+static uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] = {0};
+static uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0};
+static qwiic_matrix_t matrix_prev[QWIIC_KEYBOARD_ROWS] = {0};
+static twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received;
 
-uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {{{0}}};
-uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START;
-uint8_t qwiic_keyboard_processing_slave = false;
+static uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {{{0}}};
+static uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START;
 
 void qwiic_keyboard_init(void) {
   twi2c_init();
@@ -69,50 +69,10 @@ void qwiic_keyboard_task(void) {
   if (qwiic_keyboard_master) {
     if (qwiic_keyboard_connected) {
       // send empty message, expecting matrix info
-      if (MSG_OK == twi2c_transmit_receive(qwiic_keyboard_listening_address,
+      if (MSG_OK != twi2c_transmit_receive(qwiic_keyboard_listening_address,
         command, 1,
         qwiic_keyboard_matrix_message, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE
       )) {
-        // majority of this is pulled from keyboard.c:keyboard_task()
-        static qwiic_matrix_t matrix_prev[QWIIC_KEYBOARD_ROWS];
-        qwiic_matrix_t matrix_row = 0;
-        qwiic_matrix_t matrix_change = 0;
-        #ifdef QMK_KEYS_PER_SCAN
-          uint8_t keys_processed = 0;
-        #endif
-        for (uint8_t r = 0; r < QWIIC_KEYBOARD_ROWS; r++) {
-          matrix_row = qwiic_keyboard_matrix_message[r];
-          matrix_change = matrix_row ^ matrix_prev[r];
-          if (matrix_change) {
-            for (uint8_t c = 0; c < QWIIC_KEYBOARD_COLS; c++) {
-              if (matrix_change & ((qwiic_matrix_t)1<<c)) {
-                action_exec((keyevent_t){
-                  // Always use matrix 1 for remotes now
-                  .key = (keymatrix_t){.pos = (keypos_t){ .row = r, .col = c }, .matrix = 1},
-                  .pressed = (matrix_row & ((qwiic_matrix_t)1<<c)),
-                  .time = (timer_read() | 1) /* time should not be 0 */
-                });
-                // record a processed key
-                matrix_prev[r] ^= ((qwiic_matrix_t)1<<c);
-                #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 QWIIC_MATRIX_LOOP_END;
-              }
-            }
-          }
-        }
-        // 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);
-        QWIIC_MATRIX_LOOP_END:
-        qwiic_keyboard_processing_slave = false;
-      } else {
         // disconnect
         // qwiic_keyboard_connected = false;
       }
@@ -198,3 +158,32 @@ uint16_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key) {
     return qwiic_keyboard_keymap[(layer)][(key.pos.row)][(key.pos.col)];
   }
 }
+
+uint8_t multimatrix_get_num_matrices(void) {
+  return qwiic_keyboard_connected ? 1 : 0;
+}
+
+uint8_t multimatrix_get_num_cols(uint8_t matrix) {
+  return QWIIC_KEYBOARD_COLS;
+}
+
+uint8_t multimatrix_get_num_rows(uint8_t matrix) {
+  return QWIIC_KEYBOARD_ROWS;
+}
+
+uint32_t multimatrix_get_row(uint8_t matrix, uint8_t row) {
+return qwiic_keyboard_matrix_message[row];
+}
+
+uint32_t multimatrix_get_row_cache(uint8_t matrix, uint8_t row) {
+  return matrix_prev[row];
+}
+
+void multimatrix_set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) {
+  matrix_prev[row] = value;
+}
+
+uint8_t* multimatrix_get_source_layers_cache(uint8_t matrix) {
+    static uint8_t source_layers_cache[(QWIIC_KEYBOARD_ROWS * QWIIC_KEYBOARD_COLS * MAX_LAYER_BITS + 7) / 8] = {0};
+    return source_layers_cache;
+}

+ 37 - 12
tmk_core/common/action_layer.c

@@ -220,15 +220,32 @@ void layer_debug(void)
 #endif
 
 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
-uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0};
 static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1;
 
+__attribute__((weak))
+uint8_t* multimatrix_get_source_layers_cache(uint8_t matrix) {
+    return 0;
+}
+
+static uint8_t* get_source_layers_cache(keymatrix_t key) {
+  if (key.matrix == 0) {
+    static uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0};
+    return source_layers_cache;
+  } else {
+    return multimatrix_get_source_layers_cache(key.matrix - 1);
+  }
+}
+
 void update_source_layers_cache(keymatrix_t key, uint8_t layer)
 {
-  const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS);
+  const uint8_t num_cols = keyboard_get_num_cols(key.matrix);
+  const uint8_t num_rows = keyboard_get_num_rows(key.matrix);
+  const uint16_t num_cache_bytes = get_source_layers_cache_size(num_cols, num_rows);
+  uint8_t* cache = get_source_layers_cache(key);
+  const uint16_t key_number = key.pos.col + (key.pos.row * num_cols);
   const uint32_t bit_number = key_number * MAX_LAYER_BITS;
   const uint16_t byte_number = bit_number / 8;
-  if (byte_number >= sizeof(source_layers_cache)) {
+  if (byte_number >= num_cache_bytes) {
     return;
   }
   const uint8_t bit_position = bit_number % 8;
@@ -239,9 +256,9 @@ void update_source_layers_cache(keymatrix_t key, uint8_t layer)
     shift -= 8;
     const uint8_t mask = layer_cache_mask << shift;
     const uint8_t shifted_layer = layer << shift;
-    source_layers_cache[byte_number] = (shifted_layer & mask) | (source_layers_cache[byte_number] & (~mask));
+    cache[byte_number] = (shifted_layer & mask) | (cache[byte_number] & (~mask));
   } else {
-    if (byte_number + 1 >= sizeof(source_layers_cache)) {
+    if (byte_number + 1 >= num_cache_bytes) {
       return;
     }
     // We need to write two bytes
@@ -254,19 +271,23 @@ void update_source_layers_cache(keymatrix_t key, uint8_t layer)
     uint16_t inverse_mask = ~mask;
 
     // This could potentially be done with a single write, but then we have to assume the endian
-    source_layers_cache[byte_number + 1] = masked_value | (source_layers_cache[byte_number + 1] & (inverse_mask));
+    cache[byte_number + 1] = masked_value | (cache[byte_number + 1] & (inverse_mask));
     masked_value >>= 8;
     inverse_mask >>= 8;
-    source_layers_cache[byte_number] = masked_value | (source_layers_cache[byte_number] & (inverse_mask));
+    cache[byte_number] = masked_value | (cache[byte_number] & (inverse_mask));
   }
 }
 
 uint8_t read_source_layers_cache(keymatrix_t key)
 {
-  const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS);
+  const uint8_t num_cols = keyboard_get_num_cols(key.matrix);
+  const uint8_t num_rows = keyboard_get_num_rows(key.matrix);
+  const uint16_t num_cache_bytes = get_source_layers_cache_size(num_cols, num_rows);
+  uint8_t* cache = get_source_layers_cache(key);
+  const uint16_t key_number = key.pos.col + (key.pos.row * num_cols);
   const uint32_t bit_number = key_number * MAX_LAYER_BITS;
   const uint16_t byte_number = bit_number / 8;
-  if (byte_number >= sizeof(source_layers_cache)) {
+  if (byte_number >= num_cache_bytes) {
     return 0;
   }
   const uint8_t bit_position = bit_number % 8;
@@ -276,17 +297,21 @@ uint8_t read_source_layers_cache(keymatrix_t key)
   if (shift > 8 ) {
     // We need to read only one byte
     shift -= 8;
-    return (source_layers_cache[byte_number] >> shift) & layer_cache_mask;
+    return (cache[byte_number] >> shift) & layer_cache_mask;
   } else {
-    if (byte_number + 1 >= sizeof(source_layers_cache)) {
+    if (byte_number + 1 >= num_cache_bytes) {
       return 0;
     }
     // Otherwise read two bytes
     // This could potentially be done with a single read, but then we have to assume the endian
-    uint16_t value = source_layers_cache[byte_number] << 8 | source_layers_cache[byte_number + 1];
+    uint16_t value = cache[byte_number] << 8 | cache[byte_number + 1];
     return (value >> shift) & layer_cache_mask;
   }
 }
+
+uint8_t get_source_layers_cache_size(uint8_t num_cols, uint8_t num_rows) {
+  return (num_rows * num_cols * MAX_LAYER_BITS + 7) / 8;
+}
 #endif
 
 /** \brief Store or get action (FIXME: Needs better summary)

+ 2 - 0
tmk_core/common/action_layer.h

@@ -93,6 +93,8 @@ uint32_t layer_state_set_kb(uint32_t state);
 #define MAX_LAYER_BITS 5
 void update_source_layers_cache(keymatrix_t key, uint8_t layer);
 uint8_t read_source_layers_cache(keymatrix_t key);
+
+uint8_t get_source_layers_cache_size(uint8_t num_cols, uint8_t num_rows);
 #endif
 action_t store_or_get_action(bool pressed, keymatrix_t key);
 

+ 116 - 37
tmk_core/common/keyboard.c

@@ -145,6 +145,82 @@ bool is_keyboard_master(void) {
     return true;
 }
 
+__attribute__((weak))
+uint8_t multimatrix_get_num_matrices(void) {
+    return 0;
+}
+
+__attribute__((weak))
+uint8_t multimatrix_get_num_cols(uint8_t matrix) {
+    return 0;
+}
+
+__attribute__((weak))
+uint8_t multimatrix_get_num_rows(uint8_t matrix) {
+    return 0;
+}
+
+__attribute__((weak))
+uint32_t multimatrix_get_row(uint8_t matrix, uint8_t row) {
+    return 0;
+}
+
+__attribute__((weak))
+uint32_t multimatrix_get_row_cache(uint8_t matrix, uint8_t row) {
+    return 0;
+}
+
+__attribute__((weak))
+void multimatrix_set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) {
+}
+
+static uint8_t get_num_matrices(void) {
+    return 1 + multimatrix_get_num_matrices();
+}
+
+uint8_t keyboard_get_num_cols(uint8_t matrix) {
+    if (matrix == 0) {
+      return MATRIX_COLS;
+    } else {
+      return multimatrix_get_num_cols(matrix - 1);
+    }
+}
+
+uint8_t keyboard_get_num_rows(uint8_t matrix) {
+    if (matrix == 0) {
+      return MATRIX_ROWS;
+    } else {
+      return multimatrix_get_num_rows(matrix - 1);
+    }
+}
+
+static uint32_t get_row(uint8_t matrix, uint8_t row) {
+    if (matrix == 0) {
+      return matrix_get_row(row);
+    } else {
+      return multimatrix_get_row(matrix - 1, row);
+    }
+}
+
+static matrix_row_t matrix_prev[MATRIX_ROWS];
+
+static uint32_t get_row_cache(uint8_t matrix, uint8_t row) {
+    if (matrix == 0) {
+      return matrix_prev[row];
+    } else {
+      return multimatrix_get_row_cache(matrix - 1, row);
+    }
+}
+
+static void set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) {
+    if (matrix == 0) {
+      matrix_prev[row] = value;
+    } else {
+      return multimatrix_set_row_cache(matrix - 1, row, value);
+    }
+}
+
+
 /** \brief keyboard_init
  *
  * FIXME: needs doc
@@ -203,54 +279,57 @@ void keyboard_init(void) {
  */
 void keyboard_task(void)
 {
-    static matrix_row_t matrix_prev[MATRIX_ROWS];
-#ifdef MATRIX_HAS_GHOST
-  //  static matrix_row_t matrix_ghost[MATRIX_ROWS];
-#endif
     static uint8_t led_status = 0;
-    matrix_row_t matrix_row = 0;
-    matrix_row_t matrix_change = 0;
+    uint32_t matrix_row = 0;
+    uint32_t matrix_change = 0;
 #ifdef QMK_KEYS_PER_SCAN
     uint8_t keys_processed = 0;
 #endif
 
     matrix_scan();
     if (is_keyboard_master()) {
-        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) {
+        for (uint8_t m = 0; m < get_num_matrices(); m++) {
+            uint8_t num_cols = keyboard_get_num_cols(m);
+            uint8_t num_rows = keyboard_get_num_rows(m);
+            for (uint8_t r = 0; r < num_rows; r++) {
+                matrix_row = get_row(m, r);
+                uint32_t row_cache = get_row_cache(m, r);
+                matrix_change = matrix_row ^ row_cache;
+                if (matrix_change) {
 #ifdef MATRIX_HAS_GHOST
-                if (has_ghost_in_row(r, matrix_row)) {
-                    /* Keep track of whether ghosted status has changed for
-                    * debugging. But don't update matrix_prev until un-ghosted, or
-                    * the last key would be lost.
-                    */
-                    //if (debug_matrix && matrix_ghost[r] != matrix_row) {
-                    //    matrix_print();
-                    //}
+                    //NOTE: The we support ghosting only for the main matrix, since it's only useful for old keyboards without diodes
+                    if (has_ghost_in_row(r, matrix_row)) {
+                        /* Keep track of whether ghosted status has changed for
+                        * debugging. But don't update matrix_prev until un-ghosted, or
+                        * the last key would be lost.
+                        */
+                        //if (debug_matrix && matrix_ghost[r] != matrix_row) {
+                        //    matrix_print();
+                        //}
+                        //matrix_ghost[r] = matrix_row;
+                        continue;
+                    }
                     //matrix_ghost[r] = matrix_row;
-                    continue;
-                }
-                //matrix_ghost[r] = matrix_row;
-#endif
-                if (debug_matrix) matrix_print();
-                for (uint8_t c = 0; c < MATRIX_COLS; c++) {
-                    if (matrix_change & ((matrix_row_t)1<<c)) {
-                        action_exec((keyevent_t){
-                            // The main matrix is always 0
-                            .key = (keymatrix_t){.pos = (keypos_t){ .row = r, .col = c }, .matrix = 0},
-                            .pressed = (matrix_row & ((matrix_row_t)1<<c)),
-                            .time = (timer_read() | 1) /* time should not be 0 */
-                        });
-                        // record a processed key
-                        matrix_prev[r] ^= ((matrix_row_t)1<<c);
+#endif
+                    if (debug_matrix) matrix_print();
+                    for (uint8_t c = 0; c < num_cols; c++) {
+                        if (matrix_change & (uint32_t)(1u<<c)) {
+                            action_exec((keyevent_t){
+                                // The main matrix is always 0
+                                .key = (keymatrix_t){.pos = (keypos_t){ .row = r, .col = c }, .matrix = m},
+                                .pressed = (matrix_row & ((uint32_t)1u<<c)),
+                                .time = (timer_read() | 1) /* time should not be 0 */
+                            });
+                            // record a processed key
+                            row_cache ^= (uint32_t)(1u<<c);
+                            set_row_cache(m, r, row_cache);
 #ifdef QMK_KEYS_PER_SCAN
-                        // only jump out if we have processed "enough" keys.
-                        if (++keys_processed >= 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;
+                            // process a key per task call
+                            goto MATRIX_LOOP_END;
+                        }
                     }
                 }
             }

+ 3 - 0
tmk_core/common/keyboard.h

@@ -72,6 +72,9 @@ void keyboard_task(void);
 /* it runs when host LED status is updated */
 void keyboard_set_leds(uint8_t leds);
 
+uint8_t keyboard_get_num_cols(uint8_t matrix);
+uint8_t keyboard_get_num_rows(uint8_t matrix);
+
 #ifdef __cplusplus
 }
 #endif