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:
parent
1bc8a6e5d4
commit
d1806a26e4
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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[]);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,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;
|
||||
#ifdef 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;
|
||||
}
|
||||
// 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)
|
||||
#endif
|
||||
// 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();
|
||||
|
Loading…
Reference in New Issue
Block a user