matrix.c (5848B)
1 /* 2 Copyright 2011 Jun Wako <wakojun@gmail.com> 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 "util.h" 24 #include "debug.h" 25 #include "ps2.h" 26 #include "matrix.h" 27 28 #define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) 29 #define print_matrix_header() print("\nr/c 01234567\n") 30 #define ROW_SHIFTER ((uint8_t)1) 31 32 33 static void matrix_make(uint8_t code); 34 static void matrix_break(uint8_t code); 35 36 37 /* 38 * Matrix Array usage: 39 * 'Scan Code Set 3' is assigned into 17x8 cell matrix. 40 * 41 * 8bit wide 42 * +---------+ 43 * 0| | 44 * :| | 0x00-0x87 45 * ;| | 46 * 17| | 47 * +---------+ 48 */ 49 static uint8_t matrix[MATRIX_ROWS]; 50 #define ROW(code) (code>>3) 51 #define COL(code) (code&0x07) 52 53 54 __attribute__ ((weak)) 55 void matrix_init_user(void) { 56 } 57 58 void matrix_init(void) 59 { 60 debug_enable = true; 61 //debug_matrix = true; 62 //debug_keyboard = true; 63 //debug_mouse = false; 64 65 ps2_host_init(); 66 67 // initialize matrix state: all keys off 68 for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; 69 70 matrix_init_user(); 71 return; 72 } 73 74 uint8_t matrix_scan(void) 75 { 76 77 // scan code reading states 78 static enum { 79 RESET, 80 RESET_RESPONSE, 81 KBD_ID0, 82 KBD_ID1, 83 CONFIG, 84 READY, 85 F0_BREAK, 86 } state = RESET; 87 88 uint8_t code; 89 if ((code = ps2_host_recv())) { 90 dprintf("r%02X ", code); 91 } 92 93 switch (state) { 94 case RESET: 95 dprint("wFF "); 96 if (ps2_host_send(0xFF) == 0xFA) { 97 dprint("[ack]\nRESET_RESPONSE: "); 98 state = RESET_RESPONSE; 99 } 100 break; 101 case RESET_RESPONSE: 102 if (code == 0xAA) { 103 dprint("[ok]\nKBD_ID: "); 104 state = KBD_ID0; 105 } else if (code) { 106 dprint("err\nRESET: "); 107 state = RESET; 108 } 109 break; 110 // after reset receive keyboard ID(2 bytes) 111 case KBD_ID0: 112 if (code) { 113 state = KBD_ID1; 114 } 115 break; 116 case KBD_ID1: 117 if (code) { 118 dprint("\nCONFIG: "); 119 state = CONFIG; 120 } 121 break; 122 case CONFIG: 123 dprint("wF8 "); 124 if (ps2_host_send(0xF8) == 0xFA) { 125 dprint("[ack]\nREADY\n"); 126 state = READY; 127 } 128 break; 129 case READY: 130 switch (code) { 131 case 0x00: 132 break; 133 case 0xF0: 134 state = F0_BREAK; 135 dprint(" "); 136 break; 137 default: // normal key make 138 if (code < 0x88) { 139 matrix_make(code); 140 } else { 141 dprintf("unexpected scan code at READY: %02X\n", code); 142 } 143 state = READY; 144 dprint("\n"); 145 } 146 break; 147 case F0_BREAK: // Break code 148 switch (code) { 149 case 0x00: 150 break; 151 default: 152 if (code < 0x88) { 153 matrix_break(code); 154 } else { 155 dprintf("unexpected scan code at F0: %02X\n", code); 156 } 157 state = READY; 158 dprint("\n"); 159 } 160 break; 161 } 162 return 1; 163 } 164 165 inline 166 uint8_t matrix_get_row(uint8_t row) 167 { 168 return matrix[row]; 169 } 170 171 inline 172 static void matrix_make(uint8_t code) 173 { 174 if (!matrix_is_on(ROW(code), COL(code))) { 175 matrix[ROW(code)] |= 1<<COL(code); 176 } 177 } 178 179 inline 180 static void matrix_break(uint8_t code) 181 { 182 if (matrix_is_on(ROW(code), COL(code))) { 183 matrix[ROW(code)] &= ~(1<<COL(code)); 184 } 185 } 186 187 bool matrix_is_on(uint8_t row, uint8_t col) 188 { 189 return (matrix_get_row(row) & (1<<col)); 190 } 191 192 void matrix_print(void) 193 { 194 #if (MATRIX_COLS <= 8) 195 print("r/c 01234567\n"); 196 #elif (MATRIX_COLS <= 16) 197 print("r/c 0123456789ABCDEF\n"); 198 #elif (MATRIX_COLS <= 32) 199 print("r/c 0123456789ABCDEF0123456789ABCDEF\n"); 200 #endif 201 202 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 203 204 #if (MATRIX_COLS <= 8) 205 xprintf("%02X: %08b%s\n", row, bitrev(matrix_get_row(row)), 206 #elif (MATRIX_COLS <= 16) 207 xprintf("%02X: %016b%s\n", row, bitrev16(matrix_get_row(row)), 208 #elif (MATRIX_COLS <= 32) 209 xprintf("%02X: %032b%s\n", row, bitrev32(matrix_get_row(row)), 210 #endif 211 #ifdef MATRIX_HAS_GHOST 212 matrix_has_ghost_in_row(row) ? " <ghost" : "" 213 #else 214 "" 215 #endif 216 ); 217 } 218 } 219 220 #ifdef MATRIX_HAS_GHOST 221 __attribute__ ((weak)) 222 bool matrix_has_ghost_in_row(uint8_t row) 223 { 224 matrix_row_t matrix_row = matrix_get_row(row); 225 // No ghost exists when less than 2 keys are down on the row 226 if (((matrix_row - 1) & matrix_row) == 0) 227 return false; 228 229 // Ghost occurs when the row shares column line with other row 230 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 231 if (i != row && (matrix_get_row(i) & matrix_row)) 232 return true; 233 } 234 return false; 235 } 236 #endif