From 6bf243032aa51a71ed401817a81d3a7dff1df50c Mon Sep 17 00:00:00 2001 From: James Churchill Date: Thu, 3 Jan 2019 16:33:09 +1100 Subject: [PATCH 01/20] Eliminate separate slave loop Both master and slave run the standard keyboard_task main loop now. --- quantum/split_common/matrix.c | 118 +++++++++++++++++++------- quantum/split_common/split_util.c | 136 ++++++++++-------------------- quantum/split_common/split_util.h | 7 -- tmk_core/common/keyboard.h | 2 + 4 files changed, 134 insertions(+), 129 deletions(-) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 2c37053f883f..c2b84c675907 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -246,8 +246,8 @@ int i2c_transaction(void) { // Backlight location err = i2c_master_write(I2C_BACKLIT_START); if (err) goto i2c_error; - - // Write backlight + + // Write backlight i2c_master_write(get_backlight_level()); BACKLIT_DIRTY = false; @@ -351,48 +351,104 @@ int serial_transaction(void) { } #endif -uint8_t matrix_scan(void) +static void master_transport(void) { - uint8_t ret = _matrix_scan(); - #if defined(USE_I2C) || defined(EH) - if( i2c_transaction() ) { -#else // USE_SERIAL - if( serial_transaction() ) { + if (i2c_transaction()) + { +#else // USE_SERIAL + if (serial_transaction()) + { #endif - error_count++; + error_count++; - 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; + 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; + } } - matrix_scan_quantum(); - return ret; + } + else + { + error_count = 0; + } } -void matrix_slave_scan(void) { - _matrix_scan(); +static void slave_transport(void) { - int offset = (isLeftHand) ? 0 : ROWS_PER_HAND; + 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]; + for (int i = 0; i < ROWS_PER_HAND; ++i) + { + i2c_slave_buffer[I2C_KEYMAP_START + i] = matrix[offset + i]; + } + // Read Backlight Info + #ifdef BACKLIGHT_ENABLE + if (BACKLIT_DIRTY) + { + backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]); + BACKLIT_DIRTY = false; + } + #endif + #ifdef RGBLIGHT_ENABLE + if (RGB_DIRTY) + { + // Disable interupts (RGB data is big) + cli(); + // Create new DWORD for RGB data + uint32_t dword; + + // Fill the new DWORD with the data that was sent over + uint8_t * dword_dat = (uint8_t *)(&dword); + for (int i = 0; i < 4; i++) + { + dword_dat[i] = i2c_slave_buffer[I2C_RGB_START + i]; } + + // Update the RGB now with the new data and set RGB_DIRTY to false + rgblight_update_dword(dword); + RGB_DIRTY = false; + // Re-enable interupts now that RGB is set + sei(); + } + #endif + +#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]; + } + #ifdef BACKLIGHT_ENABLE + backlight_set(serial_m2s_buffer.backlight_level); + #endif + #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + // Add serial implementation for RGB here + #endif #endif - matrix_slave_scan_user(); +} + +uint8_t matrix_scan(void) +{ + uint8_t ret = _matrix_scan(); + + if (is_keyboard_master()) + { + master_transport(); + } + else + { + slave_transport(); + } + + matrix_scan_quantum(); + return ret; } bool matrix_is_modified(void) diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index e41b6f6386e9..a5b4a0f6b67c 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -20,26 +20,44 @@ volatile bool isLeftHand = true; -volatile uint8_t setTries = 0; - -static void setup_handedness(void) { +__attribute__((weak)) +bool is_keyboard_left(void) { #ifdef SPLIT_HAND_PIN // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand setPinInput(SPLIT_HAND_PIN); - isLeftHand = readPin(SPLIT_HAND_PIN); + return readPin(SPLIT_HAND_PIN); #else #ifdef EE_HANDS - isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS); + return eeprom_read_byte(EECONFIG_HANDEDNESS); #else #ifdef MASTER_RIGHT - isLeftHand = !has_usb(); + return !is_keyboard_master(); #else - isLeftHand = has_usb(); + return is_keyboard_master(); #endif #endif #endif } +bool is_keyboard_master(void) +{ +#ifdef __AVR__ + static enum { UNKNOWN, MASTER, SLAVE } usbstate = UNKNOWN; + + // only check once, as this is called often + if (usbstate == UNKNOWN) + { + USBCON |= (1 << OTGPADE); // enables VBUS pad + _delay_us(5); + usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE; // checks state of VBUS + } + + return (usbstate == MASTER); +#else + return true; +#endif +} + static void keyboard_master_setup(void) { #if defined(USE_I2C) || defined(EH) i2c_master_init(); @@ -50,96 +68,32 @@ static void keyboard_master_setup(void) { serial_master_init(); #endif - // For master the Backlight info needs to be sent on startup - // Otherwise the salve won't start with the proper info until an update - BACKLIT_DIRTY = true; + // For master the Backlight info needs to be sent on startup + // Otherwise the salve won't start with the proper info until an update + BACKLIT_DIRTY = true; } -static void keyboard_slave_setup(void) { - timer_init(); +static void keyboard_slave_setup(void) +{ #if defined(USE_I2C) || defined(EH) - i2c_slave_init(SLAVE_I2C_ADDRESS); + i2c_slave_init(SLAVE_I2C_ADDRESS); #else - serial_slave_init(); + serial_slave_init(); #endif } -bool has_usb(void) { - USBCON |= (1 << OTGPADE); //enables VBUS pad - _delay_us(5); - return (USBSTA & (1< Date: Thu, 3 Jan 2019 17:50:19 +1100 Subject: [PATCH 02/20] Refactor i2c/serial specific code Simplify some of the preprocessor mess by using common function names. --- quantum/split_common/matrix.c | 35 ++++++++++++++++--------------- quantum/split_common/matrix.h | 4 ++-- quantum/split_common/split_util.c | 19 +++-------------- quantum/split_common/split_util.h | 3 --- 4 files changed, 23 insertions(+), 38 deletions(-) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index c2b84c675907..a9a2f2b1b581 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -36,6 +36,7 @@ along with this program. If not, see . #if defined(USE_I2C) || defined(EH) # include "i2c.h" +# define SLAVE_I2C_ADDRESS 0x32 #else // USE_SERIAL # include "serial.h" #endif @@ -233,7 +234,7 @@ uint8_t _matrix_scan(void) #if defined(USE_I2C) || defined(EH) // Get rows from other half over i2c -int i2c_transaction(void) { +bool do_transaction(void) { int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; int err = 0; @@ -275,7 +276,7 @@ int i2c_transaction(void) { } else { i2c_error: // the cable is disconnceted, or something else went wrong i2c_reset_state(); - return err; + return false; } #ifdef RGBLIGHT_ENABLE @@ -298,11 +299,18 @@ int i2c_transaction(void) { } #endif - return 0; + return true; } -#else // USE_SERIAL +void transport_master_init(void) { + i2c_master_init(); +} +void transport_slave_init(void) { + i2c_slave_init(SLAVE_I2C_ADDRESS); +} + +#else // USE_SERIAL typedef struct _Serial_s2m_buffer_t { // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack @@ -320,17 +328,17 @@ SSTD_t transactions[] = { } }; -void serial_master_init(void) +void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } -void serial_slave_init(void) +void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } -int serial_transaction(void) { +bool do_transaction(void) { int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; if (soft_serial_transaction()) { - return 1; + return false; } // TODO: if MATRIX_COLS > 8 change to unpack() @@ -347,20 +355,13 @@ int serial_transaction(void) { serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0; #endif - return 0; + return true; } #endif static void master_transport(void) { -#if defined(USE_I2C) || defined(EH) - if (i2c_transaction()) - { -#else // USE_SERIAL - if (serial_transaction()) - { -#endif - + if (!do_transaction()) { error_count++; if (error_count > ERROR_DISCONNECT_COUNT) diff --git a/quantum/split_common/matrix.h b/quantum/split_common/matrix.h index b5cb45baed87..84ae4bd75836 100644 --- a/quantum/split_common/matrix.h +++ b/quantum/split_common/matrix.h @@ -25,7 +25,7 @@ typedef struct _Serial_m2s_buffer_t { extern volatile Serial_m2s_buffer_t serial_m2s_buffer; -void serial_master_init(void); -void serial_slave_init(void); +void transport_master_init(void); +void transport_slave_init(void); #endif diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index a5b4a0f6b67c..bd74f2022d89 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -8,14 +8,7 @@ #ifdef EE_HANDS # include "tmk_core/common/eeprom.h" -#endif - -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" -#endif - -#if defined(USE_I2C) || defined(EH) -# include "i2c.h" +# include "eeconfig.h" #endif volatile bool isLeftHand = true; @@ -60,13 +53,11 @@ bool is_keyboard_master(void) static void keyboard_master_setup(void) { #if defined(USE_I2C) || defined(EH) - i2c_master_init(); #ifdef SSD1306OLED matrix_master_OLED_init (); #endif #else - serial_master_init(); -#endif + transport_master_init(); // For master the Backlight info needs to be sent on startup // Otherwise the salve won't start with the proper info until an update @@ -75,11 +66,7 @@ static void keyboard_master_setup(void) { static void keyboard_slave_setup(void) { -#if defined(USE_I2C) || defined(EH) - i2c_slave_init(SLAVE_I2C_ADDRESS); -#else - serial_slave_init(); -#endif + transport_slave_init(); } // this code runs before the usb and keyboard is initialized diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index 1e604216ead9..a32331685ea8 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -5,9 +5,6 @@ #include #include #include -#include "eeconfig.h" - -#define SLAVE_I2C_ADDRESS 0x32 extern volatile bool isLeftHand; From 206915ebfd61e12ff1f936b98a1d6dc988bb2d35 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Fri, 4 Jan 2019 16:07:20 +1100 Subject: [PATCH 03/20] Fix missing #endif --- quantum/split_common/split_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index bd74f2022d89..e4cc424541f7 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -56,7 +56,7 @@ static void keyboard_master_setup(void) { #ifdef SSD1306OLED matrix_master_OLED_init (); #endif -#else +#endif transport_master_init(); // For master the Backlight info needs to be sent on startup From 34c100d42f79c194aac3cf0f451f8fcbc05d7f38 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Fri, 4 Jan 2019 21:19:13 +1100 Subject: [PATCH 04/20] Move direct pin mapping support from miniaxe to split_common For boards with more pins than sense--sorry, switches. --- keyboards/miniaxe/config.h | 5 +- keyboards/miniaxe/matrix.c | 641 ---------------------------------- keyboards/miniaxe/rules.mk | 3 +- quantum/config_common.h | 3 + quantum/split_common/matrix.c | 47 ++- 5 files changed, 49 insertions(+), 650 deletions(-) delete mode 100644 keyboards/miniaxe/matrix.c diff --git a/keyboards/miniaxe/config.h b/keyboards/miniaxe/config.h index 2b732ca16f96..7a68476a549a 100644 --- a/keyboards/miniaxe/config.h +++ b/keyboards/miniaxe/config.h @@ -44,8 +44,7 @@ along with this program. If not, see . */ // #define MATRIX_ROW_PINS { D0, D5 } // #define MATRIX_COL_PINS { F1, F0, B0 } -#define NO_PIN 0xFF -#define MATRIX_ROW_COL_PINS { \ +#define DIRECT_PINS { \ { F1, E6, B0, B2, B3 }, \ { F5, F0, B1, B7, D2 }, \ { F6, F7, C7, D5, D3 }, \ @@ -54,7 +53,7 @@ along with this program. If not, see . #define UNUSED_PINS /* COL2ROW, ROW2COL, or CUSTOM_MATRIX */ -#define DIODE_DIRECTION CUSTOM_MATRIX +//#define DIODE_DIRECTION CUSTOM_MATRIX // #define BACKLIGHT_PIN B7 // #define BACKLIGHT_BREATHING diff --git a/keyboards/miniaxe/matrix.c b/keyboards/miniaxe/matrix.c deleted file mode 100644 index 5fec1281dfc6..000000000000 --- a/keyboards/miniaxe/matrix.c +++ /dev/null @@ -1,641 +0,0 @@ -/* -Copyright 2012 Jun Wako - -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 . -*/ - -/* - * scan matrix - */ -#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" - -#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" -#endif - -#ifndef DEBOUNCING_DELAY -# define DEBOUNCING_DELAY 5 -#endif - -#if (DEBOUNCING_DELAY > 0) - static uint16_t debouncing_time; - static bool debouncing = false; -#endif - -#if defined(USE_I2C) || defined(EH) - -#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 - -#else // USE_SERIAL - -#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 - -#endif -static matrix_row_t matrix_debouncing[MATRIX_ROWS]; - -#define ERROR_DISCONNECT_COUNT 5 - -#define ROWS_PER_HAND (MATRIX_ROWS/2) - -static uint8_t error_count = 0; - -#if ((DIODE_DIRECTION == COL2ROW) || (DIODE_DIRECTION == ROW2COL)) -static uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; -static uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; -#elif (DIODE_DIRECTION == CUSTOM_MATRIX) -static uint8_t row_col_pins[MATRIX_ROWS][MATRIX_COLS] = MATRIX_ROW_COL_PINS; -#endif - -/* 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); -#elif (DIODE_DIRECTION == CUSTOM_MATRIX) - static void init_cols_rows(void); - static bool read_cols(matrix_row_t current_matrix[], uint8_t current_row); -#endif - -__attribute__ ((weak)) -void matrix_init_kb(void) { - matrix_init_user(); -} - -__attribute__ ((weak)) -void matrix_scan_kb(void) { - matrix_scan_user(); -} - -__attribute__ ((weak)) -void matrix_init_user(void) { -} - -__attribute__ ((weak)) -void matrix_scan_user(void) { -} - -__attribute__ ((weak)) -void matrix_slave_scan_user(void) { -} - -inline -uint8_t matrix_rows(void) -{ - return MATRIX_ROWS; -} - -inline -uint8_t matrix_cols(void) -{ - return MATRIX_COLS; -} - -void matrix_init(void) -{ -#ifdef DISABLE_JTAG - // JTAG disable for PORT F. write JTD bit twice within four cycles. - MCUCR |= (1< 0) - bool matrix_changed = read_cols_on_row(matrix_debouncing+offset, current_row); - - if (matrix_changed) { - debouncing = true; - debouncing_time = timer_read(); - } - -# else - read_cols_on_row(matrix+offset, current_row); -# endif - - } - -#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 - - } - -#elif (DIODE_DIRECTION == CUSTOM_MATRIX) - // 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(matrix_debouncing+offset, current_row); - if (matrix_changed) { - debouncing = true; - debouncing_time = timer_read(); - } -# else - read_cols(matrix+offset, current_row); -# endif - } -#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; -} - -#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 - - return 0; -} - -#else // USE_SERIAL - - -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; - -volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; -volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; -uint8_t volatile status0 = 0; - -SSTD_t transactions[] = { - { (uint8_t *)&status0, - sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer, - sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer - } -}; - -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]; - } - - #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_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0; - #endif - - return 0; -} -#endif - -uint8_t matrix_scan(void) -{ - uint8_t ret = _matrix_scan(); - -#if defined(USE_I2C) || defined(EH) - if( i2c_transaction() ) { -#else // USE_SERIAL - if( serial_transaction() ) { -#endif - - error_count++; - - 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; -} - -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]; - } -#endif - matrix_slave_scan_user(); -} - -bool matrix_is_modified(void) -{ - if (debouncing) return false; - return true; -} - -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 - } -} - -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)); - - // Populate the matrix row with the state of the col pin - current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); - } - - // Unselect row - unselect_row(current_row); - - return (last_row_value != current_matrix[current_row]); -} - -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 -} - -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 -} - -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 - } -} - -#elif (DIODE_DIRECTION == ROW2COL) - -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 - } -} - -static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) -{ - bool matrix_changed = false; - - // Select col and wait for col selecton to stabilize - select_col(current_col); - wait_us(30); - - // 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]; - - // 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; - } - } - - // 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 -} - -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 - } -} - -#elif (DIODE_DIRECTION == CUSTOM_MATRIX) - -static void init_cols_rows(void) -{ - for(int row = 0; row < MATRIX_ROWS; row++) { - for(int col = 0; col < MATRIX_COLS; col++) { - uint8_t pin = row_col_pins[row][col]; - if(pin == NO_PIN) { - continue; - } - // DDxn set 0 for input - _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); - // PORTxn set 1 for input/pullup - _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); - } - } -} - -static bool read_cols(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++) { - uint8_t pin = row_col_pins[current_row][col_index]; - if(pin == NO_PIN) { - current_matrix[current_row] |= 0; - } - else { - uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)); - current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); - } - } - - return (last_row_value != current_matrix[current_row]); -} - -#endif diff --git a/keyboards/miniaxe/rules.mk b/keyboards/miniaxe/rules.mk index 96e27686b8d8..2f56a907ba6a 100644 --- a/keyboards/miniaxe/rules.mk +++ b/keyboards/miniaxe/rules.mk @@ -1,4 +1,3 @@ -SRC += matrix.c # MCU name #MCU = at90usb1286 @@ -83,6 +82,6 @@ FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches HD44780_ENABLE = no # Enable support for HD44780 based LCDs (+400) DEBUG_ENABLE = no -CUSTOM_MATRIX = yes # Use custom matrix code +CUSTOM_MATRIX = no # Use custom matrix code SPLIT_KEYBOARD = yes # Use shared split_common code diff --git a/quantum/config_common.h b/quantum/config_common.h index cbff372eaf36..5b45370e5e65 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -21,6 +21,9 @@ #define ROW2COL 1 #define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */ +// useful for direct pin mapping +#define NO_PIN (~0) + #ifdef __AVR__ #ifndef __ASSEMBLER__ #include diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index a9a2f2b1b581..5146b0573bb8 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -89,14 +89,21 @@ static matrix_row_t matrix_debouncing[MATRIX_ROWS]; static uint8_t error_count = 0; +#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 /* 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) +#ifdef DIRECT_PINS + static void init_pins(void); + static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); +#elif (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); @@ -165,7 +172,9 @@ void matrix_init(void) } // initialize row and col -#if (DIODE_DIRECTION == COL2ROW) +#ifdef DIRECT_PINS + init_pins(); +#elif (DIODE_DIRECTION == COL2ROW) unselect_rows(); init_cols(); #elif (DIODE_DIRECTION == ROW2COL) @@ -186,7 +195,8 @@ void matrix_init(void) uint8_t _matrix_scan(void) { int offset = isLeftHand ? 0 : (ROWS_PER_HAND); -#if (DIODE_DIRECTION == COL2ROW) + +#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) // Set row, read cols for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { # if (DEBOUNCING_DELAY > 0) @@ -489,7 +499,36 @@ uint8_t matrix_key_count(void) return count; } -#if (DIODE_DIRECTION == COL2ROW) +#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); + } + } + } +} + +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); + } + } + + return (last_row_value != current_matrix[current_row]); +} + +#elif (DIODE_DIRECTION == COL2ROW) static void init_cols(void) { From f8d234d8a4aa29c883452297ea84af296ea6210d Mon Sep 17 00:00:00 2001 From: James Churchill Date: Fri, 4 Jan 2019 23:14:47 +1100 Subject: [PATCH 05/20] Reordering and reformatting only --- quantum/split_common/matrix.c | 667 ++++++++++++++++------------------ 1 file changed, 315 insertions(+), 352 deletions(-) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 5146b0573bb8..9b861b38b6b0 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -30,8 +30,8 @@ along with this program. If not, see . #include "quantum.h" #ifdef BACKLIGHT_ENABLE -# include "backlight.h" - extern backlight_config_t backlight_config; +# include "backlight.h" + extern backlight_config_t backlight_config; #endif #if defined(USE_I2C) || defined(EH) @@ -42,27 +42,14 @@ along with this program. If not, see . #endif #ifndef DEBOUNCING_DELAY -# define DEBOUNCING_DELAY 5 +# define DEBOUNCING_DELAY 5 #endif #if (DEBOUNCING_DELAY > 0) - static uint16_t debouncing_time; - static bool debouncing = false; + static uint16_t debouncing_time; + static bool debouncing = false; #endif -#if defined(USE_I2C) || defined(EH) - -#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 - -#else // USE_SERIAL - #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)) @@ -80,9 +67,6 @@ along with this program. If not, see . # define ROW_SHIFTER ((uint32_t)1) #endif -#endif -static matrix_row_t matrix_debouncing[MATRIX_ROWS]; - #define ERROR_DISCONNECT_COUNT 5 #define ROWS_PER_HAND (MATRIX_ROWS/2) @@ -101,215 +85,321 @@ static matrix_row_t matrix[MATRIX_ROWS]; static matrix_row_t matrix_debouncing[MATRIX_ROWS]; #ifdef DIRECT_PINS - static void init_pins(void); - static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); + +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); + } + } + } +} + +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); + } + } + + return (last_row_value != current_matrix[current_row]); +} + #elif (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); + +static void select_row(uint8_t row) +{ + writePinLow(row_pins[row]); + setPinOutput(row_pins[row]); +} + +static void unselect_row(uint8_t row) +{ + setPinInputHigh(row_pins[row]); +} + +static void unselect_rows(void) +{ + for(uint8_t x = 0; x < ROWS_PER_HAND; x++) { + setPinInputHigh(row_pins[x]); + } +} + +static void init_pins(void) +{ + unselect_rows(); + for(uint8_t x = 0; x < MATRIX_COLS; x++) { + setPinInputHigh(col_pins[x]); + } +} + +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++) { + // 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); + } + + // Unselect row + unselect_row(current_row); + + return (last_row_value != current_matrix[current_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_init_kb(void) { - matrix_init_user(); +static void init_pins(void) +{ + unselect_cols(); + for(uint8_t x = 0; x < ROWS_PER_HAND; x++) { + setPinInputHigh(row_pins[x]); + } } -__attribute__ ((weak)) -void matrix_scan_kb(void) { - matrix_scan_user(); +static void select_col(uint8_t col) +{ + writePinLow(col_pins[col]); + setPinOutput(col_pins[col]); } -__attribute__ ((weak)) -void matrix_init_user(void) { +static void unselect_col(uint8_t col) +{ + setPinInputHigh(col_pins[col]); } -__attribute__ ((weak)) -void matrix_scan_user(void) { +static void unselect_cols(void) +{ + for(uint8_t x = 0; x < MATRIX_COLS; x++) { + setPinInputHigh(col_pins[x]); + } } -__attribute__ ((weak)) -void matrix_slave_scan_user(void) { +static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) +{ + bool matrix_changed = false; + + // Select col and wait for col selecton to stabilize + select_col(current_col); + wait_us(30); + + // 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]; + + // 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); + } + + // Determine if the matrix changed state + if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) + { + matrix_changed = true; + } + } + + // Unselect col + unselect_col(current_col); + + return matrix_changed; } +#endif + inline uint8_t matrix_rows(void) { - return MATRIX_ROWS; + return MATRIX_ROWS; } inline uint8_t matrix_cols(void) { - return MATRIX_COLS; + return MATRIX_COLS; } void matrix_init(void) { - debug_enable = true; - debug_matrix = true; - debug_mouse = true; + debug_enable = true; + debug_matrix = true; + debug_mouse = true; - // Set pinout for right half if pinout for that half is defined - if (!isLeftHand) { + // 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]; + 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 + 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]; } - - // initialize row and col -#ifdef DIRECT_PINS - init_pins(); -#elif (DIODE_DIRECTION == COL2ROW) - unselect_rows(); - init_cols(); -#elif (DIODE_DIRECTION == ROW2COL) - unselect_cols(); - init_rows(); #endif + } - // 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(); - + // initialize key pins + init_pins(); + + // 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(); } uint8_t _matrix_scan(void) { - int offset = isLeftHand ? 0 : (ROWS_PER_HAND); + int offset = isLeftHand ? 0 : (ROWS_PER_HAND); #if defined(DIRECT_PINS) || (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); - - if (matrix_changed) { - debouncing = true; - debouncing_time = timer_read(); - } - -# else - read_cols_on_row(matrix+offset, current_row); -# endif + // 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); + if (matrix_changed) { + debouncing = true; + debouncing_time = timer_read(); } +#else + read_cols_on_row(matrix+offset, current_row); +#endif + } #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 - + // 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 + } #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 +#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 1; } #if defined(USE_I2C) || defined(EH) +#if (MATRIX_COLS > 8) +# error "Currently only supports 8 COLS" +#endif + // Get rows from other half over i2c bool do_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 + 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; - - // 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 false; + 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); } - - #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 - - return true; + 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 false; + } + +#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 + + return true; } void transport_master_init(void) { @@ -323,8 +413,8 @@ void transport_slave_init(void) { #else // USE_SERIAL 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]; + // 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; volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; @@ -332,9 +422,9 @@ volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; uint8_t volatile status0 = 0; SSTD_t transactions[] = { - { (uint8_t *)&status0, - sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer, - sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer + { (uint8_t *)&status0, + sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer, + sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer } }; @@ -345,27 +435,27 @@ void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } bool do_transaction(void) { - int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; + int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; - if (soft_serial_transaction()) { - return false; - } + if (soft_serial_transaction()) { + return false; + } - // 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 true; + // 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 true; } #endif @@ -464,186 +554,59 @@ uint8_t matrix_scan(void) bool matrix_is_modified(void) { - if (debouncing) return false; - return true; + if (debouncing) return false; + return true; } inline bool matrix_is_on(uint8_t row, uint8_t col) { - return (matrix[row] & ((matrix_row_t)1< Date: Sun, 6 Jan 2019 18:09:56 +1100 Subject: [PATCH 06/20] Don't run matrix_scan_quantum on slave side --- quantum/split_common/matrix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 9b861b38b6b0..b74ae4318904 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -542,13 +542,14 @@ uint8_t matrix_scan(void) if (is_keyboard_master()) { master_transport(); + matrix_scan_quantum(); } else { slave_transport(); + matrix_slave_scan_user(); } - matrix_scan_quantum(); return ret; } From 9013ea240a585f460ef0545daf68d1d8d46973b6 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Mon, 7 Jan 2019 23:44:30 +1000 Subject: [PATCH 07/20] Clean up the offset/slaveOffset calculations --- quantum/split_common/matrix.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index b74ae4318904..c1b638eb85ba 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -84,6 +84,9 @@ static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; static matrix_row_t matrix[MATRIX_ROWS]; static matrix_row_t matrix_debouncing[MATRIX_ROWS]; +// row offsets for each hand +uint8_t thisHand, thatHand; + #ifdef DIRECT_PINS static void init_pins(void) @@ -269,6 +272,9 @@ void matrix_init(void) #endif } + thisHand = isLeftHand ? 0 : (ROWS_PER_HAND); + thatHand = ROWS_PER_HAND - thisHand; + // initialize key pins init_pins(); @@ -283,20 +289,18 @@ void matrix_init(void) uint8_t _matrix_scan(void) { - int offset = isLeftHand ? 0 : (ROWS_PER_HAND); - #if defined(DIRECT_PINS) || (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); + bool matrix_changed = read_cols_on_row(matrix_debouncing+thisHand, current_row); if (matrix_changed) { debouncing = true; debouncing_time = timer_read(); } #else - read_cols_on_row(matrix+offset, current_row); + read_cols_on_row(matrix+thisHand, current_row); #endif } @@ -304,13 +308,13 @@ uint8_t _matrix_scan(void) // 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); + bool matrix_changed = read_rows_on_col(matrix_debouncing+thisHand, current_col); if (matrix_changed) { debouncing = true; debouncing_time = timer_read(); } #else - read_rows_on_col(matrix+offset, current_col); + read_rows_on_col(matrix+thisHand, current_col); #endif } #endif @@ -318,7 +322,7 @@ uint8_t _matrix_scan(void) #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]; + matrix[thisHand+i] = matrix_debouncing[thisHand+i]; } debouncing = false; } @@ -335,7 +339,6 @@ uint8_t _matrix_scan(void) // Get rows from other half over i2c bool do_transaction(void) { - int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; int err = 0; // write backlight info @@ -369,9 +372,9 @@ bool do_transaction(void) { if (!err) { int i; for (i = 0; i < ROWS_PER_HAND-1; ++i) { - matrix[slaveOffset+i] = i2c_master_read(I2C_ACK); + matrix[thatHand+i] = i2c_master_read(I2C_ACK); } - matrix[slaveOffset+i] = i2c_master_read(I2C_NACK); + matrix[thatHand+i] = i2c_master_read(I2C_NACK); i2c_master_stop(); } else { i2c_error: // the cable is disconnceted, or something else went wrong @@ -435,7 +438,6 @@ void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } bool do_transaction(void) { - int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0; if (soft_serial_transaction()) { return false; @@ -443,7 +445,7 @@ bool do_transaction(void) { // 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]; + matrix[thatHand+i] = serial_s2m_buffer.smatrix[i]; } #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) @@ -467,10 +469,9 @@ static void master_transport(void) 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; + matrix[thatHand + i] = 0; } } } @@ -482,12 +483,10 @@ static void master_transport(void) static void slave_transport(void) { - 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]; + i2c_slave_buffer[I2C_KEYMAP_START + i] = matrix[thisHand + i]; } // Read Backlight Info #ifdef BACKLIGHT_ENABLE @@ -524,7 +523,7 @@ static void slave_transport(void) { // 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]; + serial_s2m_buffer.smatrix[i] = matrix[thisHand + i]; } #ifdef BACKLIGHT_ENABLE backlight_set(serial_m2s_buffer.backlight_level); From 882be6f586ae1d3f05711d2793bf5a0697bfcc28 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Mon, 7 Jan 2019 23:54:11 +1000 Subject: [PATCH 08/20] Cut undebounced matrix size in half --- quantum/split_common/matrix.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index c1b638eb85ba..1e0ad4d98ca6 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -82,7 +82,7 @@ static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; /* matrix state(1:on, 0:off) */ static matrix_row_t matrix[MATRIX_ROWS]; -static matrix_row_t matrix_debouncing[MATRIX_ROWS]; +static matrix_row_t raw_matrix[ROWS_PER_HAND]; // row offsets for each hand uint8_t thisHand, thatHand; @@ -281,7 +281,6 @@ void matrix_init(void) // 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(); @@ -293,7 +292,7 @@ uint8_t _matrix_scan(void) // 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+thisHand, current_row); + bool matrix_changed = read_cols_on_row(raw_matrix, current_row); if (matrix_changed) { debouncing = true; @@ -308,7 +307,7 @@ uint8_t _matrix_scan(void) // 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+thisHand, current_col); + bool matrix_changed = read_rows_on_col(raw_matrix, current_col); if (matrix_changed) { debouncing = true; debouncing_time = timer_read(); @@ -322,7 +321,7 @@ uint8_t _matrix_scan(void) #if (DEBOUNCING_DELAY > 0) if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { - matrix[thisHand+i] = matrix_debouncing[thisHand+i]; + matrix[thisHand+i] = raw_matrix[i]; } debouncing = false; } From 71028fcf8cfb621e930c1154960bb581e26ea5a7 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Tue, 8 Jan 2019 00:17:00 +1000 Subject: [PATCH 09/20] Refactor debouncing --- quantum/split_common/matrix.c | 71 ++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 1e0ad4d98ca6..c112ab0f165e 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -45,11 +45,6 @@ along with this program. If not, see . # define DEBOUNCING_DELAY 5 #endif -#if (DEBOUNCING_DELAY > 0) - static uint16_t debouncing_time; - static bool debouncing = false; -#endif - #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)) @@ -286,46 +281,55 @@ void matrix_init(void) matrix_init_quantum(); } -uint8_t _matrix_scan(void) +#if DEBOUNCING_DELAY > 0 +void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) { -#if defined(DIRECT_PINS) || (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(raw_matrix, current_row); + static uint16_t debouncing_time; + static bool debouncing = false; - if (matrix_changed) { - debouncing = true; - debouncing_time = timer_read(); + if (changed) + { + debouncing = true; + debouncing_time = timer_read(); + } + + if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { + for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { + matrix[thisHand+i] = raw_matrix[i]; } + debouncing = false; + } +} #else - read_cols_on_row(matrix+thisHand, current_row); -#endif +// no debounce +bool debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) +{ + if (changed) + { + for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { + cooked[i] = raw[i]; + } } +} +#endif +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++) { -#if (DEBOUNCING_DELAY > 0) - bool matrix_changed = read_rows_on_col(raw_matrix, current_col); - if (matrix_changed) { - debouncing = true; - debouncing_time = timer_read(); - } -#else - read_rows_on_col(matrix+thisHand, current_col); -#endif + changed |= read_rows_on_col(raw_matrix, current_col); } #endif -#if (DEBOUNCING_DELAY > 0) - if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { - for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { - matrix[thisHand+i] = raw_matrix[i]; - } - debouncing = false; - } -#endif + debounce(raw_matrix, matrix+thisHand, changed); return 1; } @@ -553,7 +557,6 @@ uint8_t matrix_scan(void) bool matrix_is_modified(void) { - if (debouncing) return false; return true; } From 5d584dcbe228c85e826bf256ed25f639f26f6359 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Tue, 8 Jan 2019 00:17:35 +1000 Subject: [PATCH 10/20] Minor fixups --- quantum/split_common/matrix.c | 23 ++++++++++++----------- quantum/split_common/split_util.c | 3 ++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index c112ab0f165e..325e829a0cf8 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -165,14 +165,6 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) #elif (DIODE_DIRECTION == ROW2COL) -static void init_pins(void) -{ - unselect_cols(); - for(uint8_t x = 0; x < ROWS_PER_HAND; x++) { - setPinInputHigh(row_pins[x]); - } -} - static void select_col(uint8_t col) { writePinLow(col_pins[col]); @@ -191,6 +183,14 @@ static void unselect_cols(void) } } +static void init_pins(void) +{ + unselect_cols(); + for(uint8_t x = 0; x < ROWS_PER_HAND; x++) { + setPinInputHigh(row_pins[x]); + } +} + static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { bool matrix_changed = false; @@ -537,6 +537,10 @@ static void slave_transport(void) { #endif } +__attribute__ ((weak)) +void matrix_slave_scan_user(void) { +} + uint8_t matrix_scan(void) { uint8_t ret = _matrix_scan(); @@ -609,6 +613,3 @@ __attribute__ ((weak)) void matrix_scan_user(void) { } -__attribute__ ((weak)) -void matrix_slave_scan_user(void) { -} diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index e4cc424541f7..08222eece211 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -41,7 +41,8 @@ bool is_keyboard_master(void) if (usbstate == UNKNOWN) { USBCON |= (1 << OTGPADE); // enables VBUS pad - _delay_us(5); + wait_us(5); + usbstate = (USBSTA & (1 << VBUS)) ? MASTER : SLAVE; // checks state of VBUS } From 279e24da8b320fb837416b25eeb972550d6e6f6d Mon Sep 17 00:00:00 2001 From: James Churchill Date: Sun, 13 Jan 2019 14:31:14 +1000 Subject: [PATCH 11/20] Split split_common transport and debounce code into their own files Can now be replaced with custom versions per keyboard using CUSTOM_TRANSPORT = yes and CUSTOM_DEBOUNCE = yes --- common_features.mk | 13 +- quantum/split_common/debounce.c | 47 ++++++ quantum/split_common/debounce.h | 7 + quantum/split_common/i2c.h | 5 +- quantum/split_common/matrix.c | 258 ++--------------------------- quantum/split_common/matrix.h | 30 +--- quantum/split_common/serial.h | 5 +- quantum/split_common/split_flags.h | 9 +- quantum/split_common/split_util.c | 1 + quantum/split_common/split_util.h | 5 +- quantum/split_common/transport.c | 224 +++++++++++++++++++++++++ quantum/split_common/transport.h | 10 ++ 12 files changed, 317 insertions(+), 297 deletions(-) create mode 100644 quantum/split_common/debounce.c create mode 100644 quantum/split_common/debounce.h create mode 100644 quantum/split_common/transport.c create mode 100644 quantum/split_common/transport.h diff --git a/common_features.mk b/common_features.mk index c86e8bbfe397..41776de31503 100644 --- a/common_features.mk +++ b/common_features.mk @@ -265,8 +265,15 @@ endif ifeq ($(strip $(SPLIT_KEYBOARD)), yes) OPT_DEFS += -DSPLIT_KEYBOARD QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_flags.c \ - $(QUANTUM_DIR)/split_common/split_util.c - QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/i2c.c - QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/serial.c + $(QUANTUM_DIR)/split_common/split_util.c + ifneq ($(strip $(CUSTOM_TRANSPORT)), yes) + QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/transport.c \ + $(QUANTUM_DIR)/split_common/i2c.c \ + $(QUANTUM_DIR)/split_common/serial.c + endif + ifneq ($(strip $(CUSTOM_DEBOUNCE)), yes) + QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/debounce.c + endif COMMON_VPATH += $(QUANTUM_PATH)/split_common + endif diff --git a/quantum/split_common/debounce.c b/quantum/split_common/debounce.c new file mode 100644 index 000000000000..3ec58660a49a --- /dev/null +++ b/quantum/split_common/debounce.c @@ -0,0 +1,47 @@ + +#include "matrix.h" +#include "config.h" +#include "timer.h" +#include "quantum.h" + +#define ROWS_PER_HAND (MATRIX_ROWS/2) + +#ifndef DEBOUNCING_DELAY +# define DEBOUNCING_DELAY 5 +#endif + +#if DEBOUNCING_DELAY > 0 + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) +{ + static uint16_t debouncing_time; + static bool debouncing = false; + + if (changed) + { + debouncing = true; + debouncing_time = timer_read(); + } + + if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { + for (uint8_t i = 0; i < ROWS_PER_HAND/2; i++) { + cooked[i] = raw[i]; + } + debouncing = false; + } +} + +#else + +// no debounce +bool debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) +{ + if (changed) + { + for (uint8_t i = 0; i < ROWS_PER_HAND/2; i++) { + cooked[i] = raw[i]; + } + } +} + +#endif diff --git a/quantum/split_common/debounce.h b/quantum/split_common/debounce.h new file mode 100644 index 000000000000..67ef53721503 --- /dev/null +++ b/quantum/split_common/debounce.h @@ -0,0 +1,7 @@ +#pragma once + +// raw is the current key state +// on entry cooked is the previous debounced state +// on exit cooked is the current debounced state +// changed is true if raw has changed since the last call +void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed); diff --git a/quantum/split_common/i2c.h b/quantum/split_common/i2c.h index b3cbe8c826ab..91e8e96f4734 100644 --- a/quantum/split_common/i2c.h +++ b/quantum/split_common/i2c.h @@ -1,5 +1,4 @@ -#ifndef I2C_H -#define I2C_H +#pragma once #include @@ -58,5 +57,3 @@ extern unsigned char i2c_readNak(void); extern unsigned char i2c_read(unsigned char ack); #define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak(); - -#endif diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 325e829a0cf8..aa74cac8429d 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -25,25 +25,10 @@ along with this program. If not, see . #include "matrix.h" #include "split_util.h" #include "config.h" -#include "timer.h" #include "split_flags.h" #include "quantum.h" - -#ifdef BACKLIGHT_ENABLE -# include "backlight.h" - extern backlight_config_t backlight_config; -#endif - -#if defined(USE_I2C) || defined(EH) -# include "i2c.h" -# define SLAVE_I2C_ADDRESS 0x32 -#else // USE_SERIAL -# include "serial.h" -#endif - -#ifndef DEBOUNCING_DELAY -# define DEBOUNCING_DELAY 5 -#endif +#include "debounce.h" +#include "transport.h" #if (MATRIX_COLS <= 8) # define print_matrix_header() print("\nr/c 01234567\n") @@ -66,8 +51,6 @@ along with this program. If not, see . #define ROWS_PER_HAND (MATRIX_ROWS/2) -static uint8_t error_count = 0; - #ifdef DIRECT_PINS static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; #else @@ -281,38 +264,6 @@ void matrix_init(void) matrix_init_quantum(); } -#if DEBOUNCING_DELAY > 0 -void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) -{ - static uint16_t debouncing_time; - static bool debouncing = false; - - if (changed) - { - debouncing = true; - debouncing_time = timer_read(); - } - - if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { - for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { - matrix[thisHand+i] = raw_matrix[i]; - } - debouncing = false; - } -} -#else -// no debounce -bool debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) -{ - if (changed) - { - for (uint8_t i = 0; i < ROWS_PER_HAND; i++) { - cooked[i] = raw[i]; - } - } -} -#endif - uint8_t _matrix_scan(void) { bool changed = false; @@ -334,139 +285,19 @@ uint8_t _matrix_scan(void) return 1; } -#if defined(USE_I2C) || defined(EH) - -#if (MATRIX_COLS > 8) -# error "Currently only supports 8 COLS" -#endif - -// Get rows from other half over i2c -bool do_transaction(void) { - 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[thatHand+i] = i2c_master_read(I2C_ACK); - } - matrix[thatHand+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 false; - } - -#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 - - return true; -} - -void transport_master_init(void) { - i2c_master_init(); -} - -void transport_slave_init(void) { - i2c_slave_init(SLAVE_I2C_ADDRESS); -} - -#else // USE_SERIAL - -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; - -volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; -volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; -uint8_t volatile status0 = 0; - -SSTD_t transactions[] = { - { (uint8_t *)&status0, - sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer, - sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer - } -}; - -void transport_master_init(void) -{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } - -void transport_slave_init(void) -{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); } - -bool do_transaction(void) { - - if (soft_serial_transaction()) { - return false; - } - - // TODO: if MATRIX_COLS > 8 change to unpack() - for (int i = 0; i < ROWS_PER_HAND; ++i) { - matrix[thatHand+i] = serial_s2m_buffer.smatrix[i]; +__attribute__ ((weak)) +void matrix_slave_scan_user(void) { } - #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 +uint8_t matrix_scan(void) +{ + uint8_t ret = _matrix_scan(); - return true; -} -#endif + if (is_keyboard_master()) + { + static uint8_t error_count; -static void master_transport(void) -{ - if (!do_transaction()) { + if (!transport_master(matrix + thatHand)) { error_count++; if (error_count > ERROR_DISCONNECT_COUNT) @@ -482,77 +313,12 @@ static void master_transport(void) { error_count = 0; } -} - -static void slave_transport(void) { -#if defined(USE_I2C) || defined(EH) - for (int i = 0; i < ROWS_PER_HAND; ++i) - { - i2c_slave_buffer[I2C_KEYMAP_START + i] = matrix[thisHand + i]; - } - // Read Backlight Info - #ifdef BACKLIGHT_ENABLE - if (BACKLIT_DIRTY) - { - backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]); - BACKLIT_DIRTY = false; - } - #endif - #ifdef RGBLIGHT_ENABLE - if (RGB_DIRTY) - { - // Disable interupts (RGB data is big) - cli(); - // Create new DWORD for RGB data - uint32_t dword; - - // Fill the new DWORD with the data that was sent over - uint8_t * dword_dat = (uint8_t *)(&dword); - for (int i = 0; i < 4; i++) - { - dword_dat[i] = i2c_slave_buffer[I2C_RGB_START + i]; - } - - // Update the RGB now with the new data and set RGB_DIRTY to false - rgblight_update_dword(dword); - RGB_DIRTY = false; - // Re-enable interupts now that RGB is set - sei(); - } - #endif - -#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[thisHand + i]; - } - #ifdef BACKLIGHT_ENABLE - backlight_set(serial_m2s_buffer.backlight_level); - #endif - #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - // Add serial implementation for RGB here - #endif -#endif -} - -__attribute__ ((weak)) -void matrix_slave_scan_user(void) { -} - -uint8_t matrix_scan(void) -{ - uint8_t ret = _matrix_scan(); - - if (is_keyboard_master()) - { - master_transport(); matrix_scan_quantum(); } else { - slave_transport(); + transport_slave(matrix + thisHand); matrix_slave_scan_user(); } diff --git a/quantum/split_common/matrix.h b/quantum/split_common/matrix.h index 84ae4bd75836..c2bdd3098c1d 100644 --- a/quantum/split_common/matrix.h +++ b/quantum/split_common/matrix.h @@ -1,31 +1,3 @@ -#ifndef SPLIT_COMMON_MATRIX_H -#define SPLIT_COMMON_MATRIX_H +#pragma once #include - -#ifdef RGBLIGHT_ENABLE -# include "rgblight.h" -#endif - -typedef struct _Serial_m2s_buffer_t { -#ifdef BACKLIGHT_ENABLE - uint8_t backlight_level; -#endif -#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) - rgblight_config_t rgblight_config; //not yet use - // - // When MCUs on both sides drive their respective RGB LED chains, - // it is necessary to synchronize, so it is necessary to communicate RGB information. - // In that case, define the RGBLIGHT_SPLIT macro. - // - // Otherwise, if the master side MCU drives both sides RGB LED chains, - // there is no need to communicate. -#endif -} Serial_m2s_buffer_t; - -extern volatile Serial_m2s_buffer_t serial_m2s_buffer; - -void transport_master_init(void); -void transport_slave_init(void); - -#endif diff --git a/quantum/split_common/serial.h b/quantum/split_common/serial.h index b6638b3bdee9..1c1e640069c9 100644 --- a/quantum/split_common/serial.h +++ b/quantum/split_common/serial.h @@ -1,5 +1,4 @@ -#ifndef SOFT_SERIAL_H -#define SOFT_SERIAL_H +#pragma once #include @@ -61,5 +60,3 @@ int soft_serial_transaction(int sstd_index); #ifdef SERIAL_USE_MULTI_TRANSACTION int soft_serial_get_and_clean_status(int sstd_index); #endif - -#endif /* SOFT_SERIAL_H */ diff --git a/quantum/split_common/split_flags.h b/quantum/split_common/split_flags.h index f101fff5b5a2..aaac474a7dbf 100644 --- a/quantum/split_common/split_flags.h +++ b/quantum/split_common/split_flags.h @@ -1,10 +1,9 @@ -#ifndef SPLIT_FLAGS_H -#define SPLIT_FLAGS_H +#pragma once #include #include -/** +/** * Global Flags **/ @@ -14,7 +13,3 @@ extern volatile bool RGB_DIRTY; //Backlight Stuff extern volatile bool BACKLIT_DIRTY; - - - -#endif \ No newline at end of file diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 08222eece211..4c9ff1d5bdb3 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -4,6 +4,7 @@ #include "config.h" #include "timer.h" #include "split_flags.h" +#include "transport.h" #include "quantum.h" #ifdef EE_HANDS diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index a32331685ea8..20f7535bf44b 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -1,5 +1,4 @@ -#ifndef SPLIT_KEYBOARD_UTIL_H -#define SPLIT_KEYBOARD_UTIL_H +#pragma once #include #include @@ -9,5 +8,3 @@ extern volatile bool isLeftHand; void matrix_master_OLED_init (void); - -#endif diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c new file mode 100644 index 000000000000..95738530ecf4 --- /dev/null +++ b/quantum/split_common/transport.c @@ -0,0 +1,224 @@ + +#include "config.h" +#include "matrix.h" +#include "quantum.h" + +#define ROWS_PER_HAND (MATRIX_ROWS/2) + +#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" + +#ifndef SLAVE_I2C_ADDRESS +# define SLAVE_I2C_ADDRESS 0x32 +#endif + +#if (MATRIX_COLS > 8) +# error "Currently only supports 8 COLS" +#endif + +// Get rows from other half over i2c +bool transport_master(matrix_row_t matrix[]) { + 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[i] = i2c_master_read(I2C_ACK); + } + matrix[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 false; + } + +#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 + + return true; +} + +void transport_slave(matrix_row_t matrix[]) { + + for (int i = 0; i < ROWS_PER_HAND; ++i) + { + i2c_slave_buffer[I2C_KEYMAP_START + i] = matrix[i]; + } + // Read Backlight Info + #ifdef BACKLIGHT_ENABLE + if (BACKLIT_DIRTY) + { + backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]); + BACKLIT_DIRTY = false; + } + #endif + #ifdef RGBLIGHT_ENABLE + if (RGB_DIRTY) + { + // Disable interupts (RGB data is big) + cli(); + // Create new DWORD for RGB data + uint32_t dword; + + // Fill the new DWORD with the data that was sent over + uint8_t * dword_dat = (uint8_t *)(&dword); + for (int i = 0; i < 4; i++) + { + dword_dat[i] = i2c_slave_buffer[I2C_RGB_START + i]; + } + + // Update the RGB now with the new data and set RGB_DIRTY to false + rgblight_update_dword(dword); + RGB_DIRTY = false; + // Re-enable interupts now that RGB is set + sei(); + } + #endif +} + +void transport_master_init(void) { + i2c_master_init(); +} + +void transport_slave_init(void) { + i2c_slave_init(SLAVE_I2C_ADDRESS); +} + +#else // USE_SERIAL + +#include "serial.h" + +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; + +typedef struct _Serial_m2s_buffer_t { +#ifdef BACKLIGHT_ENABLE + uint8_t backlight_level; +#endif +#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + rgblight_config_t rgblight_config; //not yet use + // + // When MCUs on both sides drive their respective RGB LED chains, + // it is necessary to synchronize, so it is necessary to communicate RGB information. + // In that case, define the RGBLIGHT_SPLIT macro. + // + // Otherwise, if the master side MCU drives both sides RGB LED chains, + // there is no need to communicate. +#endif +} Serial_m2s_buffer_t; + +volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; +volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; +uint8_t volatile status0 = 0; + +SSTD_t transactions[] = { + { (uint8_t *)&status0, + sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer, + sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer + } +}; + +void transport_master_init(void) +{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } + +void transport_slave_init(void) +{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); } + +bool transport_master(matrix_row_t matrix[]) { + + if (soft_serial_transaction()) { + return false; + } + + // TODO: if MATRIX_COLS > 8 change to unpack() + for (int i = 0; i < ROWS_PER_HAND; ++i) { + matrix[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 true; +} + +void transport_slave(matrix_row_t matrix[]) { + + // TODO: if MATRIX_COLS > 8 change to pack() + for (int i = 0; i < ROWS_PER_HAND; ++i) + { + serial_s2m_buffer.smatrix[i] = matrix[i]; + } + #ifdef BACKLIGHT_ENABLE + backlight_set(serial_m2s_buffer.backlight_level); + #endif + #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) + // Add serial implementation for RGB here + #endif + +} + +#endif diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h new file mode 100644 index 000000000000..ccce57e444d5 --- /dev/null +++ b/quantum/split_common/transport.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +void transport_master_init(void); +void transport_slave_init(void); + +// returns false if valid data not received from slave +bool transport_master(matrix_row_t matrix[]); +void transport_slave(matrix_row_t matrix[]); From 686f387b32afa48dc5f2520ffe4744f95edc874d Mon Sep 17 00:00:00 2001 From: James Churchill Date: Sun, 13 Jan 2019 15:59:25 +1000 Subject: [PATCH 12/20] Refactor debounce for non-split keyboards too --- common_features.mk | 14 ++--- quantum/{split_common => }/debounce.c | 28 ++++++---- quantum/{split_common => }/debounce.h | 6 +- quantum/matrix.c | 79 ++++++--------------------- quantum/split_common/matrix.c | 5 +- 5 files changed, 51 insertions(+), 81 deletions(-) rename quantum/{split_common => }/debounce.c (51%) rename quantum/{split_common => }/debounce.h (56%) diff --git a/common_features.mk b/common_features.mk index 41776de31503..920a9ee49b91 100644 --- a/common_features.mk +++ b/common_features.mk @@ -262,18 +262,18 @@ ifneq ($(strip $(CUSTOM_MATRIX)), yes) endif endif +ifneq ($(strip $(CUSTOM_DEBOUNCE)), yes) + QUANTUM_SRC += $(QUANTUM_DIR)/debounce.c +endif + ifeq ($(strip $(SPLIT_KEYBOARD)), yes) OPT_DEFS += -DSPLIT_KEYBOARD QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_flags.c \ $(QUANTUM_DIR)/split_common/split_util.c ifneq ($(strip $(CUSTOM_TRANSPORT)), yes) - QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/transport.c \ - $(QUANTUM_DIR)/split_common/i2c.c \ - $(QUANTUM_DIR)/split_common/serial.c - endif - ifneq ($(strip $(CUSTOM_DEBOUNCE)), yes) - QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/debounce.c + QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c \ + $(QUANTUM_DIR)/split_common/i2c.c \ + $(QUANTUM_DIR)/split_common/serial.c endif COMMON_VPATH += $(QUANTUM_PATH)/split_common - endif diff --git a/quantum/split_common/debounce.c b/quantum/debounce.c similarity index 51% rename from quantum/split_common/debounce.c rename to quantum/debounce.c index 3ec58660a49a..080ca5864587 100644 --- a/quantum/split_common/debounce.c +++ b/quantum/debounce.c @@ -4,44 +4,50 @@ #include "timer.h" #include "quantum.h" -#define ROWS_PER_HAND (MATRIX_ROWS/2) - #ifndef DEBOUNCING_DELAY # define DEBOUNCING_DELAY 5 #endif +void debounce_init(uint8_t num_rows) { +} + #if DEBOUNCING_DELAY > 0 -void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) -{ +static bool debouncing = false; + +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { static uint16_t debouncing_time; - static bool debouncing = false; - if (changed) - { + if (changed) { debouncing = true; debouncing_time = timer_read(); } if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { - for (uint8_t i = 0; i < ROWS_PER_HAND/2; i++) { + for (uint8_t i = 0; i < num_rows; i++) { cooked[i] = raw[i]; } debouncing = false; } } +bool debounce_active(void) { + return debouncing; +} + #else // no debounce -bool debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed) -{ +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { if (changed) { - for (uint8_t i = 0; i < ROWS_PER_HAND/2; i++) { + for (uint8_t i = 0; i < num_rows; i++) { cooked[i] = raw[i]; } } } +bool debounce_active(void) { + return false; +} #endif diff --git a/quantum/split_common/debounce.h b/quantum/debounce.h similarity index 56% rename from quantum/split_common/debounce.h rename to quantum/debounce.h index 67ef53721503..360af77e7818 100644 --- a/quantum/split_common/debounce.h +++ b/quantum/debounce.h @@ -4,4 +4,8 @@ // on entry cooked is the previous debounced state // on exit cooked is the current debounced state // changed is true if raw has changed since the last call -void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed); +void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed); + +bool debounce_active(void); + +void debounce_init(uint8_t num_rows); \ No newline at end of file diff --git a/quantum/matrix.c b/quantum/matrix.c index 9b5ce33d2395..49a184569612 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -21,21 +21,9 @@ along with this program. If not, see . #include "debug.h" #include "util.h" #include "matrix.h" -#include "timer.h" +#include "debounce.h" #include "quantum.h" - -/* Set 0 if debouncing isn't needed */ - -#ifndef DEBOUNCING_DELAY -# define DEBOUNCING_DELAY 5 -#endif - -#if (DEBOUNCING_DELAY > 0) - static uint16_t debouncing_time; - static bool debouncing = false; -#endif - #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)) @@ -63,9 +51,9 @@ static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; #endif /* matrix state(1:on, 0:off) */ -static matrix_row_t matrix[MATRIX_ROWS]; +static matrix_row_t raw_matrix[MATRIX_ROWS]; -static matrix_row_t matrix_debouncing[MATRIX_ROWS]; +static matrix_row_t matrix[MATRIX_ROWS]; #if (DIODE_DIRECTION == COL2ROW) @@ -157,70 +145,39 @@ void matrix_init(void) { // initialize matrix state: all keys off for (uint8_t i=0; i < MATRIX_ROWS; i++) { + raw_matrix[i] = 0; matrix[i] = 0; - matrix_debouncing[i] = 0; } + debounce_init(MATRIX_ROWS); matrix_init_quantum(); } uint8_t matrix_scan(void) { + bool changed = false; #if (DIODE_DIRECTION == COL2ROW) - - // Set row, read cols - for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { -# if (DEBOUNCING_DELAY > 0) - bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row); - - if (matrix_changed) { - debouncing = true; - debouncing_time = timer_read(); - } - -# else - read_cols_on_row(matrix, current_row); -# endif - - } - + // 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); + } #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, current_col); - if (matrix_changed) { - debouncing = true; - debouncing_time = timer_read(); - } -# else - read_rows_on_col(matrix, current_col); -# endif - - } - + // 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 -# if (DEBOUNCING_DELAY > 0) - if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) { - for (uint8_t i = 0; i < MATRIX_ROWS; i++) { - matrix[i] = matrix_debouncing[i]; - } - debouncing = false; - } -# endif + debounce(raw_matrix, matrix, MATRIX_ROWS, changed); - matrix_scan_quantum(); - return 1; + matrix_scan_quantum(); + return 1; } bool matrix_is_modified(void) { -#if (DEBOUNCING_DELAY > 0) - if (debouncing) return false; -#endif + if (debounce_active()) return false; return true; } diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index aa74cac8429d..25b53872d738 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -261,6 +261,8 @@ void matrix_init(void) matrix[i] = 0; } + debounce_init(ROWS_PER_HAND); + matrix_init_quantum(); } @@ -280,7 +282,7 @@ uint8_t _matrix_scan(void) } #endif - debounce(raw_matrix, matrix+thisHand, changed); + debounce(raw_matrix, matrix+thisHand, ROWS_PER_HAND, changed); return 1; } @@ -327,6 +329,7 @@ uint8_t matrix_scan(void) bool matrix_is_modified(void) { + if (debounce_active()) return false; return true; } From 7f7536a4696401f6a5df985da6078fd07418c293 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Sun, 13 Jan 2019 16:29:30 +1000 Subject: [PATCH 13/20] Update handwired/xealous to build using new split_common --- keyboards/handwired/xealous/debounce.c | 63 ++++++++++++++++++++++++++ keyboards/handwired/xealous/rules.mk | 10 ++-- 2 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 keyboards/handwired/xealous/debounce.c diff --git a/keyboards/handwired/xealous/debounce.c b/keyboards/handwired/xealous/debounce.c new file mode 100644 index 000000000000..65a99f27f261 --- /dev/null +++ b/keyboards/handwired/xealous/debounce.c @@ -0,0 +1,63 @@ +#include +#include "config.h" +#include "matrix.h" +#include "timer.h" +#include "quantum.h" + +#ifndef DEBOUNCING_DELAY +# define DEBOUNCING_DELAY 5 +#endif + +//Debouncing counters +typedef uint8_t debounce_counter_t; +#define DEBOUNCE_COUNTER_MODULO 250 +#define DEBOUNCE_COUNTER_INACTIVE 251 + +static debounce_counter_t *debounce_counters; + +void debounce_init(uint8_t num_rows) +{ + debounce_counters = malloc(num_rows*MATRIX_COLS); + memset(debounce_counters, DEBOUNCE_COUNTER_INACTIVE, num_rows*MATRIX_COLS); +} + +void update_debounce_counters(uint8_t num_rows, uint8_t current_time) +{ + for (uint8_t row = 0; row < num_rows; row++) + { + for (uint8_t col = 0; col < MATRIX_COLS; col++) + { + if (debounce_counters[row*MATRIX_COLS + col] != DEBOUNCE_COUNTER_INACTIVE) + { + if (TIMER_DIFF(current_time, debounce_counters[row*MATRIX_COLS + col], DEBOUNCE_COUNTER_MODULO) >= DEBOUNCING_DELAY) { + debounce_counters[row*MATRIX_COLS + col] = DEBOUNCE_COUNTER_INACTIVE; + } + } + } + } +} + +void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, uint8_t current_time) +{ + for (uint8_t row = 0; row < num_rows; row++) + { + matrix_row_t delta = raw[row] ^ cooked[row]; + + for (uint8_t col = 0; col < MATRIX_COLS; col++) + { + if (debounce_counters[row*MATRIX_COLS + col] == DEBOUNCE_COUNTER_INACTIVE && (delta & (1< Date: Sun, 13 Jan 2019 16:49:46 +1000 Subject: [PATCH 14/20] Fix debounce breaking basic test --- quantum/debounce.c | 1 - 1 file changed, 1 deletion(-) diff --git a/quantum/debounce.c b/quantum/debounce.c index 080ca5864587..929023ab2df3 100644 --- a/quantum/debounce.c +++ b/quantum/debounce.c @@ -1,6 +1,5 @@ #include "matrix.h" -#include "config.h" #include "timer.h" #include "quantum.h" From 7173a14435bfe7759d3b507e424c15649a0df28a Mon Sep 17 00:00:00 2001 From: James Churchill Date: Sun, 13 Jan 2019 17:28:28 +1000 Subject: [PATCH 15/20] Dodgy method to allow a split kb to only include one of i2c/serial SPLIT_TRANSPORT = serial or SPLIT_TRANSPORT = i2c will include only that driver code in the binary. SPLIT_TRANSPORT = custom (or anything else) will include neither, the keyboard must supply it's own code if SPLIT_TRANSPORT is not defined then the original behaviour (include both avr i2c and serial code) is maintained. This could be better but it would require explicitly updating all the existing split keyboards. --- common_features.mk | 11 ++++++++++- keyboards/lets_split/sockets/rules.mk | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/common_features.mk b/common_features.mk index 920a9ee49b91..6890ec07c601 100644 --- a/common_features.mk +++ b/common_features.mk @@ -270,10 +270,19 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes) OPT_DEFS += -DSPLIT_KEYBOARD QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_flags.c \ $(QUANTUM_DIR)/split_common/split_util.c - ifneq ($(strip $(CUSTOM_TRANSPORT)), yes) + ifndef SPLIT_TRANSPORT QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c \ $(QUANTUM_DIR)/split_common/i2c.c \ $(QUANTUM_DIR)/split_common/serial.c + else + ifeq ($(strip $(SPLIT_TRANSPORT)), serial) + QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c + QUANTUM_SRC += $(QUANTUM_DIR)/split_common/serial.c + endif + ifeq ($(strip $(SPLIT_TRANSPORT)), i2c) + QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c + QUANTUM_SRC += $(QUANTUM_DIR)/split_common/i2c.c + endif endif COMMON_VPATH += $(QUANTUM_PATH)/split_common endif diff --git a/keyboards/lets_split/sockets/rules.mk b/keyboards/lets_split/sockets/rules.mk index e14d18d8de40..6c9ac36a39c7 100644 --- a/keyboards/lets_split/sockets/rules.mk +++ b/keyboards/lets_split/sockets/rules.mk @@ -1,3 +1,4 @@ BACKLIGHT_ENABLE = no AUDIO_ENABLE = yes RGBLIGHT_ENABLE = yes #Don't enable this along with I2C +SPLIT_TRANSPORT = serial #leave out the i2c code to save space \ No newline at end of file From 8dcdfc38cfb51e8bc1ac07acc0fc20e666c50926 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Sun, 13 Jan 2019 18:28:09 +1000 Subject: [PATCH 16/20] Enable LTO to get lets_split/sockets under the line --- keyboards/lets_split/sockets/config.h | 9 +++++++++ keyboards/lets_split/sockets/rules.mk | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/keyboards/lets_split/sockets/config.h b/keyboards/lets_split/sockets/config.h index 6939d37dc57e..e73c45722def 100644 --- a/keyboards/lets_split/sockets/config.h +++ b/keyboards/lets_split/sockets/config.h @@ -85,3 +85,12 @@ along with this program. If not, see . //#define NO_ACTION_ONESHOT //#define NO_ACTION_MACRO //#define NO_ACTION_FUNCTION + +#ifdef USE_Link_Time_Optimization + // LTO has issues with macros (action_get_macro) and "functions" (fn_actions), + // so just disable them + #define NO_ACTION_MACRO + #define NO_ACTION_FUNCTION + + #define DISABLE_LEADER +#endif // USE_Link_Time_Optimization \ No newline at end of file diff --git a/keyboards/lets_split/sockets/rules.mk b/keyboards/lets_split/sockets/rules.mk index 6c9ac36a39c7..bddbba559d1b 100644 --- a/keyboards/lets_split/sockets/rules.mk +++ b/keyboards/lets_split/sockets/rules.mk @@ -1,4 +1,6 @@ BACKLIGHT_ENABLE = no AUDIO_ENABLE = yes RGBLIGHT_ENABLE = yes #Don't enable this along with I2C -SPLIT_TRANSPORT = serial #leave out the i2c code to save space \ No newline at end of file +SPLIT_TRANSPORT = serial #leave out the i2c code to save space + +EXTRAFLAGS += -flto -DUSE_Link_Time_Optimization From b1a4e6268a8743a61abae870fde7f8ecaa5ad613 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Mon, 14 Jan 2019 22:21:48 +1000 Subject: [PATCH 17/20] Add docs for SPLIT_TRANSPORT, CUSTOM_MATRIX, CUSTOM_DEBOUNCE --- docs/config_options.md | 11 +++++++++-- docs/getting_started_make_guide.md | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/docs/config_options.md b/docs/config_options.md index 085ab3ee58ae..ded6fcd2b351 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -143,7 +143,7 @@ If you define these options you will enable the associated feature, which may in * Breaks any Tap Toggle functionality (`TT` or the One Shot Tap Toggle) * `#define LEADER_TIMEOUT 300` * how long before the leader key times out - * If you're having issues finishing the sequence before it times out, you may need to increase the timeout setting. Or you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped. + * If you're having issues finishing the sequence before it times out, you may need to increase the timeout setting. Or you may want to enable the `LEADER_PER_KEY_TIMING` option, which resets the timeout after each key is tapped. * `#define LEADER_PER_KEY_TIMING` * sets the timer for leader key chords to run on each key press rather than overall * `#define LEADER_KEY_STRICT_KEY_PROCESSING` @@ -197,6 +197,9 @@ If you define these options you will enable the associated feature, which may in Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk +* `SPLIT_TRANSPORT` + * Selects the driver used to communicate between master and slave on a split keyboard. Current options are `i2c`, `serial`, and `custom`. By default both i2c and serial drivers are included (USE_I2C decides which is used). ARM-based keyboards must use `custom`. + ### Setting Handedness One thing to remember, the side that the USB port is plugged into is always the master half. The side not plugged into USB is the slave. @@ -208,7 +211,7 @@ There are a few different ways to set handedness for split keyboards (listed in 3. Set `MASTER_RIGHT`: Half that is plugged into the USB port is determined to be the master and right half (inverse of the default) 4. Default: The side that is plugged into the USB port is the master half and is assumed to be the left half. The slave side is the right half -* `#define SPLIT_HAND_PIN B7` +* `#define SPLIT_HAND_PIN B7` * For using high/low pin to determine handedness, low = right hand, high = left hand. Replace `B7` with the pin you are using. This is optional, and if you leave `SPLIT_HAND_PIN` undefined, then you can still use the EE_HANDS method or MASTER_LEFT / MASTER_RIGHT defines like the stock Let's Split uses. * `#define EE_HANDS` (only works if `SPLIT_HAND_PIN` is not defined) @@ -302,6 +305,10 @@ Use these to enable or disable building certain features. The more you have enab * Current options are AdafruitEzKey, AdafruitBLE, RN42 * `SPLIT_KEYBOARD` * Enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common +* `CUSTOM_MATRIX` + * Allows replacing the standard matrix scanning routine with a custom one. +* `CUSTOM_DEBOUNCE` + * Allows replacing the standard key debouncing routine with a custom one. * `WAIT_FOR_USB` * Forces the keyboard to wait for a USB connection to be established before it starts up * `NO_USB_STARTUP_CHECK` diff --git a/docs/getting_started_make_guide.md b/docs/getting_started_make_guide.md index e515411901de..d2c210cced1e 100644 --- a/docs/getting_started_make_guide.md +++ b/docs/getting_started_make_guide.md @@ -137,6 +137,20 @@ This enables [key lock](feature_key_lock.md). This consumes an additional 260 by This enables split keyboard support (dual MCU like the let's split and bakingpy's boards) and includes all necessary files located at quantum/split_common +`SPLIT_TRANSPORT` + +Selects the protocol used to communicate between master and slave on a split keyboard. `SPLIT_TRANSPORT = i2c` will include the avr i2c driver (USE_I2C must also be set). `SPLIT_TRANSPORT = serial` will include the avr serial driver (only used if USE_I2C is not set). The default is to include both drivers, which may increase binary size unnecessarily. `SPLIT_TRANSPORT = custom` will include neither, and a custom implementation must be provided. + +As there is no standard driver for ARM-based split keyboards yet, `SPLIT_TRANSPORT = custom` must be used for these. + +`CUSTOM_MATRIX` + +Lets you replace the default matrix scanning routine with your own code. You will need to provide your own implementations of matrix_init() and matrix_scan(). + +`CUSTOM_DEBOUNCE` + +Lets you replace the default key debouncing routine with your own code. You will need to provide your own implementation of debounce(). + ## Customizing Makefile Options on a Per-Keymap Basis If your keymap directory has a file called `rules.mk` any options you set in that file will take precedence over other `rules.mk` options for your particular keyboard. From ff094f5d11166b788667579a94b639694aaf35a3 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Mon, 14 Jan 2019 22:55:22 +1000 Subject: [PATCH 18/20] Remove avr-specific sei() from split matrix_setup Not needed now that slave doesn't have a separate main loop. Both sides (on avr) call sei() in lufa's main() after exiting keyboard_setup(). --- quantum/split_common/split_util.c | 1 - 1 file changed, 1 deletion(-) diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index 4c9ff1d5bdb3..5095cb8fdce1 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -84,5 +84,4 @@ void matrix_setup(void) { keyboard_slave_setup(); } - sei(); } From 332ef9ae2d2cc84a624097cfba10ccf397dff3b7 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Tue, 15 Jan 2019 20:41:01 +1000 Subject: [PATCH 19/20] Fix QUANTUM_LIB_SRC references and simplify SPLIT_TRANSPORT. --- common_features.mk | 17 ++++------------- docs/config_options.md | 4 ++-- docs/getting_started_make_guide.md | 6 ++---- keyboards/lets_split/sockets/rules.mk | 1 - 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/common_features.mk b/common_features.mk index 4af9ec63a490..940cd5046dfd 100644 --- a/common_features.mk +++ b/common_features.mk @@ -276,19 +276,10 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes) $(QUANTUM_DIR)/split_common/split_util.c # Determine which (if any) transport files are required - ifndef SPLIT_TRANSPORT - QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c \ - $(QUANTUM_DIR)/split_common/i2c.c \ - $(QUANTUM_DIR)/split_common/serial.c - else - ifeq ($(strip $(SPLIT_TRANSPORT)), serial) - QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c - QUANTUM_SRC += $(QUANTUM_DIR)/split_common/serial.c - endif - ifeq ($(strip $(SPLIT_TRANSPORT)), i2c) - QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c - QUANTUM_SRC += $(QUANTUM_DIR)/split_common/i2c.c - endif + ifneq ($(strip $(SPLIT_TRANSPORT)), custom) + QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c + QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/i2c.c \ + $(QUANTUM_DIR)/split_common/serial.c endif COMMON_VPATH += $(QUANTUM_PATH)/split_common endif diff --git a/docs/config_options.md b/docs/config_options.md index 546afc13956b..f5c2e76e7e92 100644 --- a/docs/config_options.md +++ b/docs/config_options.md @@ -197,8 +197,8 @@ If you define these options you will enable the associated feature, which may in Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk -* `SPLIT_TRANSPORT` - * Selects the driver used to communicate between master and slave on a split keyboard. Current options are `i2c`, `serial`, and `custom`. By default both i2c and serial drivers are included (USE_I2C decides which is used). ARM-based keyboards must use `custom`. +* `SPLIT_TRANSPORT = custom` + * Allows replacing the standard split communication routines with a custom one. ARM based split keyboards must use this at present. ### Setting Handedness diff --git a/docs/getting_started_make_guide.md b/docs/getting_started_make_guide.md index f018129614b5..bb7e1e7e3b6f 100644 --- a/docs/getting_started_make_guide.md +++ b/docs/getting_started_make_guide.md @@ -97,7 +97,7 @@ This allows you to send Unicode characters using `UC()` in your keym `UNICODEMAP_ENABLE` -This allows you to send Unicode characters using `X()` in your keymap. You will need to maintain a mapping table in your keymap file. All possible code points (up to `0x10FFFF`) are supported. +This allows you to send Unicode characters using `X()` in your keymap. You will need to maintain a mapping table in your keymap file. All possible code points (up to `0x10FFFF`) are supported. `UCIS_ENABLE` @@ -137,9 +137,7 @@ This enables split keyboard support (dual MCU like the let's split and bakingpy' `SPLIT_TRANSPORT` -Selects the protocol used to communicate between master and slave on a split keyboard. `SPLIT_TRANSPORT = i2c` will include the avr i2c driver (USE_I2C must also be set). `SPLIT_TRANSPORT = serial` will include the avr serial driver (only used if USE_I2C is not set). The default is to include both drivers, which may increase binary size unnecessarily. `SPLIT_TRANSPORT = custom` will include neither, and a custom implementation must be provided. - -As there is no standard driver for ARM-based split keyboards yet, `SPLIT_TRANSPORT = custom` must be used for these. +As there is no standard split communication driver for ARM-based split keyboards yet, `SPLIT_TRANSPORT = custom` must be used for these. It will prevent the standard split keyboard communication code (which is AVR-specific) from being included, allowing a custom implementation to be used. `CUSTOM_MATRIX` diff --git a/keyboards/lets_split/sockets/rules.mk b/keyboards/lets_split/sockets/rules.mk index bddbba559d1b..da04decf4031 100644 --- a/keyboards/lets_split/sockets/rules.mk +++ b/keyboards/lets_split/sockets/rules.mk @@ -1,6 +1,5 @@ BACKLIGHT_ENABLE = no AUDIO_ENABLE = yes RGBLIGHT_ENABLE = yes #Don't enable this along with I2C -SPLIT_TRANSPORT = serial #leave out the i2c code to save space EXTRAFLAGS += -flto -DUSE_Link_Time_Optimization From 9db5a3f42952c0928a0320011f67daf6ad549423 Mon Sep 17 00:00:00 2001 From: James Churchill Date: Wed, 16 Jan 2019 22:13:31 +1000 Subject: [PATCH 20/20] Add comments and fix formatting. --- common_features.mk | 2 + quantum/split_common/matrix.c | 266 ++++++++++++++-------------------- 2 files changed, 107 insertions(+), 161 deletions(-) diff --git a/common_features.mk b/common_features.mk index 940cd5046dfd..8c3361732cd0 100644 --- a/common_features.mk +++ b/common_features.mk @@ -278,6 +278,8 @@ ifeq ($(strip $(SPLIT_KEYBOARD)), yes) # Determine which (if any) transport files are required ifneq ($(strip $(SPLIT_TRANSPORT)), custom) QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c + # Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called. + # Unused functions are pruned away, which is why we can add both drivers here without bloat. QUANTUM_LIB_SRC += $(QUANTUM_DIR)/split_common/i2c.c \ $(QUANTUM_DIR)/split_common/serial.c endif diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 25b53872d738..c3d2857ed50b 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -31,25 +31,25 @@ along with this program. If not, see . #include "transport.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) +# 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) +# 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) +# 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 #define ERROR_DISCONNECT_COUNT 5 -#define ROWS_PER_HAND (MATRIX_ROWS/2) +#define ROWS_PER_HAND (MATRIX_ROWS / 2) #ifdef DIRECT_PINS static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; @@ -65,28 +65,74 @@ static matrix_row_t raw_matrix[ROWS_PER_HAND]; // row offsets for each hand uint8_t thisHand, thatHand; +// user-defined overridable functions + +__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } + +__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } + +__attribute__((weak)) void matrix_init_user(void) {} + +__attribute__((weak)) void matrix_scan_user(void) {} + +__attribute__((weak)) void matrix_slave_scan_user(void) {} + +// helper functions + +inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } + +inline uint8_t matrix_cols(void) { return MATRIX_COLS; } + +bool matrix_is_modified(void) { + if (debounce_active()) return false; + return true; +} + +inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } + +inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } + +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_key_count(void) { + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += matrix_bitpop(i); + } + return count; +} + +// matrix code + #ifdef DIRECT_PINS -static void init_pins(void) -{ - for(int row = 0; row < MATRIX_ROWS; row++) { - for(int col = 0; col < MATRIX_COLS; col++) { +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) { + if (pin != NO_PIN) { setPinInputHigh(pin); } } } } -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t 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; - for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { + 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) { + if (pin != NO_PIN) { current_matrix[current_row] |= readPin(pin) ? 0 : (ROW_SHIFTER << col_index); } } @@ -96,34 +142,27 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) #elif (DIODE_DIRECTION == COL2ROW) -static void select_row(uint8_t row) -{ +static void select_row(uint8_t row) { writePinLow(row_pins[row]); setPinOutput(row_pins[row]); } -static void unselect_row(uint8_t row) -{ - setPinInputHigh(row_pins[row]); -} +static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); } -static void unselect_rows(void) -{ - for(uint8_t x = 0; x < ROWS_PER_HAND; x++) { +static void unselect_rows(void) { + for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { setPinInputHigh(row_pins[x]); } } -static void init_pins(void) -{ +static void init_pins(void) { unselect_rows(); - for(uint8_t x = 0; x < MATRIX_COLS; x++) { + for (uint8_t x = 0; x < MATRIX_COLS; x++) { setPinInputHigh(col_pins[x]); } } -static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) -{ +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]; @@ -135,9 +174,9 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) wait_us(30); // For each col... - for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { + 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); + current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index); } // Unselect row @@ -148,34 +187,27 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) #elif (DIODE_DIRECTION == ROW2COL) -static void select_col(uint8_t col) -{ +static void select_col(uint8_t col) { writePinLow(col_pins[col]); setPinOutput(col_pins[col]); } -static void unselect_col(uint8_t col) -{ - setPinInputHigh(col_pins[col]); -} +static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); } -static void unselect_cols(void) -{ - for(uint8_t x = 0; x < MATRIX_COLS; x++) { +static void unselect_cols(void) { + for (uint8_t x = 0; x < MATRIX_COLS; x++) { setPinInputHigh(col_pins[x]); } } -static void init_pins(void) -{ +static void init_pins(void) { unselect_cols(); - for(uint8_t x = 0; x < ROWS_PER_HAND; x++) { + for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { setPinInputHigh(row_pins[x]); } } -static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) -{ +static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { bool matrix_changed = false; // Select col and wait for col selecton to stabilize @@ -183,27 +215,21 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) wait_us(30); // For each row... - for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) - { - + 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]; // Check row pin state - if (readPin(row_pins[row_index])) - { + if (readPin(row_pins[row_index])) { // Pin HI, clear col bit current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); - } - else - { + } else { // Pin LO, set 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)) - { + if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) { matrix_changed = true; } } @@ -216,23 +242,10 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) #endif -inline -uint8_t matrix_rows(void) -{ - return MATRIX_ROWS; -} - -inline -uint8_t matrix_cols(void) -{ - return MATRIX_COLS; -} - -void matrix_init(void) -{ +void matrix_init(void) { debug_enable = true; debug_matrix = true; - debug_mouse = true; + debug_mouse = true; // Set pinout for right half if pinout for that half is defined if (!isLeftHand) { @@ -257,7 +270,7 @@ void matrix_init(void) init_pins(); // initialize matrix state: all keys off - for (uint8_t i=0; i < MATRIX_ROWS; i++) { + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { matrix[i] = 0; } @@ -266,8 +279,7 @@ void matrix_init(void) matrix_init_quantum(); } -uint8_t _matrix_scan(void) -{ +uint8_t _matrix_scan(void) { bool changed = false; #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) @@ -282,103 +294,35 @@ uint8_t _matrix_scan(void) } #endif - debounce(raw_matrix, matrix+thisHand, ROWS_PER_HAND, changed); + debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); return 1; } -__attribute__ ((weak)) -void matrix_slave_scan_user(void) { - } - -uint8_t matrix_scan(void) -{ +uint8_t matrix_scan(void) { uint8_t ret = _matrix_scan(); - if (is_keyboard_master()) - { + if (is_keyboard_master()) { static uint8_t error_count; if (!transport_master(matrix + thatHand)) { - 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; + 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; + } } + } else { + error_count = 0; } - } - else - { - error_count = 0; - } matrix_scan_quantum(); - } - else - { + } else { transport_slave(matrix + thisHand); matrix_slave_scan_user(); } return ret; } - -bool matrix_is_modified(void) -{ - if (debounce_active()) return false; - return true; -} - -inline -bool matrix_is_on(uint8_t row, uint8_t col) -{ - return (matrix[row] & ((matrix_row_t)1<