matrix.c (4709B)
1 /* 2 Copyright 2014 Ralf Schmitt <ralf@bunkertor.net> 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <stdint.h> 19 #include <stdbool.h> 20 #include <avr/io.h> 21 #include <util/delay.h> 22 #include "print.h" 23 #include "debug.h" 24 #include "util.h" 25 #include "matrix.h" 26 27 #ifndef DEBOUNCE 28 # define DEBOUNCE 5 29 #endif 30 static uint8_t debouncing = DEBOUNCE; 31 32 static matrix_row_t matrix[MATRIX_ROWS]; 33 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 34 35 static uint8_t read_rows(void); 36 static void select_col(uint8_t col); 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 inline uint8_t matrix_rows(void) { 57 return MATRIX_ROWS; 58 } 59 60 inline uint8_t matrix_cols(void) { 61 return MATRIX_COLS; 62 } 63 64 /* Column pin configuration 65 * 66 * col: 0 1 2 3 4 5 6 7 67 * pin: PC7 PD5 PD3 PD1 PC2 PD6 PD4 PD2 68 * 69 * Rrr pin configuration 70 * 71 * These rrrs uses one 74HC154 4 to 16 bit demultiplexer (low 72 * active), together with 2 rrrs driven directly from the micro 73 * controller, to control the 18 rrrs. The rrrs are driven from 74 * pins B6,5,4,3,2,1,0. 75 */ 76 void matrix_init(void) { 77 DDRC &= ~0b10000100; // Row input pins 78 DDRD &= ~0b01111110; 79 PORTC |= 0b10000100; 80 PORTD |= 0b01111110; 81 82 DDRB |= 0b01111111; // Column output pins 83 84 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 85 matrix[i] = 0; 86 matrix_debouncing[i] = 0; 87 } 88 matrix_init_kb(); 89 } 90 91 uint8_t matrix_scan(void) { 92 for (uint8_t col = 0; col < MATRIX_COLS; col++) { 93 select_col(col); 94 _delay_us(3); 95 uint8_t rows = read_rows(); 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 debouncing = DEBOUNCE; 102 } 103 } 104 } 105 106 if (debouncing) { 107 if (--debouncing) { 108 _delay_ms(1); 109 } 110 else { 111 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 112 matrix[i] = matrix_debouncing[i]; 113 } 114 } 115 } 116 matrix_scan_kb(); 117 return 1; 118 } 119 120 inline bool matrix_is_on(uint8_t row, uint8_t col) { 121 return (matrix[row] & ((matrix_row_t)1<<col)); 122 } 123 124 inline matrix_row_t matrix_get_row(uint8_t row) { 125 return matrix[row]; 126 } 127 128 void matrix_print(void) { 129 print("\nr/c 0123456789ABCDEF\n"); 130 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 131 xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row))); 132 } 133 } 134 135 static uint8_t read_rows(void) { 136 return 137 (PINC&(1<<7) ? 0 : (1<<0)) | 138 (PIND&(1<<5) ? 0 : (1<<1)) | 139 (PIND&(1<<3) ? 0 : (1<<2)) | 140 (PIND&(1<<1) ? 0 : (1<<3)) | 141 (PINC&(1<<2) ? 0 : (1<<4)) | 142 (PIND&(1<<2) ? 0 : (1<<5)) | 143 (PIND&(1<<4) ? 0 : (1<<6)) | 144 (PIND&(1<<6) ? 0 : (1<<7)); 145 } 146 147 static void select_col(uint8_t col) { 148 switch (col) { 149 case 0: PORTB = (PORTB & ~0b01111111) | 0b01100100; break; 150 case 1: PORTB = (PORTB & ~0b01111111) | 0b01101100; break; 151 case 2: PORTB = (PORTB & ~0b01111111) | 0b01100010; break; 152 case 3: PORTB = (PORTB & ~0b01111111) | 0b01111010; break; 153 case 4: PORTB = (PORTB & ~0b01111111) | 0b01100110; break; 154 case 5: PORTB = (PORTB & ~0b01111111) | 0b01110110; break; 155 case 6: PORTB = (PORTB & ~0b01111111) | 0b01101110; break; 156 case 7: PORTB = (PORTB & ~0b01111111) | 0b01111110; break; 157 case 8: PORTB = (PORTB & ~0b01111111) | 0b01000001; break; 158 case 9: PORTB = (PORTB & ~0b01111111) | 0b00100001; break; 159 case 10: PORTB = (PORTB & ~0b01111111) | 0b01101010; break; 160 case 11: PORTB = (PORTB & ~0b01111111) | 0b01110010; break; 161 case 12: PORTB = (PORTB & ~0b01111111) | 0b01111100; break; 162 case 13: PORTB = (PORTB & ~0b01111111) | 0b01110100; break; 163 case 14: PORTB = (PORTB & ~0b01111111) | 0b01111000; break; 164 case 15: PORTB = (PORTB & ~0b01111111) | 0b01110000; break; 165 case 16: PORTB = (PORTB & ~0b01111111) | 0b01100000; break; 166 case 17: PORTB = (PORTB & ~0b01111111) | 0b01101000; break; 167 } 168 }