matrix.c (7328B)
1 /* 2 Copyright 2019 worthlessowl 3 based on work by: 4 Jun Wako <wakojun@gmail.com> 5 Cole Markham <cole@ccmcomputing.net> 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 2 of the License, or 10 (at your option) any later version. 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 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 /* 20 * scan matrix 21 */ 22 #include <stdint.h> 23 #include <stdbool.h> 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 31 #if (MATRIX_COLS <= 8) 32 # define print_matrix_header() print("\nr/c 01234567\n") 33 # define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row)) 34 # define ROW_SHIFTER ((uint8_t)1) 35 #elif (MATRIX_COLS <= 16) 36 # define print_matrix_header() print("\nr/c 0123456789ABCDEF\n") 37 # define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row)) 38 # define ROW_SHIFTER ((uint16_t)1) 39 #elif (MATRIX_COLS <= 32) 40 # define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n") 41 # define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row)) 42 # define ROW_SHIFTER ((uint32_t)1) 43 #endif 44 45 static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 46 static const uint8_t col_select_pins[3] = MATRIX_COL_SELECT_PINS; 47 static const uint8_t dat_pin = MATRIX_COL_DATA_PIN; 48 49 /* matrix state(1:on, 0:off) */ 50 static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values 51 static matrix_row_t matrix[MATRIX_ROWS]; // raw values 52 53 /* 2d array containing binary representation of its index */ 54 static const uint8_t num_in_binary[8][3] = { 55 {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1}, {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1}, 56 }; 57 58 static void select_col_analog(uint8_t col); 59 static void mux_pin_control(const uint8_t binary[]); 60 void debounce_init(void); 61 void debounce(matrix_row_t raw[], matrix_row_t cooked[], bool changed); 62 63 __attribute__((weak)) void matrix_init_user(void) {} 64 65 __attribute__((weak)) void matrix_scan_user(void) {} 66 67 __attribute__((weak)) void matrix_init_kb(void) { 68 matrix_init_user(); 69 } 70 71 __attribute__((weak)) void matrix_scan_kb(void) { 72 matrix_scan_user(); 73 } 74 75 inline uint8_t matrix_rows(void) { 76 return MATRIX_ROWS; 77 } 78 79 inline uint8_t matrix_cols(void) { 80 return MATRIX_COLS; 81 } 82 83 inline bool matrix_is_on(uint8_t row, uint8_t col) { 84 return (matrix[row] & ((matrix_row_t)1 << col)); 85 } 86 87 inline matrix_row_t matrix_get_row(uint8_t row) { 88 // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a 89 // switch blocker installed and the switch is always pressed. 90 #ifdef MATRIX_MASKED 91 return matrix[row] & matrix_mask[row]; 92 #else 93 return matrix[row]; 94 #endif 95 } 96 97 void matrix_print(void) { 98 print_matrix_header(); 99 100 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 101 print_hex8(row); 102 print(": "); 103 print_matrix_row(row); 104 print("\n"); 105 } 106 } 107 108 // uses standard row code 109 static void select_row(uint8_t row) { 110 gpio_set_pin_output(row_pins[row]); 111 gpio_write_pin_low(row_pins[row]); 112 } 113 114 static void unselect_row(uint8_t row) { 115 gpio_set_pin_input_high(row_pins[row]); 116 } 117 118 static void unselect_rows(void) { 119 for (uint8_t x = 0; x < MATRIX_ROWS; x++) { 120 gpio_set_pin_input_high(row_pins[x]); 121 } 122 } 123 124 static void init_pins(void) { // still need some fixing, this might not work 125 unselect_rows(); // with the loop 126 /* 127 for (uint8_t x = 0; x < MATRIX_COLS; x++) { 128 gpio_set_pin_input_high(col_pins[x]); 129 } 130 */ 131 gpio_set_pin_input_high(dat_pin); 132 } 133 134 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { 135 // Store last value of row prior to reading 136 matrix_row_t last_row_value = current_matrix[current_row]; 137 138 // Clear data in matrix row 139 current_matrix[current_row] = 0; 140 141 // Select row and wait for row selecton to stabilize 142 select_row(current_row); 143 wait_us(30); 144 145 // For each col... 146 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 147 // Select the col pin to read (active low) 148 select_col_analog(col_index); 149 wait_us(30); 150 uint8_t pin_state = gpio_read_pin(dat_pin); 151 152 // Populate the matrix row with the state of the col pin 153 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index); 154 } 155 156 // Unselect row 157 unselect_row(current_row); 158 159 return (last_row_value != current_matrix[current_row]); 160 } 161 162 void matrix_init(void) { 163 // initialize key pins 164 init_pins(); 165 166 // initialize matrix state: all keys off 167 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 168 raw_matrix[i] = 0; 169 matrix[i] = 0; 170 } 171 172 debounce_init(); 173 174 matrix_init_kb(); 175 176 gpio_set_pin_input(D5); 177 gpio_set_pin_input(B0); 178 } 179 180 // modified for per col read matrix scan 181 uint8_t matrix_scan(void) { 182 bool changed = false; 183 184 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 185 changed |= read_cols_on_row(raw_matrix, current_row); 186 } 187 188 debounce(raw_matrix, matrix, changed); 189 190 matrix_scan_kb(); 191 return (uint8_t)changed; 192 } 193 194 /* 195 uint8_t matrix_scan(void) 196 { 197 bool changed = false; 198 199 #if (DIODE_DIRECTION == COL2ROW) 200 // Set row, read cols 201 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { 202 changed |= read_cols_on_row(raw_matrix, current_row); 203 } 204 #endif 205 206 debounce(raw_matrix, matrix, changed); 207 208 matrix_scan_kb(); 209 return (uint8_t)changed; 210 } 211 */ 212 213 static void select_col_analog(uint8_t col) { 214 switch (col) { 215 case 0: 216 mux_pin_control(num_in_binary[0]); 217 break; 218 case 1: 219 mux_pin_control(num_in_binary[1]); 220 break; 221 case 2: 222 mux_pin_control(num_in_binary[2]); 223 break; 224 case 3: 225 mux_pin_control(num_in_binary[3]); 226 break; 227 case 4: 228 mux_pin_control(num_in_binary[4]); 229 break; 230 case 5: 231 mux_pin_control(num_in_binary[5]); 232 break; 233 case 6: 234 mux_pin_control(num_in_binary[6]); 235 break; 236 case 7: 237 mux_pin_control(num_in_binary[7]); 238 break; 239 default: 240 break; 241 } 242 } 243 244 static void mux_pin_control(const uint8_t binary[]) { 245 // set pin0 246 gpio_set_pin_output(col_select_pins[0]); 247 if (binary[2] == 0) { 248 gpio_write_pin_low(col_select_pins[0]); 249 } else { 250 gpio_write_pin_high(col_select_pins[0]); 251 } 252 // set pin1 253 gpio_set_pin_output(col_select_pins[1]); 254 if (binary[1] == 0) { 255 gpio_write_pin_low(col_select_pins[1]); 256 } else { 257 gpio_write_pin_high(col_select_pins[1]); 258 } 259 // set pin2 260 gpio_set_pin_output(col_select_pins[2]); 261 if (binary[0] == 0) { 262 gpio_write_pin_low(col_select_pins[2]); 263 } else { 264 gpio_write_pin_high(col_select_pins[2]); 265 } 266 }