3 Copyright (c) 2018, JacoBurge
4 Adapted for QMK by Jack Humbert in 2018
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.
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
25 #include "i2c_master.h"
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
31 static matrix_row_t matrix[MATRIX_ROWS];
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};
36 volatile uint8_t LEDs[6][6] = {{0}};//Stores current LED values
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) {
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) {
58 uint8_t checkTSPres(void) {
59 return (readDataFromTS(0x00) == 0x3E);
62 uint8_t capSetup(void) {
64 uint8_t temp_return = checkTSPres();
66 if (temp_return == 1) {
67 // Perform measurements every 16ms
68 writeDataToTS(0x08, 1);
70 // Increase detection integrator value
71 writeDataToTS(0x0B, 1);
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);
87 // Recalibration if touch detected for more than 8 seconds n*0.16s
88 writeDataToTS(0x0C, 50);
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);
108 __attribute__ ((weak))
109 void matrix_init_user(void) {}
111 __attribute__ ((weak))
112 void matrix_scan_user(void) {}
114 __attribute__ ((weak))
115 void matrix_init_kb(void) {
119 __attribute__ ((weak))
120 void matrix_scan_kb(void) {
124 void matrix_init(void) {
153 //Capacitive Interrupt
157 writeDataToTS(0x06, 0x12); //Calibrate capacitive touch IC
159 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
161 matrix_init_quantum();
165 uint16_t touchDetectionRoutine(void) {
167 uint8_t temp1, temp2;
169 temp1 = readDataFromTS(0x04);
170 temp2 = readDataFromTS(0x03);
172 data = (data << 8) | temp2;
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) {
184 } else if (i2 == 20) {
188 dataIn = dataIn >> 1;
191 for (uint8_t j = 0; j < 6; j++) {
192 if (SENr[j] == i1 || SENr[j] == i2) {
195 if (SENc[j] == i1 || SENc[j] == i2) {
201 void touchClearCurrentDetections(void) {
202 readDataFromTS(0x05);
203 readDataFromTS(0x02);
204 readDataFromTS(0x03);
205 readDataFromTS(0x04);
208 //Check interrupt pin
209 uint8_t isTouchChangeDetected(void) {
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);
223 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
226 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
228 touchClearCurrentDetections();
231 for (uint8_t c = 0; c < 6; c++) {
232 for (uint8_t r = 0; r < 6; 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;
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;
253 if (vibrate == VIBRATE_LENGTH) {
257 } else if (vibrate > 0) {
259 } else if (vibrate == 0) {
264 matrix_scan_quantum();
270 bool matrix_is_on(uint8_t row, uint8_t col) {
271 return (matrix[row] & (1<<col));
274 matrix_row_t matrix_get_row(uint8_t row) {
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++) {