1 /* Copyright 2020 Purdea Andrei
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.
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.
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/>.
19 #if defined(CONTROLLER_IS_XWHATSIT_BEAMSPRING_REV_4)
20 #define CAPSENSE_DAC_SCLK B1
21 #define CAPSENSE_DAC_DIN B2
22 #define CAPSENSE_DAC_SYNC_N B0
24 #define CAPSENSE_SHIFT_DIN C4
25 #define CAPSENSE_SHIFT_OE C6
26 #define CAPSENSE_SHIFT_SHCP C5
27 #define CAPSENSE_SHIFT_STCP C7
28 #define CAPSENSE_SHIFT_STCP_IO _SFR_IO_ADDR(PORTC)
29 #define CAPSENSE_SHIFT_STCP_BIT 7
31 #define CAPSENSE_READ_ROWS_PIN_1 _SFR_IO_ADDR(PIND)
32 #define CAPSENSE_READ_ROWS_PIN_2 _SFR_IO_ADDR(PIND)
33 #define CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "in %[dest_row_1], %[ioreg_row_1]\n\tin %[dest_row_2], %[ioreg_row_2]"
34 #define CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS [dest_row_1] "=&r" (dest_row_1), [dest_row_2] "=&r" (dest_row_2)
35 #define CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS [ioreg_row_1] "I" (CAPSENSE_READ_ROWS_PIN_1), [ioreg_row_2] "I" (CAPSENSE_READ_ROWS_PIN_2)
36 #define CAPSENSE_READ_ROWS_LOCAL_VARS uint8_t dest_row_1, dest_row_2
37 #define CAPSENSE_READ_ROWS_VALUE (dest_row_1 & 0xf)
38 // Note: for now Beamspring reads PIND twice to match model F timings. We might change that in the future
40 #define CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row) (row)
41 #define CAPSENSE_PHYSICAL_ROW_TO_KEYMAP_ROW(row) (row)
42 #ifndef CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL
43 #define CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col) (col)
45 #define CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
46 #elif defined(CONTROLLER_IS_XWHATSIT_MODEL_F_OR_WCASS_MODEL_F)
47 #define CAPSENSE_DAC_SCLK B1
48 #define CAPSENSE_DAC_DIN B2
49 #define CAPSENSE_DAC_SYNC_N B0
51 #define CAPSENSE_SHIFT_DIN D4
52 #define CAPSENSE_SHIFT_OE D5
53 #define CAPSENSE_SHIFT_SHCP D7
54 #define CAPSENSE_SHIFT_STCP D6
55 #define CAPSENSE_SHIFT_STCP_IO _SFR_IO_ADDR(PORTD)
56 #define CAPSENSE_SHIFT_STCP_BIT 6
58 #define CAPSENSE_READ_ROWS_PIN_1 _SFR_IO_ADDR(PINC)
59 #define CAPSENSE_READ_ROWS_PIN_2 _SFR_IO_ADDR(PIND)
60 #define CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "in %[dest_row_1], %[ioreg_row_1]\n\tin %[dest_row_2], %[ioreg_row_2]"
61 #define CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS [dest_row_1] "=&r" (dest_row_1), [dest_row_2] "=&r" (dest_row_2)
62 #define CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS [ioreg_row_1] "I" (CAPSENSE_READ_ROWS_PIN_1), [ioreg_row_2] "I" (CAPSENSE_READ_ROWS_PIN_2)
63 #define CAPSENSE_READ_ROWS_LOCAL_VARS uint8_t dest_row_1, dest_row_2
64 #define CAPSENSE_READ_ROWS_VALUE ((dest_row_1 >> 4) | (dest_row_2 << 4))
66 #define CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row) (7-(row))
67 #define CAPSENSE_PHYSICAL_ROW_TO_KEYMAP_ROW(row) (7-(row))
68 #ifndef CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL
69 #define CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col) (col)
71 #define CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS
73 #ifndef CAPSENSE_DAC_SCLK
74 #error "Please select controller type in config.h, or please define each macro that is defined when selecting a particular macro type in matrix.c"
78 #ifndef CAPSENSE_KEYBOARD_SETTLE_TIME_US
79 #error "Please define CAPSENSE_KEYBOARD_SETTLE_TIME_US in config.h"
81 #ifndef CAPSENSE_DAC_SETTLE_TIME_US
82 #error "Please define CAPSENSE_DAC_SETTLE_TIME_US in config.h"
84 #ifndef CAPSENSE_HARDCODED_SAMPLE_TIME
85 #error "Please define CAPSENSE_HARDCODED_SAMPLE_TIME in config.h"
88 #ifndef CAPSENSE_CAL_ENABLED
89 #error "Please define CAPSENSE_CAL_ENABLED as 1/0 in config.h"
91 #ifndef CAPSENSE_CAL_DEBUG
92 #error "Please define CAPSENSE_CAL_DEBUG as 1/0 in config.h"
94 #ifndef CAPSENSE_CAL_INIT_REPS
95 #define CAPSENSE_CAL_INIT_REPS 16
97 #ifndef CAPSENSE_CAL_EACHKEY_REPS
98 #define CAPSENSE_CAL_EACHKEY_REPS 16
100 #ifndef CAPSENSE_CAL_BINS
101 #error "Please define CAPSENSE_CAL_BINS in config.h"
103 #ifndef CAPSENSE_CAL_THRESHOLD_OFFSET
104 #error "Please define CAPSENSE_CAL_THRESHOLD_OFFSET in config.h"
107 #if (!defined(CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS)) && (!defined(CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS))
108 #error "Please specify whether the flyplate is pushed down or pulled up on keypress!"
111 static inline uint8_t read_rows(void)
113 CAPSENSE_READ_ROWS_LOCAL_VARS
;
114 asm volatile (CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS
: CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS
: CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS
);
115 return CAPSENSE_READ_ROWS_VALUE
;
120 setPinOutput(CAPSENSE_DAC_SCLK
);
121 setPinOutput(CAPSENSE_DAC_DIN
);
122 setPinOutput(CAPSENSE_DAC_SYNC_N
);
123 writePin(CAPSENSE_DAC_SYNC_N
, 1);
124 writePin(CAPSENSE_DAC_SCLK
, 0);
125 writePin(CAPSENSE_DAC_SCLK
, 1);
126 writePin(CAPSENSE_DAC_SCLK
, 0);
129 void dac_write_threshold(uint16_t value
)
131 value
<<= 2; // The two LSB bits of this DAC are don't care.
132 writePin(CAPSENSE_DAC_SYNC_N
, 0);
136 writePin(CAPSENSE_DAC_DIN
, (value
>> 15) & 1);
138 writePin(CAPSENSE_DAC_SCLK
, 1);
139 writePin(CAPSENSE_DAC_SCLK
, 0);
141 writePin(CAPSENSE_DAC_SYNC_N
, 1);
142 writePin(CAPSENSE_DAC_SCLK
, 1);
143 writePin(CAPSENSE_DAC_SCLK
, 0);
144 wait_us(CAPSENSE_DAC_SETTLE_TIME_US
);
147 #define SHIFT_BITS ((MATRIX_COLS > 16) ? 24 : 16)
149 void shift_select_nothing(void)
151 writePin(CAPSENSE_SHIFT_DIN
, 0);
153 for (i
=0;i
<SHIFT_BITS
;i
++)
155 writePin(CAPSENSE_SHIFT_SHCP
, 1);
156 writePin(CAPSENSE_SHIFT_SHCP
, 0);
158 writePin(CAPSENSE_SHIFT_STCP
, 1);
159 writePin(CAPSENSE_SHIFT_STCP
, 0);
162 void shift_select_col_no_strobe(uint8_t col
)
165 for (i
=SHIFT_BITS
-1; i
>=0; i
--)
167 writePin(CAPSENSE_SHIFT_DIN
, !!(col
== i
));
168 writePin(CAPSENSE_SHIFT_SHCP
, 1);
169 writePin(CAPSENSE_SHIFT_SHCP
, 0);
173 static inline void shift_select_col(uint8_t col
)
175 shift_select_col_no_strobe(col
);
176 writePin(CAPSENSE_SHIFT_STCP
, 1);
177 writePin(CAPSENSE_SHIFT_STCP
, 0);
180 void shift_init(void)
182 setPinOutput(CAPSENSE_SHIFT_DIN
);
183 setPinOutput(CAPSENSE_SHIFT_OE
);
184 setPinOutput(CAPSENSE_SHIFT_STCP
);
185 setPinOutput(CAPSENSE_SHIFT_SHCP
);
186 writePin(CAPSENSE_SHIFT_STCP
, 0);
187 writePin(CAPSENSE_SHIFT_SHCP
, 0);
188 shift_select_nothing();
189 wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US
);
192 // the following function requires storage for 2 * (time + 1) bytes
193 // but returns valid data only in the first (time + 1) bytes
194 void test_multiple(uint8_t col
, uint16_t time
, uint8_t *array
)
196 shift_select_col_no_strobe(col
);
198 CAPSENSE_READ_ROWS_LOCAL_VARS
;
199 uint8_t *arrayp
= array
;
201 "ldi %A[index], 0" "\n\t"
202 "ldi %B[index], 0" "\n\t"
204 "sbi %[stcp_regaddr], %[stcp_bit]" "\n\t"
205 "1:" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS
"\n\t"
206 "st %a[arr]+, %[dest_row_1]" "\n\t"
207 "st %a[arr]+, %[dest_row_2]" "\n\t"
208 "adiw %A[index], 0x01" "\n\t"
209 "cp %A[index], %A[time]" "\n\t"
210 "cpc %B[index], %B[time]" "\n\t"
213 "cbi %[stcp_regaddr], %[stcp_bit]" "\n\t"
214 : [arr
] "=e" (arrayp
),
215 [index
] "=&w" (index
),
216 CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS
217 : [time
] "r" (time
+ 1),
218 [stcp_regaddr
] "I" (CAPSENSE_SHIFT_STCP_IO
),
219 [stcp_bit
] "I" (CAPSENSE_SHIFT_STCP_BIT
),
220 CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS
,
225 for (i
=0; i
<=time
; i
++)
227 dest_row_1
= array
[p0
++];
228 dest_row_2
= array
[p0
++];
229 array
[p1
++] = CAPSENSE_READ_ROWS_VALUE
;
231 shift_select_nothing();
232 wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US
);
235 uint8_t test_single(uint8_t col
, uint16_t time
)
237 shift_select_col_no_strobe(col
);
239 CAPSENSE_READ_ROWS_LOCAL_VARS
;
241 uint8_t *arrayp
= &dummy_data
;
243 "ldi %A[index], 0" "\n\t"
244 "ldi %B[index], 0" "\n\t"
246 "sbi %[stcp_regaddr], %[stcp_bit]" "\n\t"
247 "1:" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS
"\n\t"
248 "st %a[arr], %[dest_row_1]" "\n\t"
249 "st %a[arr], %[dest_row_2]" "\n\t"
250 "adiw %A[index], 0x01" "\n\t"
251 "cp %A[index], %A[time]" "\n\t"
252 "cpc %B[index], %B[time]" "\n\t"
255 "cbi %[stcp_regaddr], %[stcp_bit]" "\n\t"
256 : [arr
] "=e" (arrayp
),
257 [index
] "=&w" (index
),
258 CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS
259 : [time
] "r" (time
+ 1),
260 [stcp_regaddr
] "I" (CAPSENSE_SHIFT_STCP_IO
),
261 [stcp_bit
] "I" (CAPSENSE_SHIFT_STCP_BIT
),
262 CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS
,
265 shift_select_nothing();
266 wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US
);
267 return CAPSENSE_READ_ROWS_VALUE
;
273 void test_col_print_data_v2(uint8_t col
)
275 uprintf("%d: ", col
);
276 static uint8_t data
[NRTIMES
*2];
277 static uint8_t sums
[(TESTATONCE
+1) * MATRIX_ROWS
];
278 uint8_t to_time
= NRTIMES
-1;
279 uint8_t from_time
= 0;
280 while (from_time
<NRTIMES
-1)
282 if (to_time
- from_time
+ 1 > TESTATONCE
)
284 to_time
= from_time
+ TESTATONCE
- 1;
286 uint8_t curr_TESTATONCE
= to_time
- from_time
+ 1;
288 for (i
=0;i
<(sizeof(sums
)/sizeof(sums
[0]));i
++)
292 for (i
=0;i
<REPS_V2
;i
++)
294 uint8_t st
= read_rows();
295 test_multiple(col
, to_time
, data
);
299 for (j
=0;j
<curr_TESTATONCE
;j
++)
301 uint8_t dataj
= data
[j
+ from_time
];
302 for (k
=0; k
<MATRIX_ROWS
;k
++)
304 sums
[ii
] += (dataj
& 1);
309 if (from_time
== 0) {
310 ii
= TESTATONCE
* MATRIX_ROWS
;
311 for (k
=0; k
<MATRIX_ROWS
;k
++)
313 sums
[ii
] += (st
& 1);
319 if (from_time
== 0) {
320 for (i
=TESTATONCE
*MATRIX_ROWS
;i
<(TESTATONCE
+1)*MATRIX_ROWS
;i
++) {
324 uprintf("%X", sums
[i
]);
329 for (i
=0;i
<curr_TESTATONCE
*MATRIX_ROWS
;i
++)
334 uprintf("%X", sums
[i
]);
337 from_time
= to_time
+ 1;
338 to_time
= NRTIMES
- 1;
346 uprintf("Starting test in %d\n", i
);
349 uprintf("shift_init()");
352 uprintf("dac_init()");
356 for (d
=90;d
<=260;d
++)
358 uprintf("Testing threshold: %d\n", d
);
359 dac_write_threshold(d
);
362 for (c
=0; c
<MATRIX_COLS
;c
++)
364 test_col_print_data_v2(CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(c
));
367 test_col_print_data_v2(0);
368 test_col_print_data_v2(2);
369 test_col_print_data_v2(6);
370 test_col_print_data_v2(7);
371 test_col_print_data_v2(15);
374 uprintf("TEST DONE\n");
378 #define TRACKING_TEST_TIME 4
379 // Key 1 is the always non-pressed key under the space bar to the right.
380 #define TRACKING_KEY_1_COL 6
381 #define TRACKING_KEY_1_ROW 4
382 // Key 2 is the always-pressed calibration pad to the far right-bottom of the keyboard. (both on F62 and F77)
383 #define TRACKING_KEY_2_COL 15
384 #define TRACKING_KEY_2_ROW 6
385 // Key 3 is the F key
386 #define TRACKING_KEY_3_COL 2
387 #define TRACKING_KEY_3_ROW 5
388 // Key 4 is the half of the split backspace that is unused if the user has a normal backspace.
389 #define TRACKING_KEY_4_COL 7
390 #define TRACKING_KEY_4_ROW 3
391 // Key 5 is hidden key next to the left shift, which is only used in ISO layouts.
392 #define TRACKING_KEY_5_COL 0
393 #define TRACKING_KEY_5_ROW 7
395 #define TRACKING_REPS 16
397 static uint16_t measure_middle(uint8_t col
, uint8_t row
, uint8_t time
, uint8_t reps
)
399 uint8_t reps_div2
= reps
/ 2;
400 uint16_t min
= 0, max
= 1023;
403 uint16_t mid
= (min
+ max
) / 2;
404 dac_write_threshold(mid
);
409 sum
+= (test_single(col
, time
) >> row
) & 1;
414 } else if (sum
> reps_div2
) {
421 void tracking_test(void)
425 uprintf("Starting test in %d\n", i
);
428 uprintf("shift_init()");
431 uprintf("dac_init()");
435 uint32_t tt
= timer_read32();
436 uint16_t key1
= measure_middle(TRACKING_KEY_1_COL
, TRACKING_KEY_1_ROW
, TRACKING_TEST_TIME
, TRACKING_REPS
);
437 uint16_t key2
= measure_middle(TRACKING_KEY_2_COL
, TRACKING_KEY_2_ROW
, TRACKING_TEST_TIME
, TRACKING_REPS
);
438 uint16_t key3
= measure_middle(TRACKING_KEY_3_COL
, TRACKING_KEY_3_ROW
, TRACKING_TEST_TIME
, TRACKING_REPS
);
439 uint16_t key4
= measure_middle(TRACKING_KEY_4_COL
, TRACKING_KEY_4_ROW
, TRACKING_TEST_TIME
, TRACKING_REPS
);
440 uint16_t key5
= measure_middle(TRACKING_KEY_5_COL
, TRACKING_KEY_5_ROW
, TRACKING_TEST_TIME
, TRACKING_REPS
);
441 uprintf("%5lu.%03u, %u, %u, %u, %u, %u\n", tt
/1000, (uint16_t)(tt
%1000), key1
, key2
, key3
, key4
, key5
);
445 uint16_t calibration_measure_all_valid_keys(uint8_t time
, uint8_t reps
, bool looking_for_all_zero
)
447 uint16_t min
= 0, max
= 1023;
450 uint16_t mid
= (min
+ max
) / 2;
451 if (!looking_for_all_zero
) {
452 mid
= (min
+ max
+ 1) / 2;
454 dac_write_threshold(mid
);
456 for (col
= 0; col
< MATRIX_COLS
; col
++)
458 uint8_t valid_physical_rows
= 0;
460 for (row
=0; row
< MATRIX_ROWS
; row
++)
462 if (pgm_read_byte(&keymaps
[0][row
][col
]) != KC_NO
)
464 valid_physical_rows
|= (1 << CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row
)); // convert keymap row to physical row
467 uint8_t physical_col
= CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col
);
469 for (i
=0;i
<reps
;i
++) {
470 if (looking_for_all_zero
)
472 uint8_t all_zero
= (test_single(physical_col
, time
) & valid_physical_rows
) == 0;
475 goto next_binary_search
;
478 uint8_t all_ones
= (test_single(physical_col
, time
) & valid_physical_rows
) == valid_physical_rows
;
481 goto next_binary_search
;
486 if (looking_for_all_zero
) {
496 #if CAPSENSE_CAL_ENABLED
497 #if defined(BOOTMAGIC_ENABLE) || defined(BOOTMAGIC_LITE)
498 #error "Calibration is not supported in conjunction with BOOTMAGIC, because calibration requires that no keys are pressed while the keyboard is plugged in"
502 uint16_t cal_thresholds
[CAPSENSE_CAL_BINS
];
503 matrix_row_t assigned_to_threshold
[CAPSENSE_CAL_BINS
][MATRIX_ROWS
];
504 uint16_t cal_tr_allzero
;
505 uint16_t cal_tr_allone
;
506 void calibration(void)
508 uint16_t cal_thresholds_max
[CAPSENSE_CAL_BINS
]={0xFFFFU
,0xFFFFU
,0xFFFFU
};
509 uint16_t cal_thresholds_min
[CAPSENSE_CAL_BINS
]={0xFFFFU
,0xFFFFU
,0xFFFFU
};
510 cal_tr_allzero
= calibration_measure_all_valid_keys(CAPSENSE_HARDCODED_SAMPLE_TIME
, CAPSENSE_CAL_INIT_REPS
, true);
511 cal_tr_allone
= calibration_measure_all_valid_keys(CAPSENSE_HARDCODED_SAMPLE_TIME
, CAPSENSE_CAL_INIT_REPS
, false);
512 uint16_t max
= (cal_tr_allzero
== 0) ? 0 : (cal_tr_allzero
- 1);
513 uint16_t min
= cal_tr_allone
+ 1;
514 if (max
< min
) max
= min
;
515 uint16_t d
= max
- min
;
517 for (i
=0;i
<CAPSENSE_CAL_BINS
;i
++) {
518 cal_thresholds
[i
] = min
+ (d
* (2 * i
+ 1)) / 2 / CAPSENSE_CAL_BINS
;
521 for (col
= 0; col
< MATRIX_COLS
; col
++) {
522 uint8_t physical_col
= CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col
);
524 for (row
= 0; row
< MATRIX_ROWS
; row
++) {
525 if (pgm_read_byte(&keymaps
[0][row
][col
]) != KC_NO
) {
526 uint16_t threshold
= measure_middle(physical_col
, CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row
), CAPSENSE_HARDCODED_SAMPLE_TIME
, CAPSENSE_CAL_EACHKEY_REPS
);
528 uint16_t best_diff
= (uint16_t)abs(threshold
- cal_thresholds
[besti
]);
529 for (i
=1;i
<CAPSENSE_CAL_BINS
;i
++) {
530 uint16_t this_diff
= (uint16_t)abs(threshold
- cal_thresholds
[i
]);
531 if (this_diff
< best_diff
)
533 best_diff
= this_diff
;
537 assigned_to_threshold
[besti
][row
] |= (1 << col
);
538 if ((cal_thresholds_max
[besti
] = 0xFFFFU
) || (cal_thresholds_max
[besti
] < threshold
)) cal_thresholds_max
[besti
] = threshold
;
539 if ((cal_thresholds_min
[besti
] = 0xFFFFU
) || (cal_thresholds_min
[besti
] > threshold
)) cal_thresholds_min
[besti
] = threshold
;
543 for (i
=0;i
<CAPSENSE_CAL_BINS
;i
++) {
544 if ((cal_thresholds_max
[i
] == 0xFFFFU
) || (cal_thresholds_min
[i
] == 0xFFFFU
)) {
545 #ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS
546 cal_thresholds
[i
] += CAPSENSE_CAL_THRESHOLD_OFFSET
;
548 cal_thresholds
[i
] -= CAPSENSE_CAL_THRESHOLD_OFFSET
;
551 #ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS
552 cal_thresholds
[i
] = (cal_thresholds_max
[i
] + cal_thresholds_min
[i
]) / 2 + CAPSENSE_CAL_THRESHOLD_OFFSET
;
554 cal_thresholds
[i
] = (cal_thresholds_max
[i
] + cal_thresholds_min
[i
]) / 2 - CAPSENSE_CAL_THRESHOLD_OFFSET
;
560 void real_keyboard_init_basic(void)
562 uprintf("shift_init()");
565 uprintf("dac_init()");
568 #if CAPSENSE_CAL_ENABLED
571 dac_write_threshold(142);
572 dac_write_threshold(142);
573 dac_write_threshold(142);
577 void matrix_init_custom(void) {
580 real_keyboard_init_basic();
583 matrix_row_t previous_matrix
[MATRIX_ROWS
];
584 #if CAPSENSE_CAL_ENABLED && CAPSENSE_CAL_DEBUG
585 bool cal_stats_printed
= false;
588 bool matrix_scan_custom(matrix_row_t current_matrix
[]) {
589 uint8_t col
, row
, cal
;
590 #if CAPSENSE_CAL_ENABLED && CAPSENSE_CAL_DEBUG
591 if (!cal_stats_printed
)
593 uint32_t time
= timer_read32();
594 if (time
>= 10 * 1000UL) { // after 10 seconds
595 uprintf("Cal All Zero = %u, Cal All Ones = %u\n", cal_tr_allzero
, cal_tr_allone
);
596 for (cal
=0;cal
<CAPSENSE_CAL_BINS
;cal
++)
598 uprintf("Cal bin %u, Threshold=%u Assignments:\n", cal
, cal_thresholds
[cal
]);
599 for (row
=0;row
<MATRIX_ROWS
;row
++)
601 uprintf("0x%02X\n", assigned_to_threshold
[cal
][row
]);
604 cal_stats_printed
= true;
608 for (row
=0;row
<MATRIX_ROWS
;row
++)
610 current_matrix
[row
] = 0;
612 #if CAPSENSE_CAL_ENABLED
613 for (cal
=0;cal
<CAPSENSE_CAL_BINS
;cal
++) {
614 dac_write_threshold(cal_thresholds
[cal
]);
615 for (col
=0;col
<MATRIX_COLS
;col
++) {
616 uint8_t real_col
= CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col
);
618 uint8_t d_tested
= 0;
619 for (row
=0;row
<MATRIX_ROWS
;row
++) {
620 if (assigned_to_threshold
[cal
][row
] & (1 << col
))
624 d
= test_single(real_col
, CAPSENSE_HARDCODED_SAMPLE_TIME
);
625 #ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
630 uint8_t physical_row
= CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row
);
631 current_matrix
[row
] |= ((d
>> physical_row
) & 1) << col
;
637 for (col
=0;col
<MATRIX_COLS
;col
++)
639 uint8_t real_col
= CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col
);
640 uint8_t d
= test_single(real_col
, CAPSENSE_HARDCODED_SAMPLE_TIME
);
641 #ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
644 for (row
=0;row
<MATRIX_ROWS
;row
++)
646 current_matrix
[CAPSENSE_PHYSICAL_ROW_TO_KEYMAP_ROW(row
)] |= (((uint16_t)(d
& 1)) << col
);
651 bool changed
= false;
652 for (row
=0;row
<MATRIX_ROWS
;row
++)
654 if (previous_matrix
[row
] != current_matrix
[row
]) changed
= true;
655 previous_matrix
[row
] = current_matrix
[row
];