From b585ece5ef9309557ac6b61eadda4f00e4e52b0c Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sat, 31 Dec 2022 16:56:32 -0800 Subject: [PATCH] Add Split support for Haptic feedback (#19203) --- docs/feature_split_keyboard.md | 6 +++ quantum/haptic.c | 9 ++++ quantum/split_common/transaction_id_define.h | 4 ++ quantum/split_common/transactions.c | 45 ++++++++++++++++++++ quantum/split_common/transport.h | 12 ++++++ 5 files changed, 76 insertions(+) diff --git a/docs/feature_split_keyboard.md b/docs/feature_split_keyboard.md index 0b475cc63d604650fd2674dd83065d3e68bd9aa0..eaef975fb7236599c847db0b2f8d1cb0d24127b3 100644 --- a/docs/feature_split_keyboard.md +++ b/docs/feature_split_keyboard.md @@ -286,6 +286,12 @@ This enables transmitting the pointing device status to the master side of the s !> There is additional required configuration for `SPLIT_POINTING_ENABLE` outlined in the [pointing device documentation](feature_pointing_device.md?id=split-keyboard-configuration). +```c +#define SPLIT_HAPTIC_ENABLE +``` + +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. + ### 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. diff --git a/quantum/haptic.c b/quantum/haptic.c index ad64fe2cc7e73890205d6b47a0125233f6868a49..c151547fcafcbea94bb7f94a308b08a55ba525c4 100644 --- a/quantum/haptic.c +++ b/quantum/haptic.c @@ -25,6 +25,9 @@ #ifdef SOLENOID_ENABLE # include "solenoid.h" #endif +#if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE) +extern uint8_t split_haptic_play; +#endif haptic_config_t haptic_config; @@ -319,9 +322,15 @@ void haptic_play(void) { uint8_t play_eff = 0; play_eff = haptic_config.mode; DRV_pulse(play_eff); +# if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE) + split_haptic_play = haptic_config.mode; +# endif #endif #ifdef SOLENOID_ENABLE solenoid_fire_handler(); +# if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE) + split_haptic_play = 1; +# endif #endif } diff --git a/quantum/split_common/transaction_id_define.h b/quantum/split_common/transaction_id_define.h index 8c1994810752ec59ea861f3b2e57d378526756df..18d3826b838ca831bc56f9b78e1c298553fcf1ab 100644 --- a/quantum/split_common/transaction_id_define.h +++ b/quantum/split_common/transaction_id_define.h @@ -88,6 +88,10 @@ enum serial_transaction_id { PUT_WATCHDOG, #endif // defined(SPLIT_WATCHDOG_ENABLE) +#if defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE) + PUT_HAPTIC, +#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE) + #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) PUT_RPC_INFO, PUT_RPC_REQ_DATA, diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c index 527b2f4caf6582325bfc3e90398e876d0f091da4..8e1961b58623c1f3ce6456a1bf3863abace92113 100644 --- a/quantum/split_common/transactions.c +++ b/quantum/split_common/transactions.c @@ -748,6 +748,48 @@ static void watchdog_handlers_slave(matrix_row_t master_matrix[], matrix_row_t s #endif // defined(SPLIT_WATCHDOG_ENABLE) +#if defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE) + +uint8_t split_haptic_play = 0xFF; +extern haptic_config_t haptic_config; + +static bool haptic_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + static uint32_t last_update = 0; + split_slave_haptic_sync_t haptic_sync; + + memcpy(&haptic_sync.haptic_config, &haptic_config, sizeof(haptic_config_t)); + haptic_sync.haptic_play = split_haptic_play; + + bool okay = send_if_data_mismatch(PUT_HAPTIC, &last_update, &haptic_sync, &split_shmem->haptic_sync, sizeof(haptic_sync)); + + split_haptic_play = 0xFF; + + return okay; +} + +static void haptic_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) { + memcpy(&haptic_config, &split_shmem->haptic_sync.haptic_config, sizeof(haptic_config_t)); + + if (split_shmem->haptic_sync.haptic_play != 0xFF) { + haptic_set_mode(split_shmem->haptic_sync.haptic_play); + haptic_play(); + } +} + +// clang-format off +# define TRANSACTIONS_HAPTIC_MASTER() TRANSACTION_HANDLER_MASTER(haptic) +# define TRANSACTIONS_HAPTIC_SLAVE() TRANSACTION_HANDLER_SLAVE(haptic) +# define TRANSACTIONS_HAPTIC_REGISTRATIONS [PUT_HAPTIC] = trans_initiator2target_initializer(haptic_sync), +// clang-format on + +#else // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE) + +# define TRANSACTIONS_HAPTIC_MASTER() +# define TRANSACTIONS_HAPTIC_SLAVE() +# define TRANSACTIONS_HAPTIC_REGISTRATIONS + +#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE) + //////////////////////////////////////////////////// split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { @@ -775,6 +817,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = { TRANSACTIONS_ST7565_REGISTRATIONS TRANSACTIONS_POINTING_REGISTRATIONS TRANSACTIONS_WATCHDOG_REGISTRATIONS + TRANSACTIONS_HAPTIC_REGISTRATIONS // clang-format on #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) @@ -802,6 +845,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix TRANSACTIONS_ST7565_MASTER(); TRANSACTIONS_POINTING_MASTER(); TRANSACTIONS_WATCHDOG_MASTER(); + TRANSACTIONS_HAPTIC_MASTER(); return true; } @@ -822,6 +866,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[ TRANSACTIONS_ST7565_SLAVE(); TRANSACTIONS_POINTING_SLAVE(); TRANSACTIONS_WATCHDOG_SLAVE(); + TRANSACTIONS_HAPTIC_SLAVE(); } #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h index 833633edc2f949a6adda89e96b48cbaa64556ceb..adee4470d22b5eefea1856c862ab4786dfd4ab3e 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h @@ -114,6 +114,14 @@ typedef struct _split_slave_pointing_sync_t { } split_slave_pointing_sync_t; #endif // defined(POINTING_DEVICE_ENABLE) && defined(SPLIT_POINTING_ENABLE) +#if defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE) +# include "haptic.h" +typedef struct _split_slave_haptic_sync_t { + haptic_config_t haptic_config; + uint8_t haptic_play; +} split_slave_haptic_sync_t; +#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE) + #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) typedef struct _rpc_sync_info_t { uint8_t checksum; @@ -192,6 +200,10 @@ typedef struct _split_shared_memory_t { bool watchdog_pinged; #endif // defined(SPLIT_WATCHDOG_ENABLE) +#if defined(HAPTIC_ENABLE) + split_slave_haptic_sync_t haptic_sync; +#endif // defined(HAPTIC_ENABLE) + #if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER) rpc_sync_info_t rpc_info; uint8_t rpc_m2s_buffer[RPC_M2S_BUFFER_SIZE];