]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/touchpad/matrix.c
Adds support for JacoBurge's TouchPad (#4186)
[qmk_firmware.git] / keyboards / touchpad / matrix.c
1 /*
2 MIT License
3 Copyright (c) 2018, JacoBurge
4 Adapted for QMK by Jack Humbert in 2018
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 SOFTWARE.
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
29 volatile uint8_t vibrate = 0; //Trigger vibration in interrupt
30
31 static matrix_row_t matrix[MATRIX_ROWS];
32
33 const uint8_t SENr[6] = {1, 2, 3, 5, 6, 7};//Maps capacitive pads to pins
34 const uint8_t SENc[6] = {0, 4, 8, 9, 10, 11};
35
36 volatile uint8_t LEDs[6][6] = {{0}};//Stores current LED values
37
38 //Read data from the cap touch IC
39 uint8_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
48 uint8_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
58 uint8_t checkTSPres(void) {
59   return (readDataFromTS(0x00) == 0x3E);
60 }
61
62 uint8_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))
109 void matrix_init_user(void) {}
110
111 __attribute__ ((weak))
112 void matrix_scan_user(void) {}
113
114 __attribute__ ((weak))
115 void matrix_init_kb(void) {
116   matrix_init_user();
117 }
118
119 __attribute__ ((weak))
120 void matrix_scan_kb(void) {
121   matrix_scan_user();
122 }
123
124 void 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
165 uint16_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
178 void 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
201 void touchClearCurrentDetections(void) {
202   readDataFromTS(0x05);
203   readDataFromTS(0x02);
204   readDataFromTS(0x03);
205   readDataFromTS(0x04);
206 }
207
208 //Check interrupt pin
209 uint8_t isTouchChangeDetected(void) {
210   return !readPin(D2);
211 }
212
213 uint8_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
270 bool matrix_is_on(uint8_t row, uint8_t col) {
271     return (matrix[row] & (1<<col));
272 }
273
274 matrix_row_t matrix_get_row(uint8_t row) {
275     return matrix[row];
276 }
277
278 void 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 }