matrix.c (6308B)
1 /** 2 * matrix.c 3 * 4 Copyright 2020 astro <yuleiz@gmail.com> 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 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 #include "matrix.h" 17 #include "print.h" 18 #include "bitwise.h" 19 #include "wait.h" 20 21 #ifndef DEBOUNCE 22 # define DEBOUNCE 5 23 #endif 24 25 static uint8_t debouncing = DEBOUNCE; 26 27 static matrix_row_t matrix[MATRIX_ROWS]; 28 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 29 30 static uint8_t read_rows(void); 31 static void init_rows(void); 32 static void init_cols(void); 33 static void unselect_cols(void); 34 static void select_col(uint8_t col); 35 36 37 __attribute__ ((weak)) 38 void matrix_init_kb(void) 39 { 40 matrix_init_user(); 41 } 42 43 __attribute__ ((weak)) 44 void matrix_scan_kb(void) 45 { 46 matrix_scan_user(); 47 } 48 49 __attribute__ ((weak)) 50 void matrix_init_user(void) {} 51 52 __attribute__ ((weak)) 53 void matrix_scan_user(void) {} 54 55 void matrix_init(void) 56 { 57 //gpio_set_pin_output(F0); 58 //gpio_write_pin_high(F0); 59 gpio_set_pin_output(B4); 60 gpio_write_pin_low(B4); 61 62 init_cols(); 63 init_rows(); 64 65 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 66 matrix[i] = 0; 67 matrix_debouncing[i] = 0; 68 } 69 70 matrix_init_kb(); 71 } 72 73 uint8_t matrix_scan(void) 74 { 75 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 76 select_col(col); 77 _delay_us(3); 78 79 uint8_t rows = read_rows(); 80 81 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 82 bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); 83 bool curr_bit = rows & (1<<row); 84 if (prev_bit != curr_bit) { 85 matrix_debouncing[row] ^= ((matrix_row_t)1<<col); 86 debouncing = DEBOUNCE; 87 } 88 } 89 unselect_cols(); 90 } 91 92 if (debouncing) { 93 if (--debouncing) { 94 _delay_ms(1); 95 } else { 96 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 97 matrix[i] = matrix_debouncing[i]; 98 } 99 } 100 } 101 102 matrix_scan_kb(); 103 return 1; 104 } 105 106 inline matrix_row_t matrix_get_row(uint8_t row) 107 { 108 return matrix[row]; 109 } 110 111 void matrix_print(void) 112 { 113 print("\nr/c 0123456789ABCDEF\n"); 114 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 115 xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row))); 116 } 117 } 118 119 /* 120 * Row pin configuration 121 * row: 0 1 2 3 4 122 * pin: PE6 PF6 PF7 PB7 PD4 123 */ 124 static void init_rows(void) 125 { 126 gpio_set_pin_input_high(E6); 127 gpio_set_pin_input_high(F6); 128 gpio_set_pin_input_high(F7); 129 gpio_set_pin_input_high(B7); 130 gpio_set_pin_input_high(D4); 131 } 132 133 static uint8_t read_rows(void) 134 { 135 return ((gpio_read_pin(E6) ? 0 : (1 << 0)) | 136 (gpio_read_pin(F6) ? 0 : (1 << 1)) | 137 (gpio_read_pin(F7) ? 0 : (1 << 2)) | 138 (gpio_read_pin(B7) ? 0 : (1 << 3)) | 139 (gpio_read_pin(D4) ? 0 : (1 << 4))); 140 } 141 142 /* 143 * Columns 0 - 13 144 * These columns uses two 74LVC138 3 to 8 bit demultiplexers. 145 * EN Pin, PF5, PD6 146 * 147 * col / pin: PF0 PF1 PF4 148 * 0: 0 0 0 149 * 1: 1 0 0 150 * 2: 0 1 0 151 * 3: 1 1 0 152 * 4: 0 0 1 153 * 5: 1 0 1 154 * 6: 0 1 1 155 * PD2 PD3 PD5 156 * 7: 0 0 0 157 * 8: 1 0 0 158 * 9: 0 1 0 159 * 10: 1 1 0 160 * 11: 0 0 1 161 * 12: 1 0 1 162 * 13: 0 1 1 163 * 164 */ 165 static void init_cols(void) 166 { 167 gpio_set_pin_output(F0); 168 gpio_set_pin_output(F1); 169 gpio_set_pin_output(F4); 170 gpio_set_pin_output(F5); 171 172 gpio_set_pin_output(D2); 173 gpio_set_pin_output(D3); 174 gpio_set_pin_output(D5); 175 gpio_set_pin_output(D6); 176 177 unselect_cols(); 178 } 179 180 static void unselect_cols(void) 181 { 182 gpio_write_pin_high(F0); 183 gpio_write_pin_high(F1); 184 gpio_write_pin_high(F4); 185 gpio_write_pin_high(F5); 186 187 gpio_write_pin_high(D2); 188 gpio_write_pin_high(D3); 189 gpio_write_pin_high(D5); 190 gpio_write_pin_high(D6); 191 } 192 193 static void select_col(uint8_t col) { 194 195 switch (col) { 196 case 0: 197 gpio_write_pin_low(F0); 198 gpio_write_pin_low(F1); 199 gpio_write_pin_low(F4); 200 break; 201 case 1: 202 gpio_write_pin_high(F0); 203 gpio_write_pin_low(F1); 204 gpio_write_pin_low(F4); 205 break; 206 case 2: 207 gpio_write_pin_low(F0); 208 gpio_write_pin_high(F1); 209 gpio_write_pin_low(F4); 210 break; 211 case 3: 212 gpio_write_pin_high(F0); 213 gpio_write_pin_high(F1); 214 gpio_write_pin_low(F4); 215 break; 216 case 4: 217 gpio_write_pin_low(F0); 218 gpio_write_pin_low(F1); 219 gpio_write_pin_high(F4); 220 break; 221 case 5: 222 gpio_write_pin_high(F0); 223 gpio_write_pin_low(F1); 224 gpio_write_pin_high(F4); 225 break; 226 case 6: 227 gpio_write_pin_low(F0); 228 gpio_write_pin_high(F1); 229 gpio_write_pin_high(F4); 230 break; 231 case 7: 232 gpio_write_pin_low(D2); 233 gpio_write_pin_low(D3); 234 gpio_write_pin_low(D5); 235 break; 236 case 8: 237 gpio_write_pin_high(D2); 238 gpio_write_pin_low(D3); 239 gpio_write_pin_low(D5); 240 break; 241 case 9: 242 gpio_write_pin_low(D2); 243 gpio_write_pin_high(D3); 244 gpio_write_pin_low(D5); 245 break; 246 case 10: 247 gpio_write_pin_high(D2); 248 gpio_write_pin_high(D3); 249 gpio_write_pin_low(D5); 250 break; 251 case 11: 252 gpio_write_pin_low(D2); 253 gpio_write_pin_low(D3); 254 gpio_write_pin_high(D5); 255 break; 256 case 12: 257 gpio_write_pin_high(D2); 258 gpio_write_pin_low(D3); 259 gpio_write_pin_high(D5); 260 break; 261 case 13: 262 gpio_write_pin_low(D2); 263 gpio_write_pin_high(D3); 264 gpio_write_pin_high(D5); 265 break; 266 } 267 }