matrix.c (6229B)
1 /* 2 Copyright 2017 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 <util/delay.h> 18 #include <avr/io.h> 19 #include <stdio.h> 20 #include "matrix.h" 21 #include "util.h" 22 #include "print.h" 23 #include "debug.h" 24 25 #ifndef DEBOUNCE 26 # define DEBOUNCE 5 27 #endif 28 29 static uint8_t debouncing = DEBOUNCE; 30 31 /* matrix state(1:on, 0:off) */ 32 static matrix_row_t matrix[MATRIX_ROWS]; 33 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 34 35 static uint8_t read_rows(uint8_t col); 36 static void init_rows(void); 37 static void unselect_cols(void); 38 static void select_col(uint8_t col); 39 40 41 __attribute__ ((weak)) 42 void matrix_init_kb(void) { 43 matrix_init_user(); 44 } 45 46 __attribute__ ((weak)) 47 void matrix_scan_kb(void) { 48 matrix_scan_user(); 49 } 50 51 __attribute__ ((weak)) 52 void matrix_init_user(void) { 53 } 54 55 __attribute__ ((weak)) 56 void matrix_scan_user(void) { 57 } 58 59 void backlight_init_ports(void) 60 { 61 DDRB |= 0b00011111; // PB0 (caps), PB1 (alpha), PB2 (extra), PB3 (modnum), PB4 (caps) 62 DDRD |= 0b11010000; // PD4, (rgb blue), PD6 (rgb red), PD7 (rgb green) 63 DDRE |= 0b01000000; // PE6 (frow) 64 } 65 66 void matrix_init(void) { 67 backlight_init_ports(); 68 unselect_cols(); 69 init_rows(); 70 71 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 72 matrix[i] = 0; 73 matrix_debouncing[i] = 0; 74 } 75 76 matrix_init_kb(); 77 } 78 79 uint8_t matrix_scan(void) { 80 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 81 select_col(col); 82 _delay_us(3); 83 84 uint8_t rows = read_rows(col); 85 86 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 87 bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); 88 bool curr_bit = rows & (1<<row); 89 if (prev_bit != curr_bit) { 90 matrix_debouncing[row] ^= ((matrix_row_t)1<<col); 91 if (debouncing) { 92 dprint("bounce!: "); dprintf("%02X", debouncing); dprintln(); 93 } 94 debouncing = DEBOUNCE; 95 } 96 } 97 unselect_cols(); 98 } 99 100 if (debouncing) { 101 if (--debouncing) { 102 _delay_ms(1); 103 } else { 104 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 105 matrix[i] = matrix_debouncing[i]; 106 } 107 } 108 } 109 110 matrix_scan_kb(); 111 return 1; 112 } 113 114 inline matrix_row_t matrix_get_row(uint8_t row) { 115 return matrix[row]; 116 } 117 118 void matrix_print(void) { 119 print("\nr/c 0123456789ABCDEF\n"); 120 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 121 xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row))); 122 } 123 } 124 125 /* Row pin configuration 126 * row: 0 1 2 3 4 5 127 * pin: PB7 PD0 PD1 PD2 PD3 PD5 128 * 129 * Esc uses its own pin PE2 130 */ 131 static void init_rows(void) { 132 DDRD &= ~0b00101111; // PD0, PD1, PD2, PD3, PD5 input 133 PORTD &= ~0b00101111; // PD0, PD1, PD2, PD3, PD5 low 134 135 DDRB &= ~0b10000000; // PB7 input 136 PORTB &= ~0b10000000; // PB7 low 137 138 DDRE &= ~0b00000100; // PE2 input 139 PORTE |= 0b00000100; // PE2 high 140 } 141 142 static uint8_t read_rows(uint8_t col) { 143 if (col == 14) { 144 return PINE&(1<<2) ? 0 : (1<<0); // PE2 (Row 0) 145 } else { 146 return (PIND&(1<<0) ? (1<<0) : 0) | // PD0 (Row 0) 147 (PIND&(1<<1) ? (1<<1) : 0) | // PD1 (Row 1) 148 (PIND&(1<<2) ? (1<<2) : 0) | // PD2 (Row 2) 149 (PIND&(1<<3) ? (1<<3) : 0) | // PD3 (Row 3) 150 (PIND&(1<<5) ? (1<<4) : 0) | // PD5 (Row 4) 151 (PINB&(1<<7) ? (1<<5) : 0); // PB7 (Row 5) 152 } 153 } 154 155 uint8_t read_fwkey(void) 156 { 157 return PINE&(1<<2) ? 0 : (1<<0); 158 } 159 160 static void unselect_cols(void) { 161 DDRB |= 0b01000000; // PB6 (U2) output 162 PORTB &= ~0b01000000; // PB6 (U2) low 163 164 DDRC |= 0b11000000; // PC6 (U1), PC7 (A2) output 165 PORTC &= ~0b11000000; // PC6 (U1), PC7 (A2) low 166 167 DDRF |= 0b00000011; // PF0 (A0), PF1 (A1) output 168 PORTF &= ~0b00000011; // PF0 (A0), PF1 (A1) low 169 } 170 171 static void select_col(uint8_t col) { 172 173 switch (col) { 174 case 0: 175 PORTC |= 0b01000000; // PC6 high 176 break; 177 case 1: 178 PORTC |= 0b01000000; // PC6 high 179 PORTF |= 0b00000001; // PF0 high 180 break; 181 case 2: 182 PORTC |= 0b01000000; // PC6 high 183 PORTF |= 0b00000010; // PF1 high 184 break; 185 case 3: 186 PORTC |= 0b01000000; // PC6 high 187 PORTF |= 0b00000011; // PF0, PF1 high 188 break; 189 case 4: 190 PORTC |= 0b11000000; // PC6, PC7 high 191 break; 192 case 5: 193 PORTC |= 0b11000000; // PC6, PC7 high 194 PORTF |= 0b00000001; // PF0 high 195 break; 196 case 6: 197 PORTC |= 0b11000000; // PC6, PC7 high 198 PORTF |= 0b00000010; // PF1 high 199 break; 200 case 7: 201 PORTC |= 0b11000000; // PC6, PC7 high 202 PORTF |= 0b00000011; // PF0, PF1 high 203 break; 204 case 8: 205 PORTB |= 0b01000000; // PB6 high 206 break; 207 case 9: 208 PORTB |= 0b01000000; // PB6 high 209 PORTF |= 0b00000001; // PF0 high 210 break; 211 case 10: 212 PORTB |= 0b01000000; // PB6 high 213 PORTF |= 0b00000010; // PF1 high 214 break; 215 case 11: 216 PORTB |= 0b01000000; // PB6 high 217 PORTF |= 0b00000011; // PF0, PF1 high 218 break; 219 case 12: 220 PORTB |= 0b01000000; // PB6 high 221 PORTC |= 0b10000000; // PC7 high 222 break; 223 case 13: 224 PORTB |= 0b01000000; // PB6 high 225 PORTF |= 0b00000001; // PF0 high 226 PORTC |= 0b10000000; // PC7 high 227 break; 228 case 15: 229 PORTB |= 0b01000000; // PB6 high 230 PORTF |= 0b00000010; // PF1 high 231 PORTC |= 0b10000000; // PC7 high 232 break; 233 } 234 }