matrix.c (6222B)
1 /* 2 Copyright 2016 Ralf Schmitt <ralf@bunkertor.net> 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 This program is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 GNU General Public License for more details. 11 You should have received a copy of the GNU General Public License 12 along with this program. If not, see <http://www.gnu.org/licenses/>. 13 */ 14 15 #include <stdint.h> 16 #include <stdbool.h> 17 #include <avr/io.h> 18 #include <util/delay.h> 19 #include "print.h" 20 #include "debug.h" 21 #include "util.h" 22 #include "matrix.h" 23 24 #ifndef DEBOUNCE 25 # define DEBOUNCE 5 26 #endif 27 28 static uint8_t debouncing = DEBOUNCE; 29 30 /* matrix state(1:on, 0:off) */ 31 static matrix_row_t matrix[MATRIX_ROWS]; 32 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 33 34 static uint8_t read_rows(uint8_t col); 35 static void init_ports(void); 36 static void unselect_cols(void); 37 static void select_col(uint8_t col); 38 39 __attribute__ ((weak)) 40 void matrix_init_kb(void) { 41 matrix_init_user(); 42 } 43 44 __attribute__ ((weak)) 45 void matrix_scan_kb(void) { 46 matrix_scan_user(); 47 } 48 49 __attribute__ ((weak)) 50 void matrix_init_user(void) { 51 } 52 53 __attribute__ ((weak)) 54 void matrix_scan_user(void) { 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 backlight_init_ports(void) 70 { 71 DDRD |= 0b01010000; 72 PORTD &= 0b10101111; 73 DDRB |= 0b00001110; 74 PORTB &= 0b11110001; 75 DDRE |= 0b01000000; 76 PORTE &= 0b10111111; 77 } 78 79 void matrix_init(void) 80 { 81 backlight_init_ports(); 82 unselect_cols(); 83 init_ports(); 84 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 85 matrix[i] = 0; 86 matrix_debouncing[i] = 0; 87 } 88 } 89 90 uint8_t matrix_scan(void) 91 { 92 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 93 select_col(col); 94 _delay_us(3); 95 uint8_t rows = read_rows(col); 96 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 97 bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); 98 bool curr_bit = rows & (1<<row); 99 if (prev_bit != curr_bit) { 100 matrix_debouncing[row] ^= ((matrix_row_t)1<<col); 101 if (debouncing) { 102 dprint("bounce!: "); dprintf("%02X", debouncing); dprintln(); 103 } 104 debouncing = DEBOUNCE; 105 } 106 } 107 unselect_cols(); 108 } 109 110 if (debouncing) { 111 if (--debouncing) { 112 _delay_ms(1); 113 } else { 114 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 115 matrix[i] = matrix_debouncing[i]; 116 } 117 } 118 } 119 120 return 1; 121 } 122 123 inline 124 bool matrix_is_on(uint8_t row, uint8_t col) 125 { 126 return (matrix[row] & ((matrix_row_t)1<<col)); 127 } 128 129 inline 130 matrix_row_t matrix_get_row(uint8_t row) 131 { 132 return matrix[row]; 133 } 134 135 void matrix_print(void) 136 { 137 print("\nr/c 0123456789ABCDEF\n"); 138 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 139 xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row))); 140 } 141 } 142 143 static void init_ports(void) 144 { 145 // Rows are inputs (inputs are 0) 146 DDRD &= 0b11010000; 147 DDRB &= 0b01111111; 148 DDRE &= 0b11111011; 149 150 // Columns are outputs (outputs are high) 151 DDRF |= 0b00000011; 152 DDRC |= 0b11000000; 153 DDRB |= 0b01110001; 154 DDRD |= 0b10000000; 155 } 156 157 static uint8_t read_rows(uint8_t col) 158 { 159 if(col == 15) { 160 return (PINE&(1<<2) ? 0 : (1<<0)) | 161 (PIND&(1<<0) ? (1<<1) : 0) | 162 (PIND&(1<<1) ? (1<<2) : 0) | 163 (PIND&(1<<2) ? (1<<3) : 0) | 164 (PIND&(1<<3) ? (1<<4) : 0) | 165 (PIND&(1<<5) ? (1<<5) : 0); 166 167 } else { 168 return (PINB&(1<<7) ? (1<<0) : 0) | 169 (PIND&(1<<0) ? (1<<1) : 0) | 170 (PIND&(1<<1) ? (1<<2) : 0) | 171 (PIND&(1<<2) ? (1<<3) : 0) | 172 (PIND&(1<<3) ? (1<<4) : 0) | 173 (PIND&(1<<5) ? (1<<5) : 0); 174 175 } 176 } 177 178 static void unselect_cols(void) 179 { 180 PORTF &= 0b11111100; 181 PORTC &= 0b00111111; 182 PORTB &= 0b10001110; 183 PORTD &= 0b01111111; 184 } 185 186 static void select_col(uint8_t col) 187 { 188 switch (col) { 189 case 0: 190 PORTC |= 0b01000000; 191 break; 192 case 1: 193 PORTC |= 0b01000000; 194 PORTF |= 0b00000001; 195 break; 196 case 2: 197 PORTC |= 0b01000000; 198 PORTF |= 0b00000010; 199 break; 200 case 3: 201 PORTC |= 0b01000000; 202 PORTF |= 0b00000011; 203 break; 204 case 4: 205 PORTC |= 0b11000000; 206 break; 207 case 5: 208 PORTC |= 0b11000000; 209 PORTF |= 0b00000001; 210 break; 211 case 6: 212 PORTC |= 0b11000000; 213 PORTF |= 0b00000010; 214 break; 215 case 7: 216 PORTC |= 0b11000000; 217 PORTF |= 0b00000011; 218 break; 219 case 8: 220 PORTB |= 0b01000000; 221 break; 222 case 9: 223 PORTB |= 0b01000000; 224 PORTF |= 0b00000001; 225 break; 226 case 10: 227 PORTB |= 0b01000000; 228 PORTF |= 0b00000010; 229 break; 230 case 11: 231 PORTB |= 0b01000000; 232 PORTF |= 0b00000011; 233 break; 234 case 12: 235 PORTB |= 0b01000000; 236 PORTC |= 0b10000000; 237 break; 238 case 13: 239 PORTB |= 0b01000000; 240 PORTF |= 0b00000001; 241 PORTC |= 0b10000000; 242 break; 243 case 14: 244 PORTB |= 0b01000000; 245 PORTF |= 0b00000010; 246 PORTC |= 0b10000000; 247 break; 248 case 15: 249 PORTB |= 0b01000000; 250 PORTF |= 0b00000011; 251 PORTC |= 0b10000000; 252 break; 253 case 16: 254 PORTB |= 0b00100000; 255 break; 256 case 17: 257 PORTB |= 0b00010000; 258 break; 259 case 18: 260 PORTD |= 0b10000000; 261 break; 262 case 19: 263 PORTB |= 0b00000001; 264 break; 265 } 266 }