aboutsummaryrefslogtreecommitdiff
path: root/keyboards/lets_splitv2/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/lets_splitv2/matrix.c')
-rw-r--r--keyboards/lets_splitv2/matrix.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/keyboards/lets_splitv2/matrix.c b/keyboards/lets_splitv2/matrix.c
new file mode 100644
index 000000000..1d768c59b
--- /dev/null
+++ b/keyboards/lets_splitv2/matrix.c
@@ -0,0 +1,311 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along 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 <avr/wdt.h>
25#include <avr/interrupt.h>
26#include <util/delay.h>
27#include "print.h"
28#include "debug.h"
29#include "util.h"
30#include "matrix.h"
31#include "i2c.h"
32#include "serial.h"
33#include "split_util.h"
34#include "pro_micro.h"
35#include "config.h"
36
37#ifndef DEBOUNCE
38# define DEBOUNCE 5
39#endif
40
41#define ERROR_DISCONNECT_COUNT 5
42
43static uint8_t debouncing = DEBOUNCE;
44static const int ROWS_PER_HAND = MATRIX_ROWS/2;
45static uint8_t error_count = 0;
46
47static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
48static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
49
50/* matrix state(1:on, 0:off) */
51static matrix_row_t matrix[MATRIX_ROWS];
52static matrix_row_t matrix_debouncing[MATRIX_ROWS];
53
54static matrix_row_t read_cols(void);
55static void init_cols(void);
56static void unselect_rows(void);
57static void select_row(uint8_t row);
58
59__attribute__ ((weak))
60void matrix_init_quantum(void) {
61 matrix_init_kb();
62}
63
64__attribute__ ((weak))
65void matrix_scan_quantum(void) {
66 matrix_scan_kb();
67}
68
69__attribute__ ((weak))
70void matrix_init_kb(void) {
71 matrix_init_user();
72}
73
74__attribute__ ((weak))
75void matrix_scan_kb(void) {
76 matrix_scan_user();
77}
78
79__attribute__ ((weak))
80void matrix_init_user(void) {
81}
82
83__attribute__ ((weak))
84void matrix_scan_user(void) {
85}
86
87inline
88uint8_t matrix_rows(void)
89{
90 return MATRIX_ROWS;
91}
92
93inline
94uint8_t matrix_cols(void)
95{
96 return MATRIX_COLS;
97}
98
99void matrix_init(void)
100{
101 debug_enable = true;
102 debug_matrix = true;
103 debug_mouse = true;
104 // initialize row and col
105 unselect_rows();
106 init_cols();
107
108 TX_RX_LED_INIT;
109
110 // initialize matrix state: all keys off
111 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
112 matrix[i] = 0;
113 matrix_debouncing[i] = 0;
114 }
115
116 matrix_init_quantum();
117}
118
119uint8_t _matrix_scan(void)
120{
121 // Right hand is stored after the left in the matirx so, we need to offset it
122 int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
123
124 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
125 select_row(i);
126 _delay_us(30); // without this wait read unstable value.
127 matrix_row_t cols = read_cols();
128 if (matrix_debouncing[i+offset] != cols) {
129 matrix_debouncing[i+offset] = cols;
130 debouncing = DEBOUNCE;
131 }
132 unselect_rows();
133 }
134
135 if (debouncing) {
136 if (--debouncing) {
137 _delay_ms(1);
138 } else {
139 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
140 matrix[i+offset] = matrix_debouncing[i+offset];
141 }
142 }
143 }
144
145 return 1;
146}
147
148// Get rows from other half over i2c
149int i2c_transaction(void) {
150 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
151
152 int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
153 if (err) goto i2c_error;
154
155 // start of matrix stored at 0x00
156 err = i2c_master_write(0x00);
157 if (err) goto i2c_error;
158
159 // Start read
160 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
161 if (err) goto i2c_error;
162
163 if (!err) {
164 int i;
165 for (i = 0; i < ROWS_PER_HAND-1; ++i) {
166 matrix[slaveOffset+i] = i2c_master_read(I2C_ACK);
167 }
168 matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
169 i2c_master_stop();
170 } else {
171i2c_error: // the cable is disconnceted, or something else went wrong
172 i2c_reset_state();
173 return err;
174 }
175
176 return 0;
177}
178
179#ifndef USE_I2C
180int serial_transaction(void) {
181 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
182
183 if (serial_update_buffers()) {
184 return 1;
185 }
186
187 for (int i = 0; i < ROWS_PER_HAND; ++i) {
188 matrix[slaveOffset+i] = serial_slave_buffer[i];
189 }
190 return 0;
191}
192#endif
193
194uint8_t matrix_scan(void)
195{
196 int ret = _matrix_scan();
197
198
199
200#ifdef USE_I2C
201 if( i2c_transaction() ) {
202#else
203 if( serial_transaction() ) {
204#endif
205 // turn on the indicator led when halves are disconnected
206 TXLED1;
207
208 error_count++;
209
210 if (error_count > ERROR_DISCONNECT_COUNT) {
211 // reset other half if disconnected
212 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
213 for (int i = 0; i < ROWS_PER_HAND; ++i) {
214 matrix[slaveOffset+i] = 0;
215 }
216 }
217 } else {
218 // turn off the indicator led on no error
219 TXLED0;
220 error_count = 0;
221 }
222
223 matrix_scan_quantum();
224
225 return ret;
226}
227
228void matrix_slave_scan(void) {
229 _matrix_scan();
230
231 int offset = (isLeftHand) ? 0 : (MATRIX_ROWS / 2);
232
233#ifdef USE_I2C
234 for (int i = 0; i < ROWS_PER_HAND; ++i) {
235 /* i2c_slave_buffer[i] = matrix[offset+i]; */
236 i2c_slave_buffer[i] = matrix[offset+i];
237 }
238#else
239 for (int i = 0; i < ROWS_PER_HAND; ++i) {
240 serial_slave_buffer[i] = matrix[offset+i];
241 }
242#endif
243}
244
245bool matrix_is_modified(void)
246{
247 if (debouncing) return false;
248 return true;
249}
250
251inline
252bool matrix_is_on(uint8_t row, uint8_t col)
253{
254 return (matrix[row] & ((matrix_row_t)1<<col));
255}
256
257inline
258matrix_row_t matrix_get_row(uint8_t row)
259{
260 return matrix[row];
261}
262
263void matrix_print(void)
264{
265 print("\nr/c 0123456789ABCDEF\n");
266 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
267 phex(row); print(": ");
268 pbin_reverse16(matrix_get_row(row));
269 print("\n");
270 }
271}
272
273uint8_t matrix_key_count(void)
274{
275 uint8_t count = 0;
276 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
277 count += bitpop16(matrix[i]);
278 }
279 return count;
280}
281
282static void init_cols(void)
283{
284 for(int x = 0; x < MATRIX_COLS; x++) {
285 _SFR_IO8((col_pins[x] >> 4) + 1) &= ~_BV(col_pins[x] & 0xF);
286 _SFR_IO8((col_pins[x] >> 4) + 2) |= _BV(col_pins[x] & 0xF);
287 }
288}
289
290static matrix_row_t read_cols(void)
291{
292 matrix_row_t result = 0;
293 for(int x = 0; x < MATRIX_COLS; x++) {
294 result |= (_SFR_IO8(col_pins[x] >> 4) & _BV(col_pins[x] & 0xF)) ? 0 : (1 << x);
295 }
296 return result;
297}
298
299static void unselect_rows(void)
300{
301 for(int x = 0; x < ROWS_PER_HAND; x++) {
302 _SFR_IO8((row_pins[x] >> 4) + 1) &= ~_BV(row_pins[x] & 0xF);
303 _SFR_IO8((row_pins[x] >> 4) + 2) |= _BV(row_pins[x] & 0xF);
304 }
305}
306
307static void select_row(uint8_t row)
308{
309 _SFR_IO8((row_pins[row] >> 4) + 1) |= _BV(row_pins[row] & 0xF);
310 _SFR_IO8((row_pins[row] >> 4) + 2) &= ~_BV(row_pins[row] & 0xF);
311}