diff options
Diffstat (limited to 'tmk_core/common/keyboard.c')
| -rw-r--r-- | tmk_core/common/keyboard.c | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index eac1f1dd8..97a8f1cd8 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c | |||
| @@ -61,23 +61,51 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 61 | # include "visualizer/visualizer.h" | 61 | # include "visualizer/visualizer.h" |
| 62 | #endif | 62 | #endif |
| 63 | 63 | ||
| 64 | #ifdef MATRIX_HAS_GHOST | ||
| 65 | extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; | ||
| 66 | static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata){ | ||
| 67 | matrix_row_t out = 0; | ||
| 68 | for (uint8_t col = 0; col < MATRIX_COLS; col++) { | ||
| 69 | //read each key in the row data and check if the keymap defines it as a real key | ||
| 70 | if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1<<col))){ | ||
| 71 | //this creates new row data, if a key is defined in the keymap, it will be set here | ||
| 72 | out |= 1<<col; | ||
| 73 | } | ||
| 74 | } | ||
| 75 | return out; | ||
| 76 | } | ||
| 64 | 77 | ||
| 78 | static inline bool popcount_more_than_one(matrix_row_t rowdata) | ||
| 79 | { | ||
| 80 | rowdata &= rowdata-1; //if there are less than two bits (keys) set, rowdata will become zero | ||
| 81 | return rowdata; | ||
| 82 | } | ||
| 65 | 83 | ||
| 66 | #ifdef MATRIX_HAS_GHOST | 84 | static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) |
| 67 | static bool has_ghost_in_row(uint8_t row) | ||
| 68 | { | 85 | { |
| 69 | matrix_row_t matrix_row = matrix_get_row(row); | 86 | /* No ghost exists when less than 2 keys are down on the row. |
| 70 | // No ghost exists when less than 2 keys are down on the row | 87 | If there are "active" blanks in the matrix, the key can't be pressed by the user, |
| 71 | if (((matrix_row - 1) & matrix_row) == 0) | 88 | there is no doubt as to which keys are really being pressed. |
| 89 | The ghosts will be ignored, they are KC_NO. */ | ||
| 90 | rowdata = get_real_keys(row, rowdata); | ||
| 91 | if ((popcount_more_than_one(rowdata)) == 0){ | ||
| 72 | return false; | 92 | return false; |
| 73 | 93 | } | |
| 74 | // Ghost occurs when the row shares column line with other row | 94 | /* Ghost occurs when the row shares a column line with other row, |
| 95 | and two columns are read on each row. Blanks in the matrix don't matter, | ||
| 96 | so they are filtered out. | ||
| 97 | If there are two or more real keys pressed and they match columns with | ||
| 98 | at least two of another row's real keys, the row will be ignored. Keep in mind, | ||
| 99 | we are checking one row at a time, not all of them at once. | ||
| 100 | */ | ||
| 75 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | 101 | for (uint8_t i=0; i < MATRIX_ROWS; i++) { |
| 76 | if (i != row && (matrix_get_row(i) & matrix_row)) | 102 | if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)){ |
| 77 | return true; | 103 | return true; |
| 104 | } | ||
| 78 | } | 105 | } |
| 79 | return false; | 106 | return false; |
| 80 | } | 107 | } |
| 108 | |||
| 81 | #endif | 109 | #endif |
| 82 | 110 | ||
| 83 | __attribute__ ((weak)) | 111 | __attribute__ ((weak)) |
| @@ -127,7 +155,7 @@ void keyboard_task(void) | |||
| 127 | { | 155 | { |
| 128 | static matrix_row_t matrix_prev[MATRIX_ROWS]; | 156 | static matrix_row_t matrix_prev[MATRIX_ROWS]; |
| 129 | #ifdef MATRIX_HAS_GHOST | 157 | #ifdef MATRIX_HAS_GHOST |
| 130 | static matrix_row_t matrix_ghost[MATRIX_ROWS]; | 158 | // static matrix_row_t matrix_ghost[MATRIX_ROWS]; |
| 131 | #endif | 159 | #endif |
| 132 | static uint8_t led_status = 0; | 160 | static uint8_t led_status = 0; |
| 133 | matrix_row_t matrix_row = 0; | 161 | matrix_row_t matrix_row = 0; |
| @@ -139,18 +167,18 @@ void keyboard_task(void) | |||
| 139 | matrix_change = matrix_row ^ matrix_prev[r]; | 167 | matrix_change = matrix_row ^ matrix_prev[r]; |
| 140 | if (matrix_change) { | 168 | if (matrix_change) { |
| 141 | #ifdef MATRIX_HAS_GHOST | 169 | #ifdef MATRIX_HAS_GHOST |
| 142 | if (has_ghost_in_row(r)) { | 170 | if (has_ghost_in_row(r, matrix_row)) { |
| 143 | /* Keep track of whether ghosted status has changed for | 171 | /* Keep track of whether ghosted status has changed for |
| 144 | * debugging. But don't update matrix_prev until un-ghosted, or | 172 | * debugging. But don't update matrix_prev until un-ghosted, or |
| 145 | * the last key would be lost. | 173 | * the last key would be lost. |
| 146 | */ | 174 | */ |
| 147 | if (debug_matrix && matrix_ghost[r] != matrix_row) { | 175 | //if (debug_matrix && matrix_ghost[r] != matrix_row) { |
| 148 | matrix_print(); | 176 | // matrix_print(); |
| 149 | } | 177 | //} |
| 150 | matrix_ghost[r] = matrix_row; | 178 | //matrix_ghost[r] = matrix_row; |
| 151 | continue; | 179 | continue; |
| 152 | } | 180 | } |
| 153 | matrix_ghost[r] = matrix_row; | 181 | //matrix_ghost[r] = matrix_row; |
| 154 | #endif | 182 | #endif |
| 155 | if (debug_matrix) matrix_print(); | 183 | if (debug_matrix) matrix_print(); |
| 156 | for (uint8_t c = 0; c < MATRIX_COLS; c++) { | 184 | for (uint8_t c = 0; c < MATRIX_COLS; c++) { |
