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