aboutsummaryrefslogtreecommitdiff
path: root/keyboards/touchpad/matrix.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/touchpad/matrix.c')
-rw-r--r--keyboards/touchpad/matrix.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/keyboards/touchpad/matrix.c b/keyboards/touchpad/matrix.c
new file mode 100644
index 000000000..3af4c5c3c
--- /dev/null
+++ b/keyboards/touchpad/matrix.c
@@ -0,0 +1,291 @@
1/*
2MIT License
3Copyright (c) 2018, JacoBurge
4Adapted for QMK by Jack Humbert in 2018
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
22*/
23
24#include "matrix.h"
25#include "i2c_master.h"
26#include "quantum.h"
27
28#define VIBRATE_LENGTH 50 //Defines number of interrupts motor will vibrate for, must be bigger than 8 for correct operation
29volatile uint8_t vibrate = 0; //Trigger vibration in interrupt
30
31static matrix_row_t matrix[MATRIX_ROWS];
32
33const uint8_t SENr[6] = {1, 2, 3, 5, 6, 7};//Maps capacitive pads to pins
34const uint8_t SENc[6] = {0, 4, 8, 9, 10, 11};
35
36volatile uint8_t LEDs[6][6] = {{0}};//Stores current LED values
37
38//Read data from the cap touch IC
39uint8_t readDataFromTS(uint8_t reg) {
40 uint8_t rx[1] = { 0 };
41 if (i2c_readReg(0x1C << 1, reg, rx, 1, 100) == 0) {
42 return rx[0];
43 }
44 return 0;
45}
46
47//Write data to cap touch IC
48uint8_t writeDataToTS(uint8_t reg, uint8_t data) {
49 uint8_t tx[2] = { reg, data };
50 if (i2c_transmit(0x1C << 1, tx, 2, 100) == 0) {
51 return 1;
52 } else {
53 return 0;
54 }
55}
56
57
58uint8_t checkTSPres(void) {
59 return (readDataFromTS(0x00) == 0x3E);
60}
61
62uint8_t capSetup(void) {
63
64 uint8_t temp_return = checkTSPres();
65
66 if (temp_return == 1) {
67 // Perform measurements every 16ms
68 writeDataToTS(0x08, 1);
69
70 // Increase detection integrator value
71 writeDataToTS(0x0B, 1);
72
73 // Oversample to gain two bits for columns
74 writeDataToTS(0x28, 0x42);
75 writeDataToTS(0x29, 0x00);
76 writeDataToTS(0x2A, 0x00);
77 writeDataToTS(0x2B, 0x00);
78 writeDataToTS(0x2C, 0x42);
79 writeDataToTS(0x2D, 0x00);
80 writeDataToTS(0x2E, 0x00);
81 writeDataToTS(0x2F, 0x00);
82 writeDataToTS(0x30, 0x42);
83 writeDataToTS(0x31, 0x42);
84 writeDataToTS(0x32, 0x42);
85 writeDataToTS(0x33, 0x42);
86
87 // Recalibration if touch detected for more than 8 seconds n*0.16s
88 writeDataToTS(0x0C, 50);
89
90 // Enable keys and set key groups
91 writeDataToTS(0x1C, 0x00 | 0x04);
92 writeDataToTS(0x1D, 0x00 | 0x08);
93 writeDataToTS(0x1E, 0x00 | 0x08);
94 writeDataToTS(0x1F, 0x00 | 0x08);
95 writeDataToTS(0x20, 0x00 | 0x04);
96 writeDataToTS(0x21, 0x00 | 0x08);
97 writeDataToTS(0x22, 0x00 | 0x08);
98 writeDataToTS(0x23, 0x00 | 0x08);
99 writeDataToTS(0x24, 0x00 | 0x04);
100 writeDataToTS(0x25, 0x00 | 0x04);
101 writeDataToTS(0x26, 0x00 | 0x04);
102 writeDataToTS(0x27, 0x00 | 0x04);
103
104 }
105 return temp_return;
106}
107
108__attribute__ ((weak))
109void matrix_init_user(void) {}
110
111__attribute__ ((weak))
112void matrix_scan_user(void) {}
113
114__attribute__ ((weak))
115void matrix_init_kb(void) {
116 matrix_init_user();
117}
118
119__attribute__ ((weak))
120void matrix_scan_kb(void) {
121 matrix_scan_user();
122}
123
124void matrix_init(void) {
125
126 i2c_init();
127
128 //Motor enable
129 setPinOutput(E6);
130 //Motor PWM
131 setPinOutput(D7);
132
133 //Power LED
134 setPinOutput(B7);
135 writePinHigh(B7);
136
137 //LEDs Columns
138 setPinOutput(F7);
139 setPinOutput(F6);
140 setPinOutput(F5);
141 setPinOutput(F4);
142 setPinOutput(F1);
143 setPinOutput(F0);
144
145 //LEDs Rows
146 setPinOutput(D6);
147 setPinOutput(B4);
148 setPinOutput(B5);
149 setPinOutput(B6);
150 setPinOutput(C6);
151 setPinOutput(C7);
152
153 //Capacitive Interrupt
154 setPinInput(D2);
155
156 capSetup();
157 writeDataToTS(0x06, 0x12); //Calibrate capacitive touch IC
158
159 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
160
161 matrix_init_quantum();
162}
163
164
165uint16_t touchDetectionRoutine(void) {
166 uint16_t data;
167 uint8_t temp1, temp2;
168
169 temp1 = readDataFromTS(0x04);
170 temp2 = readDataFromTS(0x03);
171 data = temp1;
172 data = (data << 8) | temp2;
173 return data;
174
175}
176
177//Process raw capacitive data, map pins to rows and columns
178void decodeArray(uint16_t dataIn, uint8_t *column, uint8_t *row) {
179 uint8_t i1 = 20, i2 = 20;
180 for (uint8_t i = 0; i < 12; i++) {
181 if ((dataIn & 0b1) == 1) {
182 if (i1 == 20) {
183 i1 = i;
184 } else if (i2 == 20) {
185 i2 = i;
186 }
187 }
188 dataIn = dataIn >> 1;
189 }
190
191 for (uint8_t j = 0; j < 6; j++) {
192 if (SENr[j] == i1 || SENr[j] == i2) {
193 *row = j;
194 }
195 if (SENc[j] == i1 || SENc[j] == i2) {
196 *column = j;
197 }
198 }
199}
200
201void touchClearCurrentDetections(void) {
202 readDataFromTS(0x05);
203 readDataFromTS(0x02);
204 readDataFromTS(0x03);
205 readDataFromTS(0x04);
206}
207
208//Check interrupt pin
209uint8_t isTouchChangeDetected(void) {
210 return !readPin(D2);
211}
212
213uint8_t matrix_scan(void) {
214 if (isTouchChangeDetected()) {
215 uint16_t dataIn = touchDetectionRoutine();
216 if ((dataIn & 0b111100010001) > 0 && (dataIn & 0b000011101110) > 0) {
217 uint8_t column = 10, row = 10;
218 decodeArray(dataIn, &column, &row);
219 if (column != 10 && row != 10) {
220 vibrate = VIBRATE_LENGTH; //Trigger vibration
221 matrix[row] = _BV(column);
222 } else {
223 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
224 }
225 } else {
226 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
227 }
228 touchClearCurrentDetections();
229 }
230
231 for (uint8_t c = 0; c < 6; c++) {
232 for (uint8_t r = 0; r < 6; r++) {
233 switch (r) {
234 case 0: writePin(D6, matrix_is_on(r, c)); break;
235 case 1: writePin(B4, matrix_is_on(r, c)); break;
236 case 2: writePin(B5, matrix_is_on(r, c)); break;
237 case 3: writePin(B6, matrix_is_on(r, c)); break;
238 case 4: writePin(C6, matrix_is_on(r, c)); break;
239 case 5: writePin(C7, matrix_is_on(r, c)); break;
240 }
241
242 switch (c) {
243 case 0: writePin(F5, !matrix_is_on(r, c)); break;
244 case 1: writePin(F4, !matrix_is_on(r, c)); break;
245 case 2: writePin(F1, !matrix_is_on(r, c)); break;
246 case 3: writePin(F0, !matrix_is_on(r, c)); break;
247 case 4: writePin(F6, !matrix_is_on(r, c)); break;
248 case 5: writePin(F7, !matrix_is_on(r, c)); break;
249 }
250 }
251 }
252
253 if (vibrate == VIBRATE_LENGTH) {
254 writePinHigh(E6);
255 writePinHigh(D7);
256 vibrate--;
257 } else if (vibrate > 0) {
258 vibrate--;
259 } else if (vibrate == 0) {
260 writePinLow(D7);
261 writePinLow(E6);
262 }
263
264 matrix_scan_quantum();
265
266 return 1;
267
268}
269
270bool matrix_is_on(uint8_t row, uint8_t col) {
271 return (matrix[row] & (1<<col));
272}
273
274matrix_row_t matrix_get_row(uint8_t row) {
275 return matrix[row];
276}
277
278void matrix_print(void) {
279 printf("\nr/c 01234567\n");
280 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
281 printf("%X0: ", row);
282 matrix_row_t data = matrix_get_row(row);
283 for (int col = 0; col < MATRIX_COLS; col++) {
284 if (data & (1<<col))
285 printf("1");
286 else
287 printf("0");
288 }
289 printf("\n");
290 }
291}