]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/amj96/matrix.c
[Keyboard] Snagpad Configurator bugfix and readme refactor (#6381)
[qmk_firmware.git] / keyboards / amj96 / matrix.c
1 /*
2 Copyright 2014 Kai Ryu <kai1103@gmail.com>
3
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.
8
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.
13
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/>.
16 */
17
18 /*
19  * scan matrix
20  */
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <avr/io.h>
24 #include <util/delay.h>
25 #include "print.h"
26 #include "debug.h"
27 #include "util.h"
28 #include "matrix.h"
29 #ifdef UART_RGB_ENABLE
30 #include "uart_rgb.h"
31 #endif
32
33 #ifndef DEBOUNCE
34 #   define DEBOUNCE 5
35 #endif
36 static uint8_t debouncing = DEBOUNCE;
37
38 /* matrix state(1:on, 0:off) */
39 static matrix_row_t matrix[MATRIX_ROWS];
40 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
41
42 static matrix_row_t read_cols(void);
43 static void init_cols(void);
44 static void init_rows(void);
45 static void unselect_rows(void);
46 static void select_row(uint8_t row);
47
48 inline
49 uint8_t matrix_rows(void)
50 {
51     return MATRIX_ROWS;
52 }
53
54 inline
55 uint8_t matrix_cols(void)
56 {
57     return MATRIX_COLS;
58 }
59
60 void matrix_init(void)
61 {
62
63 #ifdef UART_RGB_ENABLE
64     uart_rgb_init();
65 #endif
66     // disable JTAG
67     MCUCR = _BV(JTD);
68     MCUCR = _BV(JTD);
69
70     // 85 REST
71     DDRD |= _BV(PD7);
72     PORTD |= _BV(PD7);
73
74     // initialize row and col
75     init_rows();
76     init_cols();
77
78     // initialize matrix state: all keys off
79     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
80         matrix[i] = 0;
81         matrix_debouncing[i] = 0;
82     }
83 }
84
85 uint8_t matrix_scan(void)
86 {
87     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
88         select_row(i);
89         _delay_us(30);  // without this wait read unstable value.
90         matrix_row_t cols = read_cols();
91         if (matrix_debouncing[i] != cols) {
92             matrix_debouncing[i] = cols;
93             if (debouncing) {
94                 debug("bounce!: "); debug_hex(debouncing); debug("\n");
95             }
96             debouncing = DEBOUNCE;
97         }
98         unselect_rows();
99     }
100
101     if (debouncing) {
102         if (--debouncing) {
103             _delay_ms(1);
104         } else {
105             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
106                 matrix[i] = matrix_debouncing[i];
107             }
108         }
109     }
110
111     return 1;
112 }
113
114 bool matrix_is_modified(void)
115 {
116     if (debouncing) return false;
117     return true;
118 }
119
120 inline
121 bool matrix_is_on(uint8_t row, uint8_t col)
122 {
123     return (matrix[row] & ((matrix_row_t)1<<col));
124 }
125
126 inline
127 matrix_row_t matrix_get_row(uint8_t row)
128 {
129     return matrix[row];
130 }
131
132 void matrix_print(void)
133 {
134     print("\nr/c 0123456789ABCDEF\n");
135     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
136         phex(row); print(": ");
137         pbin_reverse16(matrix_get_row(row));
138         print("\n");
139     }
140 }
141
142 uint8_t matrix_key_count(void)
143 {
144     uint8_t count = 0;
145     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
146         count += bitpop16(matrix[i]);
147     }
148     return count;
149 }
150
151 /* Column pin configuration
152  * col: 0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15
153  * pin: F7  F6  F5  F4  F1  F0  E6  D7  D6  D5  D1  D0  B7  B6  B0  C7
154  * */
155 static void  init_cols(void)
156 {
157     // Input with pull-up(DDR:0, PORT:1)
158     DDRF &= 0b00001100;
159     PORTF |= 0b11110011;
160
161     DDRD &= 0b00011100;
162     PORTD |= 0b11100011;
163
164     DDRB &= ~(_BV(PB6) | _BV(PB7)| _BV(PB0));
165     PORTB |= (_BV(PB6) | _BV(PB7)| _BV(PB0));
166
167     DDRE &= ~_BV(PE6);
168     PORTE |= _BV(PE6);
169
170     DDRC &= ~_BV(PC7);
171     PORTC |= _BV(PC7);
172
173 }
174
175 static matrix_row_t read_cols(void)
176 {
177
178     return (PINF&_BV(PF7) ? 0 : (1<<0)) |
179            (PINF&_BV(PF6) ? 0 : (1<<1)) |
180            (PINF&_BV(PF5) ? 0 : (1<<2)) |
181            (PINF&_BV(PF4) ? 0 : (1<<3)) |
182            (PINF&_BV(PF1) ? 0 : (1<<4)) |
183            (PINF&_BV(PF0) ? 0 : (1<<5)) |
184            (PINE&_BV(PE6) ? 0 : (1<<6)) |
185            (PIND&_BV(PD7) ? 0 : (1<<7)) |
186            (PIND&_BV(PD6) ? 0 : (1<<8)) |
187            (PIND&_BV(PD5) ? 0 : (1<<9)) |
188            (PIND&_BV(PD1) ? 0 : (1<<10)) |
189            (PIND&_BV(PD0) ? 0 : (1<<11)) |
190            (PINB&_BV(PB7) ? 0 : (1<<12)) |
191            (PINB&_BV(PB6) ? 0 : (1<<13)) |
192            (PINB&_BV(PB0) ? 0 : (1<<14)) |
193            (PINC&_BV(PC7) ? 0 : (1<<15));
194 }
195
196 /* Row pin configuration
197  * row:     0   1   2   3   4   5   x
198  * pin: B3  0   1   0   1   0   1   1
199  *      B2  0   0   1   1   0   0   1
200  *      B1  0   0   0   0   1   1   1
201  */
202
203 static void init_rows(void)
204 {
205      DDRB  |= (1<<PB1 | 1<<PB2 | 1<<PB3);
206 }
207
208 static void unselect_rows(void)
209 {
210     // Hi-Z(DDR:0, PORT:0) to unselect
211     PORTB |= (1<<PB1);
212     PORTB |= (1<<PB2);
213     PORTB |= (1<<PB3);
214 }
215
216 static void select_row(uint8_t row)
217 {
218     // Output low(DDR:1, PORT:0) to select
219     (row & (1<<0)) ? (PORTB |= (1<<PB3)) : (PORTB &= ~(1<<PB3));
220     (row & (1<<1)) ? (PORTB |= (1<<PB2)) : (PORTB &= ~(1<<PB2));
221     (row & (1<<2)) ? (PORTB |= (1<<PB1)) : (PORTB &= ~(1<<PB1));
222 }