matrix.c (6566B)
1 /* 2 Copyright 2019 MechMerlin <mechmerlin@gmail.com> 3 This program is free software: you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation, either version 2 of the License, or 6 (at your option) any later version. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 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 17 #include "matrix.h" 18 #include "debug.h" 19 #include "bitwise.h" 20 #include "wait.h" 21 22 #ifndef DEBOUNCE 23 # define DEBOUNCE 5 24 #endif 25 26 static uint8_t debouncing = DEBOUNCE; 27 28 /* matrix state(1:on, 0:off) */ 29 static matrix_row_t matrix[MATRIX_ROWS]; 30 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 31 32 static uint8_t read_rows(uint8_t col); 33 static void init_rows(void); 34 static void unselect_cols(void); 35 static void select_col(uint8_t col); 36 37 38 __attribute__ ((weak)) 39 void matrix_init_kb(void) { 40 matrix_init_user(); 41 } 42 43 __attribute__ ((weak)) 44 void matrix_scan_kb(void) { 45 matrix_scan_user(); 46 } 47 48 __attribute__ ((weak)) 49 void matrix_init_user(void) { 50 } 51 52 __attribute__ ((weak)) 53 void matrix_scan_user(void) { 54 } 55 56 void matrix_init(void) { 57 unselect_cols(); 58 init_rows(); 59 60 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 61 matrix[i] = 0; 62 matrix_debouncing[i] = 0; 63 } 64 65 matrix_init_kb(); 66 } 67 68 uint8_t matrix_scan(void) { 69 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 70 select_col(col); 71 _delay_us(3); 72 73 uint8_t rows = read_rows(col); 74 75 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 76 bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); 77 bool curr_bit = rows & (1<<row); 78 if (prev_bit != curr_bit) { 79 matrix_debouncing[row] ^= ((matrix_row_t)1<<col); 80 if (debouncing) { 81 dprint("bounce!: "); dprintf("%02X", debouncing); dprintln(); 82 } 83 debouncing = DEBOUNCE; 84 } 85 } 86 unselect_cols(); 87 } 88 89 if (debouncing) { 90 if (--debouncing) { 91 _delay_ms(1); 92 } else { 93 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 94 matrix[i] = matrix_debouncing[i]; 95 } 96 } 97 } 98 99 matrix_scan_kb(); 100 return 1; 101 } 102 103 inline matrix_row_t matrix_get_row(uint8_t row) { 104 return matrix[row]; 105 } 106 107 void matrix_print(void) { 108 print("\nr/c 0123456789ABCDEF\n"); 109 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 110 xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row))); 111 } 112 } 113 114 /* Row pin configuration - diode connected 115 * row: 0 1 2 3 4 5 116 * pin: PD0 PD1 PD2 PD3 PD5 PB7 117 * 118 * Backspace uses its own pin PE2 on the column pin, row pin is grounded 119 */ 120 static void init_rows(void) { 121 DDRD &= ~0b00101111; 122 PORTD &= ~0b00101111; 123 124 DDRB &= ~0b10000000; 125 PORTB &= ~0b10000000; 126 127 DDRE &= ~0b00000100; 128 PORTE |= 0b00000100; 129 } 130 131 static uint8_t read_rows(uint8_t col) { 132 133 return (PIND&(1<<0) ? (1<<0) : 0) | 134 (PIND&(1<<1) ? (1<<1) : 0) | 135 (PIND&(1<<2) ? (1<<2) : 0) | 136 (PIND&(1<<3) ? (1<<3) : 0) | 137 (PIND&(1<<5) ? (1<<4) : 0) | 138 (PINB&(1<<7) ? (1<<5) : 0) | 139 (col== 17 ? ((PINE&(1<<2) ? 0 : (1<<1))) : 0); 140 141 } 142 143 uint8_t read_fwkey(void) 144 { 145 return PINE&(1<<2) ? 0 : (1<<2); 146 } 147 148 /* Columns 0 - 15 149 * 150 * atmega32u4 decoder pin 151 * PC6 U1 E3 152 * PB6 U2 E3 153 * PF0 U1, U2 A0 154 * PF1 U1, U2 A1 155 * PC7 U1, U2 A2 156 * 157 * These columns uses two 74HC237D 3 to 8 bit demultiplexers. 158 * col / pin: PC6 PB6 PF0 PF1 PC7 Decoder Pin 159 * 0: 1 0 0 0 0 U1 Y0 160 * 1: 1 0 1 0 0 U1 Y1 161 * 2: 1 0 0 1 0 U1 Y2 162 * 3: 1 0 1 1 0 U1 Y3 163 * 4: 1 0 0 0 1 U1 Y4 164 * 5: 1 0 1 0 1 U1 Y5 165 * 6: 1 0 0 1 1 U1 Y6 166 * 7: 1 0 1 1 1 U1 Y7 167 * 168 * 8: 0 1 0 0 0 U2 Y0 169 * 9: 0 1 1 0 0 U2 Y1 170 * 10: 0 1 0 1 0 U2 Y2 171 * 11: 0 1 1 1 0 U2 Y3 172 * 12: 0 1 0 0 1 U2 Y4 173 * 13: 0 1 1 0 1 U2 Y5 174 * 14: 0 1 0 1 1 U2 Y6 175 * 15: 0 1 1 1 1 U2 Y7 176 * 177 */ 178 static void unselect_cols(void) { 179 DDRB |= 0b01100000; 180 PORTB &= ~0b01100000; 181 182 DDRC |= 0b11000000; 183 PORTC &= ~0b11000000; 184 185 DDRF |= 0b00000011; 186 PORTF &= ~0b00000011; 187 } 188 189 static void select_col(uint8_t col) { 190 191 switch (col) { 192 case 0: 193 PORTC |= 0b01000000; 194 break; 195 case 1: 196 PORTC |= 0b01000000; 197 PORTF |= 0b00000001; 198 break; 199 case 2: 200 PORTC |= 0b01000000; 201 PORTF |= 0b00000010; 202 break; 203 case 3: 204 PORTC |= 0b01000000; 205 PORTF |= 0b00000011; 206 break; 207 case 4: 208 PORTC |= 0b11000000; 209 break; 210 case 5: 211 PORTC |= 0b11000000; 212 PORTF |= 0b00000001; 213 break; 214 case 6: 215 PORTC |= 0b11000000; 216 PORTF |= 0b00000010; 217 break; 218 case 7: 219 PORTC |= 0b11000000; 220 PORTF |= 0b00000011; 221 break; 222 case 8: 223 PORTB |= 0b01000000; 224 break; 225 case 9: 226 PORTB |= 0b01000000; 227 PORTF |= 0b00000001; 228 break; 229 case 10: 230 PORTB |= 0b01000000; 231 PORTF |= 0b00000010; 232 break; 233 case 11: 234 PORTB |= 0b01000000; 235 PORTF |= 0b00000011; 236 break; 237 case 12: 238 PORTB |= 0b01000000; 239 PORTC |= 0b10000000; 240 break; 241 case 13: 242 PORTB |= 0b01000000; 243 PORTF |= 0b00000001; 244 PORTC |= 0b10000000; 245 break; 246 case 14: 247 PORTB |= 0b01000000; 248 PORTF |= 0b00000010; 249 PORTC |= 0b10000000; 250 break; 251 case 15: 252 PORTB |= 0b01000000; 253 PORTF |= 0b00000011; 254 PORTC |= 0b10000000; 255 break; 256 case 16: 257 PORTB |= 0b00100000; 258 break; 259 } 260 }