diff options
Diffstat (limited to 'quantum/split_common/matrix.c')
| -rw-r--r-- | quantum/split_common/matrix.c | 639 | 
1 files changed, 214 insertions, 425 deletions
| diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 4af90209f6..c3d2857ed5 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -20,520 +20,309 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #include <stdint.h>  #include <stdbool.h> -#include <avr/io.h>  #include "wait.h" -#include "print.h" -#include "debug.h"  #include "util.h"  #include "matrix.h"  #include "split_util.h" -#include "pro_micro.h"  #include "config.h" -#include "timer.h"  #include "split_flags.h" +#include "quantum.h" +#include "debounce.h" +#include "transport.h" -#ifdef RGBLIGHT_ENABLE -#   include "rgblight.h" -#endif -#ifdef BACKLIGHT_ENABLE -#   include "backlight.h" -    extern backlight_config_t backlight_config; -#endif - -#if defined(USE_I2C) || defined(EH) -#  include "i2c.h" -#else // USE_SERIAL -#  include "serial.h" +#if (MATRIX_COLS <= 8) +#  define print_matrix_header() print("\nr/c 01234567\n") +#  define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) +#  define matrix_bitpop(i) bitpop(matrix[i]) +#  define ROW_SHIFTER ((uint8_t)1) +#elif (MATRIX_COLS <= 16) +#  define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") +#  define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) +#  define matrix_bitpop(i) bitpop16(matrix[i]) +#  define ROW_SHIFTER ((uint16_t)1) +#elif (MATRIX_COLS <= 32) +#  define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") +#  define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) +#  define matrix_bitpop(i) bitpop32(matrix[i]) +#  define ROW_SHIFTER ((uint32_t)1)  #endif -#ifndef DEBOUNCING_DELAY -#   define DEBOUNCING_DELAY 5 -#endif +#define ERROR_DISCONNECT_COUNT 5 -#if (DEBOUNCING_DELAY > 0) -    static uint16_t debouncing_time; -    static bool debouncing = false; -#endif +#define ROWS_PER_HAND (MATRIX_ROWS / 2) -#if (MATRIX_COLS <= 8) -#    define print_matrix_header()  print("\nr/c 01234567\n") -#    define print_matrix_row(row)  print_bin_reverse8(matrix_get_row(row)) -#    define matrix_bitpop(i)       bitpop(matrix[i]) -#    define ROW_SHIFTER ((uint8_t)1) +#ifdef DIRECT_PINS +static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;  #else -#    error "Currently only supports 8 COLS" +static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; +static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;  #endif -static matrix_row_t matrix_debouncing[MATRIX_ROWS]; -#define ERROR_DISCONNECT_COUNT 5 +/* matrix state(1:on, 0:off) */ +static matrix_row_t matrix[MATRIX_ROWS]; +static matrix_row_t raw_matrix[ROWS_PER_HAND]; -#define ROWS_PER_HAND (MATRIX_ROWS/2) +// row offsets for each hand +uint8_t thisHand, thatHand; -static uint8_t error_count = 0; +// user-defined overridable functions -static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; -static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } -/* matrix state(1:on, 0:off) */ -static matrix_row_t matrix[MATRIX_ROWS]; -static matrix_row_t matrix_debouncing[MATRIX_ROWS]; - -#if (DIODE_DIRECTION == COL2ROW) -    static void init_cols(void); -    static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); -    static void unselect_rows(void); -    static void select_row(uint8_t row); -    static void unselect_row(uint8_t row); -#elif (DIODE_DIRECTION == ROW2COL) -    static void init_rows(void); -    static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); -    static void unselect_cols(void); -    static void unselect_col(uint8_t col); -    static void select_col(uint8_t col); -#endif +__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } -__attribute__ ((weak)) -void matrix_init_kb(void) { -    matrix_init_user(); -} +__attribute__((weak)) void matrix_init_user(void) {} -__attribute__ ((weak)) -void matrix_scan_kb(void) { -    matrix_scan_user(); -} +__attribute__((weak)) void matrix_scan_user(void) {} -__attribute__ ((weak)) -void matrix_init_user(void) { -} +__attribute__((weak)) void matrix_slave_scan_user(void) {} -__attribute__ ((weak)) -void matrix_scan_user(void) { -} +// helper functions -__attribute__ ((weak)) -void matrix_slave_scan_user(void) { -} +inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } -inline -uint8_t matrix_rows(void) -{ -    return MATRIX_ROWS; -} +inline uint8_t matrix_cols(void) { return MATRIX_COLS; } -inline -uint8_t matrix_cols(void) -{ -    return MATRIX_COLS; +bool matrix_is_modified(void) { +  if (debounce_active()) return false; +  return true;  } -void matrix_init(void) -{ -#ifdef DISABLE_JTAG -  // JTAG disable for PORT F. write JTD bit twice within four cycles. -  MCUCR |= (1<<JTD); -  MCUCR |= (1<<JTD); -#endif +inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } -    debug_enable = true; -    debug_matrix = true; -    debug_mouse = true; -    // initialize row and col -#if (DIODE_DIRECTION == COL2ROW) -    unselect_rows(); -    init_cols(); -#elif (DIODE_DIRECTION == ROW2COL) -    unselect_cols(); -    init_rows(); -#endif +inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } -    // initialize matrix state: all keys off -    for (uint8_t i=0; i < MATRIX_ROWS; i++) { -        matrix[i] = 0; -        matrix_debouncing[i] = 0; -    } -     -    matrix_init_quantum(); -     +void matrix_print(void) { +  print_matrix_header(); + +  for (uint8_t row = 0; row < MATRIX_ROWS; row++) { +    phex(row); +    print(": "); +    print_matrix_row(row); +    print("\n"); +  }  } -uint8_t _matrix_scan(void) -{ -    int offset = isLeftHand ? 0 : (ROWS_PER_HAND); -#if (DIODE_DIRECTION == COL2ROW) -    // Set row, read cols -    for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { -#       if (DEBOUNCING_DELAY > 0) -            bool matrix_changed = read_cols_on_row(matrix_debouncing+offset, current_row); +uint8_t matrix_key_count(void) { +  uint8_t count = 0; +  for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +    count += matrix_bitpop(i); +  } +  return count; +} -            if (matrix_changed) { -                debouncing = true; -                debouncing_time = timer_read(); -            } +// matrix code -#       else -            read_cols_on_row(matrix+offset, current_row); -#       endif +#ifdef DIRECT_PINS +static void 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]; +      if (pin != NO_PIN) { +        setPinInputHigh(pin); +      }      } +  } +} -#elif (DIODE_DIRECTION == ROW2COL) -    // Set col, read rows -    for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { -#       if (DEBOUNCING_DELAY > 0) -            bool matrix_changed = read_rows_on_col(matrix_debouncing+offset, current_col); -            if (matrix_changed) { -                debouncing = true; -                debouncing_time = timer_read(); -            } -#       else -             read_rows_on_col(matrix+offset, current_col); -#       endif +static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +  matrix_row_t last_row_value = current_matrix[current_row]; +  current_matrix[current_row] = 0; +  for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { +    pin_t pin = direct_pins[current_row][col_index]; +    if (pin != NO_PIN) { +      current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index);      } -#endif +  } -#   if (DEBOUNCING_DELAY > 0) -        if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { -            for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { -                matrix[i+offset] = matrix_debouncing[i+offset]; -            } -            debouncing = false; -        } -#   endif - -    return 1; +  return (last_row_value != current_matrix[current_row]);  } -#if defined(USE_I2C) || defined(EH) - -// Get rows from other half over i2c -int i2c_transaction(void) { -    int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; -    int err = 0; -     -    // write backlight info -    #ifdef BACKLIGHT_ENABLE -        if (BACKLIT_DIRTY) { -            err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE); -            if (err) goto i2c_error; -             -            // Backlight location -            err = i2c_master_write(I2C_BACKLIT_START); -            if (err) goto i2c_error; -             -            // Write backlight  -            i2c_master_write(get_backlight_level()); -             -            BACKLIT_DIRTY = false; -        } -    #endif - -    err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE); -    if (err) goto i2c_error; - -    // start of matrix stored at I2C_KEYMAP_START -    err = i2c_master_write(I2C_KEYMAP_START); -    if (err) goto i2c_error; - -    // Start read -    err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ); -    if (err) goto i2c_error; - -    if (!err) { -        int i; -        for (i = 0; i < ROWS_PER_HAND-1; ++i) { -            matrix[slaveOffset+i] = i2c_master_read(I2C_ACK); -        } -        matrix[slaveOffset+i] = i2c_master_read(I2C_NACK); -        i2c_master_stop(); -    } else { -i2c_error: // the cable is disconnceted, or something else went wrong -        i2c_reset_state(); -        return err; -    } -     -    #ifdef RGBLIGHT_ENABLE -        if (RGB_DIRTY) { -            err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE); -            if (err) goto i2c_error; -             -            // RGB Location -            err = i2c_master_write(I2C_RGB_START); -            if (err) goto i2c_error; -             -            uint32_t dword = eeconfig_read_rgblight(); -             -            // Write RGB -            err = i2c_master_write_data(&dword, 4); -            if (err) goto i2c_error; -             -            RGB_DIRTY = false; -            i2c_master_stop(); -        } -    #endif +#elif (DIODE_DIRECTION == COL2ROW) -    return 0; +static void select_row(uint8_t row) { +  writePinLow(row_pins[row]); +  setPinOutput(row_pins[row]);  } -#else // USE_SERIAL +static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); } -int serial_transaction(void) { -    int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; - -    if (serial_update_buffers()) { -        return 1; -    } +static void unselect_rows(void) { +  for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { +    setPinInputHigh(row_pins[x]); +  } +} -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        matrix[slaveOffset+i] = serial_slave_buffer[i]; -    } -     -    #ifdef RGBLIGHT_ENABLE -        // Code to send RGB over serial goes here (not implemented yet) -    #endif -     -    #ifdef BACKLIGHT_ENABLE -        // Write backlight level for slave to read -        serial_master_buffer[SERIAL_BACKLIT_START] = backlight_config.enable ? backlight_config.level : 0; -    #endif - -    return 0; +static void init_pins(void) { +  unselect_rows(); +  for (uint8_t x = 0; x < MATRIX_COLS; x++) { +    setPinInputHigh(col_pins[x]); +  }  } -#endif -uint8_t matrix_scan(void) -{ -    uint8_t ret = _matrix_scan(); +static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +  // Store last value of row prior to reading +  matrix_row_t last_row_value = current_matrix[current_row]; -#if defined(USE_I2C) || defined(EH) -    if( i2c_transaction() ) { -#else // USE_SERIAL -    if( serial_transaction() ) { -#endif +  // Clear data in matrix row +  current_matrix[current_row] = 0; -        error_count++; +  // Select row and wait for row selecton to stabilize +  select_row(current_row); +  wait_us(30); -        if (error_count > ERROR_DISCONNECT_COUNT) { -            // reset other half if disconnected -            int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; -            for (int i = 0; i < ROWS_PER_HAND; ++i) { -                matrix[slaveOffset+i] = 0; -            } -        } -    } else { -        error_count = 0; -    } -    matrix_scan_quantum(); -    return ret; -} +  // For each col... +  for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { +    // Populate the matrix row with the state of the col pin +    current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index); +  } -void matrix_slave_scan(void) { -    _matrix_scan(); +  // Unselect row +  unselect_row(current_row); -    int offset = (isLeftHand) ? 0 : ROWS_PER_HAND; +  return (last_row_value != current_matrix[current_row]); +} -#if defined(USE_I2C) || defined(EH) -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        i2c_slave_buffer[I2C_KEYMAP_START+i] = matrix[offset+i]; -    }    -#else // USE_SERIAL -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        serial_slave_buffer[i] = matrix[offset+i]; -    } -#endif -#ifdef USE_I2C -#ifdef BACKLIGHT_ENABLE -    // Read backlight level sent from master and update level on slave -    backlight_set(i2c_slave_buffer[0]); -#endif -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        i2c_slave_buffer[i+1] = matrix[offset+i]; -    } -#else // USE_SERIAL -    for (int i = 0; i < ROWS_PER_HAND; ++i) { -        serial_slave_buffer[i] = matrix[offset+i]; -    } +#elif (DIODE_DIRECTION == ROW2COL) -#ifdef BACKLIGHT_ENABLE -    // Read backlight level sent from master and update level on slave -    backlight_set(serial_master_buffer[SERIAL_BACKLIT_START]); -#endif -#endif -    matrix_slave_scan_user(); +static void select_col(uint8_t col) { +  writePinLow(col_pins[col]); +  setPinOutput(col_pins[col]);  } -bool matrix_is_modified(void) -{ -    if (debouncing) return false; -    return true; -} +static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); } -inline -bool matrix_is_on(uint8_t row, uint8_t col) -{ -    return (matrix[row] & ((matrix_row_t)1<<col)); +static void unselect_cols(void) { +  for (uint8_t x = 0; x < MATRIX_COLS; x++) { +    setPinInputHigh(col_pins[x]); +  }  } -inline -matrix_row_t matrix_get_row(uint8_t row) -{ -    return matrix[row]; +static void init_pins(void) { +  unselect_cols(); +  for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { +    setPinInputHigh(row_pins[x]); +  }  } -void matrix_print(void) -{ -    print("\nr/c 0123456789ABCDEF\n"); -    for (uint8_t row = 0; row < MATRIX_ROWS; row++) { -        phex(row); print(": "); -        pbin_reverse16(matrix_get_row(row)); -        print("\n"); -    } -} +static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { +  bool matrix_changed = false; -uint8_t matrix_key_count(void) -{ -    uint8_t count = 0; -    for (uint8_t i = 0; i < MATRIX_ROWS; i++) { -        count += bitpop16(matrix[i]); -    } -    return count; -} +  // Select col and wait for col selecton to stabilize +  select_col(current_col); +  wait_us(30); -#if (DIODE_DIRECTION == COL2ROW) +  // For each row... +  for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { +    // Store last value of row prior to reading +    matrix_row_t last_row_value = current_matrix[row_index]; -static void init_cols(void) -{ -    for(uint8_t x = 0; x < MATRIX_COLS; x++) { -        uint8_t pin = col_pins[x]; -        _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN -        _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI +    // Check row pin state +    if (readPin(row_pins[row_index])) { +      // Pin HI, clear col bit +      current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); +    } else { +      // Pin LO, set col bit +      current_matrix[row_index] |= (ROW_SHIFTER << current_col);      } -} -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) -{ -    // Store last value of row prior to reading -    matrix_row_t last_row_value = current_matrix[current_row]; +    // Determine if the matrix changed state +    if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) { +      matrix_changed = true; +    } +  } -    // Clear data in matrix row -    current_matrix[current_row] = 0; +  // Unselect col +  unselect_col(current_col); -    // Select row and wait for row selecton to stabilize -    select_row(current_row); -    wait_us(30); +  return matrix_changed; +} -    // For each col... -    for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { +#endif -        // Select the col pin to read (active low) -        uint8_t pin = col_pins[col_index]; -        uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)); +void matrix_init(void) { +  debug_enable = true; +  debug_matrix = true; +  debug_mouse  = true; -        // Populate the matrix row with the state of the col pin -        current_matrix[current_row] |=  pin_state ? 0 : (ROW_SHIFTER << col_index); +  // Set pinout for right half if pinout for that half is defined +  if (!isLeftHand) { +#ifdef MATRIX_ROW_PINS_RIGHT +    const uint8_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 uint8_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 +  } -    // Unselect row -    unselect_row(current_row); +  thisHand = isLeftHand ? 0 : (ROWS_PER_HAND); +  thatHand = ROWS_PER_HAND - thisHand; -    return (last_row_value != current_matrix[current_row]); -} +  // initialize key pins +  init_pins(); -static void select_row(uint8_t row) -{ -    uint8_t pin = row_pins[row]; -    _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT -    _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW -} +  // initialize matrix state: all keys off +  for (uint8_t i = 0; i < MATRIX_ROWS; i++) { +    matrix[i] = 0; +  } -static void unselect_row(uint8_t row) -{ -    uint8_t pin = row_pins[row]; -    _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN -    _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI -} +  debounce_init(ROWS_PER_HAND); -static void unselect_rows(void) -{ -    for(uint8_t x = 0; x < ROWS_PER_HAND; x++) { -        uint8_t pin = row_pins[x]; -        _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN -        _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI -    } +  matrix_init_quantum();  } -#elif (DIODE_DIRECTION == ROW2COL) +uint8_t _matrix_scan(void) { +  bool changed = false; -static void init_rows(void) -{ -    for(uint8_t x = 0; x < ROWS_PER_HAND; x++) { -        uint8_t pin = row_pins[x]; -        _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN -        _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI -    } -} +#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) +  // Set row, read cols +  for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { +    changed |= read_cols_on_row(raw_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); +  } +#endif -static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) -{ -    bool matrix_changed = false; +  debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); -    // Select col and wait for col selecton to stabilize -    select_col(current_col); -    wait_us(30); +  return 1; +} -    // For each row... -    for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) -    { +uint8_t matrix_scan(void) { +  uint8_t ret = _matrix_scan(); -        // Store last value of row prior to reading -        matrix_row_t last_row_value = current_matrix[row_index]; +  if (is_keyboard_master()) { +    static uint8_t error_count; -        // Check row pin state -        if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0) -        { -            // Pin LO, set col bit -            current_matrix[row_index] |= (ROW_SHIFTER << current_col); -        } -        else -        { -            // Pin HI, clear col bit -            current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); -        } +    if (!transport_master(matrix + thatHand)) { +      error_count++; -        // Determine if the matrix changed state -        if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) -        { -            matrix_changed = true; +      if (error_count > ERROR_DISCONNECT_COUNT) { +        // reset other half if disconnected +        for (int i = 0; i < ROWS_PER_HAND; ++i) { +          matrix[thatHand + i] = 0;          } +      } +    } else { +      error_count = 0;      } -    // Unselect col -    unselect_col(current_col); - -    return matrix_changed; -} - -static void select_col(uint8_t col) -{ -    uint8_t pin = col_pins[col]; -    _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT -    _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW -} - -static void unselect_col(uint8_t col) -{ -    uint8_t pin = col_pins[col]; -    _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN -    _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI -} +    matrix_scan_quantum(); +  } else { +    transport_slave(matrix + thisHand); +    matrix_slave_scan_user(); +  } -static void unselect_cols(void) -{ -    for(uint8_t x = 0; x < MATRIX_COLS; x++) { -        uint8_t pin = col_pins[x]; -        _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN -        _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI -    } +  return ret;  } - -#endif | 
