matrix.c (9530B)
1 /* 2 Copyright 2012 Jun Wako 3 Copyright 2014 Jack Humbert 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 #if defined(__AVR__) 19 #include <avr/io.h> 20 #include <avr/wdt.h> 21 #include <avr/interrupt.h> 22 #include <util/delay.h> 23 #endif 24 #include "wait.h" 25 #include "print.h" 26 #include "debug.h" 27 #include "util.h" 28 #include "matrix.h" 29 #include "timer.h" 30 #include "i2c_slave.h" 31 #include "lufa.h" 32 33 #define SLAVE_I2C_ADDRESS 0x32 34 35 /* Set 0 if debouncing isn't needed */ 36 37 #ifndef DEBOUNCE 38 # define DEBOUNCE 5 39 #endif 40 41 #if (DEBOUNCE > 0) 42 static uint16_t debouncing_time; 43 static bool debouncing = false; 44 #endif 45 46 #if (MATRIX_COLS <= 8) 47 # define print_matrix_header() print("\nr/c 01234567\n") 48 # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) 49 # define ROW_SHIFTER ((uint8_t)1) 50 #elif (MATRIX_COLS <= 16) 51 # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") 52 # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) 53 # define ROW_SHIFTER ((uint16_t)1) 54 #elif (MATRIX_COLS <= 32) 55 # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") 56 # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) 57 # define ROW_SHIFTER ((uint32_t)1) 58 #endif 59 60 #ifdef MATRIX_MASKED 61 extern const matrix_row_t matrix_mask[]; 62 #endif 63 64 #if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) 65 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 66 static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 67 #endif 68 69 /* matrix state(1:on, 0:off) */ 70 static matrix_row_t matrix[MATRIX_ROWS]; 71 72 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 73 74 75 #if (DIODE_DIRECTION == COL2ROW) 76 static void init_cols(void); 77 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row); 78 static void unselect_rows(void); 79 static void select_row(uint8_t row); 80 static void unselect_row(uint8_t row); 81 #elif (DIODE_DIRECTION == ROW2COL) 82 static void init_rows(void); 83 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); 84 static void unselect_cols(void); 85 static void unselect_col(uint8_t col); 86 static void select_col(uint8_t col); 87 #endif 88 89 __attribute__ ((weak)) 90 void matrix_init_kb(void) { 91 matrix_init_user(); 92 } 93 94 __attribute__ ((weak)) 95 void matrix_scan_kb(void) { 96 matrix_scan_user(); 97 } 98 99 __attribute__ ((weak)) 100 void matrix_init_user(void) { 101 } 102 103 __attribute__ ((weak)) 104 void matrix_scan_user(void) { 105 } 106 107 inline 108 uint8_t matrix_rows(void) { 109 return MATRIX_ROWS; 110 } 111 112 inline 113 uint8_t matrix_cols(void) { 114 return MATRIX_COLS; 115 } 116 117 void matrix_init(void) { 118 119 // initialize row and col 120 #if (DIODE_DIRECTION == COL2ROW) 121 unselect_rows(); 122 init_cols(); 123 #elif (DIODE_DIRECTION == ROW2COL) 124 unselect_cols(); 125 init_rows(); 126 #endif 127 128 // initialize matrix state: all keys off 129 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 130 matrix[i] = 0; 131 matrix_debouncing[i] = 0; 132 } 133 134 matrix_init_kb(); 135 } 136 137 uint8_t matrix_scan(void) 138 { 139 #if (DIODE_DIRECTION == COL2ROW) 140 141 // Set row, read cols 142 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 143 # if (DEBOUNCE > 0) 144 bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row); 145 146 if (matrix_changed) { 147 debouncing = true; 148 debouncing_time = timer_read(); 149 } 150 151 # else 152 read_cols_on_row(matrix, current_row); 153 # endif 154 155 } 156 157 #elif (DIODE_DIRECTION == ROW2COL) 158 159 // Set col, read rows 160 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 161 # if (DEBOUNCE > 0) 162 bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col); 163 if (matrix_changed) { 164 debouncing = true; 165 debouncing_time = timer_read(); 166 } 167 # else 168 read_rows_on_col(matrix, current_col); 169 # endif 170 171 } 172 173 #endif 174 175 # if (DEBOUNCE > 0) 176 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCE)) { 177 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 178 matrix[i] = matrix_debouncing[i]; 179 } 180 debouncing = false; 181 } 182 # endif 183 184 i2c_slave_reg[1] = 0x55; 185 for (uint8_t i = 0; i < MATRIX_ROWS; i++){ 186 i2c_slave_reg[i+2] = matrix[i]; //send matrix over i2c 187 } 188 189 matrix_scan_kb(); 190 return 1; 191 } 192 193 inline 194 bool matrix_is_on(uint8_t row, uint8_t col) 195 { 196 return (matrix[row] & ((matrix_row_t)1<<col)); 197 } 198 199 inline 200 matrix_row_t matrix_get_row(uint8_t row) 201 { 202 // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a 203 // switch blocker installed and the switch is always pressed. 204 #ifdef MATRIX_MASKED 205 return matrix[row] & matrix_mask[row]; 206 #else 207 return matrix[row]; 208 #endif 209 } 210 211 void matrix_print(void) 212 { 213 print_matrix_header(); 214 215 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 216 print_hex8(row); print(": "); 217 print_matrix_row(row); 218 print("\n"); 219 } 220 } 221 222 #if (DIODE_DIRECTION == COL2ROW) 223 224 static void init_cols(void) 225 { 226 for(uint8_t x = 0; x < MATRIX_COLS; x++) { 227 uint8_t pin = col_pins[x]; 228 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN 229 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI 230 } 231 } 232 233 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) 234 { 235 // Store last value of row prior to reading 236 matrix_row_t last_row_value = current_matrix[current_row]; 237 238 // Clear data in matrix row 239 current_matrix[current_row] = 0; 240 241 // Select row and wait for row selecton to stabilize 242 select_row(current_row); 243 wait_us(30); 244 245 // For each col... 246 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 247 248 // Select the col pin to read (active low) 249 uint8_t pin = col_pins[col_index]; 250 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)); 251 252 // Populate the matrix row with the state of the col pin 253 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); 254 } 255 256 // Unselect row 257 unselect_row(current_row); 258 259 return (last_row_value != current_matrix[current_row]); 260 } 261 262 static void select_row(uint8_t row) 263 { 264 uint8_t pin = row_pins[row]; 265 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT 266 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW 267 } 268 269 static void unselect_row(uint8_t row) 270 { 271 uint8_t pin = row_pins[row]; 272 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN 273 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI 274 } 275 276 static void unselect_rows(void) 277 { 278 for(uint8_t x = 0; x < MATRIX_ROWS; x++) { 279 uint8_t pin = row_pins[x]; 280 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN 281 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI 282 } 283 } 284 285 #elif (DIODE_DIRECTION == ROW2COL) 286 287 static void init_rows(void) 288 { 289 for(uint8_t x = 0; x < MATRIX_ROWS; x++) { 290 uint8_t pin = row_pins[x]; 291 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN 292 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI 293 } 294 } 295 296 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) 297 { 298 bool matrix_changed = false; 299 300 // Select col and wait for col selecton to stabilize 301 select_col(current_col); 302 wait_us(30); 303 304 // For each row... 305 for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) 306 { 307 308 // Store last value of row prior to reading 309 matrix_row_t last_row_value = current_matrix[row_index]; 310 311 // Check row pin state 312 if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0) 313 { 314 // Pin LO, set col bit 315 current_matrix[row_index] |= (ROW_SHIFTER << current_col); 316 } 317 else 318 { 319 // Pin HI, clear col bit 320 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col); 321 } 322 323 // Determine if the matrix changed state 324 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) 325 { 326 matrix_changed = true; 327 } 328 } 329 330 // Unselect col 331 unselect_col(current_col); 332 333 return matrix_changed; 334 } 335 336 static void select_col(uint8_t col) 337 { 338 uint8_t pin = col_pins[col]; 339 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT 340 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW 341 } 342 343 static void unselect_col(uint8_t col) 344 { 345 uint8_t pin = col_pins[col]; 346 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN 347 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI 348 } 349 350 static void unselect_cols(void) 351 { 352 for(uint8_t x = 0; x < MATRIX_COLS; x++) { 353 uint8_t pin = col_pins[x]; 354 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN 355 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI 356 } 357 } 358 359 #endif 360 361 //this replases tmk code 362 void matrix_setup(void){ 363 i2c_slave_init(SLAVE_I2C_ADDRESS); //setup address of slave i2c 364 sei(); //enable interupts 365 }