Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add modifier state to the split keyboard transport #10400

Merged
merged 3 commits into from
Dec 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/feature_split_keyboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
68 changes: 68 additions & 0 deletions quantum/split_common/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -97,6 +110,31 @@ bool transport_master(matrix_row_t matrix[]) {
}
# endif

# ifdef SPLIT_MODS_ENABLE
uint8_t real_mods = get_mods();
cwebster2 marked this conversation as resolved.
Show resolved Hide resolved
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;
cwebster2 marked this conversation as resolved.
Show resolved Hide resolved
}
}

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;
cwebster2 marked this conversation as resolved.
Show resolved Hide resolved
}
}

# 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;
cwebster2 marked this conversation as resolved.
Show resolved Hide resolved
}
}
# 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);
Expand Down Expand Up @@ -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(); }
Expand All @@ -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
Expand Down Expand Up @@ -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();
cwebster2 marked this conversation as resolved.
Show resolved Hide resolved
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
Expand Down Expand Up @@ -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);
cwebster2 marked this conversation as resolved.
Show resolved Hide resolved
set_weak_mods(serial_m2s_buffer.weak_mods);
# ifndef NO_ACTION_ONESHOT
set_oneshot_mods(serial_m2s_buffer.oneshot_mods);
# endif
# endif
}

#endif