matrix.c (3280B)
1 /* 2 * Copyright 2020 Michael Schwingen 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 #include "util.h" 18 #include "matrix.h" 19 #include "debounce.h" 20 #include "spi_master.h" 21 #include "print.h" 22 #include "mschwingen.h" 23 24 #define SPI_TIMEOUT 100 25 26 /* Keyboard Matrix Assignments */ 27 static uint16_t row_bits[MATRIX_ROWS] = { 28 0x4000, 0x8000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0100, 0x0200, 29 0x0040, 0x0080, 0x0020, 0x0010, 0x0008, 0x0004, 0x0001, 0x0002}; 30 31 static const pin_t col_pins[MATRIX_COLS] = {D1, D4, D7, B4, F7, F6, F5, F4}; 32 33 static void select_col(uint8_t col) { 34 gpio_set_pin_output(col_pins[col]); 35 gpio_write_pin_low(col_pins[col]); 36 } 37 38 static void unselect_col(uint8_t col) { gpio_set_pin_input_high(col_pins[col]); } 39 40 static void unselect_cols(void) { 41 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 42 gpio_set_pin_input_high(col_pins[x]); 43 } 44 } 45 46 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 47 uint16_t row_data; 48 bool matrix_changed = false; 49 50 // Select col and wait for col selecton to stabilize 51 select_col(current_col); 52 matrix_io_delay(); 53 54 gpio_write_pin_low(SR_LOAD_PIN); 55 gpio_write_pin_high(SR_LOAD_PIN); 56 57 row_data = spi_read() << 8; 58 row_data |= spi_read(); 59 60 dprintf("%02X ", ~row_data); 61 62 // For each row... 63 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 64 // Store last value of row prior to reading 65 matrix_row_t last_row_value = current_matrix[row_index]; 66 matrix_row_t current_row_value = last_row_value; 67 68 // Check row pin state 69 if ((row_data & row_bits[row_index]) == 0) { 70 // Pin LO, set col bit 71 current_row_value |= (MATRIX_ROW_SHIFTER << current_col); 72 } else { 73 // Pin HI, clear col bit 74 current_row_value &= ~(MATRIX_ROW_SHIFTER << current_col); 75 } 76 77 // Determine if the matrix changed state 78 if ((last_row_value != current_row_value)) { 79 matrix_changed = true; 80 current_matrix[row_index] = current_row_value; 81 } 82 } 83 84 // Unselect col 85 unselect_col(current_col); 86 87 return matrix_changed; 88 } 89 90 void matrix_init_custom(void) { 91 unselect_cols(); 92 93 // set 4MHz SPI clock 94 SPSR = 0; 95 SPCR = _BV(SPE) | _BV(MSTR) | _BV(CPOL); 96 } 97 98 bool matrix_scan_custom(matrix_row_t current_matrix[]) { 99 bool changed = false; 100 101 dprint("\r\nScan: "); 102 103 // Set col, read rows 104 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 105 changed |= read_rows_on_col(current_matrix, current_col); 106 } 107 update_layer_leds(); 108 return changed; 109 }