qmk_firmware

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

matrix.c (8803B)


      1 /*
      2 
      3 Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
      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 
     19 #include "matrix.h"
     20 #include "wait.h"
     21 #include "debug.h"
     22 #include "util.h"
     23 #include "georgi.h"
     24 
     25 #ifndef DEBOUNCE
     26 #   define DEBOUNCE	5
     27 #endif
     28 
     29 // MCP Pin Defs
     30 #define RROW1 (1<<3)
     31 #define RROW2 (1<<2)
     32 #define RROW3 (1<<1)
     33 #define RROW4 (1<<0)
     34 #define COL0 (1<<0)
     35 #define COL1 (1<<1)
     36 #define COL2 (1<<2)
     37 #define COL3 (1<<3)
     38 #define COL4 (1<<4)
     39 #define COL5 (1<<5)
     40 #define COL6 (1<<6)
     41 
     42 // ATmega pin defs
     43 #define ROW1  (1<<6)
     44 #define ROW2  (1<<5)
     45 #define ROW3  (1<<4)
     46 #define ROW4  (1<<1)
     47 #define COL7 (1<<0)
     48 #define COL8 (1<<1)
     49 #define COL9 (1<<2)
     50 #define COL10 (1<<3)
     51 #define COL11 (1<<2)
     52 #define COL12 (1<<3)
     53 #define COL13 (1<<6)
     54 
     55 
     56 // bit masks
     57 #define BMASK     (COL7 | COL8 | COL9 | COL10)
     58 #define CMASK     (COL13)
     59 #define DMASK     (COL11 | COL12)
     60 #define FMASK     (ROW1 | ROW2 | ROW3 | ROW4)
     61 #define RROWMASK  (RROW1 | RROW2 | RROW3 | RROW4)
     62 #define MCPMASK   (COL0 | COL1 | COL2 | COL3 | COL4 | COL5 | COL6)
     63 
     64 /* matrix state(1:on, 0:off) */
     65 static matrix_row_t matrix[MATRIX_ROWS];
     66 /*
     67  * matrix state(1:on, 0:off)
     68  * contains the raw values without debounce filtering of the last read cycle.
     69  */
     70 static matrix_row_t raw_matrix[MATRIX_ROWS];
     71 
     72 // Debouncing: store for each key the number of scans until it's eligible to
     73 // change.  When scanning the matrix, ignore any changes in keys that have
     74 // already changed in the last DEBOUNCE scans.
     75 static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
     76 
     77 static matrix_row_t read_cols(uint8_t row);
     78 static void init_cols(void);
     79 static void unselect_rows(void);
     80 static void select_row(uint8_t row);
     81 
     82 static uint8_t mcp23018_reset_loop;
     83 // static uint16_t mcp23018_reset_loop;
     84 
     85 __attribute__ ((weak))
     86 void matrix_init_user(void) {}
     87 
     88 __attribute__ ((weak))
     89 void matrix_scan_user(void) {}
     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 inline
    102 uint8_t matrix_rows(void)
    103 {
    104     return MATRIX_ROWS;
    105 }
    106 
    107 inline
    108 uint8_t matrix_cols(void)
    109 {
    110     return MATRIX_COLS;
    111 }
    112 
    113 
    114 void matrix_init(void)
    115 {
    116     // initialize row and col
    117     mcp23018_status = init_mcp23018();
    118     unselect_rows();
    119     init_cols();
    120 
    121     // initialize matrix state: all keys off
    122     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
    123         matrix[i] = 0;
    124         raw_matrix[i] = 0;
    125         for (uint8_t j=0; j < MATRIX_COLS; ++j) {
    126             debounce_matrix[i * MATRIX_COLS + j] = 0;
    127         }
    128     }
    129 
    130     matrix_init_kb();
    131 }
    132 
    133 void matrix_power_up(void) {
    134     mcp23018_status = init_mcp23018();
    135 
    136     unselect_rows();
    137     init_cols();
    138 
    139     // initialize matrix state: all keys off
    140     for (uint8_t i=0; i < MATRIX_ROWS; i++) {
    141         matrix[i] = 0;
    142     }
    143 }
    144 
    145 // Returns a matrix_row_t whose bits are set if the corresponding key should be
    146 // eligible to change in this scan.
    147 matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) {
    148   matrix_row_t result = 0;
    149   matrix_row_t change = rawcols ^ raw_matrix[row];
    150   raw_matrix[row] = rawcols;
    151   for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
    152     if (debounce_matrix[row * MATRIX_COLS + i]) {
    153       --debounce_matrix[row * MATRIX_COLS + i];
    154     } else {
    155       result |= (1 << i);
    156     }
    157     if (change & (1 << i)) {
    158       debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
    159     }
    160   }
    161   return result;
    162 }
    163 
    164 matrix_row_t debounce_read_cols(uint8_t row) {
    165   // Read the row without debouncing filtering and store it for later usage.
    166   matrix_row_t cols = read_cols(row);
    167   // Get the Debounce mask.
    168   matrix_row_t mask = debounce_mask(cols, row);
    169   // debounce the row and return the result.
    170   return (cols & mask) | (matrix[row] & ~mask);;
    171 }
    172 
    173 uint8_t matrix_scan(void)
    174 {
    175   // Then the keyboard
    176   if (mcp23018_status) { // if there was an error
    177       if (++mcp23018_reset_loop == 0) {
    178       // if (++mcp23018_reset_loop >= 1300) {
    179           // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
    180           // this will be approx bit more frequent than once per second
    181           print("trying to reset mcp23018\n");
    182           mcp23018_status = init_mcp23018();
    183           if (mcp23018_status) {
    184               print("left side not responding\n");
    185           } else {
    186               print("left side attached\n");
    187           }
    188       }
    189   }
    190 
    191     for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
    192         select_row(i);
    193         // and select on left hand
    194         select_row(i + MATRIX_ROWS_PER_SIDE);
    195         // we don't need a 30us delay anymore, because selecting a
    196         // left-hand row requires more than 30us for i2c.
    197 
    198         // grab cols from left hand
    199         matrix[i] = debounce_read_cols(i);
    200         // grab cols from right hand
    201         matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE);
    202 
    203         unselect_rows();
    204     }
    205 
    206     matrix_scan_kb();
    207 
    208 #ifdef DEBUG_MATRIX
    209     for (uint8_t c = 0; c < MATRIX_COLS; c++)
    210 		for (uint8_t r = 0; r < MATRIX_ROWS; r++)
    211 		  if (matrix_is_on(r, c)) xprintf("r:%d c:%d \n", r, c);
    212 #endif
    213 
    214     return 1;
    215 }
    216 
    217 inline
    218 bool matrix_is_on(uint8_t row, uint8_t col)
    219 {
    220     return (matrix[row] & ((matrix_row_t)1<<col));
    221 }
    222 
    223 inline
    224 matrix_row_t matrix_get_row(uint8_t row)
    225 {
    226     return matrix[row];
    227 }
    228 
    229 void matrix_print(void)
    230 {
    231     print("\nr/c 0123456789ABCDEF\n");
    232     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    233         print_hex8(row); print(": ");
    234         print_bin_reverse16(matrix_get_row(row));
    235         print("\n");
    236     }
    237 }
    238 
    239 // Remember this means ROWS
    240 static void  init_cols(void)
    241 {
    242     // init on mcp23018
    243     // not needed, already done as part of init_mcp23018()
    244 
    245     // Input with pull-up(DDR:0, PORT:1)
    246     DDRF  &= ~FMASK;
    247     PORTF |=  FMASK;
    248 }
    249 
    250 static matrix_row_t read_cols(uint8_t row)
    251 {
    252     if (row < 7) {
    253         if (mcp23018_status) { // if there was an error
    254             return 0;
    255         } else {
    256             uint8_t data = 0;
    257             mcp23018_status = i2c_read_register(I2C_ADDR, GPIOB, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
    258             data = ~data;
    259 
    260 #ifdef DEBUG_MATRIX
    261             if (data != 0x00) xprintf("I2C: %d\n", data);
    262 #endif
    263             return data;
    264         }
    265     } else {
    266          /* read from teensy
    267 	        * bitmask is 0b0111001, but we want the lower four
    268 	        * we'll return 1s for the top two, but that's harmless.
    269 	        */
    270         // So I need to confuckulate all this
    271         //return ~(((PIND & DMASK) >> 1  | ((PINC & CMASK) >> 6) | (PIN)));
    272         //return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2));
    273         return ~(
    274            (((PINF & ROW4) >> 1)
    275           | ((PINF & (ROW1 | ROW2 | ROW3)) >> 3))
    276         & 0xF);
    277     }
    278 }
    279 
    280 // Row pin configuration
    281 static void unselect_rows(void)
    282 {
    283     // no need to unselect on mcp23018, because the select step sets all
    284     // the other row bits high, and it's not changing to a different
    285     // direction
    286     // Hi-Z(DDR:0, PORT:0) to unselect
    287     DDRB  &= ~(BMASK);
    288     PORTB &= ~(BMASK);
    289     DDRC  &= ~CMASK;
    290     PORTC &= ~CMASK;
    291     DDRD  &= ~DMASK;
    292     PORTD &= ~DMASK;
    293 }
    294 
    295 static void select_row(uint8_t row)
    296 {
    297     if (row < 7) {
    298         // select on mcp23018
    299         if (mcp23018_status) { // do nothing on error
    300         } else { // set active row low  : 0 // set other rows hi-Z : 1
    301         uint8_t data = 0xFF & ~(1<<row);
    302         mcp23018_status = i2c_write_register(I2C_ADDR, GPIOA, &data, 1, ERGODOX_EZ_I2C_TIMEOUT);
    303 
    304         }
    305     } else {
    306         // Output low(DDR:1, PORT:0) to select
    307         switch (row) {
    308             case 7:
    309                 DDRB  |= COL7;
    310                 PORTB &= ~COL7;
    311                 break;
    312             case 8:
    313                 DDRB  |= COL8;
    314                 PORTB &= ~COL8;
    315                 break;
    316             case 9:
    317                 DDRB  |= COL9;
    318                 PORTB &= ~COL9;
    319                 break;
    320             case 10:
    321                 DDRB  |= COL10;
    322                 PORTB &= ~COL10;
    323                 break;
    324             case 11:
    325                 DDRD  |= COL11;
    326                 PORTD &= ~COL11;
    327                 break;
    328             case 12:
    329                 DDRD  |= COL12;
    330                 PORTD &= ~COL12;
    331                 break;
    332             case 13:
    333                 DDRC  |= COL13;
    334                 PORTC &= ~COL13;
    335                 break;
    336         }
    337     }
    338 }