matrix.c (5039B)
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 #include "debounce.h" 29 30 static matrix_row_t matrix[MATRIX_ROWS]; 31 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 32 33 static matrix_row_t read_cols(void); 34 static void select_row(uint8_t col); 35 36 // user-defined overridable functions 37 38 __attribute__((weak)) void matrix_init_kb(void) { 39 matrix_init_user(); 40 } 41 42 __attribute__((weak)) void matrix_scan_kb(void) { 43 matrix_scan_user(); 44 } 45 46 __attribute__((weak)) void matrix_init_user(void) {} 47 48 __attribute__((weak)) void matrix_scan_user(void) {} 49 50 // helper functions 51 52 inline uint8_t matrix_rows(void) { 53 return MATRIX_ROWS; 54 } 55 56 inline uint8_t matrix_cols(void) { 57 return MATRIX_COLS; 58 } 59 60 void matrix_init(void) { 61 /* Column output pins */ 62 DDRD |= 0b01111011; 63 /* Row input pins */ 64 DDRC &= ~0b10000000; 65 DDRB &= ~0b01111111; 66 PORTC |= 0b10000000; 67 PORTB |= 0b01111111; 68 69 for (uint8_t i = 0; i < matrix_rows(); i++) { 70 matrix[i] = 0; 71 matrix_debouncing[i] = 0; 72 } 73 74 matrix_init_kb(); 75 } 76 77 uint8_t matrix_scan(void) { 78 bool changed = false; 79 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 80 select_row(col); 81 wait_us(30); 82 matrix_row_t rows = read_cols(); 83 for (uint8_t row = 0; row < matrix_rows(); row++) { 84 bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1 << col); 85 bool curr_bit = rows & (1 << row); 86 if ((changed |= prev_bit != curr_bit)) { 87 matrix_debouncing[row] ^= (matrix_row_t)1 << col; 88 } 89 } 90 } 91 92 debounce(matrix_debouncing, matrix, changed); 93 matrix_scan_kb(); 94 95 return (uint8_t)changed; 96 } 97 98 inline matrix_row_t matrix_get_row(uint8_t row) { 99 return matrix[row]; 100 } 101 102 void matrix_print(void) { 103 print("\nr/c 0123456789ABCDEF\n"); 104 for (uint8_t row = 0; row < matrix_rows(); row++) { 105 print_hex8(row); 106 print(": "); 107 print_bin_reverse16(matrix_get_row(row)); 108 print("\n"); 109 } 110 } 111 112 static matrix_row_t read_cols(void) { 113 return (PINB & (1 << 5) ? 0 : ((matrix_row_t)1 << 0)) | (PINC & (1 << 7) ? 0 : ((matrix_row_t)1 << 1)) | (PINB & (1 << 4) ? 0 : ((matrix_row_t)1 << 2)) | (PINB & (1 << 6) ? 0 : ((matrix_row_t)1 << 3)) | (PINB & (1 << 1) ? 0 : ((matrix_row_t)1 << 4)) | (PINB & (1 << 2) ? 0 : ((matrix_row_t)1 << 5)) | (PINB & (1 << 3) ? 0 : ((matrix_row_t)1 << 6)) | (PINB & (1 << 0) ? 0 : ((matrix_row_t)1 << 7)); 114 } 115 116 static void select_row(uint8_t col) { 117 switch (col) { 118 case 0: 119 PORTD = (PORTD & ~0b01111011) | 0b00011011; 120 break; 121 case 1: 122 PORTD = (PORTD & ~0b01111011) | 0b01000011; 123 break; 124 case 2: 125 PORTD = (PORTD & ~0b01111011) | 0b01100000; 126 break; 127 case 3: 128 PORTD = (PORTD & ~0b01111011) | 0b01111001; 129 break; 130 case 4: 131 PORTD = (PORTD & ~0b01111011) | 0b01100010; 132 break; 133 case 5: 134 PORTD = (PORTD & ~0b01111011) | 0b01101010; 135 break; 136 case 6: 137 PORTD = (PORTD & ~0b01111011) | 0b01110001; 138 break; 139 case 7: 140 PORTD = (PORTD & ~0b01111011) | 0b01101001; 141 break; 142 case 8: 143 PORTD = (PORTD & ~0b01111011) | 0b01100001; 144 break; 145 case 9: 146 PORTD = (PORTD & ~0b01111011) | 0b01111000; 147 break; 148 case 10: 149 PORTD = (PORTD & ~0b01111011) | 0b00100011; 150 break; 151 case 11: 152 PORTD = (PORTD & ~0b01111011) | 0b00101011; 153 break; 154 case 12: 155 PORTD = (PORTD & ~0b01111011) | 0b00110011; 156 break; 157 case 13: 158 PORTD = (PORTD & ~0b01111011) | 0b01110000; 159 break; 160 case 14: 161 PORTD = (PORTD & ~0b01111011) | 0b00010011; 162 break; 163 case 15: 164 PORTD = (PORTD & ~0b01111011) | 0b01101000; 165 break; 166 case 16: 167 PORTD = (PORTD & ~0b01111011) | 0b00001011; 168 break; 169 case 17: 170 PORTD = (PORTD & ~0b01111011) | 0b00111011; 171 break; 172 } 173 }