]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/gingham/matrix.c
[Keyboard] Gingham (#6212)
[qmk_firmware.git] / keyboards / gingham / matrix.c
1 /*
2 Copyright 2012-2019 Jun Wako, Jack Humbert, Yiancar
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 #include <stdint.h>
18 #include <stdbool.h>
19 #include "wait.h"
20 #include "print.h"
21 #include "debug.h"
22 #include "util.h"
23 #include "matrix.h"
24 #include "debounce.h"
25 #include "quantum.h"
26 #include "i2c_master.h"
27
28 #if (MATRIX_COLS <= 8)
29 #    define print_matrix_header()  print("\nr/c 01234567\n")
30 #    define print_matrix_row(row)  print_bin_reverse8(matrix_get_row(row))
31 #    define matrix_bitpop(i)       bitpop(matrix[i])
32 #    define ROW_SHIFTER ((uint8_t)1)
33 #elif (MATRIX_COLS <= 16)
34 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF\n")
35 #    define print_matrix_row(row)  print_bin_reverse16(matrix_get_row(row))
36 #    define matrix_bitpop(i)       bitpop16(matrix[i])
37 #    define ROW_SHIFTER ((uint16_t)1)
38 #elif (MATRIX_COLS <= 32)
39 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
40 #    define print_matrix_row(row)  print_bin_reverse32(matrix_get_row(row))
41 #    define matrix_bitpop(i)       bitpop32(matrix[i])
42 #    define ROW_SHIFTER  ((uint32_t)1)
43 #endif
44
45 #ifdef MATRIX_MASKED
46     extern const matrix_row_t matrix_mask[];
47 #endif
48
49 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
50 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
51
52 /* matrix state(1:on, 0:off) */
53 static matrix_row_t raw_matrix[MATRIX_ROWS]; //raw values
54 static matrix_row_t matrix[MATRIX_ROWS]; //debounced values
55
56 __attribute__ ((weak))
57 void matrix_init_quantum(void) {
58     matrix_init_kb();
59 }
60
61 __attribute__ ((weak))
62 void matrix_scan_quantum(void) {
63     matrix_scan_kb();
64 }
65
66 __attribute__ ((weak))
67 void matrix_init_kb(void) {
68     matrix_init_user();
69 }
70
71 __attribute__ ((weak))
72 void matrix_scan_kb(void) {
73     matrix_scan_user();
74 }
75
76 __attribute__ ((weak))
77 void matrix_init_user(void) {
78 }
79
80 __attribute__ ((weak))
81 void matrix_scan_user(void) {
82 }
83
84 inline
85 uint8_t matrix_rows(void) {
86     return MATRIX_ROWS;
87 }
88
89 inline
90 uint8_t matrix_cols(void) {
91     return MATRIX_COLS;
92 }
93
94 //Deprecated.
95 bool matrix_is_modified(void)
96 {
97     if (debounce_active()) return false;
98     return true;
99 }
100
101 inline
102 bool matrix_is_on(uint8_t row, uint8_t col)
103 {
104     return (matrix[row] & ((matrix_row_t)1<<col));
105 }
106
107 inline
108 matrix_row_t matrix_get_row(uint8_t row)
109 {
110     // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
111     // switch blocker installed and the switch is always pressed.
112 #ifdef MATRIX_MASKED
113     return matrix[row] & matrix_mask[row];
114 #else
115     return matrix[row];
116 #endif
117 }
118
119 void matrix_print(void)
120 {
121     print_matrix_header();
122
123     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
124         phex(row); print(": ");
125         print_matrix_row(row);
126         print("\n");
127     }
128 }
129
130 uint8_t matrix_key_count(void)
131 {
132     uint8_t count = 0;
133     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
134         count += matrix_bitpop(i);
135     }
136     return count;
137 }
138
139 static void select_row(uint8_t row)
140 {
141     setPinOutput(row_pins[row]);
142     writePinLow(row_pins[row]);
143 }
144
145 static void unselect_row(uint8_t row)
146 {
147     setPinInputHigh(row_pins[row]);
148 }
149
150 static void unselect_rows(void)
151 {
152     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
153         setPinInput(row_pins[x]);
154     }
155 }
156
157 static void init_pins(void) {
158     unselect_rows();
159     // Set I/O
160     uint8_t send_data = 0x07;
161     i2c_writeReg((PORT_EXPANDER_ADDRESS << 1), 0x00, &send_data, 1, 20);
162     // // Set Pull-up
163     i2c_writeReg((PORT_EXPANDER_ADDRESS << 1), 0x06, &send_data, 1, 20);
164
165     for (uint8_t x = 0; x < MATRIX_COLS; x++) {
166         if ( (x > 0) && (x < 12) ) {
167         setPinInputHigh(col_pins[x]);
168         }
169     }
170 }
171
172 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
173 {
174     // Store last value of row prior to reading
175     matrix_row_t last_row_value = current_matrix[current_row];
176
177     // Clear data in matrix row
178     current_matrix[current_row] = 0;
179
180     // Select row and wait for row selecton to stabilize
181     select_row(current_row);
182     wait_us(30);
183
184     // For each col...
185     for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
186         uint8_t pin_state;
187         // Select the col pin to read (active low)
188         switch (col_index) {
189             case 0 :
190                 i2c_readReg((PORT_EXPANDER_ADDRESS << 1), 0x09, &pin_state, 1, 20);
191                 pin_state = pin_state & 0x01;
192                 break;
193             case 12 :
194                 i2c_readReg((PORT_EXPANDER_ADDRESS << 1), 0x09, &pin_state, 1, 20);
195                 pin_state = pin_state & (1 << 2);
196                 break;
197             case 13 :
198                 i2c_readReg((PORT_EXPANDER_ADDRESS << 1), 0x09, &pin_state, 1, 20);
199                 pin_state = pin_state & (1 << 1);
200                 break;
201             default :
202                 pin_state = readPin(col_pins[col_index]);
203         }
204
205         // Populate the matrix row with the state of the col pin
206         current_matrix[current_row] |=  pin_state ? 0 : (ROW_SHIFTER << col_index);
207     }
208
209     // Unselect row
210     unselect_row(current_row);
211
212     return (last_row_value != current_matrix[current_row]);
213 }
214
215 void matrix_init(void) {
216
217     // Initialize I2C
218     i2c_init();
219
220     // initialize key pins
221     init_pins();
222
223     // initialize matrix state: all keys off
224     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
225         raw_matrix[i] = 0;
226         matrix[i] = 0;
227     }
228
229     debounce_init(MATRIX_ROWS);
230
231     matrix_init_quantum();
232 }
233
234 uint8_t matrix_scan(void)
235 {
236     bool changed = false;
237
238     // Set row, read cols
239     for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
240         changed |= read_cols_on_row(raw_matrix, current_row);
241     }
242
243     debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
244
245     matrix_scan_quantum();
246     return (uint8_t)changed;
247 }