diff options
Diffstat (limited to 'quantum/matrix.c')
| -rw-r--r-- | quantum/matrix.c | 283 | 
1 files changed, 217 insertions, 66 deletions
| diff --git a/quantum/matrix.c b/quantum/matrix.c index 34d6af2e6d..d22817bf48 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -16,22 +16,69 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */  #include <stdint.h>  #include <stdbool.h> +#include <string.h>  #include "util.h"  #include "matrix.h"  #include "debounce.h"  #include "quantum.h" +#ifdef SPLIT_KEYBOARD +#    include "split_common/split_util.h" +#    include "split_common/transactions.h" + +#    ifndef ERROR_DISCONNECT_COUNT +#        define ERROR_DISCONNECT_COUNT 5 +#    endif  // ERROR_DISCONNECT_COUNT + +#    define ROWS_PER_HAND (MATRIX_ROWS / 2) +#else +#    define ROWS_PER_HAND (MATRIX_ROWS) +#endif + +#ifdef DIRECT_PINS_RIGHT +#    define SPLIT_MUTABLE +#else +#    define SPLIT_MUTABLE const +#endif +#ifdef MATRIX_ROW_PINS_RIGHT +#    define SPLIT_MUTABLE_ROW +#else +#    define SPLIT_MUTABLE_ROW const +#endif +#ifdef MATRIX_COL_PINS_RIGHT +#    define SPLIT_MUTABLE_COL +#else +#    define SPLIT_MUTABLE_COL const +#endif  #ifdef DIRECT_PINS -static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; +static SPLIT_MUTABLE pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;  #elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) -static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; -static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +#    ifdef MATRIX_ROW_PINS +static SPLIT_MUTABLE_ROW pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; +#    endif  // MATRIX_ROW_PINS +#    ifdef MATRIX_COL_PINS +static SPLIT_MUTABLE_COL pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +#    endif  // MATRIX_COL_PINS  #endif  /* matrix state(1:on, 0:off) */  extern matrix_row_t raw_matrix[MATRIX_ROWS];  // raw values  extern matrix_row_t matrix[MATRIX_ROWS];      // debounced values +#ifdef SPLIT_KEYBOARD +// row offsets for each hand +uint8_t thisHand, thatHand; +#endif + +// user-defined overridable functions +__attribute__((weak)) void matrix_init_pins(void); +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); +__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); +#ifdef SPLIT_KEYBOARD +__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); } +__attribute__((weak)) void matrix_slave_scan_user(void) {} +#endif +  static inline void setPinOutput_writeLow(pin_t pin) {      ATOMIC_BLOCK_FORCEON {          setPinOutput(pin); @@ -43,11 +90,19 @@ static inline void setPinInputHigh_atomic(pin_t pin) {      ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }  } +static inline uint8_t readMatrixPin(pin_t pin) { +    if (pin != NO_PIN) { +        return readPin(pin); +    } else { +        return 1; +    } +} +  // matrix code  #ifdef DIRECT_PINS -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      for (int row = 0; row < MATRIX_ROWS; row++) {          for (int col = 0; col < MATRIX_COLS; col++) {              pin_t pin = direct_pins[row][col]; @@ -58,7 +113,7 @@ static void init_pins(void) {      }  } -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {      // Start with a clear matrix row      matrix_row_t current_row_value = 0; @@ -69,46 +124,57 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)          }      } -    // If the row has changed, store the row and return the changed flag. -    if (current_matrix[current_row] != current_row_value) { -        current_matrix[current_row] = current_row_value; -        return true; -    } -    return false; +    // Update the matrix +    current_matrix[current_row] = current_row_value;  }  #elif defined(DIODE_DIRECTION) -#    if (DIODE_DIRECTION == COL2ROW) +#    if defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS) +#        if (DIODE_DIRECTION == COL2ROW) -static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } +static bool select_row(uint8_t row) { +    pin_t pin = row_pins[row]; +    if (pin != NO_PIN) { +        setPinOutput_writeLow(pin); +        return true; +    } +    return false; +} -static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); } +static void unselect_row(uint8_t row) { +    pin_t pin = row_pins[row]; +    if (pin != NO_PIN) { +        setPinInputHigh_atomic(pin); +    } +}  static void unselect_rows(void) { -    for (uint8_t x = 0; x < MATRIX_ROWS; x++) { -        setPinInputHigh_atomic(row_pins[x]); +    for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { +        unselect_row(x);      }  } -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      unselect_rows();      for (uint8_t x = 0; x < MATRIX_COLS; x++) { -        setPinInputHigh_atomic(col_pins[x]); +        if (col_pins[x] != NO_PIN) { +            setPinInputHigh_atomic(col_pins[x]); +        }      }  } -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {      // Start with a clear matrix row      matrix_row_t current_row_value = 0; -    // Select row -    select_row(current_row); +    if (!select_row(current_row)) {  // Select row +        return;                      // skip NO_PIN row +    }      matrix_output_select_delay();      // For each col...      for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { -        // Select the col pin to read (active low) -        uint8_t pin_state = readPin(col_pins[col_index]); +        uint8_t pin_state = readMatrixPin(col_pins[col_index]);          // Populate the matrix row with the state of the col pin          current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); @@ -116,81 +182,114 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)      // Unselect row      unselect_row(current_row); -    matrix_output_unselect_delay();  // wait for all Col signals to go HIGH +    matrix_output_unselect_delay(current_row, current_row_value != 0);  // wait for all Col signals to go HIGH -    // If the row has changed, store the row and return the changed flag. -    if (current_matrix[current_row] != current_row_value) { -        current_matrix[current_row] = current_row_value; +    // Update the matrix +    current_matrix[current_row] = current_row_value; +} + +#        elif (DIODE_DIRECTION == ROW2COL) + +static bool select_col(uint8_t col) { +    pin_t pin = col_pins[col]; +    if (pin != NO_PIN) { +        setPinOutput_writeLow(pin);          return true;      }      return false;  } -#    elif (DIODE_DIRECTION == ROW2COL) - -static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } - -static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); } +static void unselect_col(uint8_t col) { +    pin_t pin = col_pins[col]; +    if (pin != NO_PIN) { +        setPinInputHigh_atomic(pin); +    } +}  static void unselect_cols(void) {      for (uint8_t x = 0; x < MATRIX_COLS; x++) { -        setPinInputHigh_atomic(col_pins[x]); +        unselect_col(x);      }  } -static void init_pins(void) { +__attribute__((weak)) void matrix_init_pins(void) {      unselect_cols(); -    for (uint8_t x = 0; x < MATRIX_ROWS; x++) { -        setPinInputHigh_atomic(row_pins[x]); +    for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { +        if (row_pins[x] != NO_PIN) { +            setPinInputHigh_atomic(row_pins[x]); +        }      }  } -static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { -    bool matrix_changed = false; +__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { +    bool key_pressed = false;      // Select col -    select_col(current_col); +    if (!select_col(current_col)) {  // select col +        return;                      // skip NO_PIN col +    }      matrix_output_select_delay();      // For each row... -    for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { -        // Store last value of row prior to reading -        matrix_row_t last_row_value    = current_matrix[row_index]; -        matrix_row_t current_row_value = last_row_value; - +    for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) {          // Check row pin state -        if (readPin(row_pins[row_index]) == 0) { +        if (readMatrixPin(row_pins[row_index]) == 0) {              // Pin LO, set col bit -            current_row_value |= (MATRIX_ROW_SHIFTER << current_col); +            current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col); +            key_pressed = true;          } else {              // Pin HI, clear col bit -            current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); -        } - -        // Determine if the matrix changed state -        if ((last_row_value != current_row_value)) { -            matrix_changed |= true; -            current_matrix[row_index] = current_row_value; +            current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);          }      }      // Unselect col      unselect_col(current_col); -    matrix_output_unselect_delay();  // wait for all Row signals to go HIGH - -    return matrix_changed; +    matrix_output_unselect_delay(current_col, key_pressed);  // wait for all Row signals to go HIGH  } -#    else -#        error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! -#    endif +#        else +#            error DIODE_DIRECTION must be one of COL2ROW or ROW2COL! +#        endif +#    endif  // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)  #else  #    error DIODE_DIRECTION is not defined!  #endif  void matrix_init(void) { +#ifdef SPLIT_KEYBOARD +    split_pre_init(); + +    // Set pinout for right half if pinout for that half is defined +    if (!isLeftHand) { +#    ifdef DIRECT_PINS_RIGHT +        const pin_t direct_pins_right[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS_RIGHT; +        for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +            for (uint8_t j = 0; j < MATRIX_COLS; j++) { +                direct_pins[i][j] = direct_pins_right[i][j]; +            } +        } +#    endif +#    ifdef MATRIX_ROW_PINS_RIGHT +        const pin_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT; +        for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +            row_pins[i] = row_pins_right[i]; +        } +#    endif +#    ifdef MATRIX_COL_PINS_RIGHT +        const pin_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT; +        for (uint8_t i = 0; i < MATRIX_COLS; i++) { +            col_pins[i] = col_pins_right[i]; +        } +#    endif +    } + +    thisHand = isLeftHand ? 0 : (ROWS_PER_HAND); +    thatHand = ROWS_PER_HAND - thisHand; +#endif +      // initialize key pins -    init_pins(); +    matrix_init_pins();      // initialize matrix state: all keys off      for (uint8_t i = 0; i < MATRIX_ROWS; i++) { @@ -198,28 +297,80 @@ void matrix_init(void) {          matrix[i]     = 0;      } -    debounce_init(MATRIX_ROWS); +    debounce_init(ROWS_PER_HAND);      matrix_init_quantum(); + +#ifdef SPLIT_KEYBOARD +    split_post_init(); +#endif  } -uint8_t matrix_scan(void) { +#ifdef SPLIT_KEYBOARD +bool matrix_post_scan(void) {      bool changed = false; +    if (is_keyboard_master()) { +        static uint8_t error_count; + +        matrix_row_t slave_matrix[ROWS_PER_HAND] = {0}; +        if (!transport_master(matrix + thisHand, slave_matrix)) { +            error_count++; + +            if (error_count > ERROR_DISCONNECT_COUNT) { +                // reset other half if disconnected +                for (int i = 0; i < ROWS_PER_HAND; ++i) { +                    matrix[thatHand + i] = 0; +                    slave_matrix[i]      = 0; +                } + +                changed = true; +            } +        } else { +            error_count = 0; + +            for (int i = 0; i < ROWS_PER_HAND; ++i) { +                if (matrix[thatHand + i] != slave_matrix[i]) { +                    matrix[thatHand + i] = slave_matrix[i]; +                    changed              = true; +                } +            } +        } + +        matrix_scan_quantum(); +    } else { +        transport_slave(matrix + thatHand, matrix + thisHand); + +        matrix_slave_scan_kb(); +    } + +    return changed; +} +#endif + +uint8_t matrix_scan(void) { +    matrix_row_t curr_matrix[MATRIX_ROWS] = {0};  #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)      // Set row, read cols -    for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { -        changed |= read_cols_on_row(raw_matrix, current_row); +    for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { +        matrix_read_cols_on_row(curr_matrix, current_row);      }  #elif (DIODE_DIRECTION == ROW2COL)      // Set col, read rows      for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { -        changed |= read_rows_on_col(raw_matrix, current_col); +        matrix_read_rows_on_col(curr_matrix, current_col);      }  #endif -    debounce(raw_matrix, matrix, MATRIX_ROWS, changed); +    bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0; +    if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix)); +#ifdef SPLIT_KEYBOARD +    debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); +    changed = (changed || matrix_post_scan()); +#else +    debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);      matrix_scan_quantum(); +#endif      return (uint8_t)changed;  } | 
