diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md index b234114200..c285e353d4 100644 --- a/docs/feature_split_keyboard.md +++ b/docs/feature_split_keyboard.md @@ -181,6 +181,16 @@ If you're having issues with serial communication, you can change this value, as * **`4`**: about 26kbps * **`5`**: about 20kbps +```c +#define SPLIT_MODS_ENABLE +``` + +This enables transmitting modifier state (normal, weak and oneshot) to the non +primary side of the split keyboard. 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 modifer state (e.g. +displaying status on an OLED screen). + ### Hardware Configuration Options There are some settings that you may need to configure, based on how the hardware is set up. diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 6856b60558..ae0c10b827 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -32,7 +32,16 @@ typedef struct _I2C_slave_buffer_t { uint32_t sync_timer; # endif matrix_row_t smatrix[ROWS_PER_HAND]; +# ifdef SPLIT_MODS_ENABLE + uint8_t real_mods; + uint8_t weak_mods; +# ifndef NO_ACTION_ONESHOT + uint8_t oneshot_mods; +# endif +# endif +# ifdef BACKLIGHT_ENABLE uint8_t backlight_level; +# endif # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) rgblight_syncinfo_t rgblight_sync; # endif @@ -46,6 +55,10 @@ typedef struct _I2C_slave_buffer_t { static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; +# define I2C_KEYMAP_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) # define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) # define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) # define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer) @@ -97,6 +110,31 @@ bool transport_master(matrix_row_t matrix[]) { } # endif +# ifdef SPLIT_MODS_ENABLE + uint8_t real_mods = get_mods(); + if (real_mods != i2c_buffer->real_mods) { + if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) { + i2c_buffer->real_mods = real_mods; + } + } + + uint8_t weak_mods = get_weak_mods(); + if (weak_mods != i2c_buffer->weak_mods) { + if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) { + i2c_buffer->weak_mods = weak_mods; + } + } + +# ifndef NO_ACTION_ONESHOT + uint8_t oneshot_mods = get_oneshot_mods(); + if (oneshot_mods != i2c_buffer->oneshot_mods) { + if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) { + i2c_buffer->oneshot_mods = oneshot_mods; + } + } +# endif +# endif + # ifndef DISABLE_SYNC_TIMER i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); @@ -131,6 +169,14 @@ void transport_slave(matrix_row_t matrix[]) { # ifdef WPM_ENABLE set_current_wpm(i2c_buffer->current_wpm); # endif + +# ifdef SPLIT_MODS_ENABLE + set_mods(i2c_buffer->real_mods); + set_weak_mods(i2c_buffer->weak_mods); +# ifndef NO_ACTION_ONESHOT + set_oneshot_mods(i2c_buffer->oneshot_mods); +# endif +# endif } void transport_master_init(void) { i2c_init(); } @@ -152,6 +198,13 @@ typedef struct _Serial_s2m_buffer_t { } Serial_s2m_buffer_t; typedef struct _Serial_m2s_buffer_t { +# ifdef SPLIT_MODS_ENABLE + uint8_t real_mods; + uint8_t weak_mods; +# ifndef NO_ACTION_ONESHOT + uint8_t oneshot_mods; +# endif +# endif # ifndef DISABLE_SYNC_TIMER uint32_t sync_timer; # endif @@ -268,6 +321,13 @@ bool transport_master(matrix_row_t matrix[]) { serial_m2s_buffer.current_wpm = get_current_wpm(); # endif +# ifdef SPLIT_MODS_ENABLE + serial_m2s_buffer.real_mods = get_mods(); + serial_m2s_buffer.weak_mods = get_weak_mods(); +# ifndef NO_ACTION_ONESHOT + serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); +# endif +# endif # ifndef DISABLE_SYNC_TIMER serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; # endif @@ -295,6 +355,14 @@ void transport_slave(matrix_row_t matrix[]) { # ifdef WPM_ENABLE set_current_wpm(serial_m2s_buffer.current_wpm); # endif + +# ifdef SPLIT_MODS_ENABLE + set_mods(serial_m2s_buffer.real_mods); + set_weak_mods(serial_m2s_buffer.weak_mods); +# ifndef NO_ACTION_ONESHOT + set_oneshot_mods(serial_m2s_buffer.oneshot_mods); +# endif +# endif } #endif