2 Copyright 2017 Mathias Andersson <wraul@dbox.se>
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,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 /* Set 0 if debouncing isn't needed */
31 #ifndef DEBOUNCING_DELAY
32 # define DEBOUNCING_DELAY 5
35 #define COL_SHIFTER ((uint32_t)1)
37 static uint16_t debouncing_time;
38 static bool debouncing = false;
41 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
43 /* matrix state(1:on, 0:off) */
44 static matrix_row_t matrix[MATRIX_ROWS];
45 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
47 static void init_rows(void);
48 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
49 static void unselect_cols(void);
50 static void select_col(uint8_t col);
53 uint8_t matrix_rows(void) {
58 uint8_t matrix_cols(void) {
62 void matrix_init(void) {
66 // initialize matrix state: all keys off
67 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
69 matrix_debouncing[i] = 0;
72 matrix_init_quantum();
75 uint8_t matrix_scan(void)
78 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
79 bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
82 debouncing_time = timer_read();
86 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
87 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
88 matrix[i] = matrix_debouncing[i];
93 matrix_scan_quantum();
98 bool matrix_is_on(uint8_t row, uint8_t col)
100 return (matrix[row] & ((matrix_row_t)1<col));
104 matrix_row_t matrix_get_row(uint8_t row)
109 void matrix_print(void)
111 print("\nr/c 0123456789ABCDEFGHIJKLMNOPQRSTUV\n");
113 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
114 phex(row); print(": ");
115 print_bin_reverse32(matrix_get_row(row));
120 uint8_t matrix_key_count(void)
123 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
124 count += bitpop32(matrix[i]);
129 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
131 bool matrix_changed = false;
133 // Select col and wait for col selecton to stabilize
134 select_col(current_col);
138 for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
140 // Store last value of row prior to reading
141 matrix_row_t last_row_value = current_matrix[row_index];
143 // Check row pin state
144 // Use the otherwise unused row: 3, col: 0 for caps lock
145 if (row_index == 3 && current_col == 0) {
146 // Pin E2 uses active low
147 if ((_SFR_IO8(E2 >> 4) & _BV(E2 & 0xF)) == 0)
149 // Pin LO, set col bit
150 current_matrix[row_index] |= (COL_SHIFTER << current_col);
154 // Pin HI, clear col bit
155 current_matrix[row_index] &= ~(COL_SHIFTER << current_col);
159 if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)))
161 // Pin HI, set col bit
162 current_matrix[row_index] |= (COL_SHIFTER << current_col);
166 // Pin LO, clear col bit
167 current_matrix[row_index] &= ~(COL_SHIFTER << current_col);
171 // Determine if the matrix changed state
172 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
174 matrix_changed = true;
181 return matrix_changed;
184 /* Row pin configuration
186 * pin: D0 D1 D2 D3 D5 B7
188 * Caps lock uses its own pin E2
190 static void init_rows(void)
192 DDRD &= ~((1<<0)| (1<<1) | (1<<2) | (1<<3) | (1<<5)); // IN
193 PORTD &= ~((1<<0)| (1<<1) | (1<<2) | (1<<3) | (1<<5)); // LO
194 DDRB &= ~(1<<7); // IN
195 PORTB &= ~(1<<7); // LO
197 DDRE &= ~(1<<2); // IN
198 PORTE |= (1<<2); // HI
202 * These columns uses two 74HC237D 3 to 8 bit demultiplexers.
203 * col / pin: PC6 PB6 PF0 PF1 PC7
224 static void unselect_cols(void)
226 DDRB |= (1<<5) | (1<<6); // OUT
227 PORTB &= ~((1<<5) | (1<<6)); // LO
229 DDRC |= (1<<6) | (1<<7); // OUT
230 PORTC &= ~((1<<6) | (1<<7)); // LO
232 DDRF |= (1<<0) | (1<<1); // OUT
233 PORTF &= ~((1<<0) | (1<<1)); // LO
236 static void select_col(uint8_t col)
240 PORTC |= (1<<6); // HI
243 PORTC |= (1<<6); // HI
244 PORTF |= (1<<0); // HI
247 PORTC |= (1<<6); // HI
248 PORTF |= (1<<1); // HI
251 PORTC |= (1<<6); // HI
252 PORTF |= (1<<0) | (1<<1); // HI
255 PORTC |= (1<<6); // HI
256 PORTC |= (1<<7); // HI
259 PORTC |= (1<<6); // HI
260 PORTF |= (1<<0); // HI
261 PORTC |= (1<<7); // HI
264 PORTC |= (1<<6); // HI
265 PORTF |= (1<<1); // HI
266 PORTC |= (1<<7); // HI
269 PORTC |= (1<<6); // HI
270 PORTF |= (1<<0) | (1<<1); // HI
271 PORTC |= (1<<7); // HI
274 PORTB |= (1<<6); // HI
277 PORTB |= (1<<6); // HI
278 PORTF |= (1<<0); // HI
281 PORTB |= (1<<6); // HI
282 PORTF |= (1<<1); // HI
285 PORTB |= (1<<6); // HI
286 PORTF |= (1<<0) | (1<<1); // HI
289 PORTB |= (1<<6); // HI
290 PORTC |= (1<<7); // HI
293 PORTB |= (1<<6); // HI
294 PORTF |= (1<<0); // HI
295 PORTC |= (1<<7); // HI
298 PORTB |= (1<<6); // HI
299 PORTF |= (1<<1); // HI
300 PORTC |= (1<<7); // HI
303 PORTB |= (1<<6); // HI
304 PORTF |= (1<<0) | (1<<1); // HI
305 PORTC |= (1<<7); // HI
308 PORTB |= (1<<5); // HI