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