From d1806a26e4ad75fa0e0405283803eba22c1a49ba Mon Sep 17 00:00:00 2001 From: XScorpion2 Date: Mon, 15 Feb 2021 18:30:33 -0600 Subject: [PATCH] Split transport mirror (#11046) * Split transport mirror support * Updated RGB Matrix to respond to electrical events instead of key events * split matrix slave fix --- docs/feature_split_keyboard.md | 6 ++ docs/ja/understanding_qmk.md | 1 - docs/understanding_qmk.md | 1 - quantum/quantum.c | 10 --- quantum/rgb_matrix.c | 19 +++--- quantum/rgb_matrix.h | 2 +- .../typing_heatmap_anim.h | 4 +- quantum/split_common/matrix.c | 4 +- quantum/split_common/transport.c | 37 ++++++++--- quantum/split_common/transport.h | 4 +- tmk_core/common/eeconfig.h | 2 +- tmk_core/common/keyboard.c | 62 +++++++++++++------ 12 files changed, 93 insertions(+), 59 deletions(-) diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md index c285e353d491196c4586448deb5f3e7b51bc335b..90af3930f95ae37f9daebabcdf3ab12d3e3bc0e9 100644 --- a/docs/feature_split_keyboard.md +++ b/docs/feature_split_keyboard.md @@ -191,6 +191,12 @@ communication protocol and may impact the matrix scan speed when enabled. The purpose of this feature is to support cosmetic use of modifer state (e.g. displaying status on an OLED screen). +```c +#define SPLIT_TRANSPORT_MIRROR +``` + +This mirrors the master side matrix to the slave side for features that react or require knowledge of master side key presses on the slave side. This adds a few bytes of data to the split communication protocol and may impact the matrix scan speed when enabled. The purpose of this feature is to support cosmetic use of key events (e.g. RGB reacting to Keypresses). + ### Hardware Configuration Options There are some settings that you may need to configure, based on how the hardware is set up. diff --git a/docs/ja/understanding_qmk.md b/docs/ja/understanding_qmk.md index 74b37398f84a8303aadea26abc3d65cb46cf408f..ab860a60961597511bf6a9d4179f8251b4125865 100644 --- a/docs/ja/understanding_qmk.md +++ b/docs/ja/understanding_qmk.md @@ -147,7 +147,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * [`bool process_haptic(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/2cee371bf125a6ec541dd7c5a809573facc7c456/drivers/haptic/haptic.c#L216) * [`bool process_record_kb(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/card.c#L20) * [`bool process_record_user(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/keymaps/default/keymap.c#L58) - * [`bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/rgb_matrix.c#L139) * [`bool process_midi(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_midi.c#L81) * [`bool process_audio(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_audio.c#L19) * [`bool process_steno(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_steno.c#L160) diff --git a/docs/understanding_qmk.md b/docs/understanding_qmk.md index 93964242582ad8015f4a0780e49dea92f0e7ac27..331b1c893c858648ca534fbfa349b93b49f0e9fb 100644 --- a/docs/understanding_qmk.md +++ b/docs/understanding_qmk.md @@ -142,7 +142,6 @@ The `process_record()` function itself is deceptively simple, but hidden within * [`bool process_haptic(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/2cee371bf125a6ec541dd7c5a809573facc7c456/drivers/haptic/haptic.c#L216) * [`bool process_record_kb(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/card.c#L20) * [`bool process_record_user(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/keymaps/default/keymap.c#L58) - * [`bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/rgb_matrix.c#L139) * [`bool process_midi(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_midi.c#L81) * [`bool process_audio(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_audio.c#L19) * [`bool process_steno(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_steno.c#L160) diff --git a/quantum/quantum.c b/quantum/quantum.c index 6d202c515c43391a684d79f32b863066f33de346..38234bb17b36a0330be09f76de4169b42f3817bb 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -221,9 +221,6 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef HAPTIC_ENABLE process_haptic(keycode, record) && #endif // HAPTIC_ENABLE -#if defined(RGB_MATRIX_ENABLE) - process_rgb_matrix(keycode, record) && -#endif #if defined(VIA_ENABLE) process_record_via(keycode, record) && #endif @@ -624,9 +621,6 @@ void matrix_init_quantum() { #ifdef AUDIO_ENABLE audio_init(); #endif -#ifdef RGB_MATRIX_ENABLE - rgb_matrix_init(); -#endif #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE) unicode_input_mode_init(); #endif @@ -681,10 +675,6 @@ void matrix_scan_quantum() { led_matrix_task(); #endif -#ifdef RGB_MATRIX_ENABLE - rgb_matrix_task(); -#endif - #ifdef WPM_ENABLE decay_wpm(); #endif diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index a945df68e005c4da901fea5e6cfe15887e089111..ec17b4d72ca694aded369c6205d400e0aa532aa2 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -184,11 +184,12 @@ void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { rgb_matrix_driver.set_color_all(red, green, blue); } -bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) { +void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed) { +#ifndef RGB_MATRIX_SPLIT + if (!is_keyboard_master()) return; +#endif #if RGB_DISABLE_TIMEOUT > 0 - if (record->event.pressed) { - rgb_anykey_timer = 0; - } + rgb_anykey_timer = 0; #endif // RGB_DISABLE_TIMEOUT > 0 #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED @@ -196,12 +197,12 @@ bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) { uint8_t led_count = 0; # if defined(RGB_MATRIX_KEYRELEASES) - if (!record->event.pressed) + if (!pressed) # elif defined(RGB_MATRIX_KEYPRESSES) - if (record->event.pressed) + if (pressed) # endif // defined(RGB_MATRIX_KEYRELEASES) { - led_count = rgb_matrix_map_row_column_to_led(record->event.key.row, record->event.key.col, led); + led_count = rgb_matrix_map_row_column_to_led(row, col, led); } if (last_hit_buffer.count + led_count > LED_HITS_TO_REMEMBER) { @@ -224,11 +225,9 @@ bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) { #if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_TYPING_HEATMAP) if (rgb_matrix_config.mode == RGB_MATRIX_TYPING_HEATMAP) { - process_rgb_matrix_typing_heatmap(record); + process_rgb_matrix_typing_heatmap(row, col); } #endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && !defined(DISABLE_RGB_MATRIX_TYPING_HEATMAP) - - return true; } void rgb_matrix_test(void) { diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h index 8c80c1bff0ce123070c6ef664c2f33b0270cf83c..bb8bcfab68ce9c599c6b7ae765379f725352f96d 100644 --- a/quantum/rgb_matrix.h +++ b/quantum/rgb_matrix.h @@ -98,7 +98,7 @@ uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue); -bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record); +void process_rgb_matrix(uint8_t row, uint8_t col, bool pressed); void rgb_matrix_task(void); diff --git a/quantum/rgb_matrix_animations/typing_heatmap_anim.h b/quantum/rgb_matrix_animations/typing_heatmap_anim.h index e06437bf765613396ca040dd4b01897f400c019e..e7dda11a2f249436b79d32ab1efa9f1de0cde56c 100644 --- a/quantum/rgb_matrix_animations/typing_heatmap_anim.h +++ b/quantum/rgb_matrix_animations/typing_heatmap_anim.h @@ -6,9 +6,7 @@ RGB_MATRIX_EFFECT(TYPING_HEATMAP) # define RGB_MATRIX_TYPING_HEATMAP_DECREASE_DELAY_MS 25 # endif -void process_rgb_matrix_typing_heatmap(keyrecord_t* record) { - uint8_t row = record->event.key.row; - uint8_t col = record->event.key.col; +void process_rgb_matrix_typing_heatmap(uint8_t row, uint8_t col) { uint8_t m_row = row - 1; uint8_t p_row = row + 1; uint8_t m_col = col - 1; diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index bad762b4935c88e05d157aa7dfad49a495d823d9..d6636b886adf3c50a15f85cff85807f6781124ca 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -257,7 +257,7 @@ bool matrix_post_scan(void) { static uint8_t error_count; matrix_row_t slave_matrix[ROWS_PER_HAND] = {0}; - if (!transport_master(slave_matrix)) { + if (!transport_master(matrix + thisHand, slave_matrix)) { error_count++; if (error_count > ERROR_DISCONNECT_COUNT) { @@ -282,7 +282,7 @@ bool matrix_post_scan(void) { matrix_scan_quantum(); } else { - transport_slave(matrix + thisHand); + transport_slave(matrix + thatHand, matrix + thisHand); matrix_slave_scan_user(); } diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index b45ba92c3b62080ece2a63fb5dcd9f8147a76f3c..977b5dc33ee585e7e15893f990bcee70749e4f10 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -30,6 +30,9 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A; typedef struct _I2C_slave_buffer_t { # ifndef DISABLE_SYNC_TIMER uint32_t sync_timer; +# endif +# ifdef SPLIT_TRANSPORT_MIRROR + matrix_row_t mmatrix[ROWS_PER_HAND]; # endif matrix_row_t smatrix[ROWS_PER_HAND]; # ifdef SPLIT_MODS_ENABLE @@ -56,7 +59,8 @@ typedef struct _I2C_slave_buffer_t { static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; # define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer) -# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix) +# define I2C_KEYMAP_MASTER_START offsetof(I2C_slave_buffer_t, mmatrix) +# define I2C_KEYMAP_SLAVE_START offsetof(I2C_slave_buffer_t, smatrix) # define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods) # define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods) # define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods) @@ -72,8 +76,11 @@ static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_re # endif // Get rows from other half over i2c -bool transport_master(matrix_row_t matrix[]) { - i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); +bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_SLAVE_START, (void *)slave_matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); +#ifdef SPLIT_TRANSPORT_MIRROR + i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_MASTER_START, (void *)master_matrix, sizeof(i2c_buffer->mmatrix), TIMEOUT); +#endif // write backlight info # ifdef BACKLIGHT_ENABLE @@ -141,12 +148,15 @@ bool transport_master(matrix_row_t matrix[]) { return true; } -void transport_slave(matrix_row_t matrix[]) { +void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { # ifndef DISABLE_SYNC_TIMER sync_timer_update(i2c_buffer->sync_timer); # endif // Copy matrix to I2C buffer - memcpy((void *)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix)); + memcpy((void*)i2c_buffer->smatrix, (void *)slave_matrix, sizeof(i2c_buffer->smatrix)); +#ifdef SPLIT_TRANSPORT_MIRROR + memcpy((void*)master_matrix, (void *)i2c_buffer->mmatrix, sizeof(i2c_buffer->mmatrix)); +#endif // Read Backlight Info # ifdef BACKLIGHT_ENABLE @@ -207,6 +217,9 @@ typedef struct _Serial_m2s_buffer_t { # ifndef DISABLE_SYNC_TIMER uint32_t sync_timer; # endif +# ifdef SPLIT_TRANSPORT_MIRROR + matrix_row_t mmatrix[ROWS_PER_HAND]; +# endif # ifdef BACKLIGHT_ENABLE uint8_t backlight_level; # endif @@ -289,7 +302,7 @@ void transport_rgblight_slave(void) { # define transport_rgblight_slave() # endif -bool transport_master(matrix_row_t matrix[]) { +bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { # ifndef SERIAL_USE_MULTI_TRANSACTION if (soft_serial_transaction() != TRANSACTION_END) { return false; @@ -303,7 +316,10 @@ bool transport_master(matrix_row_t matrix[]) { // TODO: if MATRIX_COLS > 8 change to unpack() for (int i = 0; i < ROWS_PER_HAND; ++i) { - matrix[i] = serial_s2m_buffer.smatrix[i]; + slave_matrix[i] = serial_s2m_buffer.smatrix[i]; +#ifdef SPLIT_TRANSPORT_MIRROR + serial_m2s_buffer.mmatrix[i] = master_matrix[i]; +#endif } # ifdef BACKLIGHT_ENABLE @@ -333,7 +349,7 @@ bool transport_master(matrix_row_t matrix[]) { return true; } -void transport_slave(matrix_row_t matrix[]) { +void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { transport_rgblight_slave(); # ifndef DISABLE_SYNC_TIMER sync_timer_update(serial_m2s_buffer.sync_timer); @@ -341,7 +357,10 @@ 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]; + serial_s2m_buffer.smatrix[i] = slave_matrix[i]; +#ifdef SPLIT_TRANSPORT_MIRROR + master_matrix[i] = serial_m2s_buffer.mmatrix[i]; +#endif } # ifdef BACKLIGHT_ENABLE backlight_set(serial_m2s_buffer.backlight_level); diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h index c667bfab8537ce14aa5c93b048954f46ef90ad45..a9f66301bf6b428a41e33f9584e00f597b9a0b55 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h @@ -6,5 +6,5 @@ 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[]); +bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); +void transport_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]); diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index c4f0483913ac4f3cd5c382f8ce57d3e07fcd83b9..d66c4199c267d7627ca5ebb932716412b4963879 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h @@ -21,7 +21,7 @@ along with this program. If not, see . #include #ifndef EECONFIG_MAGIC_NUMBER -# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEC +# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEB // When changing, decrement this value to avoid future re-init issues #endif #define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 299bda2c127d2bfcb8e149bfb5a32274adf2adb1..34fed0caba8c0026809b3356634ed5343178e7c0 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -54,6 +54,9 @@ along with this program. If not, see . #ifdef RGBLIGHT_ENABLE # include "rgblight.h" #endif +#ifdef RGB_MATRIX_ENABLE +# include "rgb_matrix.h" +#endif #ifdef ENCODER_ENABLE # include "encoder.h" #endif @@ -304,6 +307,9 @@ void keyboard_init(void) { #ifdef RGBLIGHT_ENABLE rgblight_init(); #endif +#ifdef RGB_MATRIX_ENABLE + rgb_matrix_init(); +#endif #ifdef ENCODER_ENABLE encoder_init(); #endif @@ -328,6 +334,17 @@ void keyboard_init(void) { keyboard_post_init_kb(); /* Always keep this last */ } +/** \brief key_event_task + * + * This function is responsible for calling into other systems when they need to respond to electrical switch press events. + * This is differnet than keycode events as no layer processing, or filtering occurs. + */ +void switch_events(uint8_t row, uint8_t col, bool pressed) { +#if defined(RGB_MATRIX_ENABLE) + process_rgb_matrix(row, col, pressed); +#endif +} + /** \brief Keyboard task: Do keyboard routine jobs * * Do routine keyboard jobs: @@ -358,32 +375,35 @@ void keyboard_task(void) { uint8_t matrix_changed = matrix_scan(); if (matrix_changed) last_matrix_activity_trigger(); - if (should_process_keypress()) { - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row = matrix_get_row(r); - matrix_change = matrix_row ^ matrix_prev[r]; - if (matrix_change) { + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { + matrix_row = matrix_get_row(r); + matrix_change = matrix_row ^ matrix_prev[r]; + if (matrix_change) { #ifdef MATRIX_HAS_GHOST - if (has_ghost_in_row(r, matrix_row)) { - continue; - } + if (has_ghost_in_row(r, matrix_row)) { + continue; + } #endif - if (debug_matrix) matrix_print(); - matrix_row_t col_mask = 1; - for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) { - if (matrix_change & col_mask) { + if (debug_matrix) matrix_print(); + matrix_row_t col_mask = 1; + for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) { + if (matrix_change & col_mask) { + if (should_process_keypress()) { action_exec((keyevent_t){ .key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */ }); - // record a processed key - matrix_prev[r] ^= col_mask; + } + // record a processed key + matrix_prev[r] ^= col_mask; + + switch_events(r, c, (matrix_row & col_mask)); + #ifdef QMK_KEYS_PER_SCAN - // only jump out if we have processed "enough" keys. - if (++keys_processed >= QMK_KEYS_PER_SCAN) + // only jump out if we have processed "enough" keys. + if (++keys_processed >= QMK_KEYS_PER_SCAN) #endif - // process a key per task call - goto MATRIX_LOOP_END; - } + // process a key per task call + goto MATRIX_LOOP_END; } } } @@ -405,6 +425,10 @@ MATRIX_LOOP_END: rgblight_task(); #endif +#ifdef RGB_MATRIX_ENABLE + rgb_matrix_task(); +#endif + #if defined(BACKLIGHT_ENABLE) # if defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS) backlight_task();