-
-
Notifications
You must be signed in to change notification settings - Fork 39.5k
/
encoder.c
179 lines (142 loc) · 4.8 KB
/
encoder.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright 2022-2023 Nick Brassel (@tzarc)
// SPDX-License-Identifier: GPL-2.0-or-later
#include <string.h>
#include "action.h"
#include "encoder.h"
#include "wait.h"
#ifndef ENCODER_MAP_KEY_DELAY
# define ENCODER_MAP_KEY_DELAY TAP_CODE_DELAY
#endif
__attribute__((weak)) bool should_process_encoder(void) {
return is_keyboard_master();
}
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 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(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(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(index, clockwise);
#endif // ENCODER_MAP_ENABLE
changed = true;
}
return changed;
}
bool encoder_task(void) {
bool changed = false;
#ifdef SPLIT_KEYBOARD
// Attempt to process existing encoder events in case split handling has already enqueued events
if (should_process_encoder()) {
changed |= encoder_handle_queue();
}
#endif // SPLIT_KEYBOARD
if (signal_queue_drain) {
signal_queue_drain = false;
encoder_queue_drain();
}
// Let the encoder driver produce events
encoder_driver_task();
// Process any events that were enqueued
if (should_process_encoder()) {
changed |= encoder_handle_queue();
}
return changed;
}
bool encoder_queue_full_advanced(encoder_events_t *events) {
return events->tail == (events->head + 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_queue_full_advanced(events)) {
return false;
}
// Append the event
encoder_event_t new_event = {.index = index, .clockwise = clockwise ? 1 : 0};
events->queue[events->head] = new_event;
// Increment the head index
events->head = (events->head + 1) % MAX_QUEUED_ENCODER_EVENTS;
events->enqueued++;
return true;
}
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;
}
bool encoder_queue_event(uint8_t index, bool clockwise) {
return encoder_queue_event_advanced(&encoder_events, index, clockwise);
}
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;
}
__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) {
return true;
}
__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) {
bool res = encoder_update_user(index, clockwise);
#if !defined(ENCODER_TESTS)
if (res) {
if (clockwise) {
# if defined(EXTRAKEY_ENABLE)
tap_code_delay(KC_VOLU, 10);
# elif defined(MOUSEKEY_ENABLE)
tap_code_delay(QK_MOUSE_WHEEL_UP, 10);
# else
tap_code_delay(KC_PGDN, 10);
# endif
} else {
# if defined(EXTRAKEY_ENABLE)
tap_code_delay(KC_VOLD, 10);
# elif defined(MOUSEKEY_ENABLE)
tap_code_delay(QK_MOUSE_WHEEL_DOWN, 10);
# else
tap_code_delay(KC_PGUP, 10);
# endif
}
}
#endif // ENCODER_TESTS
return res;
}