2 * Copyright © 2017 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
16 #include <ao_matrix.h>
20 #define row_port(q) AO_MATRIX_ROW_ ## q ## _PORT
21 #define row_bit(q) AO_MATRIX_ROW_ ## q ## _PIN
22 #define row_pin(q) AO_MATRIX_ROW_ ## q ## _PIN
24 #define col_port(q) AO_MATRIX_COL_ ## q ## _PORT
25 #define col_bit(q) AO_MATRIX_COL_ ## q ## _PIN
26 #define col_pin(q) AO_MATRIX_COL_ ## q ## _PIN
29 _ao_matrix_drive_row(uint8_t row, uint8_t val)
32 #define drive(n) case n: ao_gpio_set(row_port(n), row_bit(n), row_pin(n), val); break
34 #if AO_MATRIX_ROWS > 1
37 #if AO_MATRIX_ROWS > 2
40 #if AO_MATRIX_ROWS > 3
43 #if AO_MATRIX_ROWS > 4
46 #if AO_MATRIX_ROWS > 5
49 #if AO_MATRIX_ROWS > 6
52 #if AO_MATRIX_ROWS > 7
59 _ao_matrix_read_cols(void)
62 #define read(n) (v |= ao_gpio_get(col_port(n), col_bit(n), col_pin(n)) << n)
65 #if AO_MATRIX_ROWS > 1
68 #if AO_MATRIX_ROWS > 2
71 #if AO_MATRIX_ROWS > 3
74 #if AO_MATRIX_ROWS > 4
77 #if AO_MATRIX_ROWS > 5
80 #if AO_MATRIX_ROWS > 6
83 #if AO_MATRIX_ROWS > 7
90 _ao_matrix_read(uint8_t row) {
92 _ao_matrix_drive_row(row, 0);
93 state = _ao_matrix_read_cols();
94 _ao_matrix_drive_row(row, 1);
98 #define AO_MATRIX_DEBOUNCE_INTERVAL AO_MS_TO_TICKS(50)
100 static uint8_t ao_matrix_keymap[AO_MATRIX_ROWS][AO_MATRIX_COLS] = AO_MATRIX_KEYCODES;
102 static uint8_t ao_matrix_state[AO_MATRIX_ROWS];
103 static AO_TICK_TYPE ao_matrix_tick[AO_MATRIX_ROWS];
106 _ao_matrix_poll_one(uint8_t row) {
107 uint8_t state = _ao_matrix_read(row);
109 if (state != ao_matrix_state[row]) {
110 AO_TICK_TYPE now = ao_time();
112 if ((now - ao_matrix_tick[row]) >= AO_MATRIX_DEBOUNCE_INTERVAL) {
114 uint8_t changes = state ^ ao_matrix_state[row];
116 for (col = 0; col < AO_MATRIX_COLS; col++) {
117 if (changes & (1 << col)) {
118 ao_event_put_isr(AO_EVENT_KEY,
119 ao_matrix_keymap[row][col],
120 ((state >> col) & 1) == 0);
123 ao_matrix_state[row] = state;
125 ao_matrix_tick[row] = now;
134 for (row = 0; row < AO_MATRIX_ROWS; row++)
135 _ao_matrix_poll_one(row);
138 #define init_row(b) do { \
139 ao_enable_output(row_port(b), row_bit(b), row_pin(v), 1); \
140 ao_gpio_set_output_mode(row_port(b), row_bit(b), row_pin(b), AO_OUTPUT_OPEN_DRAIN); \
143 #define init_col(b) do { \
144 ao_enable_input(col_port(b), col_bit(b), AO_EXTI_MODE_PULL_UP); \
153 #if AO_MATRIX_ROWS > 1
156 #if AO_MATRIX_ROWS > 2
159 #if AO_MATRIX_ROWS > 3
162 #if AO_MATRIX_ROWS > 4
165 #if AO_MATRIX_ROWS > 5
168 #if AO_MATRIX_ROWS > 6
171 #if AO_MATRIX_ROWS > 7
176 #if AO_MATRIX_COLS > 1
179 #if AO_MATRIX_COLS > 2
182 #if AO_MATRIX_COLS > 3
185 #if AO_MATRIX_COLS > 4
188 #if AO_MATRIX_COLS > 5
191 #if AO_MATRIX_COLS > 6
194 #if AO_MATRIX_COLS > 7
197 for (row = 0; row < AO_MATRIX_ROWS; row++) {
198 ao_matrix_state[row] = _ao_matrix_read(row);
199 ao_matrix_tick[row] = ao_time();