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

Added SPLIT_HAPTIC_ENABLE to trigger haptic feedback on the slave keyboard half #16233

Closed
wants to merge 1 commit into from
Closed
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
6 changes: 6 additions & 0 deletions docs/feature_split_keyboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ This enables transmitting the current OLED on/off status to the slave side of th

This enables transmitting the current ST7565 on/off status to the slave side of the split keyboard. The purpose of this feature is to support state (on/off state only) syncing.

```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.
Expand Down
9 changes: 9 additions & 0 deletions quantum/haptic.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#ifdef SOLENOID_ENABLE
# include "solenoid.h"
#endif
#if defined(SPLIT_KEYBOARD) && !defined(NO_ACTION_LAYER) && defined(SPLIT_HAPTIC_ENABLE)
# include "transactions.h"
#endif

haptic_config_t haptic_config;

Expand Down Expand Up @@ -317,9 +320,15 @@ void haptic_play(void) {
uint8_t play_eff = 0;
play_eff = haptic_config.mode;
DRV_pulse(play_eff);
#if defined(SPLIT_KEYBOARD) && !defined(NO_ACTION_LAYER) && defined(SPLIT_HAPTIC_ENABLE)
split_haptic_play = haptic_config.mode;
#endif
#endif
#ifdef SOLENOID_ENABLE
solenoid_fire();
#if defined(SPLIT_KEYBOARD) && !defined(NO_ACTION_LAYER) && defined(SPLIT_HAPTIC_ENABLE)
split_haptic_play = 1;
#endif
#endif
}

Expand Down
4 changes: 4 additions & 0 deletions quantum/split_common/transaction_id_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ enum serial_transaction_id {
PUT_ST7565,
#endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_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,
Expand Down
43 changes: 43 additions & 0 deletions quantum/split_common/transactions.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#include "transport.h"
#include "split_util.h"
#include "transaction_id_define.h"
#if !defined(NO_ACTION_LAYER) && defined(SPLIT_HAPTIC_ENABLE)
#include "haptic.h"
#endif

#define SYNC_TIMER_OFFSET 2

Expand Down Expand Up @@ -578,6 +581,43 @@ static void st7565_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sla

#endif // defined(ST7565_ENABLE) && defined(SPLIT_ST7565_ENABLE)

////////////////////////////////////////////////////
// Haptic

#if !defined(NO_ACTION_LAYER) && defined(SPLIT_HAPTIC_ENABLE)

uint8_t split_haptic_play = 0xFF;

static bool haptic_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
bool okay = transport_write(PUT_HAPTIC, &split_haptic_play, sizeof(split_haptic_play));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anything, the entire haptic config structure should be synced over, not just the mode. Especially as the "enable" states isn't being synced.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any concerns about the size of the haptic structure when sync'd? I guess it's only 8 bytes, but split transport seems sensitive to size of data being transported, at least from reading the docs.

As the patch is structured, it's not a concern that the enable state isn't sync'd, since haptic events are triggered by haptic_play(), which would only be invoked if enable status is true.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be fine. Mostly, it gets synced if there are changes, but that shouldn't be too often. And then forcibly synced on the forced timeout (defaults to 500ms).

So for the sync, it shouldn't be too much.


split_haptic_play = 0xFF;

return okay;
}

static void haptic_handlers_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
if (split_shmem->haptic_play != 0xFF) {
haptic_set_mode(split_shmem->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_play),
// clang-format on

#else // !defined(NO_ACTION_LAYER) && defined(SPLIT_LAYER_STATE_ENABLE)

# define TRANSACTIONS_HAPTIC_MASTER()
# define TRANSACTIONS_HAPTIC_SLAVE()
# define TRANSACTIONS_HAPTIC_REGISTRATIONS

#endif // !defined(NO_ACTION_LAYER) && defined(SPLIT_HAPTIC_ENABLE)

////////////////////////////////////////////////////

uint8_t dummy;
Expand All @@ -604,6 +644,7 @@ split_transaction_desc_t split_transaction_table[NUM_TOTAL_TRANSACTIONS] = {
TRANSACTIONS_WPM_REGISTRATIONS
TRANSACTIONS_OLED_REGISTRATIONS
TRANSACTIONS_ST7565_REGISTRATIONS
TRANSACTIONS_HAPTIC_REGISTRATIONS
// clang-format on

#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
Expand All @@ -629,6 +670,7 @@ bool transactions_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix
TRANSACTIONS_WPM_MASTER();
TRANSACTIONS_OLED_MASTER();
TRANSACTIONS_ST7565_MASTER();
TRANSACTIONS_HAPTIC_MASTER();
return true;
}

Expand All @@ -647,6 +689,7 @@ void transactions_slave(matrix_row_t master_matrix[], matrix_row_t slave_matrix[
TRANSACTIONS_WPM_SLAVE();
TRANSACTIONS_OLED_SLAVE();
TRANSACTIONS_ST7565_SLAVE();
TRANSACTIONS_HAPTIC_SLAVE();
}

#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
Expand Down
4 changes: 4 additions & 0 deletions quantum/split_common/transactions.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@ bool transaction_rpc_exec(int8_t transaction_id, uint8_t initiator2target_buffer

#define transaction_rpc_send(transaction_id, initiator2target_buffer_size, initiator2target_buffer) transaction_rpc_exec(transaction_id, initiator2target_buffer_size, initiator2target_buffer, 0, NULL)
#define transaction_rpc_recv(transaction_id, target2initiator_buffer_size, target2initiator_buffer) transaction_rpc_exec(transaction_id, 0, NULL, target2initiator_buffer_size, target2initiator_buffer)

#if defined(SPLIT_HAPTIC_ENABLE)
extern uint8_t split_haptic_play;
#endif
4 changes: 4 additions & 0 deletions quantum/split_common/transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ typedef struct _split_shared_memory_t {
uint8_t current_st7565_state;
#endif // ST7565_ENABLE(OLED_ENABLE) && defined(SPLIT_ST7565_ENABLE)

#if defined(HAPTIC_ENABLE) && defined(SPLIT_HAPTIC_ENABLE)
uint8_t haptic_play;
#endif // defined(HAPTIC_ENABLE) && defined(SPLIT_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];
Expand Down