matrix.c (7688B)
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 "print.h" 27 #include <string.h> 28 29 #define VIBRATE_LENGTH 50 //Defines number of interrupts motor will vibrate for, must be bigger than 8 for correct operation 30 volatile uint8_t vibrate = 0; //Trigger vibration in interrupt 31 32 static matrix_row_t matrix[MATRIX_ROWS]; 33 34 const uint8_t SENr[6] = {1, 2, 3, 5, 6, 7};//Maps capacitive pads to pins 35 const uint8_t SENc[6] = {0, 4, 8, 9, 10, 11}; 36 37 volatile uint8_t LEDs[6][6] = {{0}};//Stores current LED values 38 39 //Read data from the cap touch IC 40 uint8_t readDataFromTS(uint8_t reg) { 41 uint8_t rx[1] = { 0 }; 42 if (i2c_read_register(0x1C << 1, reg, rx, 1, 100) == 0) { 43 return rx[0]; 44 } 45 return 0; 46 } 47 48 //Write data to cap touch IC 49 uint8_t writeDataToTS(uint8_t reg, uint8_t data) { 50 uint8_t tx[2] = { reg, data }; 51 if (i2c_transmit(0x1C << 1, tx, 2, 100) == 0) { 52 return 1; 53 } else { 54 return 0; 55 } 56 } 57 58 59 uint8_t checkTSPres(void) { 60 return (readDataFromTS(0x00) == 0x3E); 61 } 62 63 uint8_t capSetup(void) { 64 65 uint8_t temp_return = checkTSPres(); 66 67 if (temp_return == 1) { 68 // Perform measurements every 16ms 69 writeDataToTS(0x08, 1); 70 71 // Increase detection integrator value 72 writeDataToTS(0x0B, 1); 73 74 // Oversample to gain two bits for columns 75 writeDataToTS(0x28, 0x42); 76 writeDataToTS(0x29, 0x00); 77 writeDataToTS(0x2A, 0x00); 78 writeDataToTS(0x2B, 0x00); 79 writeDataToTS(0x2C, 0x42); 80 writeDataToTS(0x2D, 0x00); 81 writeDataToTS(0x2E, 0x00); 82 writeDataToTS(0x2F, 0x00); 83 writeDataToTS(0x30, 0x42); 84 writeDataToTS(0x31, 0x42); 85 writeDataToTS(0x32, 0x42); 86 writeDataToTS(0x33, 0x42); 87 88 // Recalibration if touch detected for more than 8 seconds n*0.16s 89 writeDataToTS(0x0C, 50); 90 91 // Enable keys and set key groups 92 writeDataToTS(0x1C, 0x00 | 0x04); 93 writeDataToTS(0x1D, 0x00 | 0x08); 94 writeDataToTS(0x1E, 0x00 | 0x08); 95 writeDataToTS(0x1F, 0x00 | 0x08); 96 writeDataToTS(0x20, 0x00 | 0x04); 97 writeDataToTS(0x21, 0x00 | 0x08); 98 writeDataToTS(0x22, 0x00 | 0x08); 99 writeDataToTS(0x23, 0x00 | 0x08); 100 writeDataToTS(0x24, 0x00 | 0x04); 101 writeDataToTS(0x25, 0x00 | 0x04); 102 writeDataToTS(0x26, 0x00 | 0x04); 103 writeDataToTS(0x27, 0x00 | 0x04); 104 105 } 106 return temp_return; 107 } 108 109 __attribute__ ((weak)) 110 void matrix_init_user(void) {} 111 112 __attribute__ ((weak)) 113 void matrix_scan_user(void) {} 114 115 __attribute__ ((weak)) 116 void matrix_init_kb(void) { 117 matrix_init_user(); 118 } 119 120 __attribute__ ((weak)) 121 void matrix_scan_kb(void) { 122 matrix_scan_user(); 123 } 124 125 void matrix_init(void) { 126 127 i2c_init(); 128 129 //Motor enable 130 gpio_set_pin_output(E6); 131 //Motor PWM 132 gpio_set_pin_output(D7); 133 134 //Power LED 135 gpio_set_pin_output(B7); 136 gpio_write_pin_high(B7); 137 138 //LEDs Columns 139 gpio_set_pin_output(F7); 140 gpio_set_pin_output(F6); 141 gpio_set_pin_output(F5); 142 gpio_set_pin_output(F4); 143 gpio_set_pin_output(F1); 144 gpio_set_pin_output(F0); 145 146 //LEDs Rows 147 gpio_set_pin_output(D6); 148 gpio_set_pin_output(B4); 149 gpio_set_pin_output(B5); 150 gpio_set_pin_output(B6); 151 gpio_set_pin_output(C6); 152 gpio_set_pin_output(C7); 153 154 //Capacitive Interrupt 155 gpio_set_pin_input(D2); 156 157 capSetup(); 158 writeDataToTS(0x06, 0x12); //Calibrate capacitive touch IC 159 160 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); 161 162 matrix_init_kb(); 163 } 164 165 166 uint16_t touchDetectionRoutine(void) { 167 uint16_t data; 168 uint8_t temp1, temp2; 169 170 temp1 = readDataFromTS(0x04); 171 temp2 = readDataFromTS(0x03); 172 data = temp1; 173 data = (data << 8) | temp2; 174 return data; 175 176 } 177 178 //Process raw capacitive data, map pins to rows and columns 179 void decodeArray(uint16_t dataIn, uint8_t *column, uint8_t *row) { 180 uint8_t i1 = 20, i2 = 20; 181 for (uint8_t i = 0; i < 12; i++) { 182 if ((dataIn & 0b1) == 1) { 183 if (i1 == 20) { 184 i1 = i; 185 } else if (i2 == 20) { 186 i2 = i; 187 } 188 } 189 dataIn = dataIn >> 1; 190 } 191 192 for (uint8_t j = 0; j < 6; j++) { 193 if (SENr[j] == i1 || SENr[j] == i2) { 194 *row = j; 195 } 196 if (SENc[j] == i1 || SENc[j] == i2) { 197 *column = j; 198 } 199 } 200 } 201 202 void touchClearCurrentDetections(void) { 203 readDataFromTS(0x05); 204 readDataFromTS(0x02); 205 readDataFromTS(0x03); 206 readDataFromTS(0x04); 207 } 208 209 //Check interrupt pin 210 uint8_t isTouchChangeDetected(void) { 211 return !gpio_read_pin(D2); 212 } 213 214 uint8_t matrix_scan(void) { 215 if (isTouchChangeDetected()) { 216 uint16_t dataIn = touchDetectionRoutine(); 217 if ((dataIn & 0b111100010001) > 0 && (dataIn & 0b000011101110) > 0) { 218 uint8_t column = 10, row = 10; 219 decodeArray(dataIn, &column, &row); 220 if (column != 10 && row != 10) { 221 vibrate = VIBRATE_LENGTH; //Trigger vibration 222 matrix[row] = _BV(column); 223 } else { 224 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); 225 } 226 } else { 227 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); 228 } 229 touchClearCurrentDetections(); 230 } 231 232 for (uint8_t c = 0; c < 6; c++) { 233 for (uint8_t r = 0; r < 6; r++) { 234 switch (r) { 235 case 0: gpio_write_pin(D6, matrix_is_on(r, c)); break; 236 case 1: gpio_write_pin(B4, matrix_is_on(r, c)); break; 237 case 2: gpio_write_pin(B5, matrix_is_on(r, c)); break; 238 case 3: gpio_write_pin(B6, matrix_is_on(r, c)); break; 239 case 4: gpio_write_pin(C6, matrix_is_on(r, c)); break; 240 case 5: gpio_write_pin(C7, matrix_is_on(r, c)); break; 241 } 242 243 switch (c) { 244 case 0: gpio_write_pin(F5, !matrix_is_on(r, c)); break; 245 case 1: gpio_write_pin(F4, !matrix_is_on(r, c)); break; 246 case 2: gpio_write_pin(F1, !matrix_is_on(r, c)); break; 247 case 3: gpio_write_pin(F0, !matrix_is_on(r, c)); break; 248 case 4: gpio_write_pin(F6, !matrix_is_on(r, c)); break; 249 case 5: gpio_write_pin(F7, !matrix_is_on(r, c)); break; 250 } 251 } 252 } 253 254 if (vibrate == VIBRATE_LENGTH) { 255 gpio_write_pin_high(E6); 256 gpio_write_pin_high(D7); 257 vibrate--; 258 } else if (vibrate > 0) { 259 vibrate--; 260 } else if (vibrate == 0) { 261 gpio_write_pin_low(D7); 262 gpio_write_pin_low(E6); 263 } 264 265 matrix_scan_kb(); 266 267 return 1; 268 269 } 270 271 bool matrix_is_on(uint8_t row, uint8_t col) { 272 return (matrix[row] & (1<<col)); 273 } 274 275 matrix_row_t matrix_get_row(uint8_t row) { 276 return matrix[row]; 277 } 278 279 void matrix_print(void) { 280 xprintf("\nr/c 01234567\n"); 281 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 282 xprintf("%X0: ", row); 283 matrix_row_t data = matrix_get_row(row); 284 for (int col = 0; col < MATRIX_COLS; col++) { 285 if (data & (1<<col)) 286 xprintf("1"); 287 else 288 xprintf("0"); 289 } 290 xprintf("\n"); 291 } 292 }