mirror of
https://github.com/firewalkwithm3/qmk_firmware.git
synced 2024-11-22 11:30:30 +08:00
Sync activity timestamps between sides. (#20192)
Co-authored-by: Stefan Kerkmann <karlk90@pm.me>
This commit is contained in:
parent
0e1e543836
commit
a518e1e5d8
|
@ -300,6 +300,12 @@ This enables transmitting the pointing device status to the master side of the s
|
||||||
|
|
||||||
This enables triggering of haptic feedback on the slave side of the split keyboard. For DRV2605L this will send the mode, but for solenoids it is expected that the desired mode is already set up on the slave.
|
This enables triggering of haptic feedback on the slave side of the split keyboard. For DRV2605L this will send the mode, but for solenoids it is expected that the desired mode is already set up on the slave.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define SPLIT_ACTIVITY_ENABLE
|
||||||
|
```
|
||||||
|
|
||||||
|
This synchronizes the activity timestamps between sides of the split keyboard, allowing for activity timeouts to occur.
|
||||||
|
|
||||||
### Custom data sync between sides :id=custom-data-sync
|
### Custom data sync between sides :id=custom-data-sync
|
||||||
|
|
||||||
QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master.
|
QMK's split transport allows for arbitrary data transactions at both the keyboard and user levels. This is modelled on a remote procedure call, with the master invoking a function on the slave side, with the ability to send data from master to slave, process it slave side, and send data back from slave to master.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2022 Nick Brassel (@tzarc)
|
// Copyright 2018-2023 Nick Brassel (@tzarc)
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
#define SPLIT_LED_STATE_ENABLE
|
#define SPLIT_LED_STATE_ENABLE
|
||||||
#define SPLIT_MODS_ENABLE
|
#define SPLIT_MODS_ENABLE
|
||||||
#define SPLIT_WPM_ENABLE
|
#define SPLIT_WPM_ENABLE
|
||||||
|
#define SPLIT_ACTIVITY_ENABLE
|
||||||
|
|
||||||
// SPI Configuration
|
// SPI Configuration
|
||||||
#define SPI_DRIVER SPID3
|
#define SPI_DRIVER SPID3
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2022 Nick Brassel (@tzarc)
|
// Copyright 2018-2023 Nick Brassel (@tzarc)
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "quantum.h"
|
#include "quantum.h"
|
||||||
|
@ -74,7 +74,6 @@ void keyboard_post_init_kb(void) {
|
||||||
qp_init(lcd, QP_ROTATION_0);
|
qp_init(lcd, QP_ROTATION_0);
|
||||||
|
|
||||||
// Turn on the LCD and clear the display
|
// Turn on the LCD and clear the display
|
||||||
kb_state.lcd_power = 1;
|
|
||||||
qp_power(lcd, true);
|
qp_power(lcd, true);
|
||||||
qp_rect(lcd, 0, 0, 239, 319, HSV_BLACK, true);
|
qp_rect(lcd, 0, 0, 239, 319, HSV_BLACK, true);
|
||||||
|
|
||||||
|
@ -187,18 +186,14 @@ void housekeeping_task_kb(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn on/off the LCD
|
// Turn on/off the LCD
|
||||||
static bool lcd_on = false;
|
bool peripherals_on = last_input_activity_elapsed() < LCD_ACTIVITY_TIMEOUT;
|
||||||
if (lcd_on != (bool)kb_state.lcd_power) {
|
|
||||||
lcd_on = (bool)kb_state.lcd_power;
|
|
||||||
qp_power(lcd, lcd_on);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable/disable RGB
|
// Enable/disable RGB
|
||||||
if (lcd_on) {
|
if (peripherals_on) {
|
||||||
// Turn on RGB
|
// Turn on RGB
|
||||||
writePinHigh(RGB_POWER_ENABLE_PIN);
|
writePinHigh(RGB_POWER_ENABLE_PIN);
|
||||||
// Modify the RGB state if different to the LCD state
|
// Modify the RGB state if different to the LCD state
|
||||||
if (rgb_matrix_is_enabled() != lcd_on) {
|
if (rgb_matrix_is_enabled() != peripherals_on) {
|
||||||
// Wait for a small amount of time to allow the RGB capacitors to charge, before enabling RGB output
|
// Wait for a small amount of time to allow the RGB capacitors to charge, before enabling RGB output
|
||||||
wait_ms(10);
|
wait_ms(10);
|
||||||
// Enable RGB
|
// Enable RGB
|
||||||
|
@ -208,21 +203,21 @@ void housekeeping_task_kb(void) {
|
||||||
// Turn off RGB
|
// Turn off RGB
|
||||||
writePinLow(RGB_POWER_ENABLE_PIN);
|
writePinLow(RGB_POWER_ENABLE_PIN);
|
||||||
// Disable the PWM output for the RGB
|
// Disable the PWM output for the RGB
|
||||||
if (rgb_matrix_is_enabled() != lcd_on) {
|
if (rgb_matrix_is_enabled() != peripherals_on) {
|
||||||
rgb_matrix_disable_noeeprom();
|
rgb_matrix_disable_noeeprom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match the backlight to the LCD state
|
// Match the backlight to the LCD state
|
||||||
if (is_keyboard_master() && is_backlight_enabled() != lcd_on) {
|
if (is_keyboard_master() && is_backlight_enabled() != peripherals_on) {
|
||||||
if (lcd_on)
|
if (peripherals_on)
|
||||||
backlight_enable();
|
backlight_enable();
|
||||||
else
|
else
|
||||||
backlight_disable();
|
backlight_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the UI
|
// Draw the UI
|
||||||
if (kb_state.lcd_power) {
|
if (peripherals_on) {
|
||||||
draw_ui_user(false);
|
draw_ui_user(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2022 Nick Brassel (@tzarc)
|
// Copyright 2018-2023 Nick Brassel (@tzarc)
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "quantum.h"
|
#include "quantum.h"
|
||||||
|
@ -20,7 +20,6 @@ const char* usbpd_str(usbpd_allowance_t allowance);
|
||||||
#pragma pack(push)
|
#pragma pack(push)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
typedef struct kb_runtime_config {
|
typedef struct kb_runtime_config {
|
||||||
unsigned lcd_power : 1;
|
|
||||||
usbpd_allowance_t current_setting : 2;
|
usbpd_allowance_t current_setting : 2;
|
||||||
} kb_runtime_config;
|
} kb_runtime_config;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2018-2022 Nick Brassel (@tzarc)
|
// Copyright 2018-2023 Nick Brassel (@tzarc)
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "quantum.h"
|
#include "quantum.h"
|
||||||
|
@ -13,9 +13,6 @@ void kb_state_update(void) {
|
||||||
if (is_keyboard_master()) {
|
if (is_keyboard_master()) {
|
||||||
// Modify allowed current limits
|
// Modify allowed current limits
|
||||||
usbpd_update();
|
usbpd_update();
|
||||||
|
|
||||||
// Turn off the LCD if there's been no matrix activity
|
|
||||||
kb_state.lcd_power = (last_input_activity_elapsed() < LCD_ACTIVITY_TIMEOUT) ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ uint32_t last_input_activity_time(void) {
|
||||||
return last_input_modification_time;
|
return last_input_modification_time;
|
||||||
}
|
}
|
||||||
uint32_t last_input_activity_elapsed(void) {
|
uint32_t last_input_activity_elapsed(void) {
|
||||||
return timer_elapsed32(last_input_modification_time);
|
return sync_timer_elapsed32(last_input_modification_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t last_matrix_modification_time = 0;
|
static uint32_t last_matrix_modification_time = 0;
|
||||||
|
@ -122,10 +122,10 @@ uint32_t last_matrix_activity_time(void) {
|
||||||
return last_matrix_modification_time;
|
return last_matrix_modification_time;
|
||||||
}
|
}
|
||||||
uint32_t last_matrix_activity_elapsed(void) {
|
uint32_t last_matrix_activity_elapsed(void) {
|
||||||
return timer_elapsed32(last_matrix_modification_time);
|
return sync_timer_elapsed32(last_matrix_modification_time);
|
||||||
}
|
}
|
||||||
void last_matrix_activity_trigger(void) {
|
void last_matrix_activity_trigger(void) {
|
||||||
last_matrix_modification_time = last_input_modification_time = timer_read32();
|
last_matrix_modification_time = last_input_modification_time = sync_timer_read32();
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t last_encoder_modification_time = 0;
|
static uint32_t last_encoder_modification_time = 0;
|
||||||
|
@ -133,10 +133,16 @@ uint32_t last_encoder_activity_time(void) {
|
||||||
return last_encoder_modification_time;
|
return last_encoder_modification_time;
|
||||||
}
|
}
|
||||||
uint32_t last_encoder_activity_elapsed(void) {
|
uint32_t last_encoder_activity_elapsed(void) {
|
||||||
return timer_elapsed32(last_encoder_modification_time);
|
return sync_timer_elapsed32(last_encoder_modification_time);
|
||||||
}
|
}
|
||||||
void last_encoder_activity_trigger(void) {
|
void last_encoder_activity_trigger(void) {
|
||||||
last_encoder_modification_time = last_input_modification_time = timer_read32();
|
last_encoder_modification_time = last_input_modification_time = sync_timer_read32();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_activity_timestamps(uint32_t matrix_timestamp, uint32_t encoder_timestamp) {
|
||||||
|
last_matrix_modification_time = matrix_timestamp;
|
||||||
|
last_encoder_modification_time = encoder_timestamp;
|
||||||
|
last_input_modification_time = MAX(matrix_timestamp, encoder_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only enable this if console is enabled to print to
|
// Only enable this if console is enabled to print to
|
||||||
|
|
|
@ -120,6 +120,8 @@ uint32_t last_matrix_activity_elapsed(void); // Number of milliseconds since the
|
||||||
uint32_t last_encoder_activity_time(void); // Timestamp of the last encoder activity
|
uint32_t last_encoder_activity_time(void); // Timestamp of the last encoder activity
|
||||||
uint32_t last_encoder_activity_elapsed(void); // Number of milliseconds since the last encoder activity
|
uint32_t last_encoder_activity_elapsed(void); // Number of milliseconds since the last encoder activity
|
||||||
|
|
||||||
|
void set_activity_timestamps(uint32_t matrix_timestamp, uint32_t encoder_timestamp); // Set the timestamps of the last matrix and encoder activity
|
||||||
|
|
||||||
uint32_t get_matrix_scan_rate(void);
|
uint32_t get_matrix_scan_rate(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -92,6 +92,10 @@ enum serial_transaction_id {
|
||||||
PUT_HAPTIC,
|
PUT_HAPTIC,
|
||||||
#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE)
|
#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE)
|
||||||
|
|
||||||
|
#if defined(SPLIT_ACTIVITY_ENABLE)
|
||||||
|
PUT_ACTIVITY,
|
||||||
|
#endif // SPLIT_ACTIVITY_ENABLE
|
||||||
|
|
||||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||||
PUT_RPC_INFO,
|
PUT_RPC_INFO,
|
||||||
PUT_RPC_REQ_DATA,
|
PUT_RPC_REQ_DATA,
|
||||||
|
|
|
@ -790,6 +790,34 @@ static void haptic_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla
|
||||||
|
|
||||||
#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE)
|
#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE)
|
||||||
|
|
||||||
|
#if defined(SPLIT_ACTIVITY_ENABLE)
|
||||||
|
|
||||||
|
static bool activity_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
|
||||||
|
static uint32_t last_update = 0;
|
||||||
|
split_slave_activity_sync_t activity_sync;
|
||||||
|
activity_sync.matrix_timestamp = last_matrix_activity_time();
|
||||||
|
activity_sync.encoder_timestamp = last_encoder_activity_time();
|
||||||
|
return send_if_data_mismatch(PUT_ACTIVITY, &last_update, &activity_sync, &split_shmem->activity_sync, sizeof(activity_sync));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void activity_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
|
||||||
|
set_activity_timestamps(split_shmem->activity_sync.matrix_timestamp, split_shmem->activity_sync.encoder_timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
# define TRANSACTIONS_ACTIVITY_MASTER() TRANSACTION_HANDLER_MASTER(activity)
|
||||||
|
# define TRANSACTIONS_ACTIVITY_SLAVE() TRANSACTION_HANDLER_SLAVE_AUTOLOCK(activity)
|
||||||
|
# define TRANSACTIONS_ACTIVITY_REGISTRATIONS [PUT_ACTIVITY] = trans_initiator2target_initializer(activity_sync),
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#else // defined(SPLIT_ACTIVITY_ENABLE)
|
||||||
|
|
||||||
|
# define TRANSACTIONS_ACTIVITY_MASTER()
|
||||||
|
# define TRANSACTIONS_ACTIVITY_SLAVE()
|
||||||
|
# define TRANSACTIONS_ACTIVITY_REGISTRATIONS
|
||||||
|
|
||||||
|
#endif // defined(SPLIT_ACTIVITY_ENABLE)
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
|
|
||||||
split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
|
split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
|
||||||
|
@ -818,6 +846,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
|
||||||
TRANSACTIONS_POINTING_REGISTRATIONS
|
TRANSACTIONS_POINTING_REGISTRATIONS
|
||||||
TRANSACTIONS_WATCHDOG_REGISTRATIONS
|
TRANSACTIONS_WATCHDOG_REGISTRATIONS
|
||||||
TRANSACTIONS_HAPTIC_REGISTRATIONS
|
TRANSACTIONS_HAPTIC_REGISTRATIONS
|
||||||
|
TRANSACTIONS_ACTIVITY_REGISTRATIONS
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||||
|
@ -846,6 +875,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix
|
||||||
TRANSACTIONS_POINTING_MASTER();
|
TRANSACTIONS_POINTING_MASTER();
|
||||||
TRANSACTIONS_WATCHDOG_MASTER();
|
TRANSACTIONS_WATCHDOG_MASTER();
|
||||||
TRANSACTIONS_HAPTIC_MASTER();
|
TRANSACTIONS_HAPTIC_MASTER();
|
||||||
|
TRANSACTIONS_ACTIVITY_MASTER();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,6 +897,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[
|
||||||
TRANSACTIONS_POINTING_SLAVE();
|
TRANSACTIONS_POINTING_SLAVE();
|
||||||
TRANSACTIONS_WATCHDOG_SLAVE();
|
TRANSACTIONS_WATCHDOG_SLAVE();
|
||||||
TRANSACTIONS_HAPTIC_SLAVE();
|
TRANSACTIONS_HAPTIC_SLAVE();
|
||||||
|
TRANSACTIONS_ACTIVITY_SLAVE();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||||
|
|
|
@ -122,6 +122,14 @@ typedef struct _split_slave_haptic_sync_t {
|
||||||
} split_slave_haptic_sync_t;
|
} split_slave_haptic_sync_t;
|
||||||
#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE)
|
#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE)
|
||||||
|
|
||||||
|
#if defined(SPLIT_ACTIVITY_ENABLE)
|
||||||
|
# include "keyboard.h"
|
||||||
|
typedef struct _split_slave_activity_sync_t {
|
||||||
|
uint32_t matrix_timestamp;
|
||||||
|
uint32_t encoder_timestamp;
|
||||||
|
} split_slave_activity_sync_t;
|
||||||
|
#endif // defined(SPLIT_ACTIVITY_ENABLE)
|
||||||
|
|
||||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||||
typedef struct _rpc_sync_info_t {
|
typedef struct _rpc_sync_info_t {
|
||||||
uint8_t checksum;
|
uint8_t checksum;
|
||||||
|
@ -204,6 +212,10 @@ typedef struct _split_shared_memory_t {
|
||||||
split_slave_haptic_sync_t haptic_sync;
|
split_slave_haptic_sync_t haptic_sync;
|
||||||
#endif // defined(HAPTIC_ENABLE)
|
#endif // defined(HAPTIC_ENABLE)
|
||||||
|
|
||||||
|
#if defined(SPLIT_ACTIVITY_ENABLE)
|
||||||
|
split_slave_activity_sync_t activity_sync;
|
||||||
|
#endif // defined(SPLIT_ACTIVITY_ENABLE)
|
||||||
|
|
||||||
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
|
||||||
rpc_sync_info_t rpc_info;
|
rpc_sync_info_t rpc_info;
|
||||||
uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];
|
uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];
|
||||||
|
|
Loading…
Reference in a new issue