X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=quantum%2Fsplit_common%2Fmatrix.c;h=c3d2857ed50bfd9b8894817f88e76b77d305f60c;hb=24df54b80794144907db94c2cb5ceca928700e2d;hp=2611376386fce169bbcf40f4c270e0fb3dd68dcf;hpb=72d4e4bfd76b2c83b89787f8b3a8ba779a3e8d81;p=qmk_firmware.git diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 261137638..c3d2857ed 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -20,556 +20,309 @@ along with this program. If not, see . */ #include #include -#include #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 BACKLIGHT_ENABLE -# include "backlight.h" - extern backlight_config_t backlight_config; +#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 -#if defined(USE_I2C) || defined(EH) -# include "i2c.h" -#else // USE_SERIAL -# include "serial.h" -#endif +#define ERROR_DISCONNECT_COUNT 5 -#ifndef DEBOUNCING_DELAY -# define DEBOUNCING_DELAY 5 -#endif +#define ROWS_PER_HAND (MATRIX_ROWS / 2) -#if (DEBOUNCING_DELAY > 0) - static uint16_t debouncing_time; - static bool debouncing = false; +#ifdef DIRECT_PINS +static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; +#else +static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; +static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; #endif -#if defined(USE_I2C) || defined(EH) +/* matrix state(1:on, 0:off) */ +static matrix_row_t matrix[MATRIX_ROWS]; +static matrix_row_t raw_matrix[ROWS_PER_HAND]; -#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) -#else -# error "Currently only supports 8 COLS" -#endif +// row offsets for each hand +uint8_t thisHand, thatHand; -#else // USE_SERIAL +// user-defined overridable functions -#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 +__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } -#endif -static matrix_row_t matrix_debouncing[MATRIX_ROWS]; +__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } -#define ERROR_DISCONNECT_COUNT 5 +__attribute__((weak)) void matrix_init_user(void) {} -#define ROWS_PER_HAND (MATRIX_ROWS/2) +__attribute__((weak)) void matrix_scan_user(void) {} -static uint8_t error_count = 0; +__attribute__((weak)) void matrix_slave_scan_user(void) {} -static uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; -static uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +// helper functions -/* 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 +inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } -__attribute__ ((weak)) -void matrix_init_kb(void) { - matrix_init_user(); -} +inline uint8_t matrix_cols(void) { return MATRIX_COLS; } -__attribute__ ((weak)) -void matrix_scan_kb(void) { - matrix_scan_user(); +bool matrix_is_modified(void) { + if (debounce_active()) return false; + return true; } -__attribute__ ((weak)) -void matrix_init_user(void) { -} +inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } -__attribute__ ((weak)) -void matrix_scan_user(void) { -} +inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } -__attribute__ ((weak)) -void matrix_slave_scan_user(void) { -} +void matrix_print(void) { + print_matrix_header(); -inline -uint8_t matrix_rows(void) -{ - return MATRIX_ROWS; + for (uint8_t row = 0; row < MATRIX_ROWS; row++) { + phex(row); + print(": "); + print_matrix_row(row); + print("\n"); + } } -inline -uint8_t matrix_cols(void) -{ - return MATRIX_COLS; +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; } -void matrix_init(void) -{ - debug_enable = true; - debug_matrix = true; - debug_mouse = true; +// matrix code - // 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 - } - - // initialize row and col -#if (DIODE_DIRECTION == COL2ROW) - unselect_rows(); - init_cols(); -#elif (DIODE_DIRECTION == ROW2COL) - unselect_cols(); - init_rows(); -#endif +#ifdef DIRECT_PINS - // initialize matrix state: all keys off - for (uint8_t i=0; i < MATRIX_ROWS; i++) { - matrix[i] = 0; - matrix_debouncing[i] = 0; +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); + } } - - matrix_init_quantum(); - + } } -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); +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; - if (matrix_changed) { - debouncing = true; - debouncing_time = timer_read(); - } + 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); + } + } -# else - read_cols_on_row(matrix+offset, current_row); -# endif + return (last_row_value != current_matrix[current_row]); +} - } +#elif (DIODE_DIRECTION == COL2ROW) -#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 void select_row(uint8_t row) { + writePinLow(row_pins[row]); + setPinOutput(row_pins[row]); +} - } -#endif +static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); } -# 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 +static void unselect_rows(void) { + for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { + setPinInputHigh(row_pins[x]); + } +} - return 1; +static void init_pins(void) { + unselect_rows(); + for (uint8_t x = 0; x < MATRIX_COLS; x++) { + setPinInputHigh(col_pins[x]); + } } -#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 +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]; - err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE); - if (err) goto i2c_error; + // Clear data in matrix row + current_matrix[current_row] = 0; - // start of matrix stored at I2C_KEYMAP_START - err = i2c_master_write(I2C_KEYMAP_START); - if (err) goto i2c_error; + // Select row and wait for row selecton to stabilize + select_row(current_row); + wait_us(30); - // Start read - err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ); - if (err) goto i2c_error; + // 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); + } - 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 + // Unselect row + unselect_row(current_row); - return 0; + return (last_row_value != current_matrix[current_row]); } -#else // USE_SERIAL - +#elif (DIODE_DIRECTION == ROW2COL) -typedef struct _Serial_s2m_buffer_t { - // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack - matrix_row_t smatrix[ROWS_PER_HAND]; -} Serial_s2m_buffer_t; +static void select_col(uint8_t col) { + writePinLow(col_pins[col]); + setPinOutput(col_pins[col]); +} -volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; -volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; -uint8_t volatile status0 = 0; +static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); } -SSTD_t transactions[] = { - { (uint8_t *)&status0, - sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer, - sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer +static void unselect_cols(void) { + for (uint8_t x = 0; x < MATRIX_COLS; x++) { + setPinInputHigh(col_pins[x]); } -}; - -void serial_master_init(void) -{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } - -void serial_slave_init(void) -{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); } - -int serial_transaction(void) { - int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; - - if (soft_serial_transaction()) { - return 1; - } +} - // TODO: if MATRIX_COLS > 8 change to unpack() - for (int i = 0; i < ROWS_PER_HAND; ++i) { - matrix[slaveOffset+i] = serial_s2m_buffer.smatrix[i]; - } - - #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - // Code to send RGB over serial goes here (not implemented yet) - #endif - - #ifdef BACKLIGHT_ENABLE - // Write backlight level for slave to read - serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0; - #endif - - return 0; +static void init_pins(void) { + unselect_cols(); + for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { + setPinInputHigh(row_pins[x]); + } } -#endif -uint8_t matrix_scan(void) -{ - uint8_t ret = _matrix_scan(); +static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { + bool matrix_changed = false; -#if defined(USE_I2C) || defined(EH) - if( i2c_transaction() ) { -#else // USE_SERIAL - if( serial_transaction() ) { -#endif + // Select col and wait for col selecton to stabilize + select_col(current_col); + wait_us(30); - error_count++; + // 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]; - 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; - } - } + // Check row pin state + if (readPin(row_pins[row_index])) { + // Pin HI, clear col bit + current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); } else { - error_count = 0; + // Pin LO, set col bit + current_matrix[row_index] |= (ROW_SHIFTER << current_col); } - matrix_scan_quantum(); - return ret; -} - -void matrix_slave_scan(void) { - _matrix_scan(); - int offset = (isLeftHand) ? 0 : ROWS_PER_HAND; - -#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 - // TODO: if MATRIX_COLS > 8 change to pack() - for (int i = 0; i < ROWS_PER_HAND; ++i) { - serial_s2m_buffer.smatrix[i] = matrix[offset+i]; + // Determine if the matrix changed state + if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) { + matrix_changed = true; } -#endif - matrix_slave_scan_user(); -} + } -bool matrix_is_modified(void) -{ - if (debouncing) return false; - return true; -} + // Unselect col + unselect_col(current_col); -inline -bool matrix_is_on(uint8_t row, uint8_t col) -{ - return (matrix[row] & ((matrix_row_t)1<> 4) + 1) &= ~_BV(pin & 0xF); // IN - _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI +#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]; } -} - -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]; - - // Clear data in matrix row - current_matrix[current_row] = 0; - - // Select row and wait for row selecton to stabilize - select_row(current_row); - wait_us(30); - - // 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 = col_pins[col_index]; - uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)); +#endif + } - // Populate the matrix row with the state of the col pin - current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); - } + thisHand = isLeftHand ? 0 : (ROWS_PER_HAND); + thatHand = ROWS_PER_HAND - thisHand; - // Unselect row - unselect_row(current_row); + // initialize key pins + init_pins(); - return (last_row_value != current_matrix[current_row]); -} + // initialize matrix state: all keys off + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + matrix[i] = 0; + } -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 -} + debounce_init(ROWS_PER_HAND); -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 + matrix_init_quantum(); } -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 - } -} +uint8_t _matrix_scan(void) { + bool changed = false; +#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 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 - } -} + debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); -static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) -{ - bool matrix_changed = false; + return 1; +} - // Select col and wait for col selecton to stabilize - select_col(current_col); - wait_us(30); +uint8_t matrix_scan(void) { + uint8_t ret = _matrix_scan(); - // For each row... - for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) - { + if (is_keyboard_master()) { + static uint8_t error_count; - // Store last value of row prior to reading - matrix_row_t last_row_value = current_matrix[row_index]; + if (!transport_master(matrix + thatHand)) { + 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); - } - - // 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