aboutsummaryrefslogtreecommitdiff
path: root/quantum/dynamic_macro.h
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/dynamic_macro.h')
-rw-r--r--quantum/dynamic_macro.h82
1 files changed, 67 insertions, 15 deletions
diff --git a/quantum/dynamic_macro.h b/quantum/dynamic_macro.h
index 64093f293..f242405de 100644
--- a/quantum/dynamic_macro.h
+++ b/quantum/dynamic_macro.h
@@ -40,6 +40,7 @@
40enum dynamic_macro_keycodes { 40enum dynamic_macro_keycodes {
41 DYN_REC_START1 = DYNAMIC_MACRO_RANGE, 41 DYN_REC_START1 = DYNAMIC_MACRO_RANGE,
42 DYN_REC_START2, 42 DYN_REC_START2,
43 DYN_REC_STOP,
43 DYN_MACRO_PLAY1, 44 DYN_MACRO_PLAY1,
44 DYN_MACRO_PLAY2, 45 DYN_MACRO_PLAY2,
45}; 46};
@@ -47,11 +48,22 @@ enum dynamic_macro_keycodes {
47/* Blink the LEDs to notify the user about some event. */ 48/* Blink the LEDs to notify the user about some event. */
48void dynamic_macro_led_blink(void) 49void dynamic_macro_led_blink(void)
49{ 50{
51#ifdef BACKLIGHT_ENABLE
50 backlight_toggle(); 52 backlight_toggle();
51 _delay_ms(100); 53 _delay_ms(100);
52 backlight_toggle(); 54 backlight_toggle();
55#endif
53} 56}
54 57
58/* Convenience macros used for retrieving the debug info. All of them
59 * need a `direction` variable accessible at the call site.
60 */
61#define DYNAMIC_MACRO_CURRENT_SLOT() (direction > 0 ? 1 : 2)
62#define DYNAMIC_MACRO_CURRENT_LENGTH(BEGIN, POINTER) \
63 ((int)(direction * ((POINTER) - (BEGIN))))
64#define DYNAMIC_MACRO_CURRENT_CAPACITY(BEGIN, END2) \
65 ((int)(direction * ((END2) - (BEGIN)) + 1))
66
55/** 67/**
56 * Start recording of the dynamic macro. 68 * Start recording of the dynamic macro.
57 * 69 *
@@ -61,6 +73,8 @@ void dynamic_macro_led_blink(void)
61void dynamic_macro_record_start( 73void dynamic_macro_record_start(
62 keyrecord_t **macro_pointer, keyrecord_t *macro_buffer) 74 keyrecord_t **macro_pointer, keyrecord_t *macro_buffer)
63{ 75{
76 dprintln("dynamic macro recording: started");
77
64 dynamic_macro_led_blink(); 78 dynamic_macro_led_blink();
65 79
66 clear_keyboard(); 80 clear_keyboard();
@@ -78,6 +92,8 @@ void dynamic_macro_record_start(
78void dynamic_macro_play( 92void dynamic_macro_play(
79 keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction) 93 keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction)
80{ 94{
95 dprintf("dynamic macro: slot %d playback\n", DYNAMIC_MACRO_CURRENT_SLOT());
96
81 uint32_t saved_layer_state = layer_state; 97 uint32_t saved_layer_state = layer_state;
82 98
83 clear_keyboard(); 99 clear_keyboard();
@@ -96,35 +112,68 @@ void dynamic_macro_play(
96/** 112/**
97 * Record a single key in a dynamic macro. 113 * Record a single key in a dynamic macro.
98 * 114 *
115 * @param macro_buffer[in] The start of the used macro buffer.
99 * @param macro_pointer[in,out] The current buffer position. 116 * @param macro_pointer[in,out] The current buffer position.
100 * @param macro_end2[in] The end of the other macro which shouldn't be overwritten. 117 * @param macro2_end[in] The end of the other macro.
101 * @param direction[in] Either +1 or -1, which way to iterate the buffer. 118 * @param direction[in] Either +1 or -1, which way to iterate the buffer.
102 * @param record[in] The current keypress. 119 * @param record[in] The current keypress.
103 */ 120 */
104void dynamic_macro_record_key( 121void dynamic_macro_record_key(
122 keyrecord_t *macro_buffer,
105 keyrecord_t **macro_pointer, 123 keyrecord_t **macro_pointer,
106 keyrecord_t *macro_end2, 124 keyrecord_t *macro2_end,
107 int8_t direction, 125 int8_t direction,
108 keyrecord_t *record) 126 keyrecord_t *record)
109{ 127{
110 if (*macro_pointer + direction != macro_end2) { 128 /* If we've just started recording, ignore all the key releases. */
129 if (!record->event.pressed && *macro_pointer == macro_buffer) {
130 dprintln("dynamic macro: ignoring a leading key-up event");
131 return;
132 }
133
134 /* The other end of the other macro is the last buffer element it
135 * is safe to use before overwriting the other macro.
136 */
137 if (*macro_pointer - direction != macro2_end) {
111 **macro_pointer = *record; 138 **macro_pointer = *record;
112 *macro_pointer += direction; 139 *macro_pointer += direction;
113 } else { 140 } else {
114 /* Notify about the end of buffer. The blinks are paired 141 dynamic_macro_led_blink();
115 * because they should happen on both down and up events. */
116 backlight_toggle();
117 } 142 }
143
144 dprintf(
145 "dynamic macro: slot %d length: %d/%d\n",
146 DYNAMIC_MACRO_CURRENT_SLOT(),
147 DYNAMIC_MACRO_CURRENT_LENGTH(macro_buffer, *macro_pointer),
148 DYNAMIC_MACRO_CURRENT_CAPACITY(macro_buffer, macro2_end));
118} 149}
119 150
120/** 151/**
121 * End recording of the dynamic macro. Essentially just update the 152 * End recording of the dynamic macro. Essentially just update the
122 * pointer to the end of the macro. 153 * pointer to the end of the macro.
123 */ 154 */
124void dynamic_macro_record_end(keyrecord_t *macro_pointer, keyrecord_t **macro_end) 155void dynamic_macro_record_end(
156 keyrecord_t *macro_buffer,
157 keyrecord_t *macro_pointer,
158 int8_t direction,
159 keyrecord_t **macro_end)
125{ 160{
126 dynamic_macro_led_blink(); 161 dynamic_macro_led_blink();
127 162
163 /* Do not save the keys being held when stopping the recording,
164 * i.e. the keys used to access the layer DYN_REC_STOP is on.
165 */
166 while (macro_pointer != macro_buffer &&
167 (macro_pointer - direction)->event.pressed) {
168 dprintln("dynamic macro: trimming a trailing key-down event");
169 macro_pointer -= direction;
170 }
171
172 dprintf(
173 "dynamic macro: slot %d saved, length: %d\n",
174 DYNAMIC_MACRO_CURRENT_SLOT(),
175 DYNAMIC_MACRO_CURRENT_LENGTH(macro_buffer, macro_pointer));
176
128 *macro_end = macro_pointer; 177 *macro_end = macro_pointer;
129} 178}
130 179
@@ -152,7 +201,7 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)
152 * &macro_buffer macro_end 201 * &macro_buffer macro_end
153 * v v 202 * v v
154 * +------------------------------------------------------------+ 203 * +------------------------------------------------------------+
155 * |>>>>>> MACRO1 >>>>>>| |<<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| 204 * |>>>>>> MACRO1 >>>>>> <<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<|
156 * +------------------------------------------------------------+ 205 * +------------------------------------------------------------+
157 * ^ ^ 206 * ^ ^
158 * r_macro_end r_macro_buffer 207 * r_macro_end r_macro_buffer
@@ -209,18 +258,17 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)
209 } else { 258 } else {
210 /* A macro is being recorded right now. */ 259 /* A macro is being recorded right now. */
211 switch (keycode) { 260 switch (keycode) {
212 case MO(_DYN): 261 case DYN_REC_STOP:
213 /* Use the layer key used to access the macro recording as 262 /* Stop the macro recording. */
214 * a stop button. */
215 if (record->event.pressed) { /* Ignore the initial release 263 if (record->event.pressed) { /* Ignore the initial release
216 * just after the recoding 264 * just after the recoding
217 * starts. */ 265 * starts. */
218 switch (macro_id) { 266 switch (macro_id) {
219 case 1: 267 case 1:
220 dynamic_macro_record_end(macro_pointer, &macro_end); 268 dynamic_macro_record_end(macro_buffer, macro_pointer, +1, &macro_end);
221 break; 269 break;
222 case 2: 270 case 2:
223 dynamic_macro_record_end(macro_pointer, &r_macro_end); 271 dynamic_macro_record_end(r_macro_buffer, macro_pointer, -1, &r_macro_end);
224 break; 272 break;
225 } 273 }
226 macro_id = 0; 274 macro_id = 0;
@@ -230,10 +278,10 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)
230 /* Store the key in the macro buffer and process it normally. */ 278 /* Store the key in the macro buffer and process it normally. */
231 switch (macro_id) { 279 switch (macro_id) {
232 case 1: 280 case 1:
233 dynamic_macro_record_key(&macro_pointer, r_macro_end, +1, record); 281 dynamic_macro_record_key(macro_buffer, &macro_pointer, r_macro_end, +1, record);
234 break; 282 break;
235 case 2: 283 case 2:
236 dynamic_macro_record_key(&macro_pointer, macro_end, -1, record); 284 dynamic_macro_record_key(r_macro_buffer, &macro_pointer, macro_end, -1, record);
237 break; 285 break;
238 } 286 }
239 return true; 287 return true;
@@ -244,4 +292,8 @@ bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)
244 return true; 292 return true;
245} 293}
246 294
295#undef DYNAMIC_MACRO_CURRENT_SLOT
296#undef DYNAMIC_MACRO_CURRENT_LENGTH
297#undef DYNAMIC_MACRO_CURRENT_CAPACITY
298
247#endif 299#endif