diff options
Diffstat (limited to 'keyboards/halfcliff/matrix.c')
-rw-r--r-- | keyboards/halfcliff/matrix.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/keyboards/halfcliff/matrix.c b/keyboards/halfcliff/matrix.c new file mode 100644 index 000000000..556b75ca5 --- /dev/null +++ b/keyboards/halfcliff/matrix.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | Copyright 2012 Jun Wako <wakojun@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 | #include <stdint.h> | ||
18 | #include <stdbool.h> | ||
19 | #include "util.h" | ||
20 | #include "matrix.h" | ||
21 | #include "debounce.h" | ||
22 | #include "quantum.h" | ||
23 | #include "split_util.h" | ||
24 | #include "config.h" | ||
25 | #include "transport.h" | ||
26 | |||
27 | #define ERROR_DISCONNECT_COUNT 5 | ||
28 | |||
29 | #define ROWS_PER_HAND (MATRIX_ROWS / 2) | ||
30 | |||
31 | static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | ||
32 | static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; | ||
33 | |||
34 | /* matrix state(1:on, 0:off) */ | ||
35 | static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values | ||
36 | static matrix_row_t matrix[MATRIX_ROWS]; // debounced values | ||
37 | |||
38 | // row offsets for each hand | ||
39 | uint8_t thisHand, thatHand; | ||
40 | |||
41 | // user-defined overridable functions | ||
42 | __attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } | ||
43 | |||
44 | __attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } | ||
45 | |||
46 | __attribute__((weak)) void matrix_init_user(void) {} | ||
47 | |||
48 | __attribute__((weak)) void matrix_scan_user(void) {} | ||
49 | |||
50 | __attribute__((weak)) void matrix_slave_scan_user(void) {} | ||
51 | |||
52 | matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } | ||
53 | |||
54 | void matrix_print(void) {} | ||
55 | |||
56 | static inline void setPinOutput_writeLow(pin_t pin) { | ||
57 | ATOMIC_BLOCK_FORCEON { | ||
58 | setPinOutput(pin); | ||
59 | writePinLow(pin); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | static inline void setPinInputHigh_atomic(pin_t pin) { | ||
64 | ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); } | ||
65 | } | ||
66 | |||
67 | // matrix code | ||
68 | static void select_row(uint8_t row) { setPinOutput_writeLow(row_pins[row]); } | ||
69 | |||
70 | static void unselect_row(uint8_t row) { setPinInputHigh_atomic(row_pins[row]); } | ||
71 | |||
72 | static void unselect_rows(void) { | ||
73 | for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { | ||
74 | setPinInputHigh_atomic(row_pins[x]); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { | ||
79 | // Start with a clear matrix row | ||
80 | matrix_row_t current_row_value = 0; | ||
81 | |||
82 | // Select row | ||
83 | select_row(current_row); | ||
84 | wait_us(30); | ||
85 | |||
86 | // For each col... | ||
87 | for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { | ||
88 | // Select the col pin to read (active low) | ||
89 | uint8_t pin_state = readPin(col_pins[col_index]); | ||
90 | |||
91 | // Populate the matrix row with the state of the col pin | ||
92 | current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); | ||
93 | } | ||
94 | |||
95 | // Unselect row | ||
96 | unselect_row(current_row); | ||
97 | if (current_row + 1 < MATRIX_ROWS) { | ||
98 | wait_us(30); // wait for row signal to go HIGH | ||
99 | } | ||
100 | |||
101 | // If the row has changed, store the row and return the changed flag. | ||
102 | if (current_matrix[current_row] != current_row_value) { | ||
103 | current_matrix[current_row] = current_row_value; | ||
104 | return true; | ||
105 | } | ||
106 | return false; | ||
107 | } | ||
108 | |||
109 | static void select_col(uint8_t col) { setPinOutput_writeLow(col_pins[col]); } | ||
110 | |||
111 | static void unselect_col(uint8_t col) { setPinInputHigh_atomic(col_pins[col]); } | ||
112 | |||
113 | static void unselect_cols(void) { | ||
114 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
115 | setPinInputHigh_atomic(col_pins[x]); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static void init_pins(void) { | ||
120 | unselect_rows(); | ||
121 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
122 | setPinInputHigh_atomic(col_pins[x]); | ||
123 | } | ||
124 | unselect_cols(); | ||
125 | for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { | ||
126 | setPinInputHigh_atomic(row_pins[x]); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { | ||
131 | bool matrix_changed = false; | ||
132 | |||
133 | // Select col | ||
134 | select_col(current_col); | ||
135 | wait_us(30); | ||
136 | |||
137 | // For each row... | ||
138 | for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { | ||
139 | // Store last value of row prior to reading | ||
140 | matrix_row_t last_row_value = current_matrix[row_index]; | ||
141 | matrix_row_t current_row_value = last_row_value; | ||
142 | |||
143 | // Check row pin state | ||
144 | if (readPin(row_pins[row_index]) == 0) { | ||
145 | // Pin LO, set col bit | ||
146 | current_row_value |= (MATRIX_ROW_SHIFTER << current_col); | ||
147 | } else { | ||
148 | // Pin HI, clear col bit | ||
149 | current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); | ||
150 | } | ||
151 | |||
152 | // Determine if the matrix changed state | ||
153 | if ((last_row_value != current_row_value)) { | ||
154 | matrix_changed |= true; | ||
155 | current_matrix[row_index] = current_row_value; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | // Unselect col | ||
160 | unselect_col(current_col); | ||
161 | if (current_col + 1 < MATRIX_COLS) { | ||
162 | wait_us(30); // wait for col signal to go HIGH | ||
163 | } | ||
164 | |||
165 | return matrix_changed; | ||
166 | } | ||
167 | |||
168 | void matrix_init(void) { | ||
169 | split_pre_init(); | ||
170 | |||
171 | // Set pinout for right half if pinout for that half is defined | ||
172 | if (!isLeftHand) { | ||
173 | #ifdef DIRECT_PINS_RIGHT | ||
174 | const pin_t direct_pins_right[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS_RIGHT; | ||
175 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||
176 | for (uint8_t j = 0; j < MATRIX_COLS; j++) { | ||
177 | direct_pins[i][j] = direct_pins_right[i][j]; | ||
178 | } | ||
179 | } | ||
180 | #endif | ||
181 | #ifdef MATRIX_ROW_PINS_RIGHT | ||
182 | const pin_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT; | ||
183 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||
184 | row_pins[i] = row_pins_right[i]; | ||
185 | } | ||
186 | #endif | ||
187 | #ifdef MATRIX_COL_PINS_RIGHT | ||
188 | const pin_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT; | ||
189 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { | ||
190 | col_pins[i] = col_pins_right[i]; | ||
191 | } | ||
192 | #endif | ||
193 | } | ||
194 | |||
195 | thisHand = isLeftHand ? 0 : (ROWS_PER_HAND); | ||
196 | thatHand = ROWS_PER_HAND - thisHand; | ||
197 | |||
198 | // initialize key pins | ||
199 | init_pins(); | ||
200 | |||
201 | // initialize matrix state: all keys off | ||
202 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||
203 | raw_matrix[i] = 0; | ||
204 | matrix[i] = 0; | ||
205 | } | ||
206 | |||
207 | debounce_init(ROWS_PER_HAND); | ||
208 | |||
209 | matrix_init_quantum(); | ||
210 | |||
211 | split_post_init(); | ||
212 | } | ||
213 | |||
214 | bool matrix_post_scan(void) { | ||
215 | bool changed = false; | ||
216 | if (is_keyboard_master()) { | ||
217 | static uint8_t error_count; | ||
218 | |||
219 | matrix_row_t slave_matrix[ROWS_PER_HAND] = {0}; | ||
220 | if (!transport_master(matrix + thisHand, slave_matrix)) { | ||
221 | error_count++; | ||
222 | |||
223 | if (error_count > ERROR_DISCONNECT_COUNT) { | ||
224 | // reset other half if disconnected | ||
225 | for (int i = 0; i < ROWS_PER_HAND; ++i) { | ||
226 | matrix[thatHand + i] = 0; | ||
227 | slave_matrix[i] = 0; | ||
228 | } | ||
229 | |||
230 | changed = true; | ||
231 | } | ||
232 | } else { | ||
233 | error_count = 0; | ||
234 | |||
235 | for (int i = 0; i < ROWS_PER_HAND; ++i) { | ||
236 | if (matrix[thatHand + i] != slave_matrix[i]) { | ||
237 | matrix[thatHand + i] = slave_matrix[i]; | ||
238 | changed = true; | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
243 | matrix_scan_quantum(); | ||
244 | } else { | ||
245 | transport_slave(matrix + thatHand, matrix + thisHand); | ||
246 | |||
247 | matrix_slave_scan_user(); | ||
248 | } | ||
249 | |||
250 | return changed; | ||
251 | } | ||
252 | |||
253 | uint8_t matrix_scan(void) { | ||
254 | bool local_changed = false; | ||
255 | static matrix_row_t temp_raw_matrix[MATRIX_ROWS]; // temp raw values | ||
256 | |||
257 | // Set row, read cols | ||
258 | for (uint8_t current_row = 0; current_row < ROWS_PER_HAND/2; current_row++) { | ||
259 | local_changed |= read_cols_on_row(raw_matrix, current_row); | ||
260 | } | ||
261 | |||
262 | // Set col, read rows | ||
263 | for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { | ||
264 | local_changed |= read_rows_on_col(temp_raw_matrix, current_col); | ||
265 | //Updated key matrix on lines 6-10 (or lines 16-20) | ||
266 | if(local_changed) { | ||
267 | for (uint8_t i = ROWS_PER_HAND/2; i < ROWS_PER_HAND; i++) { | ||
268 | raw_matrix[i] = temp_raw_matrix[i]; | ||
269 | } | ||
270 | } | ||
271 | } | ||
272 | |||
273 | debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed); | ||
274 | |||
275 | bool remote_changed = matrix_post_scan(); | ||
276 | return (uint8_t)(local_changed || remote_changed); | ||
277 | } | ||