aboutsummaryrefslogtreecommitdiff
path: root/quantum/debounce/tests
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/debounce/tests')
-rw-r--r--quantum/debounce/tests/asym_eager_defer_pk_tests.cpp374
-rw-r--r--quantum/debounce/tests/debounce_test_common.cpp229
-rw-r--r--quantum/debounce/tests/debounce_test_common.h83
-rw-r--r--quantum/debounce/tests/rules.mk44
-rw-r--r--quantum/debounce/tests/sym_defer_g_tests.cpp223
-rw-r--r--quantum/debounce/tests/sym_defer_pk_tests.cpp225
-rw-r--r--quantum/debounce/tests/sym_eager_pk_tests.cpp237
-rw-r--r--quantum/debounce/tests/sym_eager_pr_tests.cpp280
-rw-r--r--quantum/debounce/tests/testlist.mk6
9 files changed, 1701 insertions, 0 deletions
diff --git a/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
new file mode 100644
index 000000000..fe374c3df
--- /dev/null
+++ b/quantum/debounce/tests/asym_eager_defer_pk_tests.cpp
@@ -0,0 +1,374 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 /* Release key after 1ms delay */
25 {1, {{0, 1, UP}}, {}},
26
27 /*
28 * Until the eager timer on DOWN is observed to finish, the defer timer
29 * on UP can't start. There's no workaround for this because it's not
30 * possible to debounce an event that isn't being tracked.
31 *
32 * sym_defer_pk has the same problem but the test has to track that the
33 * key changed state so the DOWN timer is always allowed to finish
34 * before starting the UP timer.
35 */
36 {5, {}, {}},
37
38 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
39 /* Press key again after 1ms delay */
40 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
41 });
42 runEvents();
43}
44
45TEST_F(DebounceTest, OneKeyShort2) {
46 addEvents({ /* Time, Inputs, Outputs */
47 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
48 /* Release key after 2ms delay */
49 {2, {{0, 1, UP}}, {}},
50
51 {5, {}, {}}, /* See OneKeyShort1 */
52
53 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
54 /* Press key again after 1ms delay */
55 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort3) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 /* Release key after 3ms delay */
64 {3, {{0, 1, UP}}, {}},
65
66 {5, {}, {}}, /* See OneKeyShort1 */
67
68 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
69 /* Press key again after 1ms delay */
70 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
71 });
72 runEvents();
73}
74
75TEST_F(DebounceTest, OneKeyShort4) {
76 addEvents({ /* Time, Inputs, Outputs */
77 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
78 /* Release key after 4ms delay */
79 {4, {{0, 1, UP}}, {}},
80
81 {5, {}, {}}, /* See OneKeyShort1 */
82
83 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
84 /* Press key again after 1ms delay */
85 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
86 });
87 runEvents();
88}
89
90TEST_F(DebounceTest, OneKeyShort5) {
91 addEvents({ /* Time, Inputs, Outputs */
92 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93
94 /* Release key after 5ms delay */
95 {5, {{0, 1, UP}}, {}},
96
97 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
98 /* Press key again after 1ms delay */
99 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 });
101 runEvents();
102}
103
104TEST_F(DebounceTest, OneKeyShort6) {
105 addEvents({ /* Time, Inputs, Outputs */
106 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
107
108 /* Release key after 6ms delay */
109 {6, {{0, 1, UP}}, {}},
110
111 {11, {}, {{0, 1, UP}}}, /* 5ms after UP at time 6 */
112 /* Press key again after 1ms delay */
113 {12, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
114 });
115 runEvents();
116}
117
118TEST_F(DebounceTest, OneKeyShort7) {
119 addEvents({ /* Time, Inputs, Outputs */
120 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
121
122 /* Release key after 7ms delay */
123 {7, {{0, 1, UP}}, {}},
124
125 {12, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */
126 /* Press key again after 1ms delay */
127 {13, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
128 });
129 runEvents();
130}
131
132TEST_F(DebounceTest, OneKeyShort8) {
133 addEvents({ /* Time, Inputs, Outputs */
134 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
135 /* Release key after 1ms delay */
136 {1, {{0, 1, UP}}, {}},
137
138 {5, {}, {}}, /* See OneKeyShort1 */
139
140 {10, {}, {{0, 1, UP}}}, /* 5ms after UP at time 7 */
141 /* Press key again after 0ms delay (scan 2) */
142 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
143 });
144 runEvents();
145}
146
147TEST_F(DebounceTest, OneKeyShort9) {
148 addEvents({ /* Time, Inputs, Outputs */
149 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
150 /* Release key after 1ms delay */
151 {1, {{0, 1, UP}}, {}},
152
153 {5, {}, {}}, /* See OneKeyShort1 */
154
155 /* Press key again after 0ms delay (same scan) before debounce finishes */
156 {10, {{0, 1, DOWN}}, {}},
157 });
158 runEvents();
159}
160
161TEST_F(DebounceTest, OneKeyBouncing1) {
162 addEvents({ /* Time, Inputs, Outputs */
163 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
164 {1, {{0, 1, UP}}, {}},
165 {2, {{0, 1, DOWN}}, {}},
166 {3, {{0, 1, UP}}, {}},
167 {4, {{0, 1, DOWN}}, {}},
168 {5, {{0, 1, UP}}, {}},
169 {6, {{0, 1, DOWN}}, {}},
170 {7, {{0, 1, UP}}, {}},
171 {8, {{0, 1, DOWN}}, {}},
172 {9, {{0, 1, UP}}, {}},
173 {10, {{0, 1, DOWN}}, {}},
174 {11, {{0, 1, UP}}, {}},
175 {12, {{0, 1, DOWN}}, {}},
176 {13, {{0, 1, UP}}, {}},
177 {14, {{0, 1, DOWN}}, {}},
178 {15, {{0, 1, UP}}, {}},
179
180 {20, {}, {{0, 1, UP}}},
181 /* Press key again after 1ms delay */
182 {21, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
183 });
184 runEvents();
185}
186
187TEST_F(DebounceTest, OneKeyBouncing2) {
188 addEvents({ /* Time, Inputs, Outputs */
189 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
190 /* Change twice in the same time period */
191 {1, {{0, 1, UP}}, {}},
192 {1, {{0, 1, DOWN}}, {}},
193 /* Change three times in the same time period */
194 {2, {{0, 1, UP}}, {}},
195 {2, {{0, 1, DOWN}}, {}},
196 {2, {{0, 1, UP}}, {}},
197 /* Change twice in the same time period */
198 {6, {{0, 1, DOWN}}, {}},
199 {6, {{0, 1, UP}}, {}},
200 /* Change three times in the same time period */
201 {7, {{0, 1, DOWN}}, {}},
202 {7, {{0, 1, UP}}, {}},
203 {7, {{0, 1, DOWN}}, {}},
204 /* Change twice in the same time period */
205 {8, {{0, 1, UP}}, {}},
206 {8, {{0, 1, DOWN}}, {}},
207 /* Change three times in the same time period */
208 {9, {{0, 1, UP}}, {}},
209 {9, {{0, 1, DOWN}}, {}},
210 {9, {{0, 1, UP}}, {}},
211
212 {14, {}, {{0, 1, UP}}},
213 /* Press key again after 1ms delay */
214 {15, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
215 });
216 runEvents();
217}
218
219TEST_F(DebounceTest, OneKeyLong) {
220 addEvents({ /* Time, Inputs, Outputs */
221 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
222
223 {25, {{0, 1, UP}}, {}},
224
225 {30, {}, {{0, 1, UP}}},
226
227 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
228
229 {75, {{0, 1, UP}}, {}},
230
231 {80, {}, {{0, 1, UP}}},
232
233 {100, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
234 });
235 runEvents();
236}
237
238TEST_F(DebounceTest, TwoKeysShort) {
239 addEvents({ /* Time, Inputs, Outputs */
240 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
241 {1, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
242 /* Release key after 2ms delay */
243 {2, {{0, 1, UP}}, {}},
244 {3, {{0, 2, UP}}, {}},
245
246 {5, {}, {}}, /* See OneKeyShort1 */
247 {6, {}, {}}, /* See OneKeyShort1 */
248
249 {10, {}, {{0, 1, UP}}}, /* 5ms+5ms after DOWN at time 0 */
250 /* Press key again after 1ms delay */
251 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}, {0, 2, UP}}}, /* 5ms+5ms after DOWN at time 0 */
252 {12, {{0, 2, DOWN}}, {{0, 2, DOWN}}}, /* 5ms+5ms after DOWN at time 0 */
253 });
254 runEvents();
255}
256
257
258TEST_F(DebounceTest, OneKeyDelayedScan1) {
259 addEvents({ /* Time, Inputs, Outputs */
260 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
261
262 /* Processing is very late, immediately release key */
263 {300, {{0, 1, UP}}, {}},
264
265 {305, {}, {{0, 1, UP}}},
266 });
267 time_jumps_ = true;
268 runEvents();
269}
270
271TEST_F(DebounceTest, OneKeyDelayedScan2) {
272 addEvents({ /* Time, Inputs, Outputs */
273 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
274
275 /* Processing is very late, immediately release key */
276 {300, {{0, 1, UP}}, {}},
277
278 /* Processing is very late again */
279 {600, {}, {{0, 1, UP}}},
280 });
281 time_jumps_ = true;
282 runEvents();
283}
284
285TEST_F(DebounceTest, OneKeyDelayedScan3) {
286 addEvents({ /* Time, Inputs, Outputs */
287 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
288
289 /* Processing is very late */
290 {300, {}, {}},
291 /* Release key after 1ms */
292 {301, {{0, 1, UP}}, {}},
293
294 {306, {}, {{0, 1, UP}}},
295 });
296 time_jumps_ = true;
297 runEvents();
298}
299
300TEST_F(DebounceTest, OneKeyDelayedScan4) {
301 addEvents({ /* Time, Inputs, Outputs */
302 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
303
304 /* Processing is very late */
305 {300, {}, {}},
306 /* Release key after 1ms */
307 {301, {{0, 1, UP}}, {}},
308
309 /* Processing is very late again */
310 {600, {}, {{0, 1, UP}}},
311 });
312 time_jumps_ = true;
313 runEvents();
314}
315
316TEST_F(DebounceTest, OneKeyDelayedScan5) {
317 addEvents({ /* Time, Inputs, Outputs */
318 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
319
320 {5, {{0, 1, UP}}, {}},
321
322 /* Processing is very late */
323 {300, {}, {{0, 1, UP}}},
324 /* Immediately press key again */
325 {300, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
326 });
327 time_jumps_ = true;
328 runEvents();
329}
330
331TEST_F(DebounceTest, OneKeyDelayedScan6) {
332 addEvents({ /* Time, Inputs, Outputs */
333 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
334
335 {5, {{0, 1, UP}}, {}},
336
337 /* Processing is very late */
338 {300, {}, {{0, 1, UP}}},
339
340 /* Press key again after 1ms */
341 {301, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
342 });
343 time_jumps_ = true;
344 runEvents();
345}
346
347TEST_F(DebounceTest, OneKeyDelayedScan7) {
348 addEvents({ /* Time, Inputs, Outputs */
349 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
350
351 {5, {{0, 1, UP}}, {}},
352
353 /* Press key again before debounce expires */
354 {300, {{0, 1, DOWN}}, {}},
355 });
356 time_jumps_ = true;
357 runEvents();
358}
359
360TEST_F(DebounceTest, OneKeyDelayedScan8) {
361 addEvents({ /* Time, Inputs, Outputs */
362 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
363
364 /* Processing is a bit late */
365 {50, {}, {}},
366 /* Release key after 1ms */
367 {51, {{0, 1, UP}}, {}},
368
369 /* Processing is a bit late again */
370 {100, {}, {{0, 1, UP}}},
371 });
372 time_jumps_ = true;
373 runEvents();
374}
diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp
new file mode 100644
index 000000000..1c5e7c9f4
--- /dev/null
+++ b/quantum/debounce/tests/debounce_test_common.cpp
@@ -0,0 +1,229 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21#include <algorithm>
22#include <iomanip>
23#include <sstream>
24
25extern "C" {
26#include "quantum.h"
27#include "timer.h"
28#include "debounce.h"
29
30void set_time(uint32_t t);
31void advance_time(uint32_t ms);
32}
33
34void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) {
35 events_.insert(events_.end(), events.begin(), events.end());
36}
37
38void DebounceTest::runEvents() {
39 /* Run the test multiple times, from 1kHz to 10kHz scan rate */
40 for (extra_iterations_ = 0; extra_iterations_ < 10; extra_iterations_++) {
41 if (time_jumps_) {
42 /* Don't advance time smoothly, jump to the next event (some tests require this) */
43 auto_advance_time_ = false;
44 runEventsInternal();
45 } else {
46 /* Run the test with both smooth and irregular time; it must produce the same result */
47 auto_advance_time_ = true;
48 runEventsInternal();
49 auto_advance_time_ = false;
50 runEventsInternal();
51 }
52 }
53}
54
55void DebounceTest::runEventsInternal() {
56 fast_timer_t previous = 0;
57 bool first = true;
58
59 /* Initialise keyboard with start time (offset to avoid testing at 0) and all keys UP */
60 debounce_init(MATRIX_ROWS);
61 set_time(time_offset_);
62 std::fill(std::begin(input_matrix_), std::end(input_matrix_), 0);
63 std::fill(std::begin(output_matrix_), std::end(output_matrix_), 0);
64
65 for (auto &event : events_) {
66 if (!auto_advance_time_) {
67 /* Jump to the next event */
68 set_time(time_offset_ + event.time_);
69 } else if (!first && event.time_ == previous + 1) {
70 /* This event immediately follows the previous one, don't make extra debounce() calls */
71 advance_time(1);
72 } else {
73 /* Fast forward to the time for this event, calling debounce() with no changes */
74 ASSERT_LT((time_offset_ + event.time_) - timer_read_fast(), 60000) << "Test tries to advance more than 1 minute of time";
75
76 while (timer_read_fast() != time_offset_ + event.time_) {
77 runDebounce(false);
78 checkCookedMatrix(false, "debounce() modified cooked matrix");
79 advance_time(1);
80 }
81 }
82
83 first = false;
84 previous = event.time_;
85
86 /* Prepare input matrix */
87 for (auto &input : event.inputs_) {
88 matrixUpdate(input_matrix_, "input", input);
89 }
90
91 /* Call debounce */
92 runDebounce(!event.inputs_.empty());
93
94 /* Prepare output matrix */
95 for (auto &output : event.outputs_) {
96 matrixUpdate(output_matrix_, "output", output);
97 }
98
99 /* Check output matrix has expected change events */
100 for (auto &output : event.outputs_) {
101 EXPECT_EQ(!!(cooked_matrix_[output.row_] & (1U << output.col_)), directionValue(output.direction_))
102 << "Missing event at " << strTime()
103 << " expected key " << output.row_ << "," << output.col_ << " " << directionLabel(output.direction_)
104 << "\ninput_matrix: changed=" << !event.inputs_.empty() << "\n" << strMatrix(input_matrix_)
105 << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
106 << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
107 }
108
109 /* Check output matrix has no other changes */
110 checkCookedMatrix(!event.inputs_.empty(), "debounce() cooked matrix does not match expected output matrix");
111
112 /* Perform some extra iterations of the matrix scan with no changes */
113 for (int i = 0; i < extra_iterations_; i++) {
114 runDebounce(false);
115 checkCookedMatrix(false, "debounce() modified cooked matrix");
116 }
117 }
118
119 /* Check that no further changes happen for 1 minute */
120 for (int i = 0; i < 60000; i++) {
121 runDebounce(false);
122 checkCookedMatrix(false, "debounce() modified cooked matrix");
123 advance_time(1);
124 }
125
126 debounce_free();
127}
128
129void DebounceTest::runDebounce(bool changed) {
130 std::copy(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_));
131 std::copy(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_));
132
133 debounce(raw_matrix_, cooked_matrix_, MATRIX_ROWS, changed);
134
135 if (!std::equal(std::begin(input_matrix_), std::end(input_matrix_), std::begin(raw_matrix_))) {
136 FAIL() << "Fatal error: debounce() modified raw matrix at " << strTime()
137 << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
138 << "\nraw_matrix:\n" << strMatrix(raw_matrix_);
139 }
140}
141
142void DebounceTest::checkCookedMatrix(bool changed, const std::string &error_message) {
143 if (!std::equal(std::begin(output_matrix_), std::end(output_matrix_), std::begin(cooked_matrix_))) {
144 FAIL() << "Unexpected event: " << error_message << " at " << strTime()
145 << "\ninput_matrix: changed=" << changed << "\n" << strMatrix(input_matrix_)
146 << "\nexpected_matrix:\n" << strMatrix(output_matrix_)
147 << "\nactual_matrix:\n" << strMatrix(cooked_matrix_);
148 }
149}
150
151std::string DebounceTest::strTime() {
152 std::stringstream text;
153
154 text << "time " << (timer_read_fast() - time_offset_)
155 << " (extra_iterations=" << extra_iterations_
156 << ", auto_advance_time=" << auto_advance_time_ << ")";
157
158 return text.str();
159}
160
161std::string DebounceTest::strMatrix(matrix_row_t matrix[]) {
162 std::stringstream text;
163
164 text << "\t" << std::setw(3) << "";
165 for (int col = 0; col < MATRIX_COLS; col++) {
166 text << " " << std::setw(2) << col;
167 }
168 text << "\n";
169
170 for (int row = 0; row < MATRIX_ROWS; row++) {
171 text << "\t" << std::setw(2) << row << ":";
172 for (int col = 0; col < MATRIX_COLS; col++) {
173 text << ((matrix[row] & (1U << col)) ? " XX" : " __");
174 }
175
176 text << "\n";
177 }
178
179 return text.str();
180}
181
182bool DebounceTest::directionValue(Direction direction) {
183 switch (direction) {
184 case DOWN:
185 return true;
186
187 case UP:
188 return false;
189 }
190}
191
192std::string DebounceTest::directionLabel(Direction direction) {
193 switch (direction) {
194 case DOWN:
195 return "DOWN";
196
197 case UP:
198 return "UP";
199 }
200}
201
202/* Modify a matrix and verify that events always specify a change */
203void DebounceTest::matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event) {
204 ASSERT_NE(!!(matrix[event.row_] & (1U << event.col_)), directionValue(event.direction_))
205 << "Test " << name << " at " << strTime()
206 << " sets key " << event.row_ << "," << event.col_ << " " << directionLabel(event.direction_)
207 << " but it is already " << directionLabel(event.direction_)
208 << "\n" << name << "_matrix:\n" << strMatrix(matrix);
209
210 switch (event.direction_) {
211 case DOWN:
212 matrix[event.row_] |= (1U << event.col_);
213 break;
214
215 case UP:
216 matrix[event.row_] &= ~(1U << event.col_);
217 break;
218 }
219}
220
221DebounceTestEvent::DebounceTestEvent(fast_timer_t time,
222 std::initializer_list<MatrixTestEvent> inputs,
223 std::initializer_list<MatrixTestEvent> outputs)
224 : time_(time), inputs_(inputs), outputs_(outputs) {
225}
226
227MatrixTestEvent::MatrixTestEvent(int row, int col, Direction direction)
228 : row_(row), col_(col), direction_(direction) {
229}
diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h
new file mode 100644
index 000000000..d87e31059
--- /dev/null
+++ b/quantum/debounce/tests/debounce_test_common.h
@@ -0,0 +1,83 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include <initializer_list>
20#include <list>
21#include <string>
22
23extern "C" {
24#include "quantum.h"
25#include "timer.h"
26}
27
28enum Direction {
29 DOWN,
30 UP,
31};
32
33class MatrixTestEvent {
34public:
35 MatrixTestEvent(int row, int col, Direction direction);
36
37 const int row_;
38 const int col_;
39 const Direction direction_;
40};
41
42class DebounceTestEvent {
43public:
44 // 0, {{0, 1, DOWN}}, {{0, 1, DOWN}})
45 DebounceTestEvent(fast_timer_t time,
46 std::initializer_list<MatrixTestEvent> inputs,
47 std::initializer_list<MatrixTestEvent> outputs);
48
49 const fast_timer_t time_;
50 const std::list<MatrixTestEvent> inputs_;
51 const std::list<MatrixTestEvent> outputs_;
52};
53
54class DebounceTest : public ::testing::Test {
55protected:
56 void addEvents(std::initializer_list<DebounceTestEvent> events);
57 void runEvents();
58
59 fast_timer_t time_offset_ = 7777;
60 bool time_jumps_ = false;
61
62private:
63 static bool directionValue(Direction direction);
64 static std::string directionLabel(Direction direction);
65
66 void runEventsInternal();
67 void runDebounce(bool changed);
68 void checkCookedMatrix(bool changed, const std::string &error_message);
69 void matrixUpdate(matrix_row_t matrix[], const std::string &name, const MatrixTestEvent &event);
70
71 std::string strTime();
72 std::string strMatrix(matrix_row_t matrix[]);
73
74 std::list<DebounceTestEvent> events_;
75
76 matrix_row_t input_matrix_[MATRIX_ROWS];
77 matrix_row_t raw_matrix_[MATRIX_ROWS];
78 matrix_row_t cooked_matrix_[MATRIX_ROWS];
79 matrix_row_t output_matrix_[MATRIX_ROWS];
80
81 int extra_iterations_;
82 bool auto_advance_time_;
83};
diff --git a/quantum/debounce/tests/rules.mk b/quantum/debounce/tests/rules.mk
new file mode 100644
index 000000000..66928d7eb
--- /dev/null
+++ b/quantum/debounce/tests/rules.mk
@@ -0,0 +1,44 @@
1# Copyright 2021 Simon Arlott
2#
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation, either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16DEBOUNCE_COMMON_DEFS := -DMATRIX_ROWS=4 -DMATRIX_COLS=10 -DDEBOUNCE=5
17
18DEBOUNCE_COMMON_SRC := $(QUANTUM_PATH)/debounce/tests/debounce_test_common.cpp \
19 $(TMK_PATH)/common/test/timer.c
20
21debounce_sym_defer_g_DEFS := $(DEBOUNCE_COMMON_DEFS)
22debounce_sym_defer_g_SRC := $(DEBOUNCE_COMMON_SRC) \
23 $(QUANTUM_PATH)/debounce/sym_defer_g.c \
24 $(QUANTUM_PATH)/debounce/tests/sym_defer_g_tests.cpp
25
26debounce_sym_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
27debounce_sym_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
28 $(QUANTUM_PATH)/debounce/sym_defer_pk.c \
29 $(QUANTUM_PATH)/debounce/tests/sym_defer_pk_tests.cpp
30
31debounce_sym_eager_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
32debounce_sym_eager_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
33 $(QUANTUM_PATH)/debounce/sym_eager_pk.c \
34 $(QUANTUM_PATH)/debounce/tests/sym_eager_pk_tests.cpp
35
36debounce_sym_eager_pr_DEFS := $(DEBOUNCE_COMMON_DEFS)
37debounce_sym_eager_pr_SRC := $(DEBOUNCE_COMMON_SRC) \
38 $(QUANTUM_PATH)/debounce/sym_eager_pr.c \
39 $(QUANTUM_PATH)/debounce/tests/sym_eager_pr_tests.cpp
40
41debounce_asym_eager_defer_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
42debounce_asym_eager_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
43 $(QUANTUM_PATH)/debounce/asym_eager_defer_pk.c \
44 $(QUANTUM_PATH)/debounce/tests/asym_eager_defer_pk_tests.cpp
diff --git a/quantum/debounce/tests/sym_defer_g_tests.cpp b/quantum/debounce/tests/sym_defer_g_tests.cpp
new file mode 100644
index 000000000..a56aecd8f
--- /dev/null
+++ b/quantum/debounce/tests/sym_defer_g_tests.cpp
@@ -0,0 +1,223 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {}},
24
25 {5, {}, {{0, 1, DOWN}}},
26 /* 0ms delay (fast scan rate) */
27 {5, {{0, 1, UP}}, {}},
28
29 {10, {}, {{0, 1, UP}}},
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {}},
37
38 {5, {}, {{0, 1, DOWN}}},
39 /* 1ms delay */
40 {6, {{0, 1, UP}}, {}},
41
42 {11, {}, {{0, 1, UP}}},
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {}},
50
51 {5, {}, {{0, 1, DOWN}}},
52 /* 2ms delay */
53 {7, {{0, 1, UP}}, {}},
54
55 {12, {}, {{0, 1, UP}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyTooQuick1) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {}},
63 /* Release key exactly on the debounce time */
64 {5, {{0, 1, UP}}, {}},
65 });
66 runEvents();
67}
68
69TEST_F(DebounceTest, OneKeyTooQuick2) {
70 addEvents({ /* Time, Inputs, Outputs */
71 {0, {{0, 1, DOWN}}, {}},
72
73 {5, {}, {{0, 1, DOWN}}},
74 {6, {{0, 1, UP}}, {}},
75
76 /* Press key exactly on the debounce time */
77 {11, {{0, 1, DOWN}}, {}},
78 });
79 runEvents();
80}
81
82TEST_F(DebounceTest, OneKeyBouncing1) {
83 addEvents({ /* Time, Inputs, Outputs */
84 {0, {{0, 1, DOWN}}, {}},
85 {1, {{0, 1, UP}}, {}},
86 {2, {{0, 1, DOWN}}, {}},
87 {3, {{0, 1, UP}}, {}},
88 {4, {{0, 1, DOWN}}, {}},
89 {5, {{0, 1, UP}}, {}},
90 {6, {{0, 1, DOWN}}, {}},
91 {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */
92 });
93 runEvents();
94}
95
96TEST_F(DebounceTest, OneKeyBouncing2) {
97 addEvents({ /* Time, Inputs, Outputs */
98 {0, {{0, 1, DOWN}}, {}},
99 {5, {}, {{0, 1, DOWN}}},
100 {6, {{0, 1, UP}}, {}},
101 {7, {{0, 1, DOWN}}, {}},
102 {8, {{0, 1, UP}}, {}},
103 {9, {{0, 1, DOWN}}, {}},
104 {10, {{0, 1, UP}}, {}},
105 {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */
106 });
107 runEvents();
108}
109
110TEST_F(DebounceTest, OneKeyLong) {
111 addEvents({ /* Time, Inputs, Outputs */
112 {0, {{0, 1, DOWN}}, {}},
113
114 {5, {}, {{0, 1, DOWN}}},
115
116 {25, {{0, 1, UP}}, {}},
117
118 {30, {}, {{0, 1, UP}}},
119
120 {50, {{0, 1, DOWN}}, {}},
121
122 {55, {}, {{0, 1, DOWN}}},
123 });
124 runEvents();
125}
126
127TEST_F(DebounceTest, TwoKeysShort) {
128 addEvents({ /* Time, Inputs, Outputs */
129 {0, {{0, 1, DOWN}}, {}},
130 {1, {{0, 2, DOWN}}, {}},
131
132 {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
133
134 {7, {{0, 1, UP}}, {}},
135 {8, {{0, 2, UP}}, {}},
136
137 {13, {}, {{0, 1, UP}, {0, 2, UP}}},
138 });
139 runEvents();
140}
141
142TEST_F(DebounceTest, TwoKeysSimultaneous1) {
143 addEvents({ /* Time, Inputs, Outputs */
144 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
145
146 {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
147 {6, {{0, 1, UP}, {0, 2, UP}}, {}},
148
149 {11, {}, {{0, 1, UP}, {0, 2, UP}}},
150 });
151 runEvents();
152}
153
154TEST_F(DebounceTest, TwoKeysSimultaneous2) {
155 addEvents({ /* Time, Inputs, Outputs */
156 {0, {{0, 1, DOWN}}, {}},
157 {1, {{0, 2, DOWN}}, {}},
158
159 {5, {}, {}},
160 {6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
161 {7, {{0, 1, UP}}, {}},
162 {8, {{0, 2, UP}}, {}},
163
164 {13, {}, {{0, 1, UP}, {0, 2, UP}}},
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, OneKeyDelayedScan1) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {}},
172
173 /* Processing is very late */
174 {300, {}, {{0, 1, DOWN}}},
175 /* Immediately release key */
176 {300, {{0, 1, UP}}, {}},
177
178 {305, {}, {{0, 1, UP}}},
179 });
180 time_jumps_ = true;
181 runEvents();
182}
183
184TEST_F(DebounceTest, OneKeyDelayedScan2) {
185 addEvents({ /* Time, Inputs, Outputs */
186 {0, {{0, 1, DOWN}}, {}},
187
188 /* Processing is very late */
189 {300, {}, {{0, 1, DOWN}}},
190 /* Release key after 1ms */
191 {301, {{0, 1, UP}}, {}},
192
193 {306, {}, {{0, 1, UP}}},
194 });
195 time_jumps_ = true;
196 runEvents();
197}
198
199TEST_F(DebounceTest, OneKeyDelayedScan3) {
200 addEvents({ /* Time, Inputs, Outputs */
201 {0, {{0, 1, DOWN}}, {}},
202
203 /* Release key before debounce expires */
204 {300, {{0, 1, UP}}, {}},
205 });
206 time_jumps_ = true;
207 runEvents();
208}
209
210TEST_F(DebounceTest, OneKeyDelayedScan4) {
211 addEvents({ /* Time, Inputs, Outputs */
212 {0, {{0, 1, DOWN}}, {}},
213
214 /* Processing is a bit late */
215 {50, {}, {{0, 1, DOWN}}},
216 /* Release key after 1ms */
217 {51, {{0, 1, UP}}, {}},
218
219 {56, {}, {{0, 1, UP}}},
220 });
221 time_jumps_ = true;
222 runEvents();
223}
diff --git a/quantum/debounce/tests/sym_defer_pk_tests.cpp b/quantum/debounce/tests/sym_defer_pk_tests.cpp
new file mode 100644
index 000000000..1f3061e59
--- /dev/null
+++ b/quantum/debounce/tests/sym_defer_pk_tests.cpp
@@ -0,0 +1,225 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {}},
24
25 {5, {}, {{0, 1, DOWN}}},
26 /* 0ms delay (fast scan rate) */
27 {5, {{0, 1, UP}}, {}},
28
29 {10, {}, {{0, 1, UP}}},
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {}},
37
38 {5, {}, {{0, 1, DOWN}}},
39 /* 1ms delay */
40 {6, {{0, 1, UP}}, {}},
41
42 {11, {}, {{0, 1, UP}}},
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {}},
50
51 {5, {}, {{0, 1, DOWN}}},
52 /* 2ms delay */
53 {7, {{0, 1, UP}}, {}},
54
55 {12, {}, {{0, 1, UP}}},
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyTooQuick1) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {}},
63 /* Release key exactly on the debounce time */
64 {5, {{0, 1, UP}}, {}},
65 });
66 runEvents();
67}
68
69TEST_F(DebounceTest, OneKeyTooQuick2) {
70 addEvents({ /* Time, Inputs, Outputs */
71 {0, {{0, 1, DOWN}}, {}},
72
73 {5, {}, {{0, 1, DOWN}}},
74 {6, {{0, 1, UP}}, {}},
75
76 /* Press key exactly on the debounce time */
77 {11, {{0, 1, DOWN}}, {}},
78 });
79 runEvents();
80}
81
82TEST_F(DebounceTest, OneKeyBouncing1) {
83 addEvents({ /* Time, Inputs, Outputs */
84 {0, {{0, 1, DOWN}}, {}},
85 {1, {{0, 1, UP}}, {}},
86 {2, {{0, 1, DOWN}}, {}},
87 {3, {{0, 1, UP}}, {}},
88 {4, {{0, 1, DOWN}}, {}},
89 {5, {{0, 1, UP}}, {}},
90 {6, {{0, 1, DOWN}}, {}},
91 {11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */
92 });
93 runEvents();
94}
95
96TEST_F(DebounceTest, OneKeyBouncing2) {
97 addEvents({ /* Time, Inputs, Outputs */
98 {0, {{0, 1, DOWN}}, {}},
99 {5, {}, {{0, 1, DOWN}}},
100 {6, {{0, 1, UP}}, {}},
101 {7, {{0, 1, DOWN}}, {}},
102 {8, {{0, 1, UP}}, {}},
103 {9, {{0, 1, DOWN}}, {}},
104 {10, {{0, 1, UP}}, {}},
105 {15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */
106 });
107 runEvents();
108}
109
110TEST_F(DebounceTest, OneKeyLong) {
111 addEvents({ /* Time, Inputs, Outputs */
112 {0, {{0, 1, DOWN}}, {}},
113
114 {5, {}, {{0, 1, DOWN}}},
115
116 {25, {{0, 1, UP}}, {}},
117
118 {30, {}, {{0, 1, UP}}},
119
120 {50, {{0, 1, DOWN}}, {}},
121
122 {55, {}, {{0, 1, DOWN}}},
123 });
124 runEvents();
125}
126
127TEST_F(DebounceTest, TwoKeysShort) {
128 addEvents({ /* Time, Inputs, Outputs */
129 {0, {{0, 1, DOWN}}, {}},
130 {1, {{0, 2, DOWN}}, {}},
131
132 {5, {}, {{0, 1, DOWN}}},
133 {6, {}, {{0, 2, DOWN}}},
134
135 {7, {{0, 1, UP}}, {}},
136 {8, {{0, 2, UP}}, {}},
137
138 {12, {}, {{0, 1, UP}}},
139 {13, {}, {{0, 2, UP}}},
140 });
141 runEvents();
142}
143
144TEST_F(DebounceTest, TwoKeysSimultaneous1) {
145 addEvents({ /* Time, Inputs, Outputs */
146 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
147
148 {5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
149 {6, {{0, 1, UP}, {0, 2, UP}}, {}},
150
151 {11, {}, {{0, 1, UP}, {0, 2, UP}}},
152 });
153 runEvents();
154}
155
156TEST_F(DebounceTest, TwoKeysSimultaneous2) {
157 addEvents({ /* Time, Inputs, Outputs */
158 {0, {{0, 1, DOWN}}, {}},
159 {1, {{0, 2, DOWN}}, {}},
160
161 {5, {}, {{0, 1, DOWN}}},
162 {6, {{0, 1, UP}}, {{0, 2, DOWN}}},
163 {7, {{0, 2, UP}}, {}},
164
165 {11, {}, {{0, 1, UP}}},
166 {12, {}, {{0, 2, UP}}},
167 });
168 runEvents();
169}
170
171TEST_F(DebounceTest, OneKeyDelayedScan1) {
172 addEvents({ /* Time, Inputs, Outputs */
173 {0, {{0, 1, DOWN}}, {}},
174
175 /* Processing is very late */
176 {300, {}, {{0, 1, DOWN}}},
177 /* Immediately release key */
178 {300, {{0, 1, UP}}, {}},
179
180 {305, {}, {{0, 1, UP}}},
181 });
182 time_jumps_ = true;
183 runEvents();
184}
185
186TEST_F(DebounceTest, OneKeyDelayedScan2) {
187 addEvents({ /* Time, Inputs, Outputs */
188 {0, {{0, 1, DOWN}}, {}},
189
190 /* Processing is very late */
191 {300, {}, {{0, 1, DOWN}}},
192 /* Release key after 1ms */
193 {301, {{0, 1, UP}}, {}},
194
195 {306, {}, {{0, 1, UP}}},
196 });
197 time_jumps_ = true;
198 runEvents();
199}
200
201TEST_F(DebounceTest, OneKeyDelayedScan3) {
202 addEvents({ /* Time, Inputs, Outputs */
203 {0, {{0, 1, DOWN}}, {}},
204
205 /* Release key before debounce expires */
206 {300, {{0, 1, UP}}, {}},
207 });
208 time_jumps_ = true;
209 runEvents();
210}
211
212TEST_F(DebounceTest, OneKeyDelayedScan4) {
213 addEvents({ /* Time, Inputs, Outputs */
214 {0, {{0, 1, DOWN}}, {}},
215
216 /* Processing is a bit late */
217 {50, {}, {{0, 1, DOWN}}},
218 /* Release key after 1ms */
219 {51, {{0, 1, UP}}, {}},
220
221 {56, {}, {{0, 1, UP}}},
222 });
223 time_jumps_ = true;
224 runEvents();
225}
diff --git a/quantum/debounce/tests/sym_eager_pk_tests.cpp b/quantum/debounce/tests/sym_eager_pk_tests.cpp
new file mode 100644
index 000000000..e0fc205e3
--- /dev/null
+++ b/quantum/debounce/tests/sym_eager_pk_tests.cpp
@@ -0,0 +1,237 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 {1, {{0, 1, UP}}, {}},
25
26 {5, {}, {{0, 1, UP}}},
27 /* Press key again after 1ms delay (debounce has not yet finished) */
28 {6, {{0, 1, DOWN}}, {}},
29 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
37 {1, {{0, 1, UP}}, {}},
38
39 {5, {}, {{0, 1, UP}}},
40 /* Press key again after 2ms delay (debounce has not yet finished) */
41 {7, {{0, 1, DOWN}}, {}},
42 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
50 {1, {{0, 1, UP}}, {}},
51
52 {5, {}, {{0, 1, UP}}},
53 /* Press key again after 3ms delay (debounce has not yet finished) */
54 {8, {{0, 1, DOWN}}, {}},
55 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort4) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 {1, {{0, 1, UP}}, {}},
64
65 {5, {}, {{0, 1, UP}}},
66 /* Press key again after 4ms delay (debounce has not yet finished) */
67 {9, {{0, 1, DOWN}}, {}},
68 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
69 });
70 runEvents();
71}
72
73TEST_F(DebounceTest, OneKeyShort5) {
74 addEvents({ /* Time, Inputs, Outputs */
75 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
76 {1, {{0, 1, UP}}, {}},
77
78 {5, {}, {{0, 1, UP}}},
79 /* Press key again after 5ms delay (debounce has finished) */
80 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
81 });
82 runEvents();
83}
84
85TEST_F(DebounceTest, OneKeyShort6) {
86 addEvents({ /* Time, Inputs, Outputs */
87 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
88 {1, {{0, 1, UP}}, {}},
89
90 {5, {}, {{0, 1, UP}}},
91 /* Press key after after 6ms delay (debounce has finished) */
92 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93 });
94 runEvents();
95}
96
97TEST_F(DebounceTest, OneKeyBouncing1) {
98 addEvents({ /* Time, Inputs, Outputs */
99 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 {1, {{0, 1, UP}}, {}},
101 {2, {{0, 1, DOWN}}, {}},
102 {3, {{0, 1, UP}}, {}},
103 {4, {{0, 1, DOWN}}, {}},
104 {5, {{0, 1, UP}}, {{0, 1, UP}}},
105 /* Press key again after 1ms delay (debounce has not yet finished) */
106 {6, {{0, 1, DOWN}}, {}},
107 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
108 });
109 runEvents();
110}
111
112TEST_F(DebounceTest, OneKeyBouncing2) {
113 addEvents({ /* Time, Inputs, Outputs */
114 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
115 /* Change twice in the same time period */
116 {1, {{0, 1, UP}}, {}},
117 {1, {{0, 1, DOWN}}, {}},
118 /* Change three times in the same time period */
119 {2, {{0, 1, UP}}, {}},
120 {2, {{0, 1, DOWN}}, {}},
121 {2, {{0, 1, UP}}, {}},
122 /* Change three times in the same time period */
123 {3, {{0, 1, DOWN}}, {}},
124 {3, {{0, 1, UP}}, {}},
125 {3, {{0, 1, DOWN}}, {}},
126 /* Change twice in the same time period */
127 {4, {{0, 1, UP}}, {}},
128 {4, {{0, 1, DOWN}}, {}},
129 {5, {{0, 1, UP}}, {{0, 1, UP}}},
130 /* Press key again after 1ms delay (debounce has not yet finished) */
131 {6, {{0, 1, DOWN}}, {}},
132 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
133 });
134 runEvents();
135}
136
137TEST_F(DebounceTest, OneKeyLong) {
138 addEvents({ /* Time, Inputs, Outputs */
139 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
140
141 {25, {{0, 1, UP}}, {{0, 1, UP}}},
142
143 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
144 });
145 runEvents();
146}
147
148TEST_F(DebounceTest, TwoKeysShort) {
149 addEvents({ /* Time, Inputs, Outputs */
150 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
151 {1, {{0, 1, UP}}, {}},
152 {2, {{0, 2, DOWN}}, {{0, 2, DOWN}}},
153 {3, {{0, 2, UP}}, {}},
154
155 {5, {}, {{0, 1, UP}}},
156 /* Press key again after 1ms delay (debounce has not yet finished) */
157 {6, {{0, 1, DOWN}}, {}},
158 {7, {}, {{0, 2, UP}}},
159
160 /* Press key again after 1ms delay (debounce has not yet finished) */
161 {9, {{0, 2, DOWN}}, {}},
162 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
163
164 {12, {}, {{0, 2, DOWN}}}, /* 5ms after UP at time 7 */
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, OneKeyDelayedScan1) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
172
173 /* Processing is very late but the change will now be accepted */
174 {300, {{0, 1, UP}}, {{0, 1, UP}}},
175 });
176 time_jumps_ = true;
177 runEvents();
178}
179
180TEST_F(DebounceTest, OneKeyDelayedScan2) {
181 addEvents({ /* Time, Inputs, Outputs */
182 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
183
184 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
185 {300, {}, {}},
186 {300, {{0, 1, UP}}, {{0, 1, UP}}},
187 });
188 time_jumps_ = true;
189 runEvents();
190}
191
192TEST_F(DebounceTest, OneKeyDelayedScan3) {
193 addEvents({ /* Time, Inputs, Outputs */
194 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
195
196 /* Processing is very late but the change will now be accepted even with a 1ms delay */
197 {300, {}, {}},
198 {301, {{0, 1, UP}}, {{0, 1, UP}}},
199 });
200 time_jumps_ = true;
201 runEvents();
202}
203
204TEST_F(DebounceTest, OneKeyDelayedScan4) {
205 addEvents({ /* Time, Inputs, Outputs */
206 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
207
208 /* Processing is a bit late but the change will now be accepted */
209 {50, {{0, 1, UP}}, {{0, 1, UP}}},
210 });
211 time_jumps_ = true;
212 runEvents();
213}
214
215TEST_F(DebounceTest, OneKeyDelayedScan5) {
216 addEvents({ /* Time, Inputs, Outputs */
217 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
218
219 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
220 {50, {}, {}},
221 {50, {{0, 1, UP}}, {{0, 1, UP}}},
222 });
223 time_jumps_ = true;
224 runEvents();
225}
226
227TEST_F(DebounceTest, OneKeyDelayedScan6) {
228 addEvents({ /* Time, Inputs, Outputs */
229 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
230
231 /* Processing is very late but the change will now be accepted even with a 1ms delay */
232 {50, {}, {}},
233 {51, {{0, 1, UP}}, {{0, 1, UP}}},
234 });
235 time_jumps_ = true;
236 runEvents();
237}
diff --git a/quantum/debounce/tests/sym_eager_pr_tests.cpp b/quantum/debounce/tests/sym_eager_pr_tests.cpp
new file mode 100644
index 000000000..2c4bca127
--- /dev/null
+++ b/quantum/debounce/tests/sym_eager_pr_tests.cpp
@@ -0,0 +1,280 @@
1/* Copyright 2021 Simon Arlott
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "gtest/gtest.h"
18
19#include "debounce_test_common.h"
20
21TEST_F(DebounceTest, OneKeyShort1) {
22 addEvents({ /* Time, Inputs, Outputs */
23 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
24 {1, {{0, 1, UP}}, {}},
25
26 {5, {}, {{0, 1, UP}}},
27 /* Press key again after 1ms delay (debounce has not yet finished) */
28 {6, {{0, 1, DOWN}}, {}},
29 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
30 });
31 runEvents();
32}
33
34TEST_F(DebounceTest, OneKeyShort2) {
35 addEvents({ /* Time, Inputs, Outputs */
36 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
37 {1, {{0, 1, UP}}, {}},
38
39 {5, {}, {{0, 1, UP}}},
40 /* Press key again after 2ms delay (debounce has not yet finished) */
41 {7, {{0, 1, DOWN}}, {}},
42 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
43 });
44 runEvents();
45}
46
47TEST_F(DebounceTest, OneKeyShort3) {
48 addEvents({ /* Time, Inputs, Outputs */
49 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
50 {1, {{0, 1, UP}}, {}},
51
52 {5, {}, {{0, 1, UP}}},
53 /* Press key again after 3ms delay (debounce has not yet finished) */
54 {8, {{0, 1, DOWN}}, {}},
55 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
56 });
57 runEvents();
58}
59
60TEST_F(DebounceTest, OneKeyShort4) {
61 addEvents({ /* Time, Inputs, Outputs */
62 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
63 {1, {{0, 1, UP}}, {}},
64
65 {5, {}, {{0, 1, UP}}},
66 /* Press key again after 4ms delay (debounce has not yet finished) */
67 {9, {{0, 1, DOWN}}, {}},
68 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
69 });
70 runEvents();
71}
72
73TEST_F(DebounceTest, OneKeyShort5) {
74 addEvents({ /* Time, Inputs, Outputs */
75 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
76 {1, {{0, 1, UP}}, {}},
77
78 {5, {}, {{0, 1, UP}}},
79 /* Press key again after 5ms delay (debounce has finished) */
80 {10, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
81 });
82 runEvents();
83}
84
85TEST_F(DebounceTest, OneKeyShort6) {
86 addEvents({ /* Time, Inputs, Outputs */
87 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
88 {1, {{0, 1, UP}}, {}},
89
90 {5, {}, {{0, 1, UP}}},
91 /* Press key after after 6ms delay (debounce has finished) */
92 {11, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
93 });
94 runEvents();
95}
96
97TEST_F(DebounceTest, OneKeyBouncing1) {
98 addEvents({ /* Time, Inputs, Outputs */
99 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
100 {1, {{0, 1, UP}}, {}},
101 {2, {{0, 1, DOWN}}, {}},
102 {3, {{0, 1, UP}}, {}},
103 {4, {{0, 1, DOWN}}, {}},
104 {5, {{0, 1, UP}}, {{0, 1, UP}}},
105 /* Press key again after 1ms delay (debounce has not yet finished) */
106 {6, {{0, 1, DOWN}}, {}},
107 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
108 });
109 runEvents();
110}
111
112TEST_F(DebounceTest, OneKeyBouncing2) {
113 addEvents({ /* Time, Inputs, Outputs */
114 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
115 /* Change twice in the same time period */
116 {1, {{0, 1, UP}}, {}},
117 {1, {{0, 1, DOWN}}, {}},
118 /* Change three times in the same time period */
119 {2, {{0, 1, UP}}, {}},
120 {2, {{0, 1, DOWN}}, {}},
121 {2, {{0, 1, UP}}, {}},
122 /* Change three times in the same time period */
123 {3, {{0, 1, DOWN}}, {}},
124 {3, {{0, 1, UP}}, {}},
125 {3, {{0, 1, DOWN}}, {}},
126 /* Change twice in the same time period */
127 {4, {{0, 1, UP}}, {}},
128 {4, {{0, 1, DOWN}}, {}},
129 {5, {{0, 1, UP}}, {{0, 1, UP}}},
130 /* Press key again after 1ms delay (debounce has not yet finished) */
131 {6, {{0, 1, DOWN}}, {}},
132 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
133 });
134 runEvents();
135}
136
137TEST_F(DebounceTest, OneKeyLong) {
138 addEvents({ /* Time, Inputs, Outputs */
139 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
140
141 {25, {{0, 1, UP}}, {{0, 1, UP}}},
142
143 {50, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
144 });
145 runEvents();
146}
147
148TEST_F(DebounceTest, TwoRowsShort) {
149 addEvents({ /* Time, Inputs, Outputs */
150 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
151 {1, {{0, 1, UP}}, {}},
152 {2, {{2, 0, DOWN}}, {{2, 0, DOWN}}},
153 {3, {{2, 0, UP}}, {}},
154
155 {5, {}, {{0, 1, UP}}},
156 /* Press key again after 1ms delay (debounce has not yet finished) */
157 {6, {{0, 1, DOWN}}, {}},
158 {7, {}, {{2, 0, UP}}},
159
160 /* Press key again after 1ms delay (debounce has not yet finished) */
161 {9, {{2, 0, DOWN}}, {}},
162 {10, {}, {{0, 1, DOWN}}}, /* 5ms after UP at time 5 */
163
164 {12, {}, {{2, 0, DOWN}}}, /* 5ms after UP at time 7 */
165 });
166 runEvents();
167}
168
169TEST_F(DebounceTest, TwoKeysOverlap) {
170 addEvents({ /* Time, Inputs, Outputs */
171 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
172 {1, {{0, 1, UP}}, {}},
173 /* Press a second key during the first debounce */
174 {2, {{0, 2, DOWN}}, {}},
175
176 /* Key registers as soon as debounce finishes, 5ms after time 0 */
177 {5, {}, {{0, 1, UP}, {0, 2, DOWN}}},
178 {6, {{0, 1, DOWN}}, {}},
179
180 /* Key registers as soon as debounce finishes, 5ms after time 5 */
181 {10, {}, {{0, 1, DOWN}}},
182 /* Release both keys */
183 {11, {{0, 1, UP}}, {}},
184 {12, {{0, 2, UP}}, {}},
185
186 /* Keys register as soon as debounce finishes, 5ms after time 10 */
187 {15, {}, {{0, 1, UP}, {0, 2, UP}}},
188 });
189 runEvents();
190}
191
192TEST_F(DebounceTest, TwoKeysSimultaneous1) {
193 addEvents({ /* Time, Inputs, Outputs */
194 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
195 {20, {{0, 1, UP}}, {{0, 1, UP}}},
196 {21, {{0, 2, UP}}, {}},
197
198 /* Key registers as soon as debounce finishes, 5ms after time 20 */
199 {25, {}, {{0, 2, UP}}},
200 });
201 runEvents();
202}
203
204TEST_F(DebounceTest, TwoKeysSimultaneous2) {
205 addEvents({ /* Time, Inputs, Outputs */
206 {0, {{0, 1, DOWN}, {0, 2, DOWN}}, {{0, 1, DOWN}, {0, 2, DOWN}}},
207 {20, {{0, 1, UP}, {0, 2, UP}}, {{0, 1, UP}, {0, 2, UP}}},
208 });
209 runEvents();
210}
211
212TEST_F(DebounceTest, OneKeyDelayedScan1) {
213 addEvents({ /* Time, Inputs, Outputs */
214 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
215
216 /* Processing is very late but the change will now be accepted */
217 {300, {{0, 1, UP}}, {{0, 1, UP}}},
218 });
219 time_jumps_ = true;
220 runEvents();
221}
222
223TEST_F(DebounceTest, OneKeyDelayedScan2) {
224 addEvents({ /* Time, Inputs, Outputs */
225 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
226
227 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
228 {300, {}, {}},
229 {300, {{0, 1, UP}}, {{0, 1, UP}}},
230 });
231 time_jumps_ = true;
232 runEvents();
233}
234
235TEST_F(DebounceTest, OneKeyDelayedScan3) {
236 addEvents({ /* Time, Inputs, Outputs */
237 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
238
239 /* Processing is very late but the change will now be accepted even with a 1ms delay */
240 {300, {}, {}},
241 {301, {{0, 1, UP}}, {{0, 1, UP}}},
242 });
243 time_jumps_ = true;
244 runEvents();
245}
246
247TEST_F(DebounceTest, OneKeyDelayedScan4) {
248 addEvents({ /* Time, Inputs, Outputs */
249 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
250
251 /* Processing is a bit late but the change will now be accepted */
252 {50, {{0, 1, UP}}, {{0, 1, UP}}},
253 });
254 time_jumps_ = true;
255 runEvents();
256}
257
258TEST_F(DebounceTest, OneKeyDelayedScan5) {
259 addEvents({ /* Time, Inputs, Outputs */
260 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
261
262 /* Processing is very late but the change will now be accepted even with a 1 scan delay */
263 {50, {}, {}},
264 {50, {{0, 1, UP}}, {{0, 1, UP}}},
265 });
266 time_jumps_ = true;
267 runEvents();
268}
269
270TEST_F(DebounceTest, OneKeyDelayedScan6) {
271 addEvents({ /* Time, Inputs, Outputs */
272 {0, {{0, 1, DOWN}}, {{0, 1, DOWN}}},
273
274 /* Processing is very late but the change will now be accepted even with a 1ms delay */
275 {50, {}, {}},
276 {51, {{0, 1, UP}}, {{0, 1, UP}}},
277 });
278 time_jumps_ = true;
279 runEvents();
280}
diff --git a/quantum/debounce/tests/testlist.mk b/quantum/debounce/tests/testlist.mk
new file mode 100644
index 000000000..c54c45aa6
--- /dev/null
+++ b/quantum/debounce/tests/testlist.mk
@@ -0,0 +1,6 @@
1TEST_LIST += \
2 debounce_sym_defer_g \
3 debounce_sym_defer_pk \
4 debounce_sym_eager_pk \
5 debounce_sym_eager_pr \
6 debounce_asym_eager_defer_pk