diff options
Diffstat (limited to 'keyboards/handwired/symmetric70_proto/matrix_fast')
10 files changed, 908 insertions, 0 deletions
diff --git a/keyboards/handwired/symmetric70_proto/matrix_fast/cpp_map.h b/keyboards/handwired/symmetric70_proto/matrix_fast/cpp_map.h new file mode 100644 index 0000000000..d197be6d9f --- /dev/null +++ b/keyboards/handwired/symmetric70_proto/matrix_fast/cpp_map.h @@ -0,0 +1,53 @@ +/* Copyright 2021 mtei + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#pragma once +// clang-format off + +#define _MAP1(E, _1) E(_1) +#define _MAP2(E, _1,_2) E(_1) E(_2) +#define _MAP3(E, _1,_2,_3) E(_1) E(_2) E(_3) +#define _MAP4(E, _1,_2,_3,_4) E(_1) E(_2) E(_3) E(_4) +#define _MAP5(E, _1,_2,_3,_4,_5) E(_1) E(_2) E(_3) E(_4) E(_5) +#define _MAP6(E, _1,_2,_3,_4,_5,_6) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) +#define _MAP7(E, _1,_2,_3,_4,_5,_6,_7) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) +#define _MAP8(E, _1,_2,_3,_4,_5,_6,_7,_8) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) +#define _MAP9(E, _1,_2,_3,_4,_5,_6,_7,_8,_9) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) +#define _MAP10(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) +#define _MAP11(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) +#define _MAP12(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) +#define _MAP13(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) +#define _MAP14(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) +#define _MAP15(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) +#define _MAP16(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) +#define _MAP17(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) +#define _MAP18(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) +#define _MAP19(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) +#define _MAP20(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) +#define _MAP21(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) +#define _MAP22(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) +#define _MAP23(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) +#define _MAP24(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) +#define _MAP25(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) E(_25) +#define _MAP26(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) E(_25) E(_26) +#define _MAP27(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) E(_25) E(_26) E(_27) +#define _MAP28(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) E(_25) E(_26) E(_27) E(_28) +#define _MAP29(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) E(_25) E(_26) E(_27) E(_28) E(_29) +#define _MAP30(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) E(_25) E(_26) E(_27) E(_28) E(_29) E(_30) +#define _MAP31(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) E(_25) E(_26) E(_27) E(_28) E(_29) E(_30) E(_31) +#define _MAP32(E, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32) E(_1) E(_2) E(_3) E(_4) E(_5) E(_6) E(_7) E(_8) E(_9) E(_10) E(_11) E(_12) E(_13) E(_14) E(_15) E(_16) E(_17) E(_18) E(_19) E(_20) E(_21) E(_22) E(_23) E(_24) E(_25) E(_26) E(_27) E(_28) E(_29) E(_30) E(_31) E(_32) + +#define SELECT_MAP(e,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,NAME,...) NAME +#define MAP(E,...) SELECT_MAP(E,__VA_ARGS__,_MAP32,_MAP31,_MAP30,_MAP29,_MAP28,_MAP27,_MAP26,_MAP25,_MAP24,_MAP23,_MAP22,_MAP21,_MAP20,_MAP19,_MAP18,_MAP17,_MAP16,_MAP15,_MAP14,_MAP13,_MAP12,_MAP11,_MAP10,_MAP9,_MAP8,_MAP7,_MAP6,_MAP5,_MAP4,_MAP3,_MAP2,_MAP1)(E,__VA_ARGS__) diff --git a/keyboards/handwired/symmetric70_proto/matrix_fast/gpio_extr.h b/keyboards/handwired/symmetric70_proto/matrix_fast/gpio_extr.h new file mode 100644 index 0000000000..e31cb5f3a5 --- /dev/null +++ b/keyboards/handwired/symmetric70_proto/matrix_fast/gpio_extr.h @@ -0,0 +1,28 @@ +#pragma once +// clang-format off + +#if defined(__AVR__) +typedef uint8_t port_data_t; + +#define readPort(port) PINx_ADDRESS(port) + +#define setPortBitInput(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) &= ~_BV((bit)&0xF)) +#define setPortBitInputHigh(port, bit) (DDRx_ADDRESS(port) &= ~_BV((bit)&0xF), PORTx_ADDRESS(port) |= _BV((bit)&0xF)) +#define setPortBitOutput(port, bit) (DDRx_ADDRESS(port) |= _BV((bit)&0xF)) + +#define writePortBitLow(port, bit) (PORTx_ADDRESS(port) &= ~_BV((bit)&0xF)) +#define writePortBitHigh(port, bit) (PORTx_ADDRESS(port) |= _BV((bit)&0xF)) + +#else +typedef uint16_t port_data_t; + +#define readPort(qmk_pin) palReadPort(PAL_PORT(qmk_pin)) + +#define setPortBitInput(qmk_pin, bit) palSetPadMode(PAL_PORT(qmk_pin), bit, PAL_MODE_INPUT) +#define setPortBitInputHigh(qmk_pin, bit) palSetPadMode(PAL_PORT(qmk_pin), bit, PAL_MODE_INPUT_PULLUP) +#define setPortBitInputLow(qmk_pin, bit) palSetPadMode(PAL_PORT(qmk_pin), bit, PAL_MODE_INPUT_PULLDOWN) +#define setPortBitOutput(qmk_pin, bit) palSetPadMode(PAL_PORT(qmk_pin), bit, PAL_MODE_OUTPUT_PUSHPULL) + +#define writePortBitLow(qmk_pin, bit) palClearLine(PAL_LINE(PAL_PORT(qmk_pin), bit)) +#define writePortBitHigh(qmk_pin, bit) palSetLine(PAL_LINE(PAL_PORT(qmk_pin), bit)) +#endif diff --git a/keyboards/handwired/symmetric70_proto/matrix_fast/matrix.c b/keyboards/handwired/symmetric70_proto/matrix_fast/matrix.c new file mode 100644 index 0000000000..cb21bfcf8d --- /dev/null +++ b/keyboards/handwired/symmetric70_proto/matrix_fast/matrix.c @@ -0,0 +1,234 @@ +/* +Copyright 2021 mtei + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +// clang-format off +#include <stdint.h> +#include <stdbool.h> +#include <gpio.h> +#ifndef readPort +# include "gpio_extr.h" +#endif +#include "util.h" +#include "matrix.h" +#include "matrix_extr.h" +#include "debounce.h" +#include "quantum.h" + +#define ALWAYS_INLINE inline __attribute__((always_inline)) +#define NO_INLINE __attribute__((noinline)) +#define LOCAL_FUNC static +#define LOCAL_DATA static + +#ifndef _BV +# define _BV(bit) (1 << (bit)) +#endif + +#ifndef MATRIX_DEBUG_PIN +# define MATRIX_DEBUG_PIN_INIT() +# define MATRIX_DEBUG_SCAN_START() +# define MATRIX_DEBUG_SCAN_END() +# define MATRIX_DEBUG_DELAY_START() +# define MATRIX_DEBUG_DELAY_END() +# define MATRIX_DEBUG_GAP() +#else +# define MATRIX_DEBUG_GAP() asm volatile("nop \n nop":::"memory") +#endif + +typedef uint16_t port_width_t; +#if MATRIX_TYPE == DIRECT_SWITCH || MATRIX_TYPE == DIODE_COL2ROW +# define MATRIX_LINES MATRIX_ROWS +typedef matrix_row_t matrix_line_t; +#endif +#if MATRIX_TYPE == DIODE_ROW2COL +# define MATRIX_LINES MATRIX_COLS +typedef matrix_col_t matrix_line_t; +#endif +typedef struct _port_descriptor { + int device; + pin_t port; +} port_descriptor; + +/* 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 + +#define setPortBitOutput_writeLow(port, bit) \ + do { setPortBitOutput(port, bit); writePortBitLow(port, bit); } while(0) +#define setPortBitOutput_writeLow_atomic(port, bit) \ + do { ATOMIC_BLOCK_FORCEON { setPortBitOutput_writeLow(port, bit); } } while(0) +#define setPortBitInputHigh_atomic(port, bit) \ + do { ATOMIC_BLOCK_FORCEON { setPortBitInputHigh(port, bit); } } while(0) + +#if defined(MATRIX_IN_PORTS) && defined(MATRIX_IN_PINS) +# include "matrix_config_expand.c" +#else +# error matrix.c need defined MATRIX_IN_PORTS and MATRIX_IN_PINS +#endif + +LOCAL_FUNC +void unselect_output(uint8_t out_index) { + unselect_output_inline(out_index); +} + +LOCAL_FUNC +void init_output_ports(void) { + for (int i = 0; i < END_outpin_index; i++) { + unselect_output(i); + } +} + +LOCAL_FUNC +void init_all_ports(void) { + init_input_ports(); + init_output_ports(); + init_inport_mask(); + init_extension(); +} + +LOCAL_FUNC ALWAYS_INLINE void select_line_and_read_input_ports(uint8_t current_line, port_width_t port_buffer[NUM_OF_INPUT_PORTS]); +LOCAL_FUNC void select_line_and_read_input_ports(uint8_t current_line, port_width_t port_buffer[NUM_OF_INPUT_PORTS]) { + // Select row (or col) + select_output(current_line); + matrix_output_select_delay(); + + // Read ports + read_all_input_ports(port_buffer, false); + + // Unselect row (or col) + unselect_output_inline(current_line); +} + +LOCAL_FUNC ALWAYS_INLINE void read_matrix_line(matrix_line_t phy_matrix[], uint8_t current_line); + +#if MATRIX_TYPE == DIODE_ROW2COL || MATRIX_TYPE == DIODE_COL2ROW +LOCAL_FUNC void read_matrix_line(matrix_line_t phy_matrix[], uint8_t current_line) { + // Start with a clear matrix row + matrix_line_t current_line_value = 0; + port_width_t port_buffer[NUM_OF_INPUT_PORTS]; + +#ifdef MATRIX_GPIO_NEED_SEPARATE_ATOMIC + select_line_and_read_input_ports(current_line, port_buffer); +#else + ATOMIC_BLOCK_FORCEON { + select_line_and_read_input_ports(current_line, port_buffer); + } +#endif + + // Build row (or col) + current_line_value = build_matrix_line(port_buffer); + + // Wait signal raise up + if (current_line_value) { + MATRIX_DEBUG_DELAY_START(); + wait_unselect_done(); + MATRIX_DEBUG_DELAY_END(); + } + phy_matrix[current_line] = current_line_value; +} +#endif // MATRIX_TYPE == DIODE_ROW2COL || MATRIX_TYPE == DIODE_COL2ROW + +#if MATRIX_TYPE == DIRECT_SWITCH +LOCAL_FUNC void read_matrix_line(matrix_line_t phy_matrix[], uint8_t current_line) { + port_width_t port_buffer[NUM_OF_INPUT_PORTS]; + + if (current_line != 0) { + return; + } + + for (uint8_t i = 0; i < MATRIX_LINES; i++) { + phy_matrix[i] = 0; + } + + read_all_input_ports(port_buffer, false); + + // Build matrix + build_matrix_direct(port_buffer, phy_matrix); +} +#endif // MATRIX_TYPE == DIRECT_SWITCH + +void matrix_init(void) { + // initialize key pins + init_all_ports(); + + // initialize matrix state: all keys off + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + raw_matrix[i] = 0; + matrix[i] = 0; + } + + debounce_init(MATRIX_ROWS); + + matrix_init_quantum(); +} + +uint8_t matrix_scan(void) { + matrix_line_t phy_matrix[MATRIX_LINES]; + + MATRIX_DEBUG_PIN_INIT(); + + MATRIX_DEBUG_SCAN_START(); + + // read I/O port to phy_matrix[] (physical matrix) + //select line, read inputs + for (uint8_t current_line = 0; current_line < MATRIX_LINES; current_line++) { + read_matrix_line(phy_matrix, current_line); + } + MATRIX_DEBUG_SCAN_END(); MATRIX_DEBUG_GAP(); MATRIX_DEBUG_SCAN_START(); + + bool changed = false; +#if MATRIX_TYPE == DIRECT_SWITCH || MATRIX_TYPE == DIODE_COL2ROW + // copy phy_matrix[] to raw_matrix[] + for (uint8_t current_line = 0; current_line < MATRIX_ROWS; current_line++) { + if (raw_matrix[current_line] != phy_matrix[current_line]) { + changed = true; + raw_matrix[current_line] = phy_matrix[current_line]; + } + } +#endif +#if MATRIX_TYPE == DIODE_ROW2COL + // transpose phy_matrix[] to raw_matrix[] + matrix_row_t trans_matrix[MATRIX_ROWS]; + for (uint8_t i = 0; i < MATRIX_ROWS; i++ ) { + trans_matrix[i] = 0; + } + for (uint8_t src_line = 0; src_line < MATRIX_LINES; src_line++) { + matrix_line_t src_line_data = phy_matrix[src_line]; + matrix_row_t dist_bit = MATRIX_ROW_SHIFTER << src_line; + for (uint8_t dist_rows = 0; dist_rows < MATRIX_ROWS; dist_rows++) { + if ((src_line_data & 1) == 1) { + trans_matrix[dist_rows] |= dist_bit; + } + src_line_data >>= 1; + } + } + for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { + if (raw_matrix[current_row] != trans_matrix[current_row]) { + changed = true; + raw_matrix[current_row] = trans_matrix[current_row]; + } + } +#endif + MATRIX_DEBUG_SCAN_END(); MATRIX_DEBUG_GAP(); MATRIX_DEBUG_SCAN_START(); + + // debounce raw_matrix[] to matrix[] + debounce(raw_matrix, matrix, MATRIX_ROWS, changed); + MATRIX_DEBUG_SCAN_END(); MATRIX_DEBUG_GAP(); + + MATRIX_DEBUG_SCAN_START(); + matrix_scan_quantum(); + MATRIX_DEBUG_SCAN_END(); + return (uint8_t)changed; +} diff --git a/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_config_expand.c b/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_config_expand.c new file mode 100644 index 0000000000..0df605db47 --- /dev/null +++ b/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_config_expand.c @@ -0,0 +1,234 @@ +/* +Copyright 2021 mtei + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +// clang-format off + +#include "matrix_extr.h" + +#ifdef DEBUG_MATRIX_CONFIG +// config expand debug +// avr-gcc -DDEBUG_MATRIX_CONFIG=\"test_config.h\" -E -C matrix_config_expand.c +# include DEBUG_MATRIX_CONFIG +#endif + +#undef NO_PIN /* cancel NO_PIN define in tmk_core/common/pin_defs.h */ +#define NO_PIN NO_PORT, 0 +#if MATRIX_TYPE == DIRECT_SWITCH +# undef MATRIX_OUT_PORTS +# define MATRIX_OUT_PINS (0, NO_PIN) +#endif + +#include "cpp_map.h" + +#if defined(MATRIX_EXTENSION_74HC157) || defined(MATRIX_EXTENSION_74HC153) +# define MATRIX_EXTENSION "matrix_extension_74hc15x.c" +#endif + +#ifdef MATRIX_EXTENSION +# include MATRIX_EXTENSION +#endif + +#ifdef MATRIX_GPIO_NEED_SEPARATE_ATOMIC +# ifndef setMatrixInputHigh +# define setMatrixInputHigh(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitInputHigh_atomic(port, bit); }} while(0) +# endif +# ifndef setMatrixOutput_writeHighZ +# define setMatrixOutput_writeHighZ(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitInputHigh_atomic(port, bit); }} while(0) +# endif +# ifndef setMatrixOutput_writeLow +# define setMatrixOutput_writeLow(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitOutput_writeLow_atomic(port, bit); }} while(0) +# endif +#else +# ifndef setMatrixInputHigh +# define setMatrixInputHigh(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitInputHigh(port, bit); }} while(0) +# endif +# ifndef setMatrixOutput_writeHighZ +# define setMatrixOutput_writeHighZ(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitInputHigh(port, bit); }} while(0) +# endif +# ifndef setMatrixOutput_writeLow +# define setMatrixOutput_writeLow(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitOutput_writeLow(port, bit); }} while(0) +# endif +#endif + +#ifndef readMatrixPort +# define readMatrixPort(dev, port) (((dev) == MCU_GPIO) ? readPort(port) : 0) +#endif +#ifndef getMatrixInputMaskBit +# define getMatrixInputMaskBit(dev, bit) (((dev) != NO_DEVICE) ? _BV((bit)&0xF) : 0) +#endif + +#ifndef init_extension +# define init_extension() +#endif + +enum DEVICE_NAME { + MCU_GPIO, + NO_DEVICE, +#ifdef MATRIX_DEVICES + MATRIX_DEVICES +#endif +}; + +#define _INPUT_PORTS_ENUM_ELEMENT(name, dev, port) inport_index_##name, +#define INPUT_PORTS_ENUM_ELEMENT(x) _INPUT_PORTS_ENUM_ELEMENT x +enum INPUT_PORTS { + INPUT_PORTS_ENUM_ELEMENT((NO_PORT, NO_DEVICE, 0)) + MAP(INPUT_PORTS_ENUM_ELEMENT, MATRIX_IN_PORTS) + NUM_OF_INPUT_PORTS +}; + +#define _INPUT_PINS_ENUM_ELEMENT(index, port, bit) inpin_index_##index, +#define INPUT_PINS_ENUM_ELEMENT(x) _INPUT_PINS_ENUM_ELEMENT x +enum INPUT_PINS { + MAP(INPUT_PINS_ENUM_ELEMENT, MATRIX_IN_PINS) + END_inpin_index +}; + +#define _OUTPUT_PORTS_ENUM_ELEMENT(name, dev, port) outport_index_##name, +#define OUTPUT_PORTS_ENUM_ELEMENT(x) _OUTPUT_PORTS_ENUM_ELEMENT x +enum OUTPUT_PORTS { + OUTPUT_PORTS_ENUM_ELEMENT((NO_PORT, NO_DEVICE, 0)) +#ifdef MATRIX_OUT_PORTS + MAP(OUTPUT_PORTS_ENUM_ELEMENT, MATRIX_OUT_PORTS) +#endif + NUM_OF_OUTPUT_PORTS +}; + +#define _OUTPUT_PINS_ENUM_ELEMENT(index, port, bit) outpin_index_##index, +#define OUTPUT_PINS_ENUM_ELEMENT(x) _OUTPUT_PINS_ENUM_ELEMENT x +enum OUTPUT_PINS { + MAP(OUTPUT_PINS_ENUM_ELEMENT, MATRIX_OUT_PINS) + END_outpin_index +}; + +port_width_t iport_mask[NUM_OF_INPUT_PORTS]; + +#define _INPUT_PORTS_LIST_ELEMENT(name, dev, port) \ + [inport_index_##name] = { dev, port }, +#define INPUT_PORTS_LIST_ELEMENT(x) _INPUT_PORTS_LIST_ELEMENT x +LOCAL_DATA +const port_descriptor inport_list[NUM_OF_INPUT_PORTS] = { + INPUT_PORTS_LIST_ELEMENT((NO_PORT, NO_DEVICE, 0)) + MAP(INPUT_PORTS_LIST_ELEMENT, MATRIX_IN_PORTS) +}; + +#define _OUTPUT_PORTS_LIST_ELEMENT(name, dev, port) \ + [outport_index_##name] = { dev, port }, +#define OUTPUT_PORTS_LIST_ELEMENT(x) _OUTPUT_PORTS_LIST_ELEMENT x +LOCAL_DATA +const port_descriptor outport_list[NUM_OF_OUTPUT_PORTS] = { + OUTPUT_PORTS_LIST_ELEMENT((NO_PORT, NO_DEVICE, 0)) +#ifdef MATRIX_OUT_PORTS + MAP(OUTPUT_PORTS_LIST_ELEMENT, MATRIX_OUT_PORTS) +#endif +}; + +#define _SELECT_OUTPUT_PIN(index, pname, bit) \ + case outpin_index_##index: \ + setMatrixOutput_writeLow(outport_list[outport_index_##pname].device, \ + outport_list[outport_index_##pname].port, bit); \ + break; +#define SELECT_OUTPUT_PIN(x) _SELECT_OUTPUT_PIN x +LOCAL_FUNC ALWAYS_INLINE void select_output(uint8_t out_index); +LOCAL_FUNC +void select_output(uint8_t out_index) { + switch (out_index) { + MAP(SELECT_OUTPUT_PIN, MATRIX_OUT_PINS) + } +} + +#define _UNSELECT_OUTPUT_PIN(index, pname, bit) \ + case outpin_index_##index: \ + setMatrixOutput_writeHighZ(outport_list[outport_index_##pname].device, \ + outport_list[outport_index_##pname].port, bit); \ + break; +#define UNSELECT_OUTPUT_PIN(x) _UNSELECT_OUTPUT_PIN x +LOCAL_FUNC ALWAYS_INLINE void unselect_output_inline(uint8_t out_index); +LOCAL_FUNC +void unselect_output_inline(uint8_t out_index) { + switch (out_index) { + MAP(UNSELECT_OUTPUT_PIN, MATRIX_OUT_PINS) + } +} + +#define _INIT_INPUT_PIN(index, pname, bit) \ + setMatrixInputHigh(inport_list[inport_index_##pname].device, \ + inport_list[inport_index_##pname].port, bit); +#define INIT_INPUT_PIN(x) _INIT_INPUT_PIN x +LOCAL_FUNC +void init_input_ports(void) { + MAP(INIT_INPUT_PIN, MATRIX_IN_PINS) +} + +#define _INIT_INPORT_MASK(index, pname, bit) \ + iport_mask[inport_index_##pname] |= getMatrixInputMaskBit(inport_list[inport_index_##pname].device, bit); +#define INIT_INPORT_MASK(x) _INIT_INPORT_MASK x +LOCAL_FUNC +void init_inport_mask(void) { + for (int i = 0; i < NUM_OF_INPUT_PORTS; i++ ) { + iport_mask[i] = 0; + } + MAP(INIT_INPORT_MASK, MATRIX_IN_PINS) +} + +#define _READ_INPUT_PORT(name, dev, port) \ + buffer[inport_index_##name] = readMatrixPort(dev, port); +#define READ_INPUT_PORT(x) _READ_INPUT_PORT x +LOCAL_FUNC +ALWAYS_INLINE void read_all_input_ports(port_width_t buffer[NUM_OF_INPUT_PORTS], bool wait_unselect); +LOCAL_FUNC +void read_all_input_ports(port_width_t buffer[NUM_OF_INPUT_PORTS], bool wait_unselect) { + READ_INPUT_PORT((NO_PORT, NO_DEVICE, 0)) + MAP(READ_INPUT_PORT, MATRIX_IN_PORTS) +} + +#define _MASK_INPUT(name, dev, port) \ + mask |= ((~buffer[inport_index_##name]) & iport_mask[inport_index_##name]); +#define MASK_INPUT(x) _MASK_INPUT x +LOCAL_FUNC ALWAYS_INLINE void wait_unselect_done(void); +LOCAL_FUNC +void wait_unselect_done(void) { + port_width_t mask; + port_width_t buffer[NUM_OF_INPUT_PORTS]; + do { + read_all_input_ports(buffer, true); + MATRIX_DEBUG_DELAY_END(); + mask = 0; + MAP(MASK_INPUT, MATRIX_IN_PORTS); + MATRIX_DEBUG_DELAY_START(); + } while (mask != 0); +} + +#define _BUILD_INPUT_PORT(index, pname, bit) \ + result |= (buffer[inport_index_##pname] & _BV(bit)) ? 0 : _BV(inpin_index_##index); +#define BUILD_INPUT_PORT(x) _BUILD_INPUT_PORT x +LOCAL_FUNC ALWAYS_INLINE matrix_line_t build_matrix_line(port_width_t buffer[NUM_OF_INPUT_PORTS]); +LOCAL_FUNC +matrix_line_t build_matrix_line(port_width_t buffer[NUM_OF_INPUT_PORTS]) { + matrix_line_t result = 0; + MAP(BUILD_INPUT_PORT, MATRIX_IN_PINS); + return result; +} + +#define _BUILD_INPUT_PORT_DIRECT(index, pname, bit) \ + matrix[(inpin_index_##index)/MATRIX_COLS] \ + |= (buffer[inport_index_##pname] & _BV(bit)) ? 0 : _BV((inpin_index_##index)%MATRIX_COLS); +#define BUILD_INPUT_PORT_DIRECT(x) _BUILD_INPUT_PORT_DIRECT x +LOCAL_FUNC ALWAYS_INLINE void build_matrix_direct(port_width_t buffer[NUM_OF_INPUT_PORTS], matrix_line_t matrix[]); +LOCAL_FUNC +void build_matrix_direct(port_width_t buffer[NUM_OF_INPUT_PORTS], matrix_line_t matrix[]) { + MAP(BUILD_INPUT_PORT_DIRECT, MATRIX_IN_PINS); +} diff --git a/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_extension_74hc15x.c b/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_extension_74hc15x.c new file mode 100644 index 0000000000..bca53da24c --- /dev/null +++ b/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_extension_74hc15x.c @@ -0,0 +1,72 @@ +/* +Copyright 2021 mtei + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +// clang-format off + +#if defined(MATRIX_EXTENSION_74HC157) +# define MATRIX_DEVICES MCU_GPIOa, MCU_GPIOb +# define IS_74HC15x(dev) ((dev)==MCU_GPIOa || (dev)==MCU_GPIOb) +# define MATRIX_EXT_74HC15x MATRIX_EXTENSION_74HC157 +#elif defined(MATRIX_EXTENSION_74HC153) +# define MATRIX_DEVICES MCU_GPIOa, MCU_GPIOb, MCU_GPIOc, MCU_GPIOd +# define IS_74HC15x(dev) ((dev)==MCU_GPIOa || (dev)==MCU_GPIOb || (dev)==MCU_GPIOc || (dev)==MCU_GPIOd) +# define MATRIX_EXT_74HC15x MATRIX_EXTENSION_74HC153 +#endif + +static const pin_t sel_pins[] = { MATRIX_EXT_74HC15x }; + +#ifdef MATRIX_GPIO_NEED_SEPARATE_ATOMIC +# define setMatrixInputHigh(dev, port, bit) \ + do { \ + if ((dev) == MCU_GPIO || IS_74HC15x(dev)) { \ + setPortBitInputHigh_atomic(port, bit); \ + } + } while(0) +#else +# define setMatrixInputHigh(dev, port, bit) \ + do { \ + if ((dev) == MCU_GPIO || IS_74HC15x(dev)) { \ + setPortBitInputHigh(port, bit); \ + } \ + } while(0) +#endif + +LOCAL_FUNC ALWAYS_INLINE void select74HC15x(uint8_t devid); +LOCAL_FUNC +void select74HC15x(uint8_t devid) { + writePin(sel_pins[0], devid&1); +#if defined(MATRIX_EXTENSION_74HC153) + writePin(sel_pins[1], devid&2); +#endif +} + +LOCAL_FUNC ALWAYS_INLINE port_width_t readPortMultiplexer(uint8_t devid, pin_t port); +LOCAL_FUNC port_width_t readPortMultiplexer(uint8_t devid, pin_t port) { + select74HC15x(devid); + waitInputPinDelay(); + return readPort(port); +} + +#define readMatrixPort(dev, port) \ + ((dev) == MCU_GPIO)? readPort(port): (IS_74HC15x(dev))? readPortMultiplexer((dev)-MCU_GPIOa, port):0 + +#define INIT_74HC15X(x) setPinOutput(x); writePinLow(x); +LOCAL_FUNC +void init_74hc15x(void) { + MAP(INIT_74HC15X, MATRIX_EXT_74HC15x) +} +#define init_extension() init_74hc15x() + diff --git a/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_extr.h b/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_extr.h new file mode 100644 index 0000000000..e0cf528919 --- /dev/null +++ b/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_extr.h @@ -0,0 +1,36 @@ +#pragma once +// clang-format off + +#define DIRECT_SWITCH 1 +#define DIODE_ROW2COL 2 +#define DIODE_COL2ROW 3 + +#ifndef ROW2COL +# define COL2ROW 0 +# define ROW2COL 1 +#endif + +#ifdef DIRECT_PINS +# define MATRIX_TYPE DIRECT_SWITCH +#else +# if DIODE_DIRECTION == ROW2COL +# define MATRIX_TYPE DIODE_ROW2COL +# endif +# if DIODE_DIRECTION == COL2ROW +# define MATRIX_TYPE DIODE_COL2ROW +# endif +#endif + +#ifndef MATRIX_TYPE +# error "MATRIX_TYPE could not be determined." +#endif + +#if (MATRIX_ROWS <= 8) +typedef uint8_t matrix_col_t; +#elif (MATRIX_ROWS <= 16) +typedef uint16_t matrix_col_t; +#elif (MATRIX_ROWS <= 32) +typedef uint32_t matrix_col_t; +#else +# error "MATRIX_ROWS: invalid value" +#endif diff --git a/keyboards/handwired/symmetric70_proto/matrix_fast/readme.md b/keyboards/handwired/symmetric70_proto/matrix_fast/readme.md new file mode 100644 index 0000000000..dc744a4c46 --- /dev/null +++ b/keyboards/handwired/symmetric70_proto/matrix_fast/readme.md @@ -0,0 +1,168 @@ +# Fast and extensible matrix.c + +This matrix.c is faster and more extensible than the standard quantum/matrix.c. + +* The execution speed of the `matrix_scan()` function is several times faster than quantum/matrix.c. +* In addition to handling MCU GPIOs, it can be extended to handle I/O extenders. + +## ToDo list +- [x] support Pro Micro +- [x] support Proton-C +- [x] support DIRECT_PINS +- [x] support DIODE_DIRECTION == ROW2COL +- [x] support 74HC157: quadruple 2-line to 1-line data selectors / multiplexers +- [x] support 74HC153: dual 4-line to 1-line data selectors / multiplexers +- [ ] support I/O expander (MCP23018) +- [ ] support MCU & I/O expander (MCP23018) mixture like ErgoDox + +## Configuration + +This matrix.c requires a different configuration than quantum/matrix.c. + +### Output pins configuration + +The output pins is the Row pins if `DIODE_DIRECTION == COL2ROW`, and the Col pins if `DIODE_DIRECTION == ROW2COL`. When DIRECT_PINS is defined, the output pins do not need to be set. + +Example: +```c +// list of OUTPUT(row) ports +#define MATRIX_OUT_PORTS \ + (Port_D, MCU_GPIO, D0), \ + (Port_C, MCU_GPIO, C0), \ + (Port_E, MCU_GPIO, E0), \ + (Port_B, MCU_GPIO, B0) +// list of OUTPUT pins +#define MATRIX_OUT_PINS \ + (0, Port_D, 4), \ + (1, Port_C, 6), \ + (2, Port_D, 7), \ + (3, Port_E, 6), \ + (4, Port_B, 4), \ + (5, Port_B, 5) +``` + +### Input pins configuration + +The input pins is the Col pins if `DIODE_DIRECTION == COL2ROW`, and the Row pins if `DIODE_DIRECTION == ROW2COL`. When DIRECT_PINS is defined, the input pin settings will enumerate the connection pins of all switches. + +Example: +```c +// list of INPUT ports +#define MATRIX_IN_PORTS (Port_F, MCU_GPIO, F0), (Port_B, MCU_GPIO, B0) +// list of INPUT pins +#define MATRIX_IN_PINS \ + (0, Port_F, 4), \ + (1, Port_F, 5), \ + (2, Port_F, 6), \ + (3, Port_F, 7), \ + (4, Port_B, 1), \ + (5, Port_B, 3) +``` + +### Multiplexer Extension + +By defining the `MATRIX_EXTENSION_74HC157` macro or `MATRIX_EXTENSION_74HC153` macro, you can connect a multiplexer to the GPIO to extend the input pins. + +Example: +```c +#define MATRIX_EXTENSION_74HC157 B2 /* or #define MATRIX_EXTENSION_74HC153 B2, B6 */ + +// list of OUTPUT ports +#define MATRIX_OUT_PORTS (Port_D, MCU_GPIO, D0), (Port_C, MCU_GPIO, C0), (Port_E, MCU_GPIO, E0), (Port_B, MCU_GPIO, B0) +// list of OUTPUT pins +#define MATRIX_OUT_PINS (0, Port_D, 4), (1, Port_C, 6), (2, Port_D, 7), (3, Port_E, 6), (4, Port_B, 4), (5, Port_B, 5) + +// list of INPUT ports +#define MATRIX_IN_PORTS \ + (Port_Fa, MCU_GPIOa, F0), \ + (Port_Ba, MCU_GPIOa, B0), \ + (Port_Fb, MCU_GPIOb, F0), \ + (Port_Bb, MCU_GPIOb, B0) +// list of INPUT pins +#define MATRIX_IN_PINS \ + (0, Port_Fa, 4), \ + (1, Port_Fb, 5), \ + (2, Port_Fb, 6), \ + (3, Port_Fa, 7), \ + (4, Port_Ba, 1), \ + (5, Port_Bb, 3) +``` + +### I/O expander Extension + +I plan to provide extensions to support I/O expanders such as MCP23018 and PCA9555. + +## Compile + +* Measure the execution time of matrix_scan() + * `make MTEST=matrix_debug_scan[,<other options>..] handwired/symmetric70_proto/promicro/fast:default:flash` +* Measure delay time. + * `make MTEST=matrix_debug_delay[,<other options>..] handwired/symmetric70_proto/promicro/fast:default:flash` + +## Measurement result +### Pro Micro (ATmega32u4 16Mhz) +#### Default setting (show `matrix_scan()` time) + - `make MTEST=matrix_debug_scan handwired/symmetric70_proto/promicro/fast:default:flash` + - CH1: Row 0 + - CH2: Row 1 + - CH3: Row 4 + - CH4: matrix_scan() + - Execution time of matrix_scan() 75.6us + - Frequency of matrix scan 8.09kHz (123.6us) + ![DS1Z_QuickPrint7](https://user-images.githubusercontent.com/2170248/116003927-538d9100-a63b-11eb-9b36-7db47d9b1541.png) + +#### Default setting (show delay time) + - `make MTEST=matrix_debug_delay handwired/symmetric70_proto/promicro/fast:default:flash` +##### Press R0C0 key + - CH1: Row 0 + - CH2: Row 1 + - CH3: Row 4 + - CH4: delay time + - Frequency of matrix scan 7.84kHz (127.6us) + +![DS1Z_QuickPrint9](https://user-images.githubusercontent.com/2170248/116003974-99e2f000-a63b-11eb-9c9e-3b3b1025db66.png) +![DS1Z_QuickPrint10](https://user-images.githubusercontent.com/2170248/116003978-a1a29480-a63b-11eb-97d8-5a6e11c0db2f.png) + +### Proton C +#### Default setting (show `matrix_scan()` time) + - `make MTEST=matrix_debug_scan handwired/symmetric70_proto/proton_c/fast:default:flash` + - CH1: Row 0 + - CH2: Row 1 + - CH3: Row 4 + - CH4: matrix_scan() + - Execution time of matrix_scan() 49.8us + - Frequency of matrix scan 15.1kHz (66.2.6us) + +![DS1Z_QuickPrint11](https://user-images.githubusercontent.com/2170248/116088141-8cca0d80-a6dc-11eb-8782-1d29c57690b8.png) + +#### Default setting (show delay time) + - `make MTEST=matrix_debug_delay handwired/symmetric70_proto/proton_c/fast:default:flash` +##### Press R0C0 key + - CH1: Row 0 + - CH2: Row 1 + - CH3: Row 4 + - CH4: delay time + - Frequency of matrix scan 13.9kHz (71.8us) + +![DS1Z_QuickPrint12](https://user-images.githubusercontent.com/2170248/116088247-a8cdaf00-a6dc-11eb-8a47-104694a40117.png) +![DS1Z_QuickPrint13](https://user-images.githubusercontent.com/2170248/116088262-ac613600-a6dc-11eb-804c-7dcbd71c83d5.png) + +##### Connect a 500pF capacitor between C0 line and GND, Press R0C0, R1C0, R2C0, R3C0, R4C0 keys + - CH1: Row 0 + - CH2: Row 1 + - CH3: Col 0 + - CH4: delay time + - Delay time 11.6us + - Threshold Voltage 1.9V + +![DS1Z_QuickPrint14](https://user-images.githubusercontent.com/2170248/116089205-90aa5f80-a6dd-11eb-89c4-72315c80ba0e.png) + +##### Connect |