matrix.c (4336B)
1 /* 2 Copyright 2012-2020 Jun Wako, Jack Humbert, Yiancar 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 "matrix.h" 18 #include "wait.h" 19 #include "i2c_master.h" 20 21 static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 22 static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 23 24 static void unselect_rows(void) { 25 for(uint8_t x = 0; x < MATRIX_ROWS; x++) { 26 gpio_set_pin_input_high(row_pins[x]); 27 } 28 } 29 30 static void select_row(uint8_t row) { 31 gpio_set_pin_output(row_pins[row]); 32 gpio_write_pin_low(row_pins[row]); 33 } 34 35 static void unselect_row(uint8_t row) { 36 gpio_set_pin_input_high(row_pins[row]); 37 } 38 39 static void init_pins(void) { 40 unselect_rows(); 41 // Set I/O 42 uint8_t send_data[2] = { 0xFF, 0x03}; 43 i2c_write_register((PORT_EXPANDER_ADDRESS << 1), 0x00, &send_data[0], 2, 20); 44 // Set Pull-up 45 i2c_write_register((PORT_EXPANDER_ADDRESS << 1), 0x0C, &send_data[0], 2, 20); 46 47 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 48 if ( x < 8 ) { 49 gpio_set_pin_input_high(col_pins[x]); 50 } 51 } 52 } 53 54 void matrix_init_custom(void) { 55 // TODO: initialize hardware here 56 // Initialize I2C 57 i2c_init(); 58 59 // initialize key pins 60 init_pins(); 61 wait_ms(50); 62 } 63 64 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 65 // Store last value of row prior to reading 66 matrix_row_t last_row_value = current_matrix[current_row]; 67 68 // Clear data in matrix row 69 current_matrix[current_row] = 0; 70 71 // Select row and wait for row selecton to stabilize 72 select_row(current_row); 73 matrix_io_delay(); 74 75 uint8_t port_expander_col_buffer[2]; 76 i2c_read_register((PORT_EXPANDER_ADDRESS << 1), 0x12, &port_expander_col_buffer[0], 2, 20); 77 78 // For each col... 79 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 80 uint8_t pin_state; 81 // Select the col pin to read (active low) 82 switch (col_index) { 83 case 8 : 84 pin_state = port_expander_col_buffer[0] & (1 << 0); 85 break; 86 case 9 : 87 pin_state = port_expander_col_buffer[0] & (1 << 1); 88 break; 89 case 10 : 90 pin_state = port_expander_col_buffer[0] & (1 << 2); 91 break; 92 case 11 : 93 pin_state = port_expander_col_buffer[0] & (1 << 3); 94 break; 95 case 12 : 96 pin_state = port_expander_col_buffer[0] & (1 << 4); 97 break; 98 case 13 : 99 pin_state = port_expander_col_buffer[0] & (1 << 5); 100 break; 101 case 14 : 102 pin_state = port_expander_col_buffer[0] & (1 << 6); 103 break; 104 case 15 : 105 pin_state = port_expander_col_buffer[0] & (1 << 7); 106 break; 107 case 16 : 108 pin_state = port_expander_col_buffer[1] & (1 << 0); 109 break; 110 case 17 : 111 pin_state = port_expander_col_buffer[1] & (1 << 1); 112 break; 113 default : 114 pin_state = gpio_read_pin(col_pins[col_index]); 115 } 116 117 // Populate the matrix row with the state of the col pin 118 current_matrix[current_row] |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index); 119 } 120 121 // Unselect row 122 unselect_row(current_row); 123 124 return (last_row_value != current_matrix[current_row]); 125 } 126 127 bool matrix_scan_custom(matrix_row_t current_matrix[]) { 128 bool matrix_has_changed = false; 129 130 // Set row, read cols 131 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 132 matrix_has_changed |= read_cols_on_row(current_matrix, current_row); 133 } 134 135 return matrix_has_changed; 136 }