]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/moon/matrix.c
Remove more commented out MCUs
[qmk_firmware.git] / keyboards / moon / matrix.c
1 /*
2 Copyright 2012-2019 Jun Wako, Jack Humbert, Yiancar, Mathias Andersson <wraul@dbox.se>
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 "pca9555.h"
27
28 /*
29  *       IC1 (PCA9555)                  IC2 (PCA9555)
30  *       ,----------.                   ,----------.
31  * SDA --| SDA  P00 |-- P1        SDA --| SDA  P00 |-- P17
32  * SCL --| SCL  P01 |-- P2        SCL --| SCL  P01 |-- P18
33  * INT --| INT  P02 |-- P3        INT --| INT  P02 |-- P19
34  *       |      P03 |-- P4              |      P03 |-- P20
35  * GND --| A0   P04 |-- P5        VCC --| A0   P04 |-- P21
36  * SJ1 --| A1   P05 |-- P6        SJ1 --| A1   P05 |-- P22
37  * GND --| A2   P06 |-- P7        GND --| A2   P06 |-- P23
38  *       |      P07 |-- P8              |      P07 |-- P24
39  *       |          |                   |          |
40  *       |      P10 |-- P9              |      P10 |-- P25
41  *       |      P11 |-- P10             |      P11 |-- P26
42  *       |      P12 |-- P11             |      P12 |-- P27
43  *       |      P13 |-- P12             |      P13 |-- P28
44  *       |      P14 |-- P13             |      P14 |-- P29
45  *       |      P15 |-- P14             |      P15 |-- P30
46  *       |      P16 |-- P15             |      P16 |-- P31
47  *       |      P17 |-- P16             |      P17 |-- P32
48  *       `----------'                   `----------'
49  */
50
51 /*
52  * | Row | Pin |   | Col | Pin |
53  * | --- | --- |   | --- | --- |
54  * | 0   | P1  |   | 0   | P25 |
55  * | 1   | P2  |   | 1   | P26 |
56  * | 2   | P3  |   | 2   | P27 |
57  * | 3   | P4  |   | 3   | P28 |
58  * | 4   | P5  |   | 4   | P29 |
59  * | 5   | P6  |   | 5   | P30 |
60  * | 6   | P7  |   | 6   | P20 |
61  * | 7   | P8  |   | 7   | P21 |
62  *                 | 8   | P22 |
63  *                 | 9   | P23 |
64  *                 | A   | P24 |
65  */
66
67 // PCA9555 slave addresses
68 #define IC1 0x20
69 #define IC2 0x21
70
71 // PCA9555 column pin masks
72 #define PORT0_COLS_MASK 0b11111000
73 #define PORT1_COLS_MASK 0b00111111
74 #define COLS_MASK 0b0000011111111111
75
76 #if (MATRIX_COLS <= 8)
77 #  define print_matrix_header() print("\nr/c 01234567\n")
78 #  define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
79 #  define matrix_bitpop(i) bitpop(matrix[i])
80 #  define ROW_SHIFTER ((uint8_t)1)
81 #elif (MATRIX_COLS <= 16)
82 #  define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
83 #  define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
84 #  define matrix_bitpop(i) bitpop16(matrix[i])
85 #  define ROW_SHIFTER ((uint16_t)1)
86 #elif (MATRIX_COLS <= 32)
87 #  define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
88 #  define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
89 #  define matrix_bitpop(i) bitpop32(matrix[i])
90 #  define ROW_SHIFTER ((uint32_t)1)
91 #endif
92
93 /* matrix state(1:on, 0:off) */
94 static matrix_row_t raw_matrix[MATRIX_ROWS];  // raw values
95 static matrix_row_t matrix[MATRIX_ROWS];      // debounced values
96
97 __attribute__((weak)) void matrix_init_quantum(void) { matrix_init_kb(); }
98
99 __attribute__((weak)) void matrix_scan_quantum(void) { matrix_scan_kb(); }
100
101 __attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
102
103 __attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
104
105 __attribute__((weak)) void matrix_init_user(void) {}
106
107 __attribute__((weak)) void matrix_scan_user(void) {}
108
109 inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
110
111 inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
112
113 inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
114
115 inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
116
117 void matrix_print(void) {
118   print_matrix_header();
119
120   for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
121     phex(row);
122     print(": ");
123     print_matrix_row(row);
124     print("\n");
125   }
126 }
127
128 uint8_t matrix_key_count(void) {
129   uint8_t count = 0;
130   for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
131     count += matrix_bitpop(i);
132   }
133   return count;
134 }
135
136 static void init_i2c(void) {
137   pca9555_init(IC1);
138   pca9555_init(IC2);
139 }
140
141 static void init_pins(void) {
142   // init cols - IC2 port0 & IC2 port1 input
143   pca9555_set_config(IC2, PCA9555_PORT0, ALL_INPUT);
144   pca9555_set_config(IC2, PCA9555_PORT1, ALL_INPUT);
145
146   // init rows - IC1 port0 output
147   pca9555_set_config(IC1, PCA9555_PORT0, ALL_OUTPUT);
148   pca9555_set_output(IC1, PCA9555_PORT0, ALL_HIGH);
149 }
150
151 static void select_row(uint8_t row) {
152   // All rows are on the same IC and port
153   uint8_t mask = 1 << row;
154
155   // set active row low  : 0
156   // set other rows hi-Z : 1
157   pca9555_set_output(IC1, PCA9555_PORT0, ALL_HIGH & (~mask));
158 }
159
160 static uint16_t read_cols(void) {
161   uint16_t state_1 = pca9555_readPins(IC2, PCA9555_PORT0);
162   uint16_t state_2 = pca9555_readPins(IC2, PCA9555_PORT1);
163
164   uint16_t state = ((state_1 & PORT0_COLS_MASK) << 3) | ((state_2 & PORT1_COLS_MASK));
165
166   // A low pin indicates an active column
167   return (~state) & COLS_MASK;
168 }
169
170 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
171   // Store last value of row prior to reading
172   matrix_row_t last_row_value = current_matrix[current_row];
173
174   // Clear data in matrix row
175   current_matrix[current_row] = 0;
176
177   // Select row and wait for row selecton to stabilize
178   select_row(current_row);
179   wait_us(30);
180
181   current_matrix[current_row] |= read_cols();
182
183   // No need to unselect as `select_row` sets all the pins.
184
185   return (last_row_value != current_matrix[current_row]);
186 }
187
188 void matrix_init(void) {
189   // initialize i2c
190   init_i2c();
191
192   // initialize key pins
193   init_pins();
194
195   // initialize matrix state: all keys off
196   for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
197     raw_matrix[i] = 0;
198     matrix[i]     = 0;
199   }
200
201   debounce_init(MATRIX_ROWS);
202
203   matrix_init_quantum();
204 }
205
206 uint8_t matrix_scan(void) {
207   bool changed = false;
208
209   for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
210     changed |= read_cols_on_row(raw_matrix, current_row);
211   }
212
213   debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
214
215   matrix_scan_quantum();
216
217   return (uint8_t)changed;
218 }