matrix.c (4593B)
1 /* 2 Copyright 2014 Ralf Schmitt <ralf@bunkertor.net> 3 Copyright 2016 Daniel Svensson <dsvensson@gmail.com> 4 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 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <stdint.h> 20 #include <stdbool.h> 21 #include <avr/io.h> 22 #include <util/delay.h> 23 #include "wait.h" 24 #include "print.h" 25 #include "debug.h" 26 #include "util.h" 27 #include "matrix.h" 28 29 #ifndef DEBOUNCE 30 # define DEBOUNCE 5 31 #endif 32 33 static uint8_t debouncing = DEBOUNCE; 34 static matrix_row_t matrix[MATRIX_ROWS]; 35 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 36 37 static matrix_row_t read_cols(void); 38 static void select_row(uint8_t col); 39 40 __attribute__ ((weak)) 41 void matrix_init_kb(void) { 42 matrix_init_user(); 43 } 44 45 __attribute__ ((weak)) 46 void matrix_scan_kb(void) { 47 matrix_scan_user(); 48 } 49 50 __attribute__ ((weak)) 51 void matrix_init_user(void) { 52 } 53 54 __attribute__ ((weak)) 55 void matrix_scan_user(void) { 56 } 57 58 inline uint8_t matrix_rows(void) 59 { 60 return MATRIX_ROWS; 61 } 62 63 inline uint8_t matrix_cols(void) 64 { 65 return MATRIX_COLS; 66 } 67 68 void matrix_init(void) 69 { 70 /* Column output pins */ 71 DDRD |= 0b01111011; 72 /* Row input pins */ 73 DDRC &= (unsigned char) ~0b00000000; 74 DDRB &= (unsigned char) ~0b11111111; 75 PORTC |= 0b00000000; 76 PORTB |= 0b11111111; 77 78 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 79 matrix[i] = 0; 80 matrix_debouncing[i] = 0; 81 } 82 83 matrix_init_kb(); 84 } 85 86 uint8_t matrix_scan(void) 87 { 88 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 89 select_row(col); 90 wait_us(30); 91 matrix_row_t rows = read_cols(); 92 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 93 bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col); 94 bool curr_bit = rows & (1<<row); 95 if (prev_bit != curr_bit) { 96 matrix_debouncing[row] ^= (matrix_row_t) 1 << col; 97 debouncing = DEBOUNCE; 98 } 99 } 100 } 101 102 if (debouncing) { 103 if (--debouncing) { 104 wait_ms(1); 105 } else { 106 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 107 matrix[i] = matrix_debouncing[i]; 108 } 109 } 110 } 111 112 matrix_scan_kb(); 113 114 return 1; 115 } 116 117 inline 118 bool matrix_is_on(uint8_t row, uint8_t col) 119 { 120 return matrix[row] & 1 << col; 121 } 122 123 inline 124 matrix_row_t matrix_get_row(uint8_t row) 125 { 126 return matrix[row]; 127 } 128 129 void matrix_print(void) 130 { 131 print("\nr/c 0123456789ABCDEF\n"); 132 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 133 print_hex8(row); print(": "); 134 print_bin_reverse16(matrix_get_row(row)); 135 print("\n"); 136 } 137 } 138 139 static matrix_row_t read_cols(void) 140 { 141 return 142 (PINB & (1 << 5) ? 0 : (matrix_row_t) 1 << 0) | 143 (PINB & (1 << 7) ? 0 : (matrix_row_t) 1 << 1) | 144 (PINB & (1 << 4) ? 0 : (matrix_row_t) 1 << 2) | 145 (PINB & (1 << 6) ? 0 : (matrix_row_t) 1 << 3) | 146 (PINB & (1 << 1) ? 0 : (matrix_row_t) 1 << 4) | 147 (PINB & (1 << 2) ? 0 : (matrix_row_t) 1 << 5) | 148 (PINB & (1 << 3) ? 0 : (matrix_row_t) 1 << 6) | 149 (PINB & (1 << 0) ? 0 : (matrix_row_t) 1 << 7); 150 } 151 152 static void select_row(uint8_t col) 153 { 154 switch (col) { 155 case 0: 156 PORTD = (PORTD & ~0b01111011) | 0b00010011; 157 break; 158 case 1: 159 PORTD = (PORTD & ~0b01111011) | 0b01000011; 160 break; 161 case 2: 162 PORTD = (PORTD & ~0b01111011) | 0b01100000; 163 break; 164 case 3: 165 PORTD = (PORTD & ~0b01111011) | 0b01111001; 166 break; 167 case 4: 168 PORTD = (PORTD & ~0b01111011) | 0b01100010; 169 break; 170 case 5: 171 PORTD = (PORTD & ~0b01111011) | 0b01101010; 172 break; 173 case 6: 174 PORTD = (PORTD & ~0b01111011) | 0b01110001; 175 break; 176 case 7: 177 PORTD = (PORTD & ~0b01111011) | 0b01101001; 178 break; 179 case 8: 180 PORTD = (PORTD & ~0b01111011) | 0b01100001; 181 break; 182 case 9: 183 PORTD = (PORTD & ~0b01111011) | 0b01111000; 184 break; 185 case 10: 186 PORTD = (PORTD & ~0b01111011) | 0b00011011; 187 break; 188 case 11: 189 PORTD = (PORTD & ~0b01111011) | 0b00100011; 190 break; 191 case 12: 192 PORTD = (PORTD & ~0b01111011) | 0b00101011; 193 break; 194 case 13: 195 PORTD = (PORTD & ~0b01111011) | 0b01110000; 196 break; 197 case 14: 198 PORTD = (PORTD & ~0b01111011) | 0b00001011; 199 break; 200 case 15: 201 PORTD = (PORTD & ~0b01111011) | 0b01101000; 202 break; 203 case 16: 204 PORTD = (PORTD & ~0b01111011) | 0b00000011; 205 break; 206 case 17: 207 PORTD = (PORTD & ~0b01111011) | 0b00111011; 208 break; 209 } 210 }