qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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 }