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

Fixes for encoder abstraction. #23195

Merged
merged 6 commits into from
Mar 10, 2024
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
92 changes: 67 additions & 25 deletions quantum/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,39 @@ __attribute__((weak)) bool should_process_encoder(void) {
}

static encoder_events_t encoder_events;
static bool signal_queue_drain = false;

void encoder_init(void) {
memset(&encoder_events, 0, sizeof(encoder_events));
encoder_driver_init();
}

static bool encoder_handle_queue(void) {
bool changed = false;
while (encoder_events.tail != encoder_events.head) {
encoder_event_t event = encoder_events.queue[encoder_events.tail];
encoder_events.tail = (encoder_events.tail + 1) % MAX_QUEUED_ENCODER_EVENTS;
static void encoder_queue_drain(void) {
encoder_events.tail = encoder_events.head;
encoder_events.dequeued = encoder_events.enqueued;
}

static bool encoder_handle_queue(void) {
bool changed = false;
uint8_t index;
bool clockwise;
while (encoder_dequeue_event(&index, &clockwise)) {
#ifdef ENCODER_MAP_ENABLE

// The delays below cater for Windows and its wonderful requirements.
action_exec(event.clockwise ? MAKE_ENCODER_CW_EVENT(event.index, true) : MAKE_ENCODER_CCW_EVENT(event.index, true));
action_exec(clockwise ? MAKE_ENCODER_CW_EVENT(index, true) : MAKE_ENCODER_CCW_EVENT(index, true));
# if ENCODER_MAP_KEY_DELAY > 0
wait_ms(ENCODER_MAP_KEY_DELAY);
# endif // ENCODER_MAP_KEY_DELAY > 0

action_exec(event.clockwise ? MAKE_ENCODER_CW_EVENT(event.index, false) : MAKE_ENCODER_CCW_EVENT(event.index, false));
action_exec(clockwise ? MAKE_ENCODER_CW_EVENT(index, false) : MAKE_ENCODER_CCW_EVENT(index, false));
# if ENCODER_MAP_KEY_DELAY > 0
wait_ms(ENCODER_MAP_KEY_DELAY);
# endif // ENCODER_MAP_KEY_DELAY > 0

#else // ENCODER_MAP_ENABLE

encoder_update_kb(event.index, event.clockwise ? true : false);
encoder_update_kb(index, clockwise);

#endif // ENCODER_MAP_ENABLE

Expand All @@ -61,6 +66,11 @@ bool encoder_task(void) {
}
#endif // SPLIT_KEYBOARD

if (signal_queue_drain) {
signal_queue_drain = false;
encoder_queue_drain();
}

// Let the encoder driver produce events
encoder_driver_task();

Expand All @@ -72,39 +82,71 @@ bool encoder_task(void) {
return changed;
}

bool encoder_queue_event(uint8_t index, bool clockwise) {
bool encoder_queue_full_advanced(encoder_events_t *events) {
return events->head == (events->tail - 1) % MAX_QUEUED_ENCODER_EVENTS;
}

bool encoder_queue_full(void) {
return encoder_queue_full_advanced(&encoder_events);
}

bool encoder_queue_empty_advanced(encoder_events_t *events) {
return events->head == events->tail;
}

bool encoder_queue_empty(void) {
return encoder_queue_empty_advanced(&encoder_events);
}

bool encoder_queue_event_advanced(encoder_events_t *events, uint8_t index, bool clockwise) {
// Drop out if we're full
if ((encoder_events.head + 1) % MAX_QUEUED_ENCODER_EVENTS == encoder_events.tail) {
if (encoder_queue_full_advanced(events)) {
return false;
}

// Append the event
encoder_event_t new_event = {.index = index, .clockwise = clockwise ? 1 : 0};
encoder_events.queue[encoder_events.head] = new_event;
encoder_event_t new_event = {.index = index, .clockwise = clockwise ? 1 : 0};
events->queue[events->head] = new_event;

// Increment the head index
encoder_events.head = (encoder_events.head + 1) % MAX_QUEUED_ENCODER_EVENTS;
events->head = (events->head + 1) % MAX_QUEUED_ENCODER_EVENTS;
events->enqueued++;

return true;
}

void encoder_retrieve_events(encoder_events_t *events) {
memcpy(events, &encoder_events, sizeof(encoder_events));
bool encoder_dequeue_event_advanced(encoder_events_t *events, uint8_t *index, bool *clockwise) {
if (encoder_queue_empty_advanced(events)) {
return false;
}

// Retrieve the event
encoder_event_t event = events->queue[events->tail];
*index = event.index;
*clockwise = event.clockwise;

// Increment the tail index
events->tail = (events->tail + 1) % MAX_QUEUED_ENCODER_EVENTS;
events->dequeued++;

return true;
}

#ifdef SPLIT_KEYBOARD
void encoder_set_tail_index(uint8_t tail_index) {
encoder_events.tail = tail_index;
bool encoder_queue_event(uint8_t index, bool clockwise) {
return encoder_queue_event_advanced(&encoder_events, index, clockwise);
}

void encoder_handle_slave_events(encoder_events_t *events) {
while (events->tail != events->head) {
encoder_event_t event = events->queue[events->tail];
events->tail = (events->tail + 1) % MAX_QUEUED_ENCODER_EVENTS;
encoder_queue_event(event.index, event.clockwise ? true : false);
}
bool encoder_dequeue_event(uint8_t *index, bool *clockwise) {
return encoder_dequeue_event_advanced(&encoder_events, index, clockwise);
}

void encoder_retrieve_events(encoder_events_t *events) {
memcpy(events, &encoder_events, sizeof(encoder_events));
}

void encoder_signal_queue_drain(void) {
signal_queue_drain = true;
}
#endif // SPLIT_KEYBOARD

__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) {
return true;
Expand Down
13 changes: 9 additions & 4 deletions quantum/encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ __attribute__((weak)) bool should_process_encoder(void);
void encoder_init(void);
bool encoder_task(void);
bool encoder_queue_event(uint8_t index, bool clockwise);
bool encoder_dequeue_event(uint8_t *index, bool *clockwise);

bool encoder_update_kb(uint8_t index, bool clockwise);
bool encoder_update_user(uint8_t index, bool clockwise);
Expand Down Expand Up @@ -82,6 +83,8 @@ typedef struct encoder_event_t {
} encoder_event_t;

typedef struct encoder_events_t {
uint8_t enqueued;
uint8_t dequeued;
uint8_t head;
uint8_t tail;
encoder_event_t queue[MAX_QUEUED_ENCODER_EVENTS];
Expand All @@ -90,10 +93,12 @@ typedef struct encoder_events_t {
// Get the current queued events
void encoder_retrieve_events(encoder_events_t *events);

# ifdef SPLIT_KEYBOARD
void encoder_set_tail_index(uint8_t tail_index);
void encoder_handle_slave_events(encoder_events_t *events);
# endif // SPLIT_KEYBOARD
// Encoder event queue management
bool encoder_queue_event_advanced(encoder_events_t *events, uint8_t index, bool clockwise);
bool encoder_dequeue_event_advanced(encoder_events_t *events, uint8_t *index, bool *clockwise);

// Reset the queue to be empty
void encoder_signal_queue_drain(void);

# ifdef ENCODER_MAP_ENABLE
# define NUM_DIRECTIONS 2
Expand Down
2 changes: 1 addition & 1 deletion quantum/split_common/transaction_id_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ enum serial_transaction_id {
#ifdef ENCODER_ENABLE
GET_ENCODERS_CHECKSUM,
GET_ENCODERS_DATA,
PUT_ENCODER_TAIL,
CMD_ENCODER_DRAIN,
#endif // ENCODER_ENABLE

#ifndef DISABLE_SYNC_TIMER
Expand Down
32 changes: 24 additions & 8 deletions quantum/split_common/transactions.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdint.h>
#include <string.h>
#include <stddef.h>

Expand Down Expand Up @@ -80,8 +81,12 @@
{ 0, 0, sizeof_member(split_shared_memory_t, member), offsetof(split_shared_memory_t, member), cb }
#define trans_target2initiator_initializer(member) trans_target2initiator_initializer_cb(member, NULL)

#define trans_initiator2target_cb(cb) \
{ 0, 0, 0, 0, cb }

#define transport_write(id, data, length) transport_execute_transaction(id, data, length, NULL, 0)
#define transport_read(id, data, length) transport_execute_transaction(id, NULL, 0, data, length)
#define transport_exec(id) transport_execute_transaction(id, NULL, 0, NULL, 0)

#if defined(SPLIT_TRANSACTION_IDS_KB) || defined(SPLIT_TRANSACTION_IDS_USER)
// Forward-declare the RPC callback handlers
Expand Down Expand Up @@ -234,14 +239,26 @@ static void master_matrix_handlers_slave(matrix_row_t master_matrix[], matrix_ro
#ifdef ENCODER_ENABLE

static bool encoder_handlers_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
static uint32_t last_update = 0;
static uint32_t last_update = 0;
static uint8_t last_checksum = 0;
encoder_events_t temp_events;

bool okay = read_if_checksum_mismatch(GET_ENCODERS_CHECKSUM, GET_ENCODERS_DATA, &last_update, &temp_events, &split_shmem->encoders.events, sizeof(temp_events));
if (okay) {
encoder_handle_slave_events(&split_shmem->encoders.events);
transport_write(PUT_ENCODER_TAIL, &split_shmem->encoders.events.tail, sizeof(split_shmem->encoders.events.tail));
split_shmem->encoders.checksum = crc8(&split_shmem->encoders.events, sizeof(split_shmem->encoders.events));
if (last_checksum != split_shmem->encoders.checksum) {
bool actioned = false;
uint8_t index;
bool clockwise;
while (okay && encoder_dequeue_event_advanced(&split_shmem->encoders.events, &index, &clockwise)) {
okay &= encoder_queue_event(index, clockwise);
actioned = true;
}

if (actioned) {
okay &= transport_exec(CMD_ENCODER_DRAIN);
}
last_checksum = split_shmem->encoders.checksum;
}
}
return okay;
}
Expand All @@ -253,9 +270,8 @@ static void encoder_handlers_slave(matrix_row_t master_matrix[], matrix_row_t sl
split_shmem->encoders.checksum = crc8(&split_shmem->encoders.events, sizeof(split_shmem->encoders.events));
}

static void encoder_handlers_slave_reset(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
uint8_t tail_index = *(uint8_t *)initiator2target_buffer;
encoder_set_tail_index(tail_index);
static void encoder_handlers_slave_drain(uint8_t initiator2target_buffer_size, const void *initiator2target_buffer, uint8_t target2initiator_buffer_size, void *target2initiator_buffer) {
encoder_signal_queue_drain();
}

// clang-format off
Expand All @@ -264,7 +280,7 @@ static void encoder_handlers_slave_reset(uint8_t initiator2target_buffer_size, c
# define TRANSACTIONS_ENCODERS_REGISTRATIONS \
[GET_ENCODERS_CHECKSUM] = trans_target2initiator_initializer(encoders.checksum), \
[GET_ENCODERS_DATA] = trans_target2initiator_initializer(encoders.events), \
[PUT_ENCODER_TAIL] = trans_initiator2target_initializer_cb(encoders.events.tail, encoder_handlers_slave_reset),
[CMD_ENCODER_DRAIN] = trans_initiator2target_cb(encoder_handlers_slave_drain),
// clang-format on

#else // ENCODER_ENABLE
Expand Down
Loading