matrix.c (8803B)
1 /* 2 3 Copyright 2013 Oleg Kostyuk <cub.uanic@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 "matrix.h" 20 #include "wait.h" 21 #include "debug.h" 22 #include "util.h" 23 #include "georgi.h" 24 25 #ifndef DEBOUNCE 26 # define DEBOUNCE 5 27 #endif 28 29 // MCP Pin Defs 30 #define RROW1 (1<<3) 31 #define RROW2 (1<<2) 32 #define RROW3 (1<<1) 33 #define RROW4 (1<<0) 34 #define COL0 (1<<0) 35 #define COL1 (1<<1) 36 #define COL2 (1<<2) 37 #define COL3 (1<<3) 38 #define COL4 (1<<4) 39 #define COL5 (1<<5) 40 #define COL6 (1<<6) 41 42 // ATmega pin defs 43 #define ROW1 (1<<6) 44 #define ROW2 (1<<5) 45 #define ROW3 (1<<4) 46 #define ROW4 (1<<1) 47 #define COL7 (1<<0) 48 #define COL8 (1<<1) 49 #define COL9 (1<<2) 50 #define COL10 (1<<3) 51 #define COL11 (1<<2) 52 #define COL12 (1<<3) 53 #define COL13 (1<<6) 54 55 56 // bit masks 57 #define BMASK (COL7 | COL8 | COL9 | COL10) 58 #define CMASK (COL13) 59 #define DMASK (COL11 | COL12) 60 #define FMASK (ROW1 | ROW2 | ROW3 | ROW4) 61 #define RROWMASK (RROW1 | RROW2 | RROW3 | RROW4) 62 #define MCPMASK (COL0 | COL1 | COL2 | COL3 | COL4 | COL5 | COL6) 63 64 /* matrix state(1:on, 0:off) */ 65 static matrix_row_t matrix[MATRIX_ROWS]; 66 /* 67 * matrix state(1:on, 0:off) 68 * contains the raw values without debounce filtering of the last read cycle. 69 */ 70 static matrix_row_t raw_matrix[MATRIX_ROWS]; 71 72 // Debouncing: store for each key the number of scans until it's eligible to 73 // change. When scanning the matrix, ignore any changes in keys that have 74 // already changed in the last DEBOUNCE scans. 75 static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS]; 76 77 static matrix_row_t read_cols(uint8_t row); 78 static void init_cols(void); 79 static void unselect_rows(void); 80 static void select_row(uint8_t row); 81 82 static uint8_t mcp23018_reset_loop; 83 // static uint16_t mcp23018_reset_loop; 84 85 __attribute__ ((weak)) 86 void matrix_init_user(void) {} 87 88 __attribute__ ((weak)) 89 void matrix_scan_user(void) {} 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 inline 102 uint8_t matrix_rows(void) 103 { 104 return MATRIX_ROWS; 105 } 106 107 inline 108 uint8_t matrix_cols(void) 109 { 110 return MATRIX_COLS; 111 } 112 113 114 void matrix_init(void) 115 { 116 // initialize row and col 117 mcp23018_status = init_mcp23018(); 118 unselect_rows(); 119 init_cols(); 120 121 // initialize matrix state: all keys off 122 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 123 matrix[i] = 0; 124 raw_matrix[i] = 0; 125 for (uint8_t j=0; j < MATRIX_COLS; ++j) { 126 debounce_matrix[i * MATRIX_COLS + j] = 0; 127 } 128 } 129 130 matrix_init_kb(); 131 } 132 133 void matrix_power_up(void) { 134 mcp23018_status = init_mcp23018(); 135 136 unselect_rows(); 137 init_cols(); 138 139 // initialize matrix state: all keys off 140 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 141 matrix[i] = 0; 142 } 143 } 144 145 // Returns a matrix_row_t whose bits are set if the corresponding key should be 146 // eligible to change in this scan. 147 matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) { 148 matrix_row_t result = 0; 149 matrix_row_t change = rawcols ^ raw_matrix[row]; 150 raw_matrix[row] = rawcols; 151 for (uint8_t i = 0; i < MATRIX_COLS; ++i) { 152 if (debounce_matrix[row * MATRIX_COLS + i]) { 153 --debounce_matrix[row * MATRIX_COLS + i]; 154 } else { 155 result |= (1 << i); 156 } 157 if (change & (1 << i)) { 158 debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE; 159 } 160 } 161 return result; 162 } 163 164 matrix_row_t debounce_read_cols(uint8_t row) { 165 // Read the row without debouncing filtering and store it for later usage. 166 matrix_row_t cols = read_cols(row); 167 // Get the Debounce mask. 168 matrix_row_t mask = debounce_mask(cols, row); 169 // debounce the row and return the result. 170 return (cols & mask) | (matrix[row] & ~mask);; 171 } 172 173 uint8_t matrix_scan(void) 174 { 175 // Then the keyboard 176 if (mcp23018_status) { // if there was an error 177 if (++mcp23018_reset_loop == 0) { 178 // if (++mcp23018_reset_loop >= 1300) { 179 // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans 180 // this will be approx bit more frequent than once per second 181 print("trying to reset mcp23018\n"); 182 mcp23018_status = init_mcp23018(); 183 if (mcp23018_status) { 184 print("left side not responding\n"); 185 } else { 186 print("left side attached\n"); 187 } 188 } 189 } 190 191 for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) { 192 select_row(i); 193 // and select on left hand 194 select_row(i + MATRIX_ROWS_PER_SIDE); 195 // we don't need a 30us delay anymore, because selecting a 196 // left-hand row requires more than 30us for i2c. 197 198 // grab cols from left hand 199 matrix[i] = debounce_read_cols(i); 200 // grab cols from right hand 201 matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE); 202 203 unselect_rows(); 204 } 205 206 matrix_scan_kb(); 207 208 #ifdef DEBUG_MATRIX 209 for (uint8_t c = 0; c < MATRIX_COLS; c++) 210 for (uint8_t r = 0; r < MATRIX_ROWS; r++) 211 if (matrix_is_on(r, c)) xprintf("r:%d c:%d \n", r, c); 212 #endif 213 214 return 1; 215 } 216 217 inline 218 bool matrix_is_on(uint8_t row, uint8_t col) 219 { 220 return (matrix[row] & ((matrix_row_t)1<<col)); 221 } 222 223 inline 224 matrix_row_t matrix_get_row(uint8_t row) 225 { 226 return matrix[row]; 227 } 228 229 void matrix_print(void) 230 { 231 print("\nr/c 0123456789ABCDEF\n"); 232 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 233 print_hex8(row); print(": "); 234 print_bin_reverse16(matrix_get_row(row)); 235 print("\n"); 236 } 237 } 238 239 // Remember this means ROWS 240 static void init_cols(void) 241 { 242 // init on mcp23018 243 // not needed, already done as part of init_mcp23018() 244 245 // Input with pull-up(DDR:0, PORT:1) 246 DDRF &= ~FMASK; 247 PORTF |= FMASK; 248 } 249 250 static matrix_row_t read_cols(uint8_t row) 251 { 252 if (row < 7) { 253 if (mcp23018_status) { // if there was an error 254 return 0; 255 } else { 256 uint8_t data = 0; 257 mcp23018_status = i2c_read_register(I2C_ADDR, GPIOB, &data, 1, ERGODOX_EZ_I2C_TIMEOUT); 258 data = ~data; 259 260 #ifdef DEBUG_MATRIX 261 if (data != 0x00) xprintf("I2C: %d\n", data); 262 #endif 263 return data; 264 } 265 } else { 266 /* read from teensy 267 * bitmask is 0b0111001, but we want the lower four 268 * we'll return 1s for the top two, but that's harmless. 269 */ 270 // So I need to confuckulate all this 271 //return ~(((PIND & DMASK) >> 1 | ((PINC & CMASK) >> 6) | (PIN))); 272 //return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2)); 273 return ~( 274 (((PINF & ROW4) >> 1) 275 | ((PINF & (ROW1 | ROW2 | ROW3)) >> 3)) 276 & 0xF); 277 } 278 } 279 280 // Row pin configuration 281 static void unselect_rows(void) 282 { 283 // no need to unselect on mcp23018, because the select step sets all 284 // the other row bits high, and it's not changing to a different 285 // direction 286 // Hi-Z(DDR:0, PORT:0) to unselect 287 DDRB &= ~(BMASK); 288 PORTB &= ~(BMASK); 289 DDRC &= ~CMASK; 290 PORTC &= ~CMASK; 291 DDRD &= ~DMASK; 292 PORTD &= ~DMASK; 293 } 294 295 static void select_row(uint8_t row) 296 { 297 if (row < 7) { 298 // select on mcp23018 299 if (mcp23018_status) { // do nothing on error 300 } else { // set active row low : 0 // set other rows hi-Z : 1 301 uint8_t data = 0xFF & ~(1<<row); 302 mcp23018_status = i2c_write_register(I2C_ADDR, GPIOA, &data, 1, ERGODOX_EZ_I2C_TIMEOUT); 303 304 } 305 } else { 306 // Output low(DDR:1, PORT:0) to select 307 switch (row) { 308 case 7: 309 DDRB |= COL7; 310 PORTB &= ~COL7; 311 break; 312 case 8: 313 DDRB |= COL8; 314 PORTB &= ~COL8; 315 break; 316 case 9: 317 DDRB |= COL9; 318 PORTB &= ~COL9; 319 break; 320 case 10: 321 DDRB |= COL10; 322 PORTB &= ~COL10; 323 break; 324 case 11: 325 DDRD |= COL11; 326 PORTD &= ~COL11; 327 break; 328 case 12: 329 DDRD |= COL12; 330 PORTD &= ~COL12; 331 break; 332 case 13: 333 DDRC |= COL13; 334 PORTC &= ~COL13; 335 break; 336 } 337 } 338 }