qmk_firmware

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

matrix.c (9530B)


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