Split transport mirror (#11046)

* Split transport mirror support

* Updated RGB Matrix to respond to electrical events instead of key events

* split matrix slave fix
This commit is contained in:
XScorpion2 2021-02-15 18:30:33 -06:00 committed by GitHub
parent 1bc8a6e5d4
commit d1806a26e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 94 additions and 60 deletions

View file

@ -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.

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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;
}
#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) {

View file

@ -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);

View file

@ -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;

View file

@ -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();
}

View file

@ -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);

View file

@ -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[]);

View file

@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdbool.h>
#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

View file

@ -54,6 +54,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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,7 +375,6 @@ 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];
@ -372,11 +388,16 @@ void keyboard_task(void) {
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;
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)
@ -387,7 +408,6 @@ void keyboard_task(void) {
}
}
}
}
// call with pseudo tick event when no real key event.
#ifdef QMK_KEYS_PER_SCAN
// we can get here with some keys processed now.
@ -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();