qmk_firmware

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

matrix.c (5136B)


      1 #include <stdint.h>
      2 #include <stdbool.h>
      3 #include <avr/io.h>
      4 #include "wait.h"
      5 #include "action_layer.h"
      6 #include "print.h"
      7 #include "debug.h"
      8 #include "util.h"
      9 #include "matrix.h"
     10 #include "hotdox.h"
     11 #include "left.h"
     12 
     13 /*
     14  * This constant define not debouncing time in msecs, but amount of matrix
     15  * scan loops which should be made to get stable debounced results.
     16  *
     17  * On Ergodox matrix scan rate is relatively low, because of slow I2C.
     18  * Now it's only 317 scans/second, or about 3.15 msec/scan.
     19  * According to Cherry specs, debouncing time is 5 msec.
     20  *
     21  * And so, there is no sense to have DEBOUNCE higher than 2.
     22  */
     23 
     24 #ifndef DEBOUNCE
     25 #   define DEBOUNCE	5
     26 #endif
     27 
     28 /* matrix state(1:on, 0:off) */
     29 static matrix_row_t matrix[MATRIX_ROWS];
     30 
     31 // Debouncing: store for each key the number of scans until it's eligible to
     32 // change.  When scanning the matrix, ignore any changes in keys that have
     33 // already changed in the last DEBOUNCE scans.
     34 static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
     35 
     36 static matrix_row_t read_cols(uint8_t row);
     37 static void init_cols(void);
     38 static void unselect_rows(void);
     39 static void select_row(uint8_t row);
     40 
     41 __attribute__ ((weak))
     42 void matrix_init_user(void) {}
     43 
     44 __attribute__ ((weak))
     45 void matrix_scan_user(void) {}
     46 
     47 __attribute__ ((weak))
     48 void matrix_init_kb(void) {
     49   matrix_init_user();
     50 }
     51 
     52 __attribute__ ((weak))
     53 void matrix_scan_kb(void) {
     54   matrix_scan_user();
     55 }
     56 
     57 inline
     58 uint8_t matrix_rows(void)
     59 {
     60   return MATRIX_ROWS;
     61 }
     62 
     63 inline
     64 uint8_t matrix_cols(void)
     65 {
     66   return MATRIX_COLS;
     67 }
     68 
     69 void matrix_init(void)
     70 {
     71   unselect_rows();
     72   init_cols();
     73 
     74   //eeprom_update_word(EECONFIG_MAGIC, 0x0000);
     75 
     76   // initialize matrix state: all keys off
     77   for (uint8_t i=0; i < MATRIX_ROWS; i++) {
     78     matrix[i] = 0;
     79     for (uint8_t j=0; j < MATRIX_COLS; ++j) {
     80       debounce_matrix[i * MATRIX_COLS + j] = 0;
     81     }
     82   }
     83 
     84   matrix_init_kb();
     85 }
     86 
     87 void matrix_power_up(void) {
     88   unselect_rows();
     89   init_cols();
     90 
     91   // initialize matrix state: all keys off
     92   for (uint8_t i=0; i < MATRIX_ROWS; i++) {
     93     matrix[i] = 0;
     94   }
     95 }
     96 
     97 // Returns a matrix_row_t whose bits are set if the corresponding key should be
     98 // eligible to change in this scan.
     99 matrix_row_t debounce_mask(uint8_t row) {
    100   matrix_row_t result = 0;
    101   for (uint8_t j=0; j < MATRIX_COLS; ++j) {
    102     if (debounce_matrix[row * MATRIX_COLS + j]) {
    103       --debounce_matrix[row * MATRIX_COLS + j];
    104     } else {
    105       result |= (1 << j);
    106     }
    107   }
    108   return result;
    109 }
    110 
    111 // Report changed keys in the given row.  Resets the debounce countdowns
    112 // corresponding to each set bit in 'change' to DEBOUNCE.
    113 void debounce_report(matrix_row_t change, uint8_t row) {
    114   for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
    115     if (change & (1 << i)) {
    116       debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
    117     }
    118   }
    119 }
    120 
    121 uint8_t matrix_scan(void)
    122 {
    123   left_scan();
    124 
    125   for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
    126     select_row(i);
    127     wait_us(30);  // without this wait read unstable value.
    128     matrix_row_t mask = debounce_mask(i);
    129     matrix_row_t cols = (read_cols(i) & mask) | (matrix[i] & ~mask);
    130     debounce_report(cols ^ matrix[i], i);
    131     matrix[i] = cols;
    132 
    133     unselect_rows();
    134   }
    135 
    136   matrix_scan_kb();
    137 
    138   return 1;
    139 }
    140 
    141 inline
    142 bool matrix_is_on(uint8_t row, uint8_t col)
    143 {
    144   return (matrix[row] & ((matrix_row_t)1<<col));
    145 }
    146 
    147 inline
    148 matrix_row_t matrix_get_row(uint8_t row)
    149 {
    150   return matrix[row];
    151 }
    152 
    153 void matrix_print(void)
    154 {
    155   print("\nr/c 0123456789ABCDEF\n");
    156   for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
    157     print_hex8(row); print(": ");
    158     print_bin_reverse16(matrix_get_row(row));
    159     print("\n");
    160   }
    161 }
    162 
    163 static void init_cols(void)
    164 {
    165   // Pro Micro
    166   gpio_set_pin_input_high(B0);
    167   gpio_set_pin_input_high(B1);
    168   gpio_set_pin_input_high(B2);
    169   gpio_set_pin_input_high(B3);
    170 
    171   gpio_set_pin_input_high(D2);
    172   gpio_set_pin_input_high(D3);
    173 
    174   gpio_set_pin_input_high(C6);
    175 
    176   left_init();
    177 }
    178 
    179 static matrix_row_t read_cols(uint8_t row)
    180 {
    181   matrix_row_t cols0 = 0x00, cols1 = 0x00;
    182 
    183   cols0 = left_read_cols();
    184 
    185   cols1 = (PINC&(1<<PC6) ? 0 : (1<<(0+7))) |
    186           (PIND&(1<<PD3) ? 0 : (1<<(1+7))) |
    187           (PIND&(1<<PD2) ? 0 : (1<<(2+7))) |
    188           (PINB&(1<<PB3) ? 0 : (1<<(3+7))) |
    189           (PINB&(1<<PB2) ? 0 : (1<<(4+7))) |
    190           (PINB&(1<<PB1) ? 0 : (1<<(5+7))) |
    191           (PINB&(1<<PB0) ? 0 : (1<<(6+7))) ;
    192 
    193   return (cols0 | cols1);
    194 }
    195 
    196 static void unselect_rows(void)
    197 {
    198   // Pro Micro
    199   gpio_set_pin_input(F0);
    200   gpio_set_pin_input(F1);
    201   gpio_set_pin_input(F4);
    202   gpio_set_pin_input(F5);
    203   gpio_set_pin_input(F6);
    204   gpio_set_pin_input(F7);
    205 
    206   left_unselect_rows();
    207 }
    208 
    209 static void select_row(uint8_t row)
    210 {
    211   // Pro Micro
    212   switch (row) {
    213   case 5:
    214     gpio_set_pin_output(F0);
    215     gpio_write_pin_low(F0);
    216     break;
    217   case 4:
    218     gpio_set_pin_output(F1);
    219     gpio_write_pin_low(F1);
    220     break;
    221   case 3:
    222     gpio_set_pin_output(F4);
    223     gpio_write_pin_low(F4);
    224     break;
    225   case 2:
    226     gpio_set_pin_output(F5);
    227     gpio_write_pin_low(F5);
    228     break;
    229   case 1:
    230     gpio_set_pin_output(F6);
    231     gpio_write_pin_low(F6);
    232     break;
    233   case 0:
    234     gpio_set_pin_output(F7);
    235     gpio_write_pin_low(F7);
    236     break;
    237   }
    238 
    239   left_select_row(row);
    240 }
    241