qmk_firmware

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

matrix.c (10607B)


      1 /*
      2 Copyright 2012 Jun Wako
      3 Copyright 2014 Jack Humbert
      4 
      5 This program is free software: you can redistribute it and/or modify
      6 it under the terms of the GNU General Public License as published by
      7 the Free Software Foundation, either version 2 of the License, or
      8 (at your option) any later version.
      9 
     10 This program is distributed in the hope that it will be useful,
     11 but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 */
     18 #include <stdint.h>
     19 #include <stdbool.h>
     20 #if defined(__AVR__)
     21 #include <avr/io.h>
     22 #include <avr/wdt.h>
     23 #include <avr/interrupt.h>
     24 #include <util/delay.h>
     25 #endif
     26 #include "wait.h"
     27 #include "print.h"
     28 #include "debug.h"
     29 #include "gpio.h"
     30 #include "util.h"
     31 #include "matrix.h"
     32 #include "timer.h"
     33 #include "i2c_master.h"
     34 
     35 #define SLAVE_I2C_ADDRESS_RIGHT 0x32
     36 #define SLAVE_I2C_ADDRESS_NUMPAD 0x36
     37 #define SLAVE_I2C_ADDRESS_ARROW 0x40
     38 
     39 #define ERROR_DISCONNECT_COUNT 5
     40 
     41 /* Set 0 if debouncing isn't needed */
     42 
     43 #ifndef DEBOUNCE
     44 #    define DEBOUNCE 5
     45 #endif
     46 
     47 #if (DEBOUNCE > 0)
     48     static uint16_t debouncing_time;
     49     static bool debouncing = false;
     50 #endif
     51 
     52 #if (MATRIX_COLS <= 8)
     53 #    define print_matrix_header()  print("\nr/c 01234567\n")
     54 #    define print_matrix_row(row)  print_bin_reverse8(matrix_get_row(row))
     55 #    define ROW_SHIFTER ((uint8_t)1)
     56 #elif (MATRIX_COLS <= 16)
     57 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF\n")
     58 #    define print_matrix_row(row)  print_bin_reverse16(matrix_get_row(row))
     59 #    define ROW_SHIFTER ((uint16_t)1)
     60 #elif (MATRIX_COLS <= 32)
     61 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
     62 #    define print_matrix_row(row)  print_bin_reverse32(matrix_get_row(row))
     63 #    define ROW_SHIFTER  ((uint32_t)1)
     64 #endif
     65 
     66 #ifdef MATRIX_MASKED
     67     extern const matrix_row_t matrix_mask[];
     68 #endif
     69 
     70 #if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
     71 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     72 static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
     73 #endif
     74 
     75 /* matrix state(1:on, 0:off) */
     76 static matrix_row_t matrix[MATRIX_ROWS];
     77 
     78 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
     79 
     80 
     81 #if (DIODE_DIRECTION == COL2ROW)
     82     static void init_cols(void);
     83     static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
     84     static void unselect_rows(void);
     85     static void select_row(uint8_t row);
     86     static void unselect_row(uint8_t row);
     87 #elif (DIODE_DIRECTION == ROW2COL)
     88     static void init_rows(void);
     89     static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
     90     static void unselect_cols(void);
     91     static void unselect_col(uint8_t col);
     92     static void select_col(uint8_t col);
     93 #endif
     94 
     95 __attribute__ ((weak))
     96 void matrix_init_kb(void) {
     97     matrix_init_user();
     98 }
     99 
    100 __attribute__ ((weak))
    101 void matrix_scan_kb(void) {
    102     matrix_scan_user();
    103 }
    104 
    105 __attribute__ ((weak))
    106 void matrix_init_user(void) {
    107 }
    108 
    109 __attribute__ ((weak))
    110 void matrix_scan_user(void) {
    111 }
    112 
    113 inline
    114 uint8_t matrix_rows(void) {
    115     return MATRIX_ROWS;
    116 }
    117 
    118 inline
    119 uint8_t matrix_cols(void) {
    120     return MATRIX_COLS;
    121 }
    122 
    123 i2c_status_t i2c_transaction(uint8_t address, uint32_t mask, uint8_t col_offset);
    124 
    125 //this replases tmk code
    126 void matrix_setup(void){
    127     i2c_init();
    128 }
    129 
    130 void matrix_init(void) {
    131 
    132     // initialize row and col
    133 #if (DIODE_DIRECTION == COL2ROW)
    134     unselect_rows();
    135     init_cols();
    136 #elif (DIODE_DIRECTION == ROW2COL)
    137     unselect_cols();
    138     init_rows();
    139 #endif
    140 
    141     // initialize matrix state: all keys off
    142     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
    143         matrix[i] = 0;
    144         matrix_debouncing[i] = 0;
    145     }
    146 
    147     matrix_init_kb();
    148 }
    149 
    150 uint8_t matrix_scan(void)
    151 {
    152 
    153 #if (DIODE_DIRECTION == COL2ROW)
    154 
    155     // Set row, read cols
    156     for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    157 #       if (DEBOUNCE > 0)
    158             bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
    159 
    160             if (matrix_changed) {
    161                 debouncing = true;
    162                 debouncing_time = timer_read();
    163             }
    164 
    165 #       else
    166             read_cols_on_row(matrix, current_row);
    167 #       endif
    168 
    169     }
    170 
    171 #elif (DIODE_DIRECTION == ROW2COL)
    172 
    173     // Set col, read rows
    174     for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
    175 #       if (DEBOUNCE > 0)
    176             bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
    177             if (matrix_changed) {
    178                 debouncing = true;
    179                 debouncing_time = timer_read();
    180             }
    181 #       else
    182              read_rows_on_col(matrix, current_col);
    183 #       endif
    184 
    185     }
    186 
    187 #endif
    188 
    189 #   if (DEBOUNCE > 0)
    190         if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCE)) {
    191             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
    192                 matrix[i] = matrix_debouncing[i];
    193             }
    194             debouncing = false;
    195         }
    196 #   endif
    197 
    198 if (i2c_transaction(SLAVE_I2C_ADDRESS_RIGHT, 0x3F, 0)) {
    199     for (uint8_t i = 0; i < MATRIX_ROWS ; i++) {
    200         matrix[i] &= 0x3F; //mask bits to keep
    201     }
    202 }
    203 
    204 if (i2c_transaction(SLAVE_I2C_ADDRESS_ARROW, 0X3FFF, 8)) {
    205     for (uint8_t i = 0; i < MATRIX_ROWS ; i++) {
    206         matrix[i] &= 0x3FFF; //mask bits to keep
    207     }
    208 }
    209 
    210 if (i2c_transaction(SLAVE_I2C_ADDRESS_NUMPAD, 0x1FFFF, 11)) {
    211     for (uint8_t i = 0; i < MATRIX_ROWS ; i++) {
    212         matrix[i] &= 0x1FFFF; //mask bits to keep
    213     }
    214 }
    215 
    216     matrix_scan_kb();
    217     return 1;
    218 }
    219 
    220 inline
    221 bool matrix_is_on(uint8_t row, uint8_t col)
    222 {
    223     return (matrix[row] & ((matrix_row_t)1<<col));
    224 }
    225 
    226 inline
    227 matrix_row_t matrix_get_row(uint8_t row)
    228 {
    229     // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
    230     // switch blocker installed and the switch is always pressed.
    231 #ifdef MATRIX_MASKED
    232     return matrix[row] & matrix_mask[row];
    233 #else
    234     return matrix[row];
    235 #endif
    236 }
    237 
    238 void matrix_print(void)
    239 {
    240     print_matrix_header();
    241 
    242     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    243         print_hex8(row); print(": ");
    244         print_matrix_row(row);
    245         print("\n");
    246     }
    247 }
    248 
    249 #if (DIODE_DIRECTION == COL2ROW)
    250 
    251 static void init_cols(void)
    252 {
    253     for(uint8_t x = 0; x < MATRIX_COLS_SCANNED; x++) {
    254         uint8_t pin = col_pins[x];
    255         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    256         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    257     }
    258 }
    259 
    260 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
    261 {
    262     // Store last value of row prior to reading
    263     matrix_row_t last_row_value = current_matrix[current_row];
    264 
    265     // Clear data in matrix row
    266     current_matrix[current_row] = 0;
    267 
    268     // Select row and wait for row selecton to stabilize
    269     select_row(current_row);
    270     wait_us(30);
    271 
    272     // For each col...
    273     for(uint8_t col_index = 0; col_index < MATRIX_COLS_SCANNED; col_index++) {
    274 
    275         // Select the col pin to read (active low)
    276         uint8_t pin = col_pins[col_index];
    277         uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
    278 
    279         // Populate the matrix row with the state of the col pin
    280         current_matrix[current_row] |=  pin_state ? 0 : (ROW_SHIFTER << col_index);
    281     }
    282 
    283     // Unselect row
    284     unselect_row(current_row);
    285 
    286     return (last_row_value != current_matrix[current_row]);
    287 }
    288 
    289 static void select_row(uint8_t row)
    290 {
    291     uint8_t pin = row_pins[row];
    292     _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
    293     _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
    294 }
    295 
    296 static void unselect_row(uint8_t row)
    297 {
    298     uint8_t pin = row_pins[row];
    299     _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    300     _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    301 }
    302 
    303 static void unselect_rows(void)
    304 {
    305     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
    306         uint8_t pin = row_pins[x];
    307         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    308         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    309     }
    310 }
    311 
    312 #elif (DIODE_DIRECTION == ROW2COL)
    313 
    314 static void init_rows(void)
    315 {
    316     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
    317         uint8_t pin = row_pins[x];
    318         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    319         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    320     }
    321 }
    322 
    323 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
    324 {
    325     bool matrix_changed = false;
    326 
    327     // Select col and wait for col selecton to stabilize
    328     select_col(current_col);
    329     wait_us(30);
    330 
    331     // For each row...
    332     for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
    333     {
    334 
    335         // Store last value of row prior to reading
    336         matrix_row_t last_row_value = current_matrix[row_index];
    337 
    338         // Check row pin state
    339         if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
    340         {
    341             // Pin LO, set col bit
    342             current_matrix[row_index] |= (ROW_SHIFTER << current_col);
    343         }
    344         else
    345         {
    346             // Pin HI, clear col bit
    347             current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
    348         }
    349 
    350         // Determine if the matrix changed state
    351         if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
    352         {
    353             matrix_changed = true;
    354         }
    355     }
    356 
    357     // Unselect col
    358     unselect_col(current_col);
    359 
    360     return matrix_changed;
    361 }
    362 
    363 static void select_col(uint8_t col)
    364 {
    365     uint8_t pin = col_pins[col];
    366     _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
    367     _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
    368 }
    369 
    370 static void unselect_col(uint8_t col)
    371 {
    372     uint8_t pin = col_pins[col];
    373     _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    374     _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    375 }
    376 
    377 static void unselect_cols(void)
    378 {
    379     for(uint8_t x = 0; x < MATRIX_COLS_SCANNED; x++) {
    380         uint8_t pin = col_pins[x];
    381         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    382         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    383     }
    384 }
    385 
    386 #endif
    387 
    388 // Complete rows from other modules over i2c
    389 i2c_status_t i2c_transaction(uint8_t address, uint32_t mask, uint8_t col_offset) {
    390     uint8_t data[MATRIX_ROWS + 1];
    391     i2c_status_t status = i2c_read_register(address, 0x01, data, (MATRIX_ROWS + 1), 5);
    392 
    393     for (uint8_t i = 0; i < (MATRIX_ROWS) && status >= 0; i++) { //assemble slave matrix in main matrix
    394         matrix[i] &= mask;  //mask bits to keep
    395         matrix[i] |= ((uint32_t)data[i+1] << (MATRIX_COLS_SCANNED + col_offset)); //add new bits at the end
    396     }
    397 
    398     return status;
    399 }