diff options
| -rw-r--r-- | quantum/matrix.c | 292 | ||||
| -rw-r--r-- | tmk_core/common/avr/suspend.c | 6 | ||||
| -rw-r--r-- | tmk_core/common/bootmagic.c | 16 | ||||
| -rw-r--r-- | tmk_core/common/keyboard.c | 107 | ||||
| -rw-r--r-- | tmk_core/common/matrix.h | 57 |
5 files changed, 261 insertions, 217 deletions
diff --git a/quantum/matrix.c b/quantum/matrix.c index a38c13f15..094917025 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c | |||
| @@ -26,32 +26,46 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 26 | #include "util.h" | 26 | #include "util.h" |
| 27 | #include "matrix.h" | 27 | #include "matrix.h" |
| 28 | 28 | ||
| 29 | #ifdef MATRIX_HAS_GHOST | 29 | /* Set 0 if debouncing isn't needed */ |
| 30 | # error "The universal matrix.c file cannot be used for this keyboard." | 30 | /* |
| 31 | #endif | 31 | * This constant define not debouncing time in msecs, but amount of matrix |
| 32 | * scan loops which should be made to get stable debounced results. | ||
| 33 | * | ||
| 34 | * On Ergodox matrix scan rate is relatively low, because of slow I2C. | ||
| 35 | * Now it's only 317 scans/second, or about 3.15 msec/scan. | ||
| 36 | * According to Cherry specs, debouncing time is 5 msec. | ||
| 37 | * | ||
| 38 | * And so, there is no sense to have DEBOUNCE higher than 2. | ||
| 39 | */ | ||
| 32 | 40 | ||
| 33 | #ifndef DEBOUNCING_DELAY | 41 | #ifndef DEBOUNCING_DELAY |
| 34 | # define DEBOUNCING_DELAY 5 | 42 | # define DEBOUNCING_DELAY 5 |
| 35 | #endif | 43 | #endif |
| 44 | static uint8_t debouncing = DEBOUNCING_DELAY; | ||
| 36 | 45 | ||
| 37 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | 46 | static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; |
| 38 | static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; | 47 | static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; |
| 39 | /* matrix state */ | 48 | |
| 40 | #if DIODE_DIRECTION == COL2ROW | 49 | /* matrix state(1:on, 0:off) */ |
| 41 | static matrix_row_t matrix[MATRIX_ROWS]; | 50 | static matrix_row_t matrix[MATRIX_ROWS]; |
| 42 | #else | 51 | static matrix_row_t matrix_debouncing[MATRIX_ROWS]; |
| 43 | static matrix_col_t matrix[MATRIX_COLS]; | 52 | |
| 53 | #if DIODE_DIRECTION == ROW2COL | ||
| 54 | static matrix_row_t matrix_reversed[MATRIX_COLS]; | ||
| 55 | static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS]; | ||
| 44 | #endif | 56 | #endif |
| 45 | static int8_t debouncing_delay = -1; | ||
| 46 | 57 | ||
| 47 | #if DIODE_DIRECTION == COL2ROW | 58 | #if MATRIX_COLS > 16 |
| 48 | static void toggle_row(uint8_t row); | 59 | #define SHIFTER 1UL |
| 49 | static matrix_row_t read_cols(void); | ||
| 50 | #else | 60 | #else |
| 51 | static void toggle_col(uint8_t col); | 61 | #define SHIFTER 1 |
| 52 | static matrix_col_t read_rows(void); | ||
| 53 | #endif | 62 | #endif |
| 54 | 63 | ||
| 64 | static matrix_row_t read_cols(void); | ||
| 65 | static void init_cols(void); | ||
| 66 | static void unselect_rows(void); | ||
| 67 | static void select_row(uint8_t row); | ||
| 68 | |||
| 55 | __attribute__ ((weak)) | 69 | __attribute__ ((weak)) |
| 56 | void matrix_init_quantum(void) { | 70 | void matrix_init_quantum(void) { |
| 57 | matrix_init_kb(); | 71 | matrix_init_kb(); |
| @@ -80,10 +94,12 @@ __attribute__ ((weak)) | |||
| 80 | void matrix_scan_user(void) { | 94 | void matrix_scan_user(void) { |
| 81 | } | 95 | } |
| 82 | 96 | ||
| 97 | inline | ||
| 83 | uint8_t matrix_rows(void) { | 98 | uint8_t matrix_rows(void) { |
| 84 | return MATRIX_ROWS; | 99 | return MATRIX_ROWS; |
| 85 | } | 100 | } |
| 86 | 101 | ||
| 102 | inline | ||
| 87 | uint8_t matrix_cols(void) { | 103 | uint8_t matrix_cols(void) { |
| 88 | return MATRIX_COLS; | 104 | return MATRIX_COLS; |
| 89 | } | 105 | } |
| @@ -113,161 +129,179 @@ uint8_t matrix_cols(void) { | |||
| 113 | // } | 129 | // } |
| 114 | 130 | ||
| 115 | void matrix_init(void) { | 131 | void matrix_init(void) { |
| 116 | /* frees PORTF by setting the JTD bit twice within four cycles */ | 132 | // To use PORTF disable JTAG with writing JTD bit twice within four cycles. |
| 117 | #ifdef __AVR_ATmega32U4__ | 133 | #ifdef __AVR_ATmega32U4__ |
| 118 | MCUCR |= _BV(JTD); | 134 | MCUCR |= _BV(JTD); |
| 119 | MCUCR |= _BV(JTD); | 135 | MCUCR |= _BV(JTD); |
| 120 | #endif | 136 | #endif |
| 121 | /* initializes the I/O pins */ | 137 | |
| 122 | #if DIODE_DIRECTION == COL2ROW | 138 | // initialize row and col |
| 123 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 139 | unselect_rows(); |
| 124 | /* DDRxn */ | 140 | init_cols(); |
| 125 | _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); | 141 | |
| 126 | toggle_row(r); | 142 | // initialize matrix state: all keys off |
| 127 | } | 143 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { |
| 128 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 144 | matrix[i] = 0; |
| 129 | /* PORTxn */ | 145 | matrix_debouncing[i] = 0; |
| 130 | _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); | ||
| 131 | } | ||
| 132 | #else | ||
| 133 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | ||
| 134 | /* DDRxn */ | ||
| 135 | _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); | ||
| 136 | toggle_col(c); | ||
| 137 | } | ||
| 138 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | ||
| 139 | /* PORTxn */ | ||
| 140 | _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF); | ||
| 141 | } | 146 | } |
| 142 | #endif | 147 | |
| 143 | matrix_init_quantum(); | 148 | matrix_init_quantum(); |
| 144 | } | 149 | } |
| 145 | 150 | ||
| 151 | uint8_t matrix_scan(void) | ||
| 152 | { | ||
| 153 | |||
| 146 | #if DIODE_DIRECTION == COL2ROW | 154 | #if DIODE_DIRECTION == COL2ROW |
| 147 | uint8_t matrix_scan(void) { | 155 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| 148 | static matrix_row_t debouncing_matrix[MATRIX_ROWS]; | 156 | select_row(i); |
| 149 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 157 | wait_us(30); // without this wait read unstable value. |
| 150 | toggle_row(r); | 158 | matrix_row_t cols = read_cols(); |
| 151 | matrix_row_t state = read_cols(); | 159 | if (matrix_debouncing[i] != cols) { |
| 152 | if (debouncing_matrix[r] != state) { | 160 | matrix_debouncing[i] = cols; |
| 153 | debouncing_matrix[r] = state; | 161 | if (debouncing) { |
| 154 | debouncing_delay = DEBOUNCING_DELAY; | 162 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); |
| 155 | } | ||
| 156 | toggle_row(r); | ||
| 157 | } | ||
| 158 | if (debouncing_delay >= 0) { | ||
| 159 | dprintf("Debouncing delay remaining: %X\n", debouncing_delay); | ||
| 160 | --debouncing_delay; | ||
| 161 | if (debouncing_delay >= 0) { | ||
| 162 | wait_ms(1); | ||
| 163 | } | ||
| 164 | else { | ||
| 165 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | ||
| 166 | matrix[r] = debouncing_matrix[r]; | ||
| 167 | } | 163 | } |
| 164 | debouncing = DEBOUNCING_DELAY; | ||
| 168 | } | 165 | } |
| 166 | unselect_rows(); | ||
| 169 | } | 167 | } |
| 170 | matrix_scan_quantum(); | ||
| 171 | return 1; | ||
| 172 | } | ||
| 173 | |||
| 174 | static void toggle_row(uint8_t row) { | ||
| 175 | /* PINxn */ | ||
| 176 | _SFR_IO8((row_pins[row] >> 4)) = _BV(row_pins[row] & 0xF); | ||
| 177 | } | ||
| 178 | 168 | ||
| 179 | static matrix_row_t read_cols(void) { | 169 | if (debouncing) { |
| 180 | matrix_row_t state = 0; | 170 | if (--debouncing) { |
| 181 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 171 | wait_us(1); |
| 182 | /* PINxn */ | 172 | } else { |
| 183 | if (!(_SFR_IO8((col_pins[c] >> 4)) & _BV(col_pins[c] & 0xF))) { | 173 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| 184 | state |= (matrix_row_t)1 << c; | 174 | matrix[i] = matrix_debouncing[i]; |
| 175 | } | ||
| 185 | } | 176 | } |
| 186 | } | 177 | } |
| 187 | return state; | ||
| 188 | } | ||
| 189 | |||
| 190 | matrix_row_t matrix_get_row(uint8_t row) { | ||
| 191 | return matrix[row]; | ||
| 192 | } | ||
| 193 | |||
| 194 | #else | 178 | #else |
| 195 | uint8_t matrix_scan(void) { | 179 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { |
| 196 | static matrix_col_t debouncing_matrix[MATRIX_COLS]; | 180 | select_row(i); |
| 197 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 181 | wait_us(30); // without this wait read unstable value. |
| 198 | toggle_col(c); | 182 | matrix_row_t rows = read_cols(); |
| 199 | matrix_col_t state = read_rows(); | 183 | if (matrix_reversed_debouncing[i] != rows) { |
| 200 | if (debouncing_matrix[c] != state) { | 184 | matrix_reversed_debouncing[i] = rows; |
| 201 | debouncing_matrix[c] = state; | 185 | if (debouncing) { |
| 202 | debouncing_delay = DEBOUNCING_DELAY; | 186 | debug("bounce!: "); debug_hex(debouncing); debug("\n"); |
| 187 | } | ||
| 188 | debouncing = DEBOUNCING_DELAY; | ||
| 203 | } | 189 | } |
| 204 | toggle_col(c); | 190 | unselect_rows(); |
| 205 | } | 191 | } |
| 206 | if (debouncing_delay >= 0) { | 192 | |
| 207 | dprintf("Debouncing delay remaining: %X\n", debouncing_delay); | 193 | if (debouncing) { |
| 208 | --debouncing_delay; | 194 | if (--debouncing) { |
| 209 | if (debouncing_delay >= 0) { | 195 | wait_us(1); |
| 210 | wait_ms(1); | 196 | } else { |
| 211 | } | 197 | for (uint8_t i = 0; i < MATRIX_COLS; i++) { |
| 212 | else { | 198 | matrix_reversed[i] = matrix_reversed_debouncing[i]; |
| 213 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | ||
| 214 | matrix[c] = debouncing_matrix[c]; | ||
| 215 | } | 199 | } |
| 216 | } | 200 | } |
| 217 | } | 201 | } |
| 202 | for (uint8_t y = 0; y < MATRIX_ROWS; y++) { | ||
| 203 | matrix_row_t row = 0; | ||
| 204 | for (uint8_t x = 0; x < MATRIX_COLS; x++) { | ||
| 205 | row |= ((matrix_reversed[x] & (1<<y)) >> y) << x; | ||
| 206 | } | ||
| 207 | matrix[y] = row; | ||
| 208 | } | ||
| 209 | #endif | ||
| 210 | |||
| 218 | matrix_scan_quantum(); | 211 | matrix_scan_quantum(); |
| 212 | |||
| 219 | return 1; | 213 | return 1; |
| 220 | } | 214 | } |
| 221 | 215 | ||
| 222 | static void toggle_col(uint8_t col) { | 216 | bool matrix_is_modified(void) |
| 223 | /* PINxn */ | 217 | { |
| 224 | _SFR_IO8((col_pins[col] >> 4)) = _BV(col_pins[col] & 0xF); | 218 | if (debouncing) return false; |
| 219 | return true; | ||
| 225 | } | 220 | } |
| 226 | 221 | ||
| 227 | static matrix_col_t read_rows(void) { | 222 | inline |
| 228 | matrix_col_t state = 0; | 223 | bool matrix_is_on(uint8_t row, uint8_t col) |
| 229 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 224 | { |
| 230 | /* PINxn */ | 225 | return (matrix[row] & ((matrix_row_t)1<col)); |
| 231 | if (!(_SFR_IO8((row_pins[r] >> 4)) & _BV(row_pins[r] & 0xF))) { | 226 | } |
| 232 | state |= (matrix_col_t)1 << r; | 227 | |
| 233 | } | 228 | inline |
| 229 | matrix_row_t matrix_get_row(uint8_t row) | ||
| 230 | { | ||
| 231 | return matrix[row]; | ||
| 232 | } | ||
| 233 | |||
| 234 | void matrix_print(void) | ||
| 235 | { | ||
| 236 | print("\nr/c 0123456789ABCDEF\n"); | ||
| 237 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | ||
| 238 | phex(row); print(": "); | ||
| 239 | pbin_reverse16(matrix_get_row(row)); | ||
| 240 | print("\n"); | ||
| 234 | } | 241 | } |
| 235 | return state; | ||
| 236 | } | 242 | } |
| 237 | 243 | ||
| 238 | matrix_row_t matrix_get_row(uint8_t row) { | 244 | uint8_t matrix_key_count(void) |
| 239 | matrix_row_t state = 0; | 245 | { |
| 240 | matrix_col_t mask = (matrix_col_t)1 << row; | 246 | uint8_t count = 0; |
| 241 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 247 | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
| 242 | if (matrix[c] & mask) { | 248 | count += bitpop16(matrix[i]); |
| 243 | state |= (matrix_row_t)1 << c; | ||
| 244 | } | ||
| 245 | } | 249 | } |
| 246 | return state; | 250 | return count; |
| 247 | } | 251 | } |
| 248 | 252 | ||
| 253 | static void init_cols(void) | ||
| 254 | { | ||
| 255 | #if DIODE_DIRECTION == COL2ROW | ||
| 256 | for(int x = 0; x < MATRIX_COLS; x++) { | ||
| 257 | int pin = col_pins[x]; | ||
| 258 | #else | ||
| 259 | for(int x = 0; x < MATRIX_ROWS; x++) { | ||
| 260 | int pin = row_pins[x]; | ||
| 249 | #endif | 261 | #endif |
| 250 | 262 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); | |
| 251 | bool matrix_is_modified(void) { | 263 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); |
| 252 | if (debouncing_delay >= 0) return false; | 264 | } |
| 253 | return true; | ||
| 254 | } | 265 | } |
| 255 | 266 | ||
| 256 | bool matrix_is_on(uint8_t row, uint8_t col) { | 267 | static matrix_row_t read_cols(void) |
| 257 | return matrix_get_row(row) & (matrix_row_t)1 << col; | 268 | { |
| 258 | } | 269 | matrix_row_t result = 0; |
| 259 | 270 | ||
| 260 | void matrix_print(void) { | 271 | #if DIODE_DIRECTION == COL2ROW |
| 261 | dprintln("Human-readable matrix state:"); | 272 | for(int x = 0; x < MATRIX_COLS; x++) { |
| 262 | for (uint8_t r = 0; r < MATRIX_ROWS; r++) { | 273 | int pin = col_pins[x]; |
| 263 | dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r))); | 274 | #else |
| 275 | for(int x = 0; x < MATRIX_ROWS; x++) { | ||
| 276 | int pin = row_pins[x]; | ||
| 277 | #endif | ||
| 278 | result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x); | ||
| 264 | } | 279 | } |
| 280 | return result; | ||
| 265 | } | 281 | } |
| 266 | 282 | ||
| 267 | uint8_t matrix_key_count(void) { | 283 | static void unselect_rows(void) |
| 268 | uint8_t count = 0; | 284 | { |
| 269 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 285 | #if DIODE_DIRECTION == COL2ROW |
| 270 | count += bitpop16(matrix_get_row(r)); | 286 | for(int x = 0; x < MATRIX_ROWS; x++) { |
| 287 | int pin = row_pins[x]; | ||
| 288 | #else | ||
| 289 | for(int x = 0; x < MATRIX_COLS; x++) { | ||
| 290 | int pin = col_pins[x]; | ||
| 291 | #endif | ||
| 292 | _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); | ||
| 293 | _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); | ||
| 271 | } | 294 | } |
| 272 | return count; | 295 | } |
| 296 | |||
| 297 | static void select_row(uint8_t row) | ||
| 298 | { | ||
| 299 | |||
| 300 | #if DIODE_DIRECTION == COL2ROW | ||
| 301 | int pin = row_pins[row]; | ||
| 302 | #else | ||
| 303 | int pin = col_pins[row]; | ||
| 304 | #endif | ||
| 305 | _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); | ||
| 306 | _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); | ||
| 273 | } | 307 | } |
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index a6f3c6441..8a7272bbc 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c | |||
| @@ -114,8 +114,10 @@ bool suspend_wakeup_condition(void) | |||
| 114 | matrix_power_up(); | 114 | matrix_power_up(); |
| 115 | matrix_scan(); | 115 | matrix_scan(); |
| 116 | matrix_power_down(); | 116 | matrix_power_down(); |
| 117 | if (matrix_key_count()) return true; | 117 | for (uint8_t r = 0; r < MATRIX_ROWS; r++) { |
| 118 | return false; | 118 | if (matrix_get_row(r)) return true; |
| 119 | } | ||
| 120 | return false; | ||
| 119 | } | 121 | } |
| 120 | 122 | ||
| 121 | // run immediately after wakeup | 123 | // run immediately after wakeup |
diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c index 90275a18b..6730a2a4a 100644 --- a/tmk_core/common/bootmagic.c +++ b/tmk_core/common/bootmagic.c | |||
| @@ -106,13 +106,15 @@ void bootmagic(void) | |||
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static bool scan_keycode(uint8_t keycode) { | 109 | static bool scan_keycode(uint8_t keycode) |
| 110 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 110 | { |
| 111 | for (uint8_t r = 0; r < MATRIX_ROWS; r++) { | ||
| 111 | matrix_row_t matrix_row = matrix_get_row(r); | 112 | matrix_row_t matrix_row = matrix_get_row(r); |
| 112 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 113 | for (uint8_t c = 0; c < MATRIX_COLS; c++) { |
| 113 | if (matrix_row & (matrix_row_t)1 << c) { | 114 | if (matrix_row & ((matrix_row_t)1<<c)) { |
| 114 | keypos_t key = (keypos_t){ .row = r, .col = c }; | 115 | if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) { |
| 115 | if (keycode == keymap_key_to_keycode(0, key)) return true; | 116 | return true; |
| 117 | } | ||
| 116 | } | 118 | } |
| 117 | } | 119 | } |
| 118 | } | 120 | } |
| @@ -124,4 +126,4 @@ bool bootmagic_scan_keycode(uint8_t keycode) | |||
| 124 | if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; | 126 | if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false; |
| 125 | 127 | ||
| 126 | return scan_keycode(keycode); | 128 | return scan_keycode(keycode); |
| 127 | } | 129 | } \ No newline at end of file |
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 34e1ceeca..81df8eb73 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c | |||
| @@ -51,17 +51,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 51 | #endif | 51 | #endif |
| 52 | 52 | ||
| 53 | #ifdef MATRIX_HAS_GHOST | 53 | #ifdef MATRIX_HAS_GHOST |
| 54 | static bool is_row_ghosting(uint8_t row){ | 54 | static bool has_ghost_in_row(uint8_t row) |
| 55 | matrix_row_t state = matrix_get_row(row); | 55 | { |
| 56 | /* no ghosting happens when only one key in the row is pressed */ | 56 | matrix_row_t matrix_row = matrix_get_row(row); |
| 57 | if (!(state - 1 & state)) return false; | 57 | // No ghost exists when less than 2 keys are down on the row |
| 58 | /* ghosting occurs when two keys in the same column are pressed */ | 58 | if (((matrix_row - 1) & matrix_row) == 0) |
| 59 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 59 | return false; |
| 60 | if (r != row && matrix_get_row(r) & state) return true; | 60 | |
| 61 | // Ghost occurs when the row shares column line with other row | ||
| 62 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | ||
| 63 | if (i != row && (matrix_get_row(i) & matrix_row)) | ||
| 64 | return true; | ||
| 61 | } | 65 | } |
| 62 | return false; | 66 | return false; |
| 63 | } | 67 | } |
| 64 | |||
| 65 | #endif | 68 | #endif |
| 66 | 69 | ||
| 67 | __attribute__ ((weak)) | 70 | __attribute__ ((weak)) |
| @@ -100,72 +103,86 @@ void keyboard_init(void) { | |||
| 100 | #endif | 103 | #endif |
| 101 | } | 104 | } |
| 102 | 105 | ||
| 103 | /* does routine keyboard jobs */ | 106 | /* |
| 104 | void keyboard_task(void) { | 107 | * Do keyboard routine jobs: scan mantrix, light LEDs, ... |
| 105 | static uint8_t led_status; | 108 | * This is repeatedly called as fast as possible. |
| 109 | */ | ||
| 110 | void keyboard_task(void) | ||
| 111 | { | ||
| 112 | static matrix_row_t matrix_prev[MATRIX_ROWS]; | ||
| 113 | #ifdef MATRIX_HAS_GHOST | ||
| 114 | static matrix_row_t matrix_ghost[MATRIX_ROWS]; | ||
| 115 | #endif | ||
| 116 | static uint8_t led_status = 0; | ||
| 117 | matrix_row_t matrix_row = 0; | ||
| 118 | matrix_row_t matrix_change = 0; | ||
| 119 | |||
| 106 | matrix_scan(); | 120 | matrix_scan(); |
| 107 | for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { | 121 | for (uint8_t r = 0; r < MATRIX_ROWS; r++) { |
| 108 | static matrix_row_t previous_matrix[MATRIX_ROWS]; | 122 | matrix_row = matrix_get_row(r); |
| 109 | matrix_row_t state = matrix_get_row(r); | 123 | matrix_change = matrix_row ^ matrix_prev[r]; |
| 110 | matrix_row_t changes = state ^ previous_matrix[r]; | 124 | if (matrix_change) { |
| 111 | if (changes) { | ||
| 112 | #ifdef MATRIX_HAS_GHOST | 125 | #ifdef MATRIX_HAS_GHOST |
| 113 | static matrix_row_t deghosting_matrix[MATRIX_ROWS]; | 126 | if (has_ghost_in_row(r)) { |
| 114 | if (is_row_ghosting(r)) { | 127 | /* Keep track of whether ghosted status has changed for |
| 115 | /* debugs the deghosting mechanism */ | 128 | * debugging. But don't update matrix_prev until un-ghosted, or |
| 116 | /* doesn't update previous_matrix until the ghosting has stopped | 129 | * the last key would be lost. |
| 117 | * in order to prevent the last key from being lost | ||
| 118 | */ | 130 | */ |
| 119 | if (debug_matrix && deghosting_matrix[r] != state) { | 131 | if (debug_matrix && matrix_ghost[r] != matrix_row) { |
| 120 | matrix_print(); | 132 | matrix_print(); |
| 121 | } | 133 | } |
| 122 | deghosting_matrix[r] = state; | 134 | matrix_ghost[r] = matrix_row; |
| 123 | continue; | 135 | continue; |
| 124 | } | 136 | } |
| 125 | deghosting_matrix[r] = state; | 137 | matrix_ghost[r] = matrix_row; |
| 126 | #endif | 138 | #endif |
| 127 | if (debug_matrix) matrix_print(); | 139 | if (debug_matrix) matrix_print(); |
| 128 | for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { | 140 | for (uint8_t c = 0; c < MATRIX_COLS; c++) { |
| 129 | matrix_row_t mask = (matrix_row_t)1 << c; | 141 | if (matrix_change & ((matrix_row_t)1<<c)) { |
| 130 | if (changes & mask) { | 142 | action_exec((keyevent_t){ |
| 131 | keyevent_t event; | 143 | .key = (keypos_t){ .row = r, .col = c }, |
| 132 | event.key = (keypos_t){ .row = r, .col = c }; | 144 | .pressed = (matrix_row & ((matrix_row_t)1<<c)), |
| 133 | event.pressed = state & mask; | 145 | .time = (timer_read() | 1) /* time should not be 0 */ |
| 134 | /* the time should not be 0 */ | 146 | }); |
| 135 | event.time = timer_read() | 1; | 147 | // record a processed key |
| 136 | action_exec(event); | 148 | matrix_prev[r] ^= ((matrix_row_t)1<<c); |
| 137 | /* records the processed key event */ | 149 | // process a key per task call |
| 138 | previous_matrix[r] ^= mask; | 150 | goto MATRIX_LOOP_END; |
| 139 | /* processes one key event per call */ | ||
| 140 | goto event_processed; | ||
| 141 | } | 151 | } |
| 142 | } | 152 | } |
| 143 | } | 153 | } |
| 144 | } | 154 | } |
| 145 | /* sends tick events when the keyboard is idle */ | 155 | // call with pseudo tick event when no real key event. |
| 146 | action_exec(TICK); | 156 | action_exec(TICK); |
| 147 | event_processed: | 157 | |
| 158 | MATRIX_LOOP_END: | ||
| 159 | |||
| 148 | #ifdef MOUSEKEY_ENABLE | 160 | #ifdef MOUSEKEY_ENABLE |
| 149 | /* repeats and accelerates the mouse keys */ | 161 | // mousekey repeat & acceleration |
| 150 | mousekey_task(); | 162 | mousekey_task(); |
| 151 | #endif | 163 | #endif |
| 164 | |||
| 152 | #ifdef PS2_MOUSE_ENABLE | 165 | #ifdef PS2_MOUSE_ENABLE |
| 153 | ps2_mouse_task(); | 166 | ps2_mouse_task(); |
| 154 | #endif | 167 | #endif |
| 168 | |||
| 155 | #ifdef SERIAL_MOUSE_ENABLE | 169 | #ifdef SERIAL_MOUSE_ENABLE |
| 156 | serial_mouse_task(); | 170 | serial_mouse_task(); |
| 157 | #endif | 171 | #endif |
| 172 | |||
| 158 | #ifdef ADB_MOUSE_ENABLE | 173 | #ifdef ADB_MOUSE_ENABLE |
| 159 | adb_mouse_task(); | 174 | adb_mouse_task(); |
| 160 | #endif | 175 | #endif |
| 161 | /* updates the LEDs */ | 176 | |
| 177 | // update LED | ||
| 162 | if (led_status != host_keyboard_leds()) { | 178 | if (led_status != host_keyboard_leds()) { |
| 163 | led_status = host_keyboard_leds(); | 179 | led_status = host_keyboard_leds(); |
| 164 | keyboard_set_leds(led_status); | 180 | keyboard_set_leds(led_status); |
| 165 | } | 181 | } |
| 166 | } | 182 | } |
| 167 | 183 | ||
| 168 | void keyboard_set_leds(uint8_t leds) { | 184 | void keyboard_set_leds(uint8_t leds) |
| 169 | if (debug_keyboard) dprintf("Keyboard LEDs state: %x\n", leds); | 185 | { |
| 186 | if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); } | ||
| 170 | led_set(leds); | 187 | led_set(leds); |
| 171 | } | 188 | } |
diff --git a/tmk_core/common/matrix.h b/tmk_core/common/matrix.h index 5f2f831b4..71153a5f5 100644 --- a/tmk_core/common/matrix.h +++ b/tmk_core/common/matrix.h | |||
| @@ -20,59 +20,48 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 20 | #include <stdint.h> | 20 | #include <stdint.h> |
| 21 | #include <stdbool.h> | 21 | #include <stdbool.h> |
| 22 | 22 | ||
| 23 | #if MATRIX_COLS <= 8 | 23 | |
| 24 | typedef uint8_t matrix_row_t; | 24 | #if (MATRIX_COLS <= 8) |
| 25 | #elif MATRIX_COLS <= 16 | 25 | typedef uint8_t matrix_row_t; |
| 26 | typedef uint16_t matrix_row_t; | 26 | #elif (MATRIX_COLS <= 16) |
| 27 | #elif MATRIX_COLS <= 32 | 27 | typedef uint16_t matrix_row_t; |
| 28 | typedef uint32_t matrix_row_t; | 28 | #elif (MATRIX_COLS <= 32) |
| 29 | typedef uint32_t matrix_row_t; | ||
| 29 | #else | 30 | #else |
| 30 | # error "There are too many columns." | 31 | #error "MATRIX_COLS: invalid value" |
| 31 | #endif | 32 | #endif |
| 32 | 33 | ||
| 33 | #if DIODE_DIRECTION == ROW2COL | 34 | #define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col)) |
| 34 | # if MATRIX_ROWS <= 8 | ||
| 35 | typedef uint8_t matrix_col_t; | ||
| 36 | # elif MATRIX_ROWS <= 16 | ||
| 37 | typedef uint16_t matrix_col_t; | ||
| 38 | # elif MATRIX_ROWS <= 32 | ||
| 39 | typedef uint32_t matrix_col_t; | ||
| 40 | # else | ||
| 41 | # error "There are too many rows." | ||
| 42 | # endif | ||
| 43 | #endif | ||
| 44 | 35 | ||
| 45 | typedef struct { | ||
| 46 | uint8_t input_addr:4; | ||
| 47 | uint8_t bit:4; | ||
| 48 | } io_pin_t; | ||
| 49 | 36 | ||
| 50 | #ifdef __cplusplus | 37 | #ifdef __cplusplus |
| 51 | extern "C" { | 38 | extern "C" { |
| 52 | #endif | 39 | #endif |
| 53 | /* counts the number of rows in the matrix */ | 40 | |
| 41 | /* number of matrix rows */ | ||
| 54 | uint8_t matrix_rows(void); | 42 | uint8_t matrix_rows(void); |
| 55 | /* counts the number of columns in the matrix */ | 43 | /* number of matrix columns */ |
| 56 | uint8_t matrix_cols(void); | 44 | uint8_t matrix_cols(void); |
| 57 | /* sets up the matrix before matrix_init */ | 45 | /* should be called at early stage of startup before matrix_init.(optional) */ |
| 58 | void matrix_setup(void); | 46 | void matrix_setup(void); |
| 59 | /* intializes the matrix */ | 47 | /* intialize matrix for scaning. */ |
| 60 | void matrix_init(void); | 48 | void matrix_init(void); |
| 61 | /* scans the entire matrix */ | 49 | /* scan all key states on matrix */ |
| 62 | uint8_t matrix_scan(void); | 50 | uint8_t matrix_scan(void); |
| 63 | /* checks if the matrix has been modified */ | 51 | /* whether modified from previous scan. used after matrix_scan. */ |
| 64 | bool matrix_is_modified(void) __attribute__ ((deprecated)); | 52 | bool matrix_is_modified(void) __attribute__ ((deprecated)); |
| 65 | /* checks if a key is pressed */ | 53 | /* whether a swtich is on */ |
| 66 | bool matrix_is_on(uint8_t row, uint8_t col); | 54 | bool matrix_is_on(uint8_t row, uint8_t col); |
| 67 | /* inspects the state of a row in the matrix */ | 55 | /* matrix state on row */ |
| 68 | matrix_row_t matrix_get_row(uint8_t row); | 56 | matrix_row_t matrix_get_row(uint8_t row); |
| 69 | /* prints the matrix for debugging */ | 57 | /* print matrix for debug */ |
| 70 | void matrix_print(void); | 58 | void matrix_print(void); |
| 71 | /* counts the total number of keys pressed */ | 59 | |
| 72 | uint8_t matrix_key_count(void); | 60 | |
| 73 | /* controls power to the matrix */ | 61 | /* power control */ |
| 74 | void matrix_power_up(void); | 62 | void matrix_power_up(void); |
| 75 | void matrix_power_down(void); | 63 | void matrix_power_down(void); |
| 64 | |||
| 76 | /* executes code for Quantum */ | 65 | /* executes code for Quantum */ |
| 77 | void matrix_init_quantum(void); | 66 | void matrix_init_quantum(void); |
| 78 | void matrix_scan_quantum(void); | 67 | void matrix_scan_quantum(void); |
