matrix.c (5468B)
1 /* 2 * Copyright 2018 Jack Humbert <jack.humb@gmail.com> 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 18 #include "matrix.h" 19 #include "debug.h" 20 #include "timer.h" 21 #include "wait.h" 22 23 #ifndef DEBOUNCE 24 # define DEBOUNCE 5 25 #endif 26 27 typedef uint16_t matrix_col_t; 28 29 /* 30 * col: { B11, B10, B2, B1, A7, B0 } 31 * row: { A10, A9, A8, B15, C13, C14, C15, A2 } 32 */ 33 /* matrix state(1:on, 0:off) */ 34 static matrix_row_t matrix[MATRIX_ROWS]; 35 static matrix_col_t matrix_debouncing[MATRIX_COLS]; 36 static bool debouncing = false; 37 static uint16_t debouncing_time = 0; 38 39 __attribute__((weak)) void matrix_init_user(void) {} 40 41 __attribute__((weak)) void matrix_scan_user(void) {} 42 43 __attribute__((weak)) void matrix_init_kb(void) { 44 matrix_init_user(); 45 } 46 47 __attribute__((weak)) void matrix_scan_kb(void) { 48 matrix_scan_user(); 49 } 50 51 void matrix_init(void) { 52 dprintf("matrix init\n"); 53 // debug_matrix = true; 54 55 // actual matrix setup 56 palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL); 57 palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL); 58 palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL); 59 palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL); 60 palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL); 61 palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL); 62 63 palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLDOWN); 64 palSetPadMode(GPIOA, 9, PAL_MODE_INPUT_PULLDOWN); 65 palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN); 66 palSetPadMode(GPIOB, 15, PAL_MODE_INPUT_PULLDOWN); 67 palSetPadMode(GPIOC, 13, PAL_MODE_INPUT_PULLDOWN); 68 palSetPadMode(GPIOC, 14, PAL_MODE_INPUT_PULLDOWN); 69 palSetPadMode(GPIOC, 15, PAL_MODE_INPUT_PULLDOWN); 70 palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_PULLDOWN); 71 palSetPadMode(GPIOA, 3, PAL_MODE_INPUT_PULLDOWN); 72 palSetPadMode(GPIOA, 6, PAL_MODE_INPUT_PULLDOWN); 73 74 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); 75 memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_col_t)); 76 77 matrix_init_kb(); 78 } 79 80 uint8_t matrix_scan(void) { 81 // actual matrix 82 for (int col = 0; col < MATRIX_COLS; col++) { 83 matrix_col_t data = 0; 84 85 // strobe col { B11, B10, B2, B1, A7, B0 } 86 switch (col) { 87 case 0: 88 palSetPad(GPIOB, 11); 89 break; 90 case 1: 91 palSetPad(GPIOB, 10); 92 break; 93 case 2: 94 palSetPad(GPIOB, 2); 95 break; 96 case 3: 97 palSetPad(GPIOB, 1); 98 break; 99 case 4: 100 palSetPad(GPIOA, 7); 101 break; 102 case 5: 103 palSetPad(GPIOB, 0); 104 break; 105 } 106 107 // need wait to settle pin state 108 wait_us(20); 109 110 // read row data { A10, A9, A8, B15, C13, C14, C15, A2 } 111 data = ((palReadPad(GPIOA, 10) << 0) | (palReadPad(GPIOA, 9) << 1) | (palReadPad(GPIOA, 8) << 2) | (palReadPad(GPIOB, 15) << 3) | (palReadPad(GPIOC, 13) << 4) | (palReadPad(GPIOC, 14) << 5) | (palReadPad(GPIOC, 15) << 6) | (palReadPad(GPIOA, 2) << 7) | (palReadPad(GPIOA, 3) << 8) | (palReadPad(GPIOA, 6) << 9)); 112 113 // unstrobe col { B11, B10, B2, B1, A7, B0 } 114 switch (col) { 115 case 0: 116 palClearPad(GPIOB, 11); 117 break; 118 case 1: 119 palClearPad(GPIOB, 10); 120 break; 121 case 2: 122 palClearPad(GPIOB, 2); 123 break; 124 case 3: 125 palClearPad(GPIOB, 1); 126 break; 127 case 4: 128 palClearPad(GPIOA, 7); 129 break; 130 case 5: 131 palClearPad(GPIOB, 0); 132 break; 133 } 134 135 if (matrix_debouncing[col] != data) { 136 matrix_debouncing[col] = data; 137 debouncing = true; 138 debouncing_time = timer_read(); 139 } 140 } 141 142 if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { 143 for (int row = 0; row < MATRIX_ROWS; row++) { 144 matrix[row] = 0; 145 for (int col = 0; col < MATRIX_COLS; col++) { 146 matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col); 147 } 148 } 149 debouncing = false; 150 } 151 152 matrix_scan_kb(); 153 154 return 1; 155 } 156 157 bool matrix_is_on(uint8_t row, uint8_t col) { 158 return (matrix[row] & (1 << col)); 159 } 160 161 matrix_row_t matrix_get_row(uint8_t row) { 162 return matrix[row]; 163 } 164 165 void matrix_print(void) { 166 dprintf("\nr/c 01234567\n"); 167 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 168 dprintf("%X0: ", row); 169 matrix_row_t data = matrix_get_row(row); 170 for (int col = 0; col < MATRIX_COLS; col++) { 171 if (data & (1 << col)) 172 dprintf("1"); 173 else 174 dprintf("0"); 175 } 176 dprintf("\n"); 177 } 178 }