diff options
| author | Drashna Jaelre <drashna@live.com> | 2020-08-22 07:44:42 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-22 07:44:42 -0700 |
| commit | 220b1c9db40d95271dcdd8d8050e46a2a3143c65 (patch) | |
| tree | f98a2177f5ec0009df4400cfd5b100a3ff816297 /keyboards/moonlander/matrix.c | |
| parent | 346bfb2a052f4e05cc91e55e1317c8529c405ac6 (diff) | |
| download | qmk_firmware-220b1c9db40d95271dcdd8d8050e46a2a3143c65.tar.gz qmk_firmware-220b1c9db40d95271dcdd8d8050e46a2a3143c65.zip | |
[Keyboard] Add ZSA Moonlander (#9853)
Diffstat (limited to 'keyboards/moonlander/matrix.c')
| -rw-r--r-- | keyboards/moonlander/matrix.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/keyboards/moonlander/matrix.c b/keyboards/moonlander/matrix.c new file mode 100644 index 000000000..774b01187 --- /dev/null +++ b/keyboards/moonlander/matrix.c | |||
| @@ -0,0 +1,270 @@ | |||
| 1 | /* Copyright 2020 ZSA Technology Labs, Inc <@zsa> | ||
| 2 | * Copyright 2020 Jack Humbert <jack.humb@gmail.com> | ||
| 3 | * Copyright 2020 Drashna Jael're <drashna@live.com> | ||
| 4 | * | ||
| 5 | * This program is free software: you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation, either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 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 | |||
| 21 | #include <stdint.h> | ||
| 22 | #include <stdbool.h> | ||
| 23 | #include <string.h> | ||
| 24 | #include "hal.h" | ||
| 25 | #include "timer.h" | ||
| 26 | #include "wait.h" | ||
| 27 | #include "printf.h" | ||
| 28 | #include "matrix.h" | ||
| 29 | #include "action.h" | ||
| 30 | #include "keycode.h" | ||
| 31 | #include <string.h> | ||
| 32 | #include "moonlander.h" | ||
| 33 | #include "i2c_master.h" | ||
| 34 | #include "debounce.h" | ||
| 35 | |||
| 36 | /* | ||
| 37 | #define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 } outputs | ||
| 38 | #define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 } inputs | ||
| 39 | */ | ||
| 40 | /* matrix state(1:on, 0:off) */ | ||
| 41 | static matrix_row_t matrix[MATRIX_ROWS]; | ||
| 42 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | ||
| 43 | static matrix_row_t matrix_debouncing_right[MATRIX_COLS]; | ||
| 44 | static bool debouncing = false; | ||
| 45 | static uint16_t debouncing_time = 0; | ||
| 46 | static bool debouncing_right = false; | ||
| 47 | static uint16_t debouncing_time_right = 0; | ||
| 48 | |||
| 49 | #define ROWS_PER_HAND (MATRIX_ROWS / 2) | ||
| 50 | |||
| 51 | #ifndef MATRIX_IO_DELAY | ||
| 52 | # define MATRIX_IO_DELAY 20 | ||
| 53 | #endif | ||
| 54 | |||
| 55 | extern bool mcp23018_leds[3]; | ||
| 56 | extern bool is_launching; | ||
| 57 | |||
| 58 | __attribute__((weak)) void matrix_init_user(void) {} | ||
| 59 | |||
| 60 | __attribute__((weak)) void matrix_scan_user(void) {} | ||
| 61 | |||
| 62 | __attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } | ||
| 63 | |||
| 64 | __attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } | ||
| 65 | |||
| 66 | __attribute__((weak)) void matrix_io_delay(void) { wait_us(MATRIX_IO_DELAY); } | ||
| 67 | |||
| 68 | bool mcp23018_initd = false; | ||
| 69 | static uint8_t mcp23018_reset_loop; | ||
| 70 | |||
| 71 | uint8_t mcp23018_tx[3]; | ||
| 72 | uint8_t mcp23018_rx[1]; | ||
| 73 | |||
| 74 | void mcp23018_init(void) { | ||
| 75 | i2c_init(); | ||
| 76 | |||
| 77 | // #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs | ||
| 78 | // #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs | ||
| 79 | |||
| 80 | mcp23018_tx[0] = 0x00; // IODIRA | ||
| 81 | mcp23018_tx[1] = 0b00000000; // A is output | ||
| 82 | mcp23018_tx[2] = 0b00111111; // B is inputs | ||
| 83 | |||
| 84 | if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) { | ||
| 85 | printf("error hori\n"); | ||
| 86 | } else { | ||
| 87 | mcp23018_tx[0] = 0x0C; // GPPUA | ||
| 88 | mcp23018_tx[1] = 0b10000000; // A is not pulled-up | ||
| 89 | mcp23018_tx[2] = 0b11111111; // B is pulled-up | ||
| 90 | |||
| 91 | if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) { | ||
| 92 | printf("error hori\n"); | ||
| 93 | } else { | ||
| 94 | mcp23018_initd = is_launching = true; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | void matrix_init(void) { | ||
| 100 | printf("matrix init\n"); | ||
| 101 | // debug_matrix = true; | ||
| 102 | |||
| 103 | // outputs | ||
| 104 | setPinOutput(B10); | ||
| 105 | setPinOutput(B11); | ||
| 106 | setPinOutput(B12); | ||
| 107 | setPinOutput(B13); | ||
| 108 | setPinOutput(B14); | ||
| 109 | setPinOutput(B15); | ||
| 110 | |||
| 111 | // inputs | ||
| 112 | setPinInputLow(A0); | ||
| 113 | setPinInputLow(A1); | ||
| 114 | setPinInputLow(A2); | ||
| 115 | setPinInputLow(A3); | ||
| 116 | setPinInputLow(A6); | ||
| 117 | setPinInputLow(A7); | ||
| 118 | setPinInputLow(B0); | ||
| 119 | |||
| 120 | memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); | ||
| 121 | memset(matrix_debouncing, 0, MATRIX_ROWS * sizeof(matrix_row_t)); | ||
| 122 | memset(matrix_debouncing_right, 0, MATRIX_COLS * sizeof(matrix_row_t)); | ||
| 123 | |||
| 124 | mcp23018_init(); | ||
| 125 | |||
| 126 | matrix_init_quantum(); | ||
| 127 | } | ||
| 128 | |||
| 129 | uint8_t matrix_scan(void) { | ||
| 130 | bool changed = false; | ||
| 131 | |||
| 132 | matrix_row_t data = 0; | ||
| 133 | // actual matrix | ||
| 134 | for (uint8_t row = 0; row < ROWS_PER_HAND; row++) { | ||
| 135 | // strobe row | ||
| 136 | switch (row) { | ||
| 137 | case 0: writePinHigh(B10); break; | ||
| 138 | case 1: writePinHigh(B11); break; | ||
| 139 | case 2: writePinHigh(B12); break; | ||
| 140 | case 3: writePinHigh(B13); break; | ||
| 141 | case 4: writePinHigh(B14); break; | ||
| 142 | case 5: writePinHigh(B15); break; | ||
| 143 | } | ||
| 144 | |||
| 145 | // need wait to settle pin state | ||
| 146 | matrix_io_delay(); | ||
| 147 | |||
| 148 | // read col data | ||
| 149 | data = ( | ||
| 150 | (readPin(A0) << 0 ) | | ||
| 151 | (readPin(A1) << 1 ) | | ||
| 152 | (readPin(A2) << 2 ) | | ||
| 153 | (readPin(A3) << 3 ) | | ||
| 154 | (readPin(A6) << 4 ) | | ||
| 155 | (readPin(A7) << 5 ) | | ||
| 156 | (readPin(B0) << 6 ) | ||
| 157 | ); | ||
| 158 | |||
| 159 | // unstrobe row | ||
| 160 | switch (row) { | ||
| 161 | case 0: writePinLow(B10); break; | ||
| 162 | case 1: writePinLow(B11); break; | ||
| 163 | case 2: writePinLow(B12); break; | ||
| 164 | case 3: writePinLow(B13); break; | ||
| 165 | case 4: writePinLow(B14); break; | ||
| 166 | case 5: writePinLow(B15); break; | ||
| 167 | } | ||
| 168 | |||
| 169 | if (matrix_debouncing[row] != data) { | ||
| 170 | matrix_debouncing[row] = data; | ||
| 171 | debouncing = true; | ||
| 172 | debouncing_time = timer_read(); | ||
| 173 | changed = true; | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | for (uint8_t row = 0; row <= ROWS_PER_HAND; row++) { | ||
| 178 | // right side | ||
| 179 | |||
| 180 | if (!mcp23018_initd) { | ||
| 181 | if (++mcp23018_reset_loop == 0) { | ||
| 182 | // if (++mcp23018_reset_loop >= 1300) { | ||
| 183 | // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans | ||
| 184 | // this will be approx bit more frequent than once per second | ||
| 185 | print("trying to reset mcp23018\n"); | ||
| 186 | mcp23018_init(); | ||
| 187 | if (!mcp23018_initd) { | ||
| 188 | print("left side not responding\n"); | ||
| 189 | } else { | ||
| 190 | print("left side attached\n"); | ||
| 191 | #ifdef RGB_MATRIX_ENABLE | ||
| 192 | rgb_matrix_init(); | ||
| 193 | #endif | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | // #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs | ||
| 199 | // #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs | ||
| 200 | |||
| 201 | // select row | ||
| 202 | |||
| 203 | mcp23018_tx[0] = 0x12; // GPIOA | ||
| 204 | mcp23018_tx[1] = (0b01111111 & ~(1 << (row))) | ((uint8_t)!mcp23018_leds[2] << 7); // activate row | ||
| 205 | mcp23018_tx[2] = ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7); // activate row | ||
| 206 | |||
| 207 | if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) { | ||
| 208 | printf("error hori\n"); | ||
| 209 | mcp23018_initd = false; | ||
| 210 | } | ||
| 211 | |||
| 212 | // read col | ||
| 213 | |||
| 214 | mcp23018_tx[0] = 0x13; // GPIOB | ||
| 215 | if (MSG_OK != i2c_readReg(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx[0], &mcp23018_rx[0], 1, I2C_TIMEOUT)) { | ||
| 216 | printf("error vert\n"); | ||
| 217 | mcp23018_initd = false; | ||
| 218 | } | ||
| 219 | |||
| 220 | data = ~(mcp23018_rx[0] & 0b00111111); | ||
| 221 | // data = 0x01; | ||
| 222 | |||
| 223 | if (matrix_debouncing_right[row] != data) { | ||
| 224 | matrix_debouncing_right[row] = data; | ||
| 225 | debouncing_right = true; | ||
| 226 | debouncing_time_right = timer_read(); | ||
| 227 | changed = true; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { | ||
| 232 | for (int row = 0; row < ROWS_PER_HAND; row++) { | ||
| 233 | matrix[row] = matrix_debouncing[row]; | ||
| 234 | } | ||
| 235 | debouncing = false; | ||
| 236 | } | ||
| 237 | |||
| 238 | if (debouncing_right && timer_elapsed(debouncing_time_right) > DEBOUNCE && mcp23018_initd) { | ||
| 239 | for (int row = 0; row < ROWS_PER_HAND; row++) { | ||
| 240 | matrix[11 - row] = 0; | ||
| 241 | for (int col = 0; col < MATRIX_COLS; col++) { | ||
| 242 | matrix[11 - row] |= ((matrix_debouncing_right[6 - col] & (1 << row) ? 1 : 0) << col); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | debouncing_right = false; | ||
| 246 | } | ||
| 247 | |||
| 248 | matrix_scan_quantum(); | ||
| 249 | |||
| 250 | return (uint8_t)changed; | ||
| 251 | } | ||
| 252 | |||
| 253 | bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & (1 << col)); } | ||
| 254 | |||
| 255 | matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } | ||
| 256 | |||
| 257 | void matrix_print(void) { | ||
| 258 | printf("\nr/c 01234567\n"); | ||
| 259 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | ||
| 260 | printf("%X0: ", row); | ||
| 261 | matrix_row_t data = matrix_get_row(row); | ||
| 262 | for (int col = 0; col < MATRIX_COLS; col++) { | ||
| 263 | if (data & (1 << col)) | ||
| 264 | printf("1"); | ||
| 265 | else | ||
| 266 | printf("0"); | ||
| 267 | } | ||
| 268 | printf("\n"); | ||
| 269 | } | ||
| 270 | } | ||
