diff options
| author | Alex Ong <the.onga@gmail.com> | 2019-04-04 08:45:55 +1100 |
|---|---|---|
| committer | Drashna Jaelre <drashna@live.com> | 2019-04-03 14:45:55 -0700 |
| commit | 17e7762de7e3fdfc61c20aa61022f47370630c6a (patch) | |
| tree | acad10cdb64e24d78154c7c04de3585dece32cc3 /keyboards/ergodox_ez/matrix.c | |
| parent | e1e08a494bf9ea46e1385559df76d5f49b8e9087 (diff) | |
| download | qmk_firmware-17e7762de7e3fdfc61c20aa61022f47370630c6a.tar.gz qmk_firmware-17e7762de7e3fdfc61c20aa61022f47370630c6a.zip | |
Eager Per Row Debouncing added (added to Ergodox) (#5498)
* Implemented Eager Per Row debouncing algorithm.
Good for when fingers can only press one row at a time (e.g. when keyboard is wired so that "rows" are vertical)
* Added documentation for eager_pr
* Ported ergodox_ez to eager_pr debouncing.
* Removed check for changes in matrix_scan.
* Added further clarification in docs.
* Accidental merge with ergodox_ez
* Small cleanup in eager_pr
* Forgot to debounce_init - this would probably cause seg-faults.
Diffstat (limited to 'keyboards/ergodox_ez/matrix.c')
| -rw-r--r-- | keyboards/ergodox_ez/matrix.c | 458 |
1 files changed, 196 insertions, 262 deletions
diff --git a/keyboards/ergodox_ez/matrix.c b/keyboards/ergodox_ez/matrix.c index 860cf7b22..97f764113 100644 --- a/keyboards/ergodox_ez/matrix.c +++ b/keyboards/ergodox_ez/matrix.c | |||
| @@ -33,14 +33,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 33 | #include "debug.h" | 33 | #include "debug.h" |
| 34 | #include "util.h" | 34 | #include "util.h" |
| 35 | #include "matrix.h" | 35 | #include "matrix.h" |
| 36 | #include "debounce.h" | ||
| 36 | #include QMK_KEYBOARD_H | 37 | #include QMK_KEYBOARD_H |
| 37 | #ifdef DEBUG_MATRIX_SCAN_RATE | 38 | #ifdef DEBUG_MATRIX_SCAN_RATE |
| 38 | #include "timer.h" | 39 | # include "timer.h" |
| 39 | #endif | 40 | #endif |
| 40 | 41 | ||
| 41 | /* | 42 | /* |
| 42 | * This constant define not debouncing time in msecs, but amount of matrix | 43 | * This constant define not debouncing time in msecs, assuming eager_pr. |
| 43 | * scan loops which should be made to get stable debounced results. | ||
| 44 | * | 44 | * |
| 45 | * On Ergodox matrix scan rate is relatively low, because of slow I2C. | 45 | * On Ergodox matrix scan rate is relatively low, because of slow I2C. |
| 46 | * Now it's only 317 scans/second, or about 3.15 msec/scan. | 46 | * Now it's only 317 scans/second, or about 3.15 msec/scan. |
| @@ -52,26 +52,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | #ifndef DEBOUNCE | 54 | #ifndef DEBOUNCE |
| 55 | # define DEBOUNCE 5 | 55 | # define DEBOUNCE 5 |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | /* matrix state(1:on, 0:off) */ | 58 | /* matrix state(1:on, 0:off) */ |
| 59 | static matrix_row_t matrix[MATRIX_ROWS]; | 59 | static matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values |
| 60 | /* | 60 | static matrix_row_t matrix[MATRIX_ROWS]; // debounced values |
| 61 | * matrix state(1:on, 0:off) | ||
| 62 | * contains the raw values without debounce filtering of the last read cycle. | ||
| 63 | */ | ||
| 64 | static matrix_row_t raw_matrix[MATRIX_ROWS]; | ||
| 65 | |||
| 66 | // Debouncing: store for each key the number of scans until it's eligible to | ||
| 67 | // change. When scanning the matrix, ignore any changes in keys that have | ||
| 68 | // already changed in the last DEBOUNCE scans. | ||
| 69 | static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS]; | ||
| 70 | 61 | ||
| 71 | static matrix_row_t read_cols(uint8_t row); | 62 | static matrix_row_t read_cols(uint8_t row); |
| 72 | static void init_cols(void); | 63 | static void init_cols(void); |
| 73 | static void unselect_rows(void); | 64 | static void unselect_rows(void); |
| 74 | static void select_row(uint8_t row); | 65 | static void select_row(uint8_t row); |
| 75 | 66 | ||
| 76 | static uint8_t mcp23018_reset_loop; | 67 | static uint8_t mcp23018_reset_loop; |
| 77 | // static uint16_t mcp23018_reset_loop; | 68 | // static uint16_t mcp23018_reset_loop; |
| @@ -81,197 +72,137 @@ uint32_t matrix_timer; | |||
| 81 | uint32_t matrix_scan_count; | 72 | uint32_t matrix_scan_count; |
| 82 | #endif | 73 | #endif |
| 83 | 74 | ||
| 75 | __attribute__((weak)) void matrix_init_user(void) {} | ||
| 84 | 76 | ||
| 85 | __attribute__ ((weak)) | 77 | __attribute__((weak)) void matrix_scan_user(void) {} |
| 86 | void matrix_init_user(void) {} | ||
| 87 | 78 | ||
| 88 | __attribute__ ((weak)) | 79 | __attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); } |
| 89 | void matrix_scan_user(void) {} | ||
| 90 | 80 | ||
| 91 | __attribute__ ((weak)) | 81 | __attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } |
| 92 | void matrix_init_kb(void) { | ||
| 93 | matrix_init_user(); | ||
| 94 | } | ||
| 95 | 82 | ||
| 96 | __attribute__ ((weak)) | 83 | inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } |
| 97 | void matrix_scan_kb(void) { | ||
| 98 | matrix_scan_user(); | ||
| 99 | } | ||
| 100 | |||
| 101 | inline | ||
| 102 | uint8_t matrix_rows(void) | ||
| 103 | { | ||
| 104 | return MATRIX_ROWS; | ||
| 105 | } | ||
| 106 | 84 | ||
| 107 | inline | 85 | inline uint8_t matrix_cols(void) { return MATRIX_COLS; } |
| 108 | uint8_t matrix_cols(void) | ||
| 109 | { | ||
| 110 | return MATRIX_COLS; | ||
| 111 | } | ||
| 112 | 86 | ||
| 113 | void matrix_init(void) | 87 | void matrix_init(void) { |
| 114 | { | 88 | // initialize row and col |
| 115 | // initialize row and col | ||
| 116 | 89 | ||
| 117 | mcp23018_status = init_mcp23018(); | 90 | mcp23018_status = init_mcp23018(); |
| 118 | 91 | ||
| 92 | unselect_rows(); | ||
| 93 | init_cols(); | ||
| 119 | 94 | ||
| 120 | unselect_rows(); | 95 | // initialize matrix state: all keys off |
| 121 | init_cols(); | 96 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| 122 | 97 | matrix[i] = 0; | |
| 123 | // initialize matrix state: all keys off | 98 | raw_matrix[i] = 0; |
| 124 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | 99 | } |
| 125 | matrix[i] = 0; | ||
| 126 | raw_matrix[i] = 0; | ||
| 127 | for (uint8_t j=0; j < MATRIX_COLS; ++j) { | ||
| 128 | debounce_matrix[i * MATRIX_COLS + j] = 0; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | 100 | ||
| 132 | #ifdef DEBUG_MATRIX_SCAN_RATE | 101 | #ifdef DEBUG_MATRIX_SCAN_RATE |
| 133 | matrix_timer = timer_read32(); | 102 | matrix_timer = timer_read32(); |
| 134 | matrix_scan_count = 0; | 103 | matrix_scan_count = 0; |
| 135 | #endif | 104 | #endif |
| 136 | 105 | debounce_init(MATRIX_ROWS); | |
| 137 | matrix_init_quantum(); | 106 | matrix_init_quantum(); |
| 138 | |||
| 139 | } | 107 | } |
| 140 | 108 | ||
| 141 | void matrix_power_up(void) { | 109 | void matrix_power_up(void) { |
| 142 | mcp23018_status = init_mcp23018(); | 110 | mcp23018_status = init_mcp23018(); |
| 143 | 111 | ||
| 144 | unselect_rows(); | 112 | unselect_rows(); |
| 145 | init_cols(); | 113 | init_cols(); |
| 146 | 114 | ||
| 147 | // initialize matrix state: all keys off | 115 | // initialize matrix state: all keys off |
| 148 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | 116 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| 149 | matrix[i] = 0; | 117 | matrix[i] = 0; |
| 150 | } | 118 | } |
| 151 | 119 | ||
| 152 | #ifdef DEBUG_MATRIX_SCAN_RATE | 120 | #ifdef DEBUG_MATRIX_SCAN_RATE |
| 153 | matrix_timer = timer_read32(); | 121 | matrix_timer = timer_read32(); |
| 154 | matrix_scan_count = 0; | 122 | matrix_scan_count = 0; |
| 155 | #endif | 123 | #endif |
| 156 | } | 124 | } |
| 157 | 125 | ||
| 158 | // Returns a matrix_row_t whose bits are set if the corresponding key should be | 126 | uint8_t matrix_scan(void) { |
| 159 | // eligible to change in this scan. | 127 | if (mcp23018_status) { // if there was an error |
| 160 | matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) { | 128 | if (++mcp23018_reset_loop == 0) { |
| 161 | matrix_row_t result = 0; | 129 | // if (++mcp23018_reset_loop >= 1300) { |
| 162 | matrix_row_t change = rawcols ^ raw_matrix[row]; | 130 | // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans |
| 163 | raw_matrix[row] = rawcols; | 131 | // this will be approx bit more frequent than once per second |
| 164 | for (uint8_t i = 0; i < MATRIX_COLS; ++i) { | 132 | print("trying to reset mcp23018\n"); |
| 165 | if (debounce_matrix[row * MATRIX_COLS + i]) { | 133 | mcp23018_status = init_mcp23018(); |
| 166 | --debounce_matrix[row * MATRIX_COLS + i]; | 134 | if (mcp23018_status) { |
| 167 | } else { | 135 | print("left side not responding\n"); |
| 168 | result |= (1 << i); | 136 | } else { |
| 169 | } | 137 | print("left side attached\n"); |
| 170 | if (change & (1 << i)) { | 138 | ergodox_blink_all_leds(); |
| 171 | debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE; | 139 | } |
| 172 | } | 140 | } |
| 173 | } | 141 | } |
| 174 | return result; | ||
| 175 | } | ||
| 176 | |||
| 177 | matrix_row_t debounce_read_cols(uint8_t row) { | ||
| 178 | // Read the row without debouncing filtering and store it for later usage. | ||
| 179 | matrix_row_t cols = read_cols(row); | ||
| 180 | // Get the Debounce mask. | ||
| 181 | matrix_row_t mask = debounce_mask(cols, row); | ||
| 182 | // debounce the row and return the result. | ||
| 183 | return (cols & mask) | (matrix[row] & ~mask);; | ||
| 184 | } | ||
| 185 | |||
| 186 | uint8_t matrix_scan(void) | ||
| 187 | { | ||
| 188 | if (mcp23018_status) { // if there was an error | ||
| 189 | if (++mcp23018_reset_loop == 0) { | ||
| 190 | // if (++mcp23018_reset_loop >= 1300) { | ||
| 191 | // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans | ||
| 192 | // this will be approx bit more frequent than once per second | ||
| 193 | print("trying to reset mcp23018\n"); | ||
| 194 | mcp23018_status = init_mcp23018(); | ||
| 195 | if (mcp23018_status) { | ||
| 196 | print("left side not responding\n"); | ||
| 197 | } else { | ||
| 198 | print("left side attached\n"); | ||
| 199 | ergodox_blink_all_leds(); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | } | ||
| 203 | 142 | ||
| 204 | #ifdef DEBUG_MATRIX_SCAN_RATE | 143 | #ifdef DEBUG_MATRIX_SCAN_RATE |
| 205 | matrix_scan_count++; | 144 | matrix_scan_count++; |
| 206 | 145 | ||
| 207 | uint32_t timer_now = timer_read32(); | 146 | uint32_t timer_now = timer_read32(); |
| 208 | if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) { | 147 | if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) { |
| 209 | print("matrix scan frequency: "); | 148 | print("matrix scan frequency: "); |
| 210 | pdec(matrix_scan_count); | 149 | pdec(matrix_scan_count); |
| 211 | print("\n"); | 150 | print("\n"); |
| 212 | 151 | ||
| 213 | matrix_timer = timer_now; | 152 | matrix_timer = timer_now; |
| 214 | matrix_scan_count = 0; | 153 | matrix_scan_count = 0; |
| 215 | } | 154 | } |
| 216 | #endif | 155 | #endif |
| 217 | 156 | ||
| 218 | #ifdef LEFT_LEDS | 157 | #ifdef LEFT_LEDS |
| 219 | mcp23018_status = ergodox_left_leds_update(); | 158 | mcp23018_status = ergodox_left_leds_update(); |
| 220 | #endif // LEFT_LEDS | 159 | #endif // LEFT_LEDS |
| 221 | for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) { | 160 | for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) { |
| 222 | select_row(i); | 161 | // select rows from left and right hands |
| 223 | // and select on left hand | 162 | select_row(i); |
| 224 | select_row(i + MATRIX_ROWS_PER_SIDE); | 163 | select_row(i + MATRIX_ROWS_PER_SIDE); |
| 225 | // we don't need a 30us delay anymore, because selecting a | 164 | |
| 226 | // left-hand row requires more than 30us for i2c. | 165 | // we don't need a 30us delay anymore, because selecting a |
| 227 | 166 | // left-hand row requires more than 30us for i2c. | |
| 228 | // grab cols from left hand | 167 | |
| 229 | matrix[i] = debounce_read_cols(i); | 168 | // grab left + right cols. |
| 230 | // grab cols from right hand | 169 | raw_matrix[i] = read_cols(i); |
| 231 | matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE); | 170 | raw_matrix[i+MATRIX_ROWS_PER_SIDE] = read_cols(i+MATRIX_ROWS_PER_SIDE); |
| 232 | 171 | ||
| 233 | unselect_rows(); | 172 | unselect_rows(); |
| 234 | } | 173 | } |
| 235 | 174 | ||
| 236 | matrix_scan_quantum(); | 175 | debounce(raw_matrix, matrix, MATRIX_ROWS, true); |
| 176 | matrix_scan_quantum(); | ||
| 237 | 177 | ||
| 238 | return 1; | 178 | return 1; |
| 239 | } | 179 | } |
| 240 | 180 | ||
| 241 | bool matrix_is_modified(void) // deprecated and evidently not called. | 181 | bool matrix_is_modified(void) // deprecated and evidently not called. |
| 242 | { | 182 | { |
| 243 | return true; | 183 | return true; |
| 244 | } | 184 | } |
| 245 | 185 | ||
| 246 | inline | 186 | inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); } |
| 247 | bool matrix_is_on(uint8_t row, uint8_t col) | ||
| 248 | { | ||
| 249 | return (matrix[row] & ((matrix_row_t)1<<col)); | ||
| 250 | } | ||
| 251 | 187 | ||
| 252 | inline | 188 | inline matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } |
| 253 | matrix_row_t matrix_get_row(uint8_t row) | ||
| 254 | { | ||
| 255 | return matrix[row]; | ||
| 256 | } | ||
| 257 | 189 | ||
| 258 | void matrix_print(void) | 190 | void matrix_print(void) { |
| 259 | { | 191 | print("\nr/c 0123456789ABCDEF\n"); |
| 260 | print("\nr/c 0123456789ABCDEF\n"); | 192 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { |
| 261 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | 193 | phex(row); |
| 262 | phex(row); print(": "); | 194 | print(": "); |
| 263 | pbin_reverse16(matrix_get_row(row)); | 195 | pbin_reverse16(matrix_get_row(row)); |
| 264 | print("\n"); | 196 | print("\n"); |
| 265 | } | 197 | } |
| 266 | } | 198 | } |
| 267 | 199 | ||
| 268 | uint8_t matrix_key_count(void) | 200 | uint8_t matrix_key_count(void) { |
| 269 | { | 201 | uint8_t count = 0; |
| 270 | uint8_t count = 0; | 202 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| 271 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | 203 | count += bitpop16(matrix[i]); |
| 272 | count += bitpop16(matrix[i]); | 204 | } |
| 273 | } | 205 | return count; |
| 274 | return count; | ||
| 275 | } | 206 | } |
| 276 | 207 | ||
| 277 | /* Column pin configuration | 208 | /* Column pin configuration |
| @@ -284,43 +215,45 @@ uint8_t matrix_key_count(void) | |||
| 284 | * col: 0 1 2 3 4 5 | 215 | * col: 0 1 2 3 4 5 |
| 285 | * pin: B5 B4 B3 B2 B1 B0 | 216 | * pin: B5 B4 B3 B2 B1 B0 |
| 286 | */ | 217 | */ |
| 287 | static void init_cols(void) | 218 | static void init_cols(void) { |
| 288 | { | 219 | // init on mcp23018 |
| 289 | // init on mcp23018 | 220 | // not needed, already done as part of init_mcp23018() |
| 290 | // not needed, already done as part of init_mcp23018() | 221 | |
| 291 | 222 | // init on teensy | |
| 292 | // init on teensy | 223 | // Input with pull-up(DDR:0, PORT:1) |
| 293 | // Input with pull-up(DDR:0, PORT:1) | 224 | DDRF &= ~(1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 1 | 1 << 0); |
| 294 | DDRF &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); | 225 | PORTF |= (1 << 7 | 1 << 6 | 1 << 5 | 1 << 4 | 1 << 1 | 1 << 0); |
| 295 | PORTF |= (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0); | ||
| 296 | } | 226 | } |
| 297 | 227 | ||
| 298 | static matrix_row_t read_cols(uint8_t row) | 228 | static matrix_row_t read_cols(uint8_t row) { |
| 299 | { | 229 | if (row < 7) { |
| 300 | if (row < 7) { | 230 | if (mcp23018_status) { // if there was an error |
| 301 | if (mcp23018_status) { // if there was an error | 231 | return 0; |
| 302 | return 0; | ||
| 303 | } else { | ||
| 304 | uint8_t data = 0; | ||
| 305 | mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; | ||
| 306 | mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; | ||
| 307 | mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; | ||
| 308 | mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out; | ||
| 309 | data = ~((uint8_t)mcp23018_status); | ||
| 310 | mcp23018_status = I2C_STATUS_SUCCESS; | ||
| 311 | out: | ||
| 312 | i2c_stop(); | ||
| 313 | return data; | ||
| 314 | } | ||
| 315 | } else { | 232 | } else { |
| 316 | /* read from teensy | 233 | uint8_t data = 0; |
| 317 | * bitmask is 0b11110011, but we want those all | 234 | mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); |
| 318 | * in the lower six bits. | 235 | if (mcp23018_status) goto out; |
| 319 | * we'll return 1s for the top two, but that's harmless. | 236 | mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); |
| 320 | */ | 237 | if (mcp23018_status) goto out; |
| 321 | 238 | mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); | |
| 322 | return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2)); | 239 | if (mcp23018_status) goto out; |
| 240 | mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); | ||
| 241 | if (mcp23018_status < 0) goto out; | ||
| 242 | data = ~((uint8_t)mcp23018_status); | ||
| 243 | mcp23018_status = I2C_STATUS_SUCCESS; | ||
| 244 | out: | ||
| 245 | i2c_stop(); | ||
| 246 | return data; | ||
| 323 | } | 247 | } |
| 248 | } else { | ||
| 249 | /* read from teensy | ||
| 250 | * bitmask is 0b11110011, but we want those all | ||
| 251 | * in the lower six bits. | ||
| 252 | * we'll return 1s for the top two, but that's harmless. | ||
| 253 | */ | ||
| 254 | |||
| 255 | return ~((PINF & 0x03) | ((PINF & 0xF0) >> 2)); | ||
| 256 | } | ||
| 324 | } | 257 | } |
| 325 | 258 | ||
| 326 | /* Row pin configuration | 259 | /* Row pin configuration |
| @@ -333,69 +266,70 @@ static matrix_row_t read_cols(uint8_t row) | |||
| 333 | * row: 0 1 2 3 4 5 6 | 266 | * row: 0 1 2 3 4 5 6 |
| 334 | * pin: A0 A1 A2 A3 A4 A5 A6 | 267 | * pin: A0 A1 A2 A3 A4 A5 A6 |
| 335 | */ | 268 | */ |
| 336 | static void unselect_rows(void) | 269 | static void unselect_rows(void) { |
| 337 | { | 270 | // no need to unselect on mcp23018, because the select step sets all |
| 338 | // no need to unselect on mcp23018, because the select step sets all | 271 | // the other row bits high, and it's not changing to a different |
| 339 | // the other row bits high, and it's not changing to a different | 272 | // direction |
| 340 | // direction | 273 | |
| 341 | 274 | // unselect on teensy | |
| 342 | // unselect on teensy | 275 | // Hi-Z(DDR:0, PORT:0) to unselect |
| 343 | // Hi-Z(DDR:0, PORT:0) to unselect | 276 | DDRB &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); |
| 344 | DDRB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); | 277 | PORTB &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3); |
| 345 | PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3); | 278 | DDRD &= ~(1 << 2 | 1 << 3); |
| 346 | DDRD &= ~(1<<2 | 1<<3); | 279 | PORTD &= ~(1 << 2 | 1 << 3); |
| 347 | PORTD &= ~(1<<2 | 1<<3); | 280 | DDRC &= ~(1 << 6); |
| 348 | DDRC &= ~(1<<6); | 281 | PORTC &= ~(1 << 6); |
| 349 | PORTC &= ~(1<<6); | ||
| 350 | } | 282 | } |
| 351 | 283 | ||
| 352 | static void select_row(uint8_t row) | 284 | static void select_row(uint8_t row) { |
| 353 | { | 285 | if (row < 7) { |
| 354 | if (row < 7) { | 286 | // select on mcp23018 |
| 355 | // select on mcp23018 | 287 | if (mcp23018_status) { // if there was an error |
| 356 | if (mcp23018_status) { // if there was an error | 288 | // do nothing |
| 357 | // do nothing | ||
| 358 | } else { | ||
| 359 | // set active row low : 0 | ||
| 360 | // set other rows hi-Z : 1 | ||
| 361 | mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; | ||
| 362 | mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; | ||
| 363 | mcp23018_status = i2c_write(0xFF & ~(1<<row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out; | ||
| 364 | out: | ||
| 365 | i2c_stop(); | ||
| 366 | } | ||
| 367 | } else { | 289 | } else { |
| 368 | // select on teensy | 290 | // set active row low : 0 |
| 369 | // Output low(DDR:1, PORT:0) to select | 291 | // set other rows hi-Z : 1 |
| 370 | switch (row) { | 292 | mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); |
| 371 | case 7: | 293 | if (mcp23018_status) goto out; |
| 372 | DDRB |= (1<<0); | 294 | mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); |
| 373 | PORTB &= ~(1<<0); | 295 | if (mcp23018_status) goto out; |
| 374 | break; | 296 | mcp23018_status = i2c_write(0xFF & ~(1 << row), ERGODOX_EZ_I2C_TIMEOUT); |
| 375 | case 8: | 297 | if (mcp23018_status) goto out; |
| 376 | DDRB |= (1<<1); | 298 | out: |
| 377 | PORTB &= ~(1<<1); | 299 | i2c_stop(); |
| 378 | break; | 300 | } |
| 379 | case 9: | 301 | } else { |
| 380 | DDRB |= (1<<2); | 302 | // select on teensy |
| 381 | PORTB &= ~(1<<2); | 303 | // Output low(DDR:1, PORT:0) to select |
| 382 | break; | 304 | switch (row) { |
| 383 | case 10: | 305 | case 7: |
| 384 | DDRB |= (1<<3); | 306 | DDRB |= (1 << 0); |
| 385 | PORTB &= ~(1<<3); | 307 | PORTB &= ~(1 << 0); |
| 386 | break; | 308 | break; |
| 387 | case 11: | 309 | case 8: |
| 388 | DDRD |= (1<<2); | 310 | DDRB |= (1 << 1); |
| 389 | PORTD &= ~(1<<2); | 311 | PORTB &= ~(1 << 1); |
| 390 | break; | 312 | break; |
| 391 | case 12: | 313 | case 9: |
| 392 | DDRD |= (1<<3); | 314 | DDRB |= (1 << 2); |
| 393 | PORTD &= ~(1<<3); | 315 | PORTB &= ~(1 << 2); |
| 394 | break; | 316 | break; |
| 395 | case 13: | 317 | case 10: |
| 396 | DDRC |= (1<<6); | 318 | DDRB |= (1 << 3); |
| 397 | PORTC &= ~(1<<6); | 319 | PORTB &= ~(1 << 3); |
| 398 | break; | 320 | break; |
| 399 | } | 321 | case 11: |
| 322 | DDRD |= (1 << 2); | ||
| 323 | PORTD &= ~(1 << 2); | ||
| 324 | break; | ||
| 325 | case 12: | ||
| 326 | DDRD |= (1 << 3); | ||
| 327 | PORTD &= ~(1 << 3); | ||
| 328 | break; | ||
| 329 | case 13: | ||
| 330 | DDRC |= (1 << 6); | ||
| 331 | PORTC &= ~(1 << 6); | ||
| 332 | break; | ||
| 400 | } | 333 | } |
| 334 | } | ||
| 401 | } | 335 | } |
