qmk_firmware

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

matrix.c (9571B)


      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 "util.h"
     30 #include "matrix.h"
     31 #include "timer.h"
     32 #include "i2c_slave.h"
     33 #include "lufa.h"
     34 
     35 #define SLAVE_I2C_ADDRESS 0x40
     36 
     37 /* Set 0 if debouncing isn't needed */
     38 
     39 #ifndef DEBOUNCE
     40 #   define DEBOUNCE 5
     41 #endif
     42 
     43 #if (DEBOUNCE > 0)
     44     static uint16_t debouncing_time;
     45     static bool debouncing = false;
     46 #endif
     47 
     48 #if (MATRIX_COLS <= 8)
     49 #    define print_matrix_header()  print("\nr/c 01234567\n")
     50 #    define print_matrix_row(row)  print_bin_reverse8(matrix_get_row(row))
     51 #    define ROW_SHIFTER ((uint8_t)1)
     52 #elif (MATRIX_COLS <= 16)
     53 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF\n")
     54 #    define print_matrix_row(row)  print_bin_reverse16(matrix_get_row(row))
     55 #    define ROW_SHIFTER ((uint16_t)1)
     56 #elif (MATRIX_COLS <= 32)
     57 #    define print_matrix_header()  print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
     58 #    define print_matrix_row(row)  print_bin_reverse32(matrix_get_row(row))
     59 #    define ROW_SHIFTER  ((uint32_t)1)
     60 #endif
     61 
     62 #ifdef MATRIX_MASKED
     63     extern const matrix_row_t matrix_mask[];
     64 #endif
     65 
     66 #if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
     67 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
     68 static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
     69 #endif
     70 
     71 /* matrix state(1:on, 0:off) */
     72 static matrix_row_t matrix[MATRIX_ROWS];
     73 
     74 static matrix_row_t matrix_debouncing[MATRIX_ROWS];
     75 
     76 
     77 #if (DIODE_DIRECTION == COL2ROW)
     78     static void init_cols(void);
     79     static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
     80     static void unselect_rows(void);
     81     static void select_row(uint8_t row);
     82     static void unselect_row(uint8_t row);
     83 #elif (DIODE_DIRECTION == ROW2COL)
     84     static void init_rows(void);
     85     static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
     86     static void unselect_cols(void);
     87     static void unselect_col(uint8_t col);
     88     static void select_col(uint8_t col);
     89 #endif
     90 
     91 __attribute__ ((weak))
     92 void matrix_init_kb(void) {
     93     matrix_init_user();
     94 }
     95 
     96 __attribute__ ((weak))
     97 void matrix_scan_kb(void) {
     98     matrix_scan_user();
     99 }
    100 
    101 __attribute__ ((weak))
    102 void matrix_init_user(void) {
    103 }
    104 
    105 __attribute__ ((weak))
    106 void matrix_scan_user(void) {
    107 }
    108 
    109 inline
    110 uint8_t matrix_rows(void) {
    111     return MATRIX_ROWS;
    112 }
    113 
    114 inline
    115 uint8_t matrix_cols(void) {
    116     return MATRIX_COLS;
    117 }
    118 
    119 void matrix_init(void) {
    120 
    121     // initialize row and col
    122 #if (DIODE_DIRECTION == COL2ROW)
    123     unselect_rows();
    124     init_cols();
    125 #elif (DIODE_DIRECTION == ROW2COL)
    126     unselect_cols();
    127     init_rows();
    128 #endif
    129 
    130     // initialize matrix state: all keys off
    131     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
    132         matrix[i] = 0;
    133         matrix_debouncing[i] = 0;
    134     }
    135 
    136     matrix_init_kb();
    137 }
    138 
    139 uint8_t matrix_scan(void)
    140 {
    141 #if (DIODE_DIRECTION == COL2ROW)
    142 
    143     // Set row, read cols
    144     for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
    145 #       if (DEBOUNCE > 0)
    146             bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
    147 
    148             if (matrix_changed) {
    149                 debouncing = true;
    150                 debouncing_time = timer_read();
    151             }
    152 
    153 #       else
    154             read_cols_on_row(matrix, current_row);
    155 #       endif
    156 
    157     }
    158 
    159 #elif (DIODE_DIRECTION == ROW2COL)
    160 
    161     // Set col, read rows
    162     for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
    163 #       if (DEBOUNCE > 0)
    164             bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
    165             if (matrix_changed) {
    166                 debouncing = true;
    167                 debouncing_time = timer_read();
    168             }
    169 #       else
    170              read_rows_on_col(matrix, current_col);
    171 #       endif
    172 
    173     }
    174 
    175 #endif
    176 
    177 #   if (DEBOUNCE > 0)
    178         if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCE)) {
    179             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
    180                 matrix[i] = matrix_debouncing[i];
    181             }
    182             debouncing = false;
    183         }
    184 #   endif
    185 
    186     i2c_slave_reg[1] = 0x55;
    187     for (uint8_t i = 0; i < MATRIX_ROWS; i++){
    188         i2c_slave_reg[i+2] = matrix[i]; //send matrix over i2c
    189     }
    190 
    191     matrix_scan_kb();
    192     return 1;
    193 }
    194 
    195 inline
    196 bool matrix_is_on(uint8_t row, uint8_t col)
    197 {
    198     return (matrix[row] & ((matrix_row_t)1<<col));
    199 }
    200 
    201 inline
    202 matrix_row_t matrix_get_row(uint8_t row)
    203 {
    204     // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
    205     // switch blocker installed and the switch is always pressed.
    206 #ifdef MATRIX_MASKED
    207     return matrix[row] & matrix_mask[row];
    208 #else
    209     return matrix[row];
    210 #endif
    211 }
    212 
    213 void matrix_print(void)
    214 {
    215     print_matrix_header();
    216 
    217     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    218         print_hex8(row); print(": ");
    219         print_matrix_row(row);
    220         print("\n");
    221     }
    222 }
    223 
    224 #if (DIODE_DIRECTION == COL2ROW)
    225 
    226 static void init_cols(void)
    227 {
    228     for(uint8_t x = 0; x < MATRIX_COLS; x++) {
    229         uint8_t pin = col_pins[x];
    230         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    231         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    232     }
    233 }
    234 
    235 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
    236 {
    237     // Store last value of row prior to reading
    238     matrix_row_t last_row_value = current_matrix[current_row];
    239 
    240     // Clear data in matrix row
    241     current_matrix[current_row] = 0;
    242 
    243     // Select row and wait for row selecton to stabilize
    244     select_row(current_row);
    245     wait_us(30);
    246 
    247     // For each col...
    248     for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
    249 
    250         // Select the col pin to read (active low)
    251         uint8_t pin = col_pins[col_index];
    252         uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
    253 
    254         // Populate the matrix row with the state of the col pin
    255         current_matrix[current_row] |=  pin_state ? 0 : (ROW_SHIFTER << col_index);
    256     }
    257 
    258     // Unselect row
    259     unselect_row(current_row);
    260 
    261     return (last_row_value != current_matrix[current_row]);
    262 }
    263 
    264 static void select_row(uint8_t row)
    265 {
    266     uint8_t pin = row_pins[row];
    267     _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
    268     _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
    269 }
    270 
    271 static void unselect_row(uint8_t row)
    272 {
    273     uint8_t pin = row_pins[row];
    274     _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    275     _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    276 }
    277 
    278 static void unselect_rows(void)
    279 {
    280     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
    281         uint8_t pin = row_pins[x];
    282         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    283         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    284     }
    285 }
    286 
    287 #elif (DIODE_DIRECTION == ROW2COL)
    288 
    289 static void init_rows(void)
    290 {
    291     for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
    292         uint8_t pin = row_pins[x];
    293         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    294         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    295     }
    296 }
    297 
    298 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
    299 {
    300     bool matrix_changed = false;
    301 
    302     // Select col and wait for col selecton to stabilize
    303     select_col(current_col);
    304     wait_us(30);
    305 
    306     // For each row...
    307     for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
    308     {
    309 
    310         // Store last value of row prior to reading
    311         matrix_row_t last_row_value = current_matrix[row_index];
    312 
    313         // Check row pin state
    314         if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
    315         {
    316             // Pin LO, set col bit
    317             current_matrix[row_index] |= (ROW_SHIFTER << current_col);
    318         }
    319         else
    320         {
    321             // Pin HI, clear col bit
    322             current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
    323         }
    324 
    325         // Determine if the matrix changed state
    326         if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
    327         {
    328             matrix_changed = true;
    329         }
    330     }
    331 
    332     // Unselect col
    333     unselect_col(current_col);
    334 
    335     return matrix_changed;
    336 }
    337 
    338 static void select_col(uint8_t col)
    339 {
    340     uint8_t pin = col_pins[col];
    341     _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
    342     _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
    343 }
    344 
    345 static void unselect_col(uint8_t col)
    346 {
    347     uint8_t pin = col_pins[col];
    348     _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    349     _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    350 }
    351 
    352 static void unselect_cols(void)
    353 {
    354     for(uint8_t x = 0; x < MATRIX_COLS; x++) {
    355         uint8_t pin = col_pins[x];
    356         _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
    357         _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
    358     }
    359 }
    360 
    361 #endif
    362 
    363 //this replases tmk code
    364 void matrix_setup(void){
    365     i2c_slave_init(SLAVE_I2C_ADDRESS); //setup address of slave i2c
    366     sei(); //enable interupts
    367 }