Commit | Line | Data |
---|---|---|
332fa7c4 PA |
1 | /* Copyright 2020 Purdea Andrei |
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 "quantum.h" | |
18 | ||
405cc8cf PA |
19 | #define DAC_SCLK B1 |
20 | #define DAC_DIN B2 | |
21 | #define DAC_SYNC_N B0 | |
22 | ||
23 | #define SHIFT_DIN D4 | |
24 | #define SHIFT_OE D5 | |
405cc8cf | 25 | #define SHIFT_SHCP D7 |
31b3f2de PA |
26 | #define SHIFT_STCP D6 |
27 | #define SHIFT_STCP_IO _SFR_IO_ADDR(PORTD) | |
28 | #define SHIFT_STCP_BIT 6 | |
405cc8cf PA |
29 | |
30 | #define KEYBOARD_SETTLE_TIME_US 8 | |
31 | #define DAC_SETTLE_TIME_US 8 | |
32 | ||
f3f721b9 PA |
33 | #define HARDCODED_SAMPLE_TIME 4 |
34 | ||
31b3f2de PA |
35 | #define READ_ROWS_PIN_1 _SFR_IO_ADDR(PINC) |
36 | #define READ_ROWS_PIN_2 _SFR_IO_ADDR(PIND) | |
37 | #define READ_ROWS_ASM_INSTRUCTIONS "in %[dest_row_1], %[ioreg_row_1]\n\tin %[dest_row_2], %[ioreg_row_2]" | |
f2a03868 | 38 | #define READ_ROWS_OUTPUT_CONSTRAINTS [dest_row_1] "=&r" (dest_row_1), [dest_row_2] "=&r" (dest_row_2) |
31b3f2de PA |
39 | #define READ_ROWS_INPUT_CONSTRAINTS [ioreg_row_1] "I" (READ_ROWS_PIN_1), [ioreg_row_2] "I" (READ_ROWS_PIN_2) |
40 | #define READ_ROWS_LOCAL_VARS uint8_t dest_row_1, dest_row_2 | |
41 | #define READ_ROWS_VALUE ((dest_row_1 >> 4) | (dest_row_2 << 4)) | |
42 | ||
0162369b | 43 | static inline uint8_t read_rows(void) |
405cc8cf | 44 | { |
31b3f2de PA |
45 | READ_ROWS_LOCAL_VARS; |
46 | asm volatile (READ_ROWS_ASM_INSTRUCTIONS : READ_ROWS_OUTPUT_CONSTRAINTS : READ_ROWS_INPUT_CONSTRAINTS); | |
47 | return READ_ROWS_VALUE; | |
405cc8cf PA |
48 | } |
49 | ||
50 | void dac_init(void) | |
51 | { | |
52 | setPinOutput(DAC_SCLK); | |
53 | setPinOutput(DAC_DIN); | |
54 | setPinOutput(DAC_SYNC_N); | |
55 | writePin(DAC_SYNC_N, 1); | |
56 | writePin(DAC_SCLK, 0); | |
57 | writePin(DAC_SCLK, 1); | |
58 | writePin(DAC_SCLK, 0); | |
59 | } | |
60 | ||
61 | void dac_write_threshold(uint16_t value) | |
62 | { | |
c733dd82 | 63 | value <<= 2; // The two LSB bits of this DAC are don't care. |
405cc8cf PA |
64 | writePin(DAC_SYNC_N, 0); |
65 | int i; | |
66 | for (i=0;i<16;i++) | |
67 | { | |
68 | writePin(DAC_DIN, (value >> 15) & 1); | |
69 | value <<= 1; | |
70 | writePin(DAC_SCLK, 1); | |
71 | writePin(DAC_SCLK, 0); | |
72 | } | |
73 | writePin(DAC_SYNC_N, 1); | |
74 | writePin(DAC_SCLK, 1); | |
75 | writePin(DAC_SCLK, 0); | |
76 | wait_us(DAC_SETTLE_TIME_US); | |
77 | } | |
78 | ||
79 | void shift_select_nothing(void) | |
80 | { | |
81 | writePin(SHIFT_DIN, 0); | |
82 | int i; | |
83 | for (i=0;i<16;i++) | |
84 | { | |
85 | writePin(SHIFT_SHCP, 1); | |
86 | writePin(SHIFT_SHCP, 0); | |
87 | } | |
88 | writePin(SHIFT_STCP, 1); | |
89 | writePin(SHIFT_STCP, 0); | |
90 | } | |
91 | ||
31b3f2de | 92 | void shift_select_col_no_strobe(uint8_t col) |
405cc8cf PA |
93 | { |
94 | int i; | |
95 | for (i=15; i>=0; i--) | |
96 | { | |
97 | writePin(SHIFT_DIN, !!(col == i)); | |
98 | writePin(SHIFT_SHCP, 1); | |
99 | writePin(SHIFT_SHCP, 0); | |
100 | } | |
405cc8cf PA |
101 | } |
102 | ||
31b3f2de PA |
103 | static inline void shift_select_col(uint8_t col) |
104 | { | |
105 | shift_select_col_no_strobe(col); | |
106 | writePin(SHIFT_STCP, 1); | |
107 | writePin(SHIFT_STCP, 0); | |
108 | } | |
109 | ||
405cc8cf PA |
110 | void shift_init(void) |
111 | { | |
112 | setPinOutput(SHIFT_DIN); | |
113 | setPinOutput(SHIFT_OE); | |
114 | setPinOutput(SHIFT_STCP); | |
115 | setPinOutput(SHIFT_SHCP); | |
116 | writePin(SHIFT_STCP, 0); | |
117 | writePin(SHIFT_SHCP, 0); | |
118 | shift_select_nothing(); | |
119 | wait_us(KEYBOARD_SETTLE_TIME_US); | |
120 | } | |
121 | ||
31b3f2de PA |
122 | // the following function requires storage for 2 * (time + 1) bytes |
123 | // but returns valid data only in the first (time + 1) bytes | |
124 | void test_multiple(uint8_t col, uint16_t time, uint8_t *array) | |
125 | { | |
126 | shift_select_col_no_strobe(col); | |
127 | uint16_t index; | |
128 | READ_ROWS_LOCAL_VARS; | |
129 | uint8_t *arrayp = array; | |
130 | asm volatile ( | |
131 | "ldi %A[index], 0" "\n\t" | |
132 | "ldi %B[index], 0" "\n\t" | |
133 | "cli" "\n\t" | |
134 | "sbi %[stcp_regaddr], %[stcp_bit]" "\n\t" | |
135 | "1:" READ_ROWS_ASM_INSTRUCTIONS "\n\t" | |
136 | "st %a[arr]+, %[dest_row_1]" "\n\t" | |
137 | "st %a[arr]+, %[dest_row_2]" "\n\t" | |
138 | "adiw %A[index], 0x01" "\n\t" | |
139 | "cp %A[index], %A[time]" "\n\t" | |
140 | "cpc %B[index], %B[time]" "\n\t" | |
141 | "brlo 1b" "\n\t" | |
142 | "sei" "\n\t" | |
143 | "cbi %[stcp_regaddr], %[stcp_bit]" "\n\t" | |
144 | : [arr] "=e" (arrayp), | |
145 | [index] "=&w" (index), | |
146 | READ_ROWS_OUTPUT_CONSTRAINTS | |
147 | : [time] "r" (time + 1), | |
148 | [stcp_regaddr] "I" (SHIFT_STCP_IO), | |
149 | [stcp_bit] "I" (SHIFT_STCP_BIT), | |
150 | READ_ROWS_INPUT_CONSTRAINTS, | |
151 | "0" (arrayp) | |
152 | : "memory" ); | |
153 | uint16_t i, p0, p1; | |
154 | p0 = p1 = 0; | |
155 | for (i=0; i<=time; i++) | |
156 | { | |
157 | dest_row_1 = array[p0++]; | |
158 | dest_row_2 = array[p0++]; | |
159 | array[p1++] = READ_ROWS_VALUE; | |
160 | } | |
f2a03868 PA |
161 | shift_select_nothing(); |
162 | wait_us(KEYBOARD_SETTLE_TIME_US); | |
31b3f2de PA |
163 | } |
164 | ||
165 | uint8_t test_single(uint8_t col, uint16_t time) | |
166 | { | |
167 | shift_select_col_no_strobe(col); | |
168 | uint16_t index; | |
169 | READ_ROWS_LOCAL_VARS; | |
170 | uint8_t dummy_data; | |
171 | uint8_t *arrayp = &dummy_data; | |
172 | asm volatile ( | |
173 | "ldi %A[index], 0" "\n\t" | |
174 | "ldi %B[index], 0" "\n\t" | |
175 | "cli" "\n\t" | |
176 | "sbi %[stcp_regaddr], %[stcp_bit]" "\n\t" | |
177 | "1:" READ_ROWS_ASM_INSTRUCTIONS "\n\t" | |
178 | "st %a[arr], %[dest_row_1]" "\n\t" | |
179 | "st %a[arr], %[dest_row_2]" "\n\t" | |
180 | "adiw %A[index], 0x01" "\n\t" | |
181 | "cp %A[index], %A[time]" "\n\t" | |
182 | "cpc %B[index], %B[time]" "\n\t" | |
183 | "brlo 1b" "\n\t" | |
184 | "sei" "\n\t" | |
185 | "cbi %[stcp_regaddr], %[stcp_bit]" "\n\t" | |
186 | : [arr] "=e" (arrayp), | |
187 | [index] "=&w" (index), | |
188 | READ_ROWS_OUTPUT_CONSTRAINTS | |
189 | : [time] "r" (time + 1), | |
190 | [stcp_regaddr] "I" (SHIFT_STCP_IO), | |
191 | [stcp_bit] "I" (SHIFT_STCP_BIT), | |
192 | READ_ROWS_INPUT_CONSTRAINTS, | |
193 | "0" (arrayp) | |
194 | : "memory" ); | |
f2a03868 PA |
195 | shift_select_nothing(); |
196 | wait_us(KEYBOARD_SETTLE_TIME_US); | |
31b3f2de PA |
197 | return READ_ROWS_VALUE; |
198 | } | |
405cc8cf | 199 | |
f2a03868 PA |
200 | #define NRTIMES 128 |
201 | #define TESTATONCE 8 | |
202 | #define REPS_V2 15 | |
203 | void test_col_print_data_v2(uint8_t col) | |
204 | { | |
205 | uprintf("%d: ", col); | |
206 | static uint8_t data[NRTIMES*2]; | |
207 | static uint8_t sums[(TESTATONCE+1) * 8]; | |
208 | uint8_t to_time = NRTIMES-1; | |
209 | uint8_t from_time = 0; | |
210 | while (from_time<NRTIMES-1) | |
211 | { | |
212 | if (to_time - from_time + 1 > TESTATONCE) | |
213 | { | |
214 | to_time = from_time + TESTATONCE - 1; | |
215 | } | |
216 | uint8_t curr_TESTATONCE = to_time - from_time + 1; | |
217 | uint8_t i; | |
218 | for (i=0;i<(sizeof(sums)/sizeof(sums[0]));i++) | |
219 | { | |
220 | sums[i] = 0; | |
221 | } | |
222 | for (i=0;i<REPS_V2;i++) | |
223 | { | |
224 | uint8_t st = read_rows(); | |
225 | test_multiple(col, to_time, data); | |
226 | uint8_t j; | |
227 | uint8_t ii = 0; | |
228 | uint8_t k; | |
229 | for (j=0;j<curr_TESTATONCE;j++) | |
230 | { | |
231 | uint8_t dataj = data[j + from_time]; | |
232 | for (k=0; k<8;k++) | |
233 | { | |
234 | sums[ii] += (dataj & 1); | |
235 | dataj >>= 1; | |
236 | ii += 1; | |
237 | } | |
238 | } | |
239 | if (from_time == 0) { | |
240 | ii = TESTATONCE * 8; | |
241 | for (k=0; k<8;k++) | |
242 | { | |
243 | sums[ii] += (st & 1); | |
244 | st >>= 1; | |
245 | ii += 1; | |
246 | } | |
247 | } | |
248 | } | |
249 | if (from_time == 0) { | |
250 | for (i=TESTATONCE*8;i<(TESTATONCE+1)*8;i++) { | |
251 | if (sums[i] > 0xf) { | |
252 | print("?"); | |
253 | } else { | |
254 | uprintf("%X", sums[i]); | |
255 | } | |
256 | } | |
257 | print(":"); | |
258 | } | |
259 | for (i=0;i<curr_TESTATONCE*8;i++) | |
260 | { | |
261 | if (sums[i] > 0xf) { | |
262 | print("?"); | |
263 | } else { | |
264 | uprintf("%X", sums[i]); | |
265 | } | |
266 | } | |
267 | from_time = to_time + 1; | |
268 | to_time = NRTIMES - 1; | |
269 | } | |
270 | print("\n"); | |
271 | } | |
272 | ||
f2a03868 PA |
273 | void test_v2(void) { |
274 | int i; | |
275 | for (i=7;i>0;i--) { | |
276 | uprintf("Starting test in %d\n", i); | |
277 | wait_ms(1000); | |
278 | } | |
279 | uprintf("shift_init()"); | |
280 | shift_init(); | |
281 | uprintf(" DONE\n"); | |
282 | uprintf("dac_init()"); | |
283 | dac_init(); | |
284 | uprintf(" DONE\n"); | |
285 | int d; | |
286 | for (d=90;d<=260;d++) | |
287 | { | |
288 | uprintf("Testing threshold: %d\n", d); | |
289 | dac_write_threshold(d); | |
290 | #if 1 | |
291 | int c; | |
292 | for (c=0; c<10;c++) | |
293 | { | |
294 | test_col_print_data_v2(c); | |
295 | } | |
296 | test_col_print_data_v2(15); | |
297 | #else | |
298 | test_col_print_data_v2(0); | |
299 | test_col_print_data_v2(2); | |
300 | test_col_print_data_v2(6); | |
301 | test_col_print_data_v2(7); | |
302 | test_col_print_data_v2(15); | |
303 | #endif | |
304 | } | |
305 | uprintf("TEST DONE\n"); | |
306 | while(1); | |
307 | } | |
308 | ||
1e57a998 PA |
309 | #define TRACKING_TEST_TIME 4 |
310 | // Key 1 is the always non-pressed key under the space bar to the right. | |
311 | #define TRACKING_KEY_1_COL 6 | |
312 | #define TRACKING_KEY_1_ROW 4 | |
313 | // Key 2 is the always-pressed calibration pad to the far right-bottom of the keyboard. (both on F62 and F77) | |
314 | #define TRACKING_KEY_2_COL 15 | |
315 | #define TRACKING_KEY_2_ROW 6 | |
316 | // Key 3 is the F key | |
317 | #define TRACKING_KEY_3_COL 2 | |
318 | #define TRACKING_KEY_3_ROW 5 | |
319 | // Key 4 is the half of the split backspace that is unused if the user has a normal backspace. | |
320 | #define TRACKING_KEY_4_COL 7 | |
321 | #define TRACKING_KEY_4_ROW 3 | |
322 | // Key 5 is hidden key next to the left shift, which is only used in ISO layouts. | |
323 | #define TRACKING_KEY_5_COL 0 | |
324 | #define TRACKING_KEY_5_ROW 7 | |
325 | ||
326 | #define TRACKING_REPS 16 | |
327 | ||
f3f721b9 | 328 | static uint16_t measure_middle(uint8_t col, uint8_t row, uint8_t time, uint8_t reps) |
1e57a998 | 329 | { |
f3f721b9 | 330 | uint8_t reps_div2 = reps / 2; |
1e57a998 PA |
331 | uint16_t min = 0, max = 1023; |
332 | while (min < max) | |
333 | { | |
334 | uint16_t mid = (min + max) / 2; | |
335 | dac_write_threshold(mid); | |
336 | uint8_t sum = 0; | |
337 | uint8_t i; | |
f3f721b9 | 338 | for (i=0;i<reps;i++) |
1e57a998 PA |
339 | { |
340 | sum += (test_single(col, time) >> row) & 1; | |
341 | } | |
f3f721b9 | 342 | if (sum < reps_div2) |
1e57a998 PA |
343 | { |
344 | max = mid - 1; | |
f3f721b9 | 345 | } else if (sum > reps_div2) { |
1e57a998 PA |
346 | min = mid + 1; |
347 | } else return mid; | |
348 | } | |
349 | return min; | |
350 | } | |
351 | ||
352 | void tracking_test(void) | |
353 | { | |
354 | int i; | |
355 | for (i=7;i>0;i--) { | |
356 | uprintf("Starting test in %d\n", i); | |
357 | wait_ms(1000); | |
358 | } | |
359 | uprintf("shift_init()"); | |
360 | shift_init(); | |
361 | uprintf(" DONE\n"); | |
362 | uprintf("dac_init()"); | |
363 | dac_init(); | |
364 | uprintf(" DONE\n"); | |
365 | while (1) { | |
f3f721b9 PA |
366 | uint16_t key1 = measure_middle(TRACKING_KEY_1_COL, TRACKING_KEY_1_ROW, TRACKING_TEST_TIME, TRACKING_REPS); |
367 | uint16_t key2 = measure_middle(TRACKING_KEY_2_COL, TRACKING_KEY_2_ROW, TRACKING_TEST_TIME, TRACKING_REPS); | |
368 | uint16_t key3 = measure_middle(TRACKING_KEY_3_COL, TRACKING_KEY_3_ROW, TRACKING_TEST_TIME, TRACKING_REPS); | |
369 | uint16_t key4 = measure_middle(TRACKING_KEY_4_COL, TRACKING_KEY_4_ROW, TRACKING_TEST_TIME, TRACKING_REPS); | |
370 | uint16_t key5 = measure_middle(TRACKING_KEY_5_COL, TRACKING_KEY_5_ROW, TRACKING_TEST_TIME, TRACKING_REPS); | |
1e57a998 PA |
371 | uprintf("%u, %u, %u, %u, %u\n", key1, key2, key3, key4, key5); |
372 | } | |
373 | } | |
f2a03868 | 374 | |
f3f721b9 PA |
375 | #define KEYMAP_ROW_TO_PHYSICAL_ROW(row) (7-(row)) |
376 | #define PHYSICAL_ROW_TO_KEYMAP_ROW(row) (7-(row)) | |
377 | #define KEYMAP_COL_TO_PHYSICAL_COL(col) (((col) == 10)?15:(col)) | |
378 | ||
379 | uint16_t calibration_measure_all_valid_keys(uint8_t time, uint8_t reps, bool looking_for_all_zero) | |
380 | { | |
381 | uint16_t min = 0, max = 1023; | |
382 | while (min < max) | |
383 | { | |
384 | uint16_t mid = (min + max) / 2; | |
385 | if (!looking_for_all_zero) { | |
386 | mid = (min + max + 1) / 2; | |
387 | } | |
388 | dac_write_threshold(mid); | |
389 | uint8_t col; | |
390 | for (col = 0; col < MATRIX_COLS; col++) | |
391 | { | |
392 | uint8_t valid_physical_rows = 0; | |
393 | uint8_t row; | |
394 | for (row=0; row < MATRIX_ROWS; row++) | |
395 | { | |
396 | if (pgm_read_byte(&keymaps[0][row][col]) != KC_NO) | |
397 | { | |
398 | valid_physical_rows |= (1 << KEYMAP_ROW_TO_PHYSICAL_ROW(row)); // convert keymap row to physical row | |
399 | } | |
400 | } | |
401 | uint8_t physical_col = KEYMAP_COL_TO_PHYSICAL_COL(col); | |
402 | uint8_t i; | |
403 | for (i=0;i<reps;i++) { | |
404 | if (looking_for_all_zero) | |
405 | { | |
406 | uint8_t all_zero = (test_single(physical_col, time) & valid_physical_rows) == 0; | |
407 | if (!all_zero) { | |
408 | min = mid + 1; | |
409 | goto next_binary_search; | |
410 | } | |
411 | } else { | |
412 | uint8_t all_ones = (test_single(physical_col, time) & valid_physical_rows) == valid_physical_rows; | |
413 | if (!all_ones) { | |
414 | max = mid - 1; | |
415 | goto next_binary_search; | |
416 | } | |
417 | } | |
418 | } | |
419 | } | |
420 | if (looking_for_all_zero) { | |
421 | max = mid; | |
422 | } else { | |
423 | min = mid; | |
424 | } | |
425 | next_binary_search:; | |
426 | } | |
427 | return min; | |
428 | } | |
429 | ||
430 | #define CAL_ENABLED | |
431 | #define CAL_DEBUG | |
432 | #define CAL_INIT_REPS 16 | |
433 | #define CAL_EACHKEY_REPS 16 | |
434 | #define CAL_BINS 3 | |
435 | #define CAL_THRESHOLD_OFFSET 12 | |
436 | ||
c737e37a PA |
437 | #if defined(CAL_ENABLED) |
438 | #if defined(BOOTMAGIC_ENABLE) || defined(BOOTMAGIC_LITE) | |
439 | #error "Calibration is not supported in conjunction with BOOTMAGIC, because calibration requires that no keys are pressed while the keyboard is plugged in" | |
440 | #endif | |
441 | #endif | |
442 | ||
f3f721b9 PA |
443 | uint16_t cal_thresholds[CAL_BINS]; |
444 | matrix_row_t assigned_to_threshold[CAL_BINS][MATRIX_ROWS]; | |
445 | uint16_t cal_tr_allzero; | |
446 | uint16_t cal_tr_allone; | |
f3f721b9 PA |
447 | void calibration(void) |
448 | { | |
3f49a80b PA |
449 | uint16_t cal_thresholds_max[CAL_BINS]={0xFFFFU,0xFFFFU,0xFFFFU}; |
450 | uint16_t cal_thresholds_min[CAL_BINS]={0xFFFFU,0xFFFFU,0xFFFFU}; | |
f3f721b9 PA |
451 | cal_tr_allzero = calibration_measure_all_valid_keys(HARDCODED_SAMPLE_TIME, CAL_INIT_REPS, true); |
452 | cal_tr_allone = calibration_measure_all_valid_keys(HARDCODED_SAMPLE_TIME, CAL_INIT_REPS, false); | |
453 | uint16_t max = (cal_tr_allzero == 0) ? 0 : (cal_tr_allzero - 1); | |
454 | uint16_t min = cal_tr_allone + 1; | |
455 | if (max < min) max = min; | |
456 | uint16_t d = max - min; | |
457 | uint8_t i; | |
458 | for (i=0;i<CAL_BINS;i++) { | |
459 | cal_thresholds[i] = min + (d * (2 * i + 1)) / 2 / CAL_BINS; | |
460 | } | |
461 | uint8_t col; | |
462 | for (col = 0; col < MATRIX_COLS; col++) { | |
463 | uint8_t physical_col = KEYMAP_COL_TO_PHYSICAL_COL(col); | |
464 | uint8_t row; | |
465 | for (row = 0; row < MATRIX_ROWS; row++) { | |
466 | if (pgm_read_byte(&keymaps[0][row][col]) != KC_NO) { | |
467 | uint16_t threshold = measure_middle(physical_col, KEYMAP_ROW_TO_PHYSICAL_ROW(row), HARDCODED_SAMPLE_TIME, CAL_EACHKEY_REPS); | |
468 | uint8_t besti = 0; | |
469 | uint16_t best_diff = (uint16_t)abs(threshold - cal_thresholds[besti]); | |
470 | for (i=1;i<CAL_BINS;i++) { | |
471 | uint16_t this_diff = (uint16_t)abs(threshold - cal_thresholds[i]); | |
472 | if (this_diff < best_diff) | |
473 | { | |
474 | best_diff = this_diff; | |
475 | besti = i; | |
476 | } | |
477 | } | |
478 | assigned_to_threshold[besti][row] |= (1 << col); | |
3f49a80b PA |
479 | if ((cal_thresholds_max[besti] = 0xFFFFU) || (cal_thresholds_max[besti] < threshold)) cal_thresholds_max[besti] = threshold; |
480 | if ((cal_thresholds_min[besti] = 0xFFFFU) || (cal_thresholds_min[besti] > threshold)) cal_thresholds_min[besti] = threshold; | |
f3f721b9 PA |
481 | } |
482 | } | |
483 | } | |
484 | for (i=0;i<CAL_BINS;i++) { | |
3f49a80b PA |
485 | if ((cal_thresholds_max[i] == 0xFFFFU) || (cal_thresholds_min[i] == 0xFFFFU)) { |
486 | cal_thresholds[i] += CAL_THRESHOLD_OFFSET; | |
487 | } else { | |
488 | cal_thresholds[i] = (cal_thresholds_max[i] + cal_thresholds_min[i]) / 2 + CAL_THRESHOLD_OFFSET; | |
489 | } | |
f3f721b9 PA |
490 | } |
491 | } | |
492 | ||
09c2b24e PA |
493 | void real_keyboard_init_basic(void) |
494 | { | |
495 | uprintf("shift_init()"); | |
496 | shift_init(); | |
497 | uprintf(" DONE\n"); | |
498 | uprintf("dac_init()"); | |
499 | dac_init(); | |
500 | uprintf(" DONE\n"); | |
f3f721b9 PA |
501 | #if defined(CAL_ENABLED) |
502 | calibration(); | |
503 | #else | |
c733dd82 | 504 | dac_write_threshold(142); |
9d9305db PA |
505 | dac_write_threshold(142); |
506 | dac_write_threshold(142); | |
f3f721b9 | 507 | #endif |
09c2b24e PA |
508 | } |
509 | ||
06b963f3 | 510 | void matrix_init_custom(void) { |
9d9305db | 511 | //test_v2(); |
1e57a998 | 512 | //tracking_test(); |
09c2b24e | 513 | real_keyboard_init_basic(); |
06b963f3 PA |
514 | } |
515 | ||
f3f721b9 PA |
516 | matrix_row_t previous_matrix[MATRIX_ROWS]; |
517 | #if defined(CAL_ENABLED) && defined(CAL_DEBUG) | |
518 | bool cal_stats_printed = false; | |
519 | #endif | |
dabf024c | 520 | |
332fa7c4 | 521 | bool matrix_scan_custom(matrix_row_t current_matrix[]) { |
f3f721b9 PA |
522 | uint8_t col, row, cal; |
523 | #if defined(CAL_ENABLED) && defined(CAL_DEBUG) | |
524 | if (!cal_stats_printed) | |
525 | { | |
526 | uint32_t time = timer_read32(); | |
527 | if (time >= 10 * 1000UL) { // after 10 seconds | |
528 | uprintf("Cal All Zero = %u, Cal All Ones = %u\n", cal_tr_allzero, cal_tr_allone); | |
529 | for (cal=0;cal<CAL_BINS;cal++) | |
530 | { | |
531 | uprintf("Cal bin %u, Threshold=%u Assignments:\n", cal, cal_thresholds[cal]); | |
532 | for (row=0;row<MATRIX_ROWS;row++) | |
533 | { | |
534 | uprintf("0x%02X\n", assigned_to_threshold[cal][row]); | |
535 | } | |
536 | } | |
537 | cal_stats_printed = true; | |
538 | } | |
539 | } | |
540 | #endif | |
09c2b24e PA |
541 | for (row=0;row<8;row++) |
542 | { | |
543 | current_matrix[row] = 0; | |
544 | } | |
f3f721b9 PA |
545 | #if defined(CAL_ENABLED) |
546 | for (cal=0;cal<CAL_BINS;cal++) { | |
547 | dac_write_threshold(cal_thresholds[cal]); | |
548 | for (col=0;col<MATRIX_COLS;col++) { | |
549 | uint8_t real_col = KEYMAP_COL_TO_PHYSICAL_COL(col); | |
550 | uint8_t d; | |
551 | uint8_t d_tested = 0; | |
552 | for (row=0;row<MATRIX_ROWS;row++) { | |
553 | if (assigned_to_threshold[cal][row] & (1 << col)) | |
554 | { | |
555 | if (!d_tested) | |
556 | { | |
557 | d = test_single(real_col, HARDCODED_SAMPLE_TIME); | |
558 | d_tested = 1; | |
559 | } | |
560 | uint8_t physical_row = KEYMAP_ROW_TO_PHYSICAL_ROW(row); | |
561 | current_matrix[row] |= ((d >> physical_row) & 1) << col; | |
562 | } | |
563 | } | |
564 | } | |
565 | } | |
566 | #else | |
567 | for (col=0;col<MATRIX_COLS;col++) | |
09c2b24e | 568 | { |
f3f721b9 PA |
569 | uint8_t real_col = KEYMAP_COL_TO_PHYSICAL_COL(col); |
570 | uint8_t d = test_single(real_col, HARDCODED_SAMPLE_TIME); | |
571 | for (row=0;row<MATRIX_ROWS;row++) | |
09c2b24e | 572 | { |
f3f721b9 | 573 | current_matrix[PHYSICAL_ROW_TO_KEYMAP_ROW(row)] |= (((uint16_t)(d & 1)) << col); |
09c2b24e PA |
574 | d >>= 1; |
575 | } | |
576 | } | |
f3f721b9 PA |
577 | #endif |
578 | bool changed = false; | |
579 | for (row=0;row<MATRIX_ROWS;row++) | |
580 | { | |
581 | if (previous_matrix[row] != current_matrix[row]) changed = true; | |
582 | previous_matrix[row] = current_matrix[row]; | |
583 | } | |
dabf024c | 584 | return changed; |
332fa7c4 | 585 | } |