matrix.c (4434B)
1 #include "matrix.h" 2 #include <string.h> 3 #include "timer.h" 4 #include "wait.h" 5 #include "debug.h" 6 #include "i2c_master.h" 7 #include "ergodox_stm32.h" 8 9 #ifndef DEBOUNCE 10 #define DEBOUNCE 10 11 #endif 12 13 static uint8_t mcp23017_reset_loop = 0; 14 15 volatile matrix_row_t matrix[MATRIX_ROWS]; 16 volatile matrix_row_t raw_matrix[MATRIX_ROWS]; 17 volatile uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS]; 18 19 static matrix_row_t read_cols(uint8_t row); 20 21 static void init_cols(void); 22 23 static void unselect_rows(void); 24 25 static void select_row(uint8_t row); 26 27 static void init_rows(void); 28 29 __attribute__((weak)) void matrix_init_user(void) {} 30 31 __attribute__((weak)) void matrix_scan_user(void) {} 32 33 __attribute__((weak)) void matrix_init_kb(void) { 34 matrix_init_user(); 35 } 36 37 __attribute__((weak)) void matrix_scan_kb(void) { 38 matrix_scan_user(); 39 } 40 41 void matrix_init(void) { 42 mcp23017_status = init_mcp23017(); 43 (void) mcp23017_reset_loop; 44 init_rows(); 45 unselect_rows(); 46 init_cols(); 47 48 49 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 50 matrix[i] = 0; 51 raw_matrix[i] = 0; 52 for (uint8_t j = 0; j < MATRIX_COLS; ++j) { 53 debounce_matrix[i * MATRIX_COLS + j] = 0; 54 } 55 } 56 matrix_init_kb(); 57 } 58 59 void matrix_power_up(void) { 60 mcp23017_status = init_mcp23017(); 61 62 init_rows(); 63 unselect_rows(); 64 init_cols(); 65 66 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 67 matrix[i] = 0; 68 } 69 } 70 71 matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) { 72 matrix_row_t result = 0; 73 matrix_row_t change = rawcols ^raw_matrix[row]; 74 raw_matrix[row] = rawcols; 75 for (uint8_t i = 0; i < MATRIX_COLS; ++i) { 76 if (debounce_matrix[row * MATRIX_COLS + i]) { 77 --debounce_matrix[row * MATRIX_COLS + i]; 78 } else { 79 result |= (1 << i); 80 } 81 if (change & (1 << i)) { 82 debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE; 83 } 84 } 85 return result; 86 } 87 88 matrix_row_t debounce_read_cols(uint8_t row) { 89 // Read the row without debouncing filtering and store it for later usage. 90 matrix_row_t cols = read_cols(row); 91 // Get the Debounce mask. 92 matrix_row_t mask = debounce_mask(cols, row); 93 // debounce the row and return the result. 94 return (cols & mask) | (matrix[row] & ~mask);; 95 } 96 97 uint8_t matrix_scan(void) { 98 if (mcp23017_status) { 99 if (++mcp23017_reset_loop == 0) { 100 mcp23017_status = init_mcp23017(); 101 if (!mcp23017_status) { 102 ergodox_blink_all_leds(); 103 } 104 } 105 } 106 for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) { 107 select_row(i); 108 select_row(i + MATRIX_ROWS_PER_SIDE); 109 110 matrix[i] = debounce_read_cols(i); 111 matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE); 112 113 unselect_rows(); 114 } 115 matrix_scan_kb(); 116 return 0; 117 } 118 119 inline 120 bool matrix_is_on(uint8_t row, uint8_t col) { 121 return (matrix[row] & (1 << col)); 122 } 123 124 inline 125 matrix_row_t matrix_get_row(uint8_t row) { 126 return matrix[row]; 127 } 128 129 void matrix_print(void) { 130 } 131 132 static matrix_row_t read_cols(uint8_t row) { 133 if (row < MATRIX_ROWS_PER_SIDE) { 134 uint8_t data = 0xFF; 135 if (!mcp23017_status) { 136 uint8_t regAddr = I2C_GPIOB; 137 mcp23017_status = i2c_read_register(I2C_ADDR, regAddr, &data, 1, 10); 138 } 139 if (mcp23017_status) { 140 return 0; 141 } 142 return (~data) & 0x3F; 143 } else { 144 uint8_t data_p = (GPIOB -> IDR); 145 uint8_t data = data_p; 146 return ((~data) & 0x3f); 147 } 148 } 149 150 static void init_cols(void) { 151 palSetPadMode(GPIOB, 0, PAL_MODE_INPUT_PULLUP); 152 palSetPadMode(GPIOB, 1, PAL_MODE_INPUT_PULLUP); 153 palSetPadMode(GPIOB, 2, PAL_MODE_INPUT_PULLUP); 154 palSetPadMode(GPIOB, 3, PAL_MODE_INPUT_PULLUP); 155 palSetPadMode(GPIOB, 4, PAL_MODE_INPUT_PULLUP); 156 palSetPadMode(GPIOB, 5, PAL_MODE_INPUT_PULLUP); 157 } 158 159 static void init_rows(void) { 160 palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL); 161 palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL); 162 palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL); 163 palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL); 164 palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL); 165 palSetPadMode(GPIOB, 13, PAL_MODE_OUTPUT_PUSHPULL); 166 palSetPadMode(GPIOB, 14, PAL_MODE_OUTPUT_PUSHPULL); 167 } 168 169 static void unselect_rows(void) { 170 GPIOB->BSRR = 0b1111111 << 8; 171 } 172 173 static void select_row(uint8_t row) { 174 if (row < MATRIX_ROWS_PER_SIDE) { 175 if (!mcp23017_status) { 176 uint8_t data = (0xFF & ~(1 << row)); 177 mcp23017_status = i2c_write_register(I2C_ADDR, I2C_GPIOA, &data, 1, 10); 178 } 179 } else { 180 GPIOB->BRR = 0x1 << (row+1); 181 } 182 }