Merge pull request #40 from system76/wip/ghost
Ignore key presses that trigger ghost keys
This commit is contained in:
		| @@ -31,6 +31,72 @@ void kbscan_init(void) { | ||||
| // Debounce time in milliseconds | ||||
| #define DEBOUNCE_DELAY 20 | ||||
|  | ||||
| static uint8_t kbscan_get_row(int i) { | ||||
|     // Set current line as output | ||||
|     if (i < 8) { | ||||
|         KSOLGOEN = 1 << i; | ||||
|         KSOHGOEN = 0; | ||||
|         GPCRC3 = GPIO_IN; | ||||
|         GPCRC5 = GPIO_IN; | ||||
|     } else if (i < 16) { | ||||
|         KSOLGOEN = 0; | ||||
|         KSOHGOEN = 1 << (i - 8); | ||||
|         GPCRC3 = GPIO_IN; | ||||
|         GPCRC5 = GPIO_IN; | ||||
|     } else if (i == 16) { | ||||
|         KSOLGOEN = 0; | ||||
|         KSOHGOEN = 0; | ||||
|         GPCRC3 = GPIO_OUT; | ||||
|         GPCRC5 = GPIO_IN; | ||||
|     } else if (i == 17) { | ||||
|         KSOLGOEN = 0; | ||||
|         KSOHGOEN = 0; | ||||
|         GPCRC3 = GPIO_IN; | ||||
|         GPCRC5 = GPIO_OUT; | ||||
|     } | ||||
|     GPDRC &= ~((1 << 3) | (1 << 5)); | ||||
|  | ||||
|     // TODO: figure out optimal delay | ||||
|     delay_ticks(10); | ||||
|  | ||||
|     return ~KSI; | ||||
| } | ||||
|  | ||||
| static inline bool popcount_more_than_one(uint8_t rowdata) { | ||||
|     return rowdata & (rowdata - 1); | ||||
| } | ||||
|  | ||||
| static uint8_t kbscan_get_real_keys(int row, uint8_t rowdata) { | ||||
|     // Remove any "active" blanks from the matrix. | ||||
|     uint8_t realdata = 0; | ||||
|     for (uint8_t col = 0; col < KM_IN; col++) { | ||||
|         if (KEYMAP[0][row][col] && (rowdata & (1 << col))) { | ||||
|             realdata |=  1 << col; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return realdata; | ||||
| } | ||||
|  | ||||
| static bool kbscan_has_ghost_in_row(int row, uint8_t rowdata) { | ||||
|     rowdata = kbscan_get_real_keys(row, rowdata); | ||||
|  | ||||
|     // No ghosts exist when  less than 2 keys in the row are active. | ||||
|     if (!popcount_more_than_one(rowdata)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Check against other rows to see if more than one column matches. | ||||
|     for (int i = 0; i < KM_OUT; i++) { | ||||
|         uint8_t otherrow = kbscan_get_real_keys(i, kbscan_get_row(i)); | ||||
|         if (i != row && popcount_more_than_one(otherrow & rowdata)) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| bool kbscan_press(uint16_t key, bool pressed, uint8_t * layer) { | ||||
|     if (pressed && | ||||
|         (power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3)) { | ||||
| @@ -142,36 +208,14 @@ void kbscan_event(void) { | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; i < KM_OUT; i++) { | ||||
|         // Set current line as output | ||||
|         if (i < 8) { | ||||
|             KSOLGOEN = 1 << i; | ||||
|             KSOHGOEN = 0; | ||||
|             GPCRC3 = GPIO_IN; | ||||
|             GPCRC5 = GPIO_IN; | ||||
|         } else if (i < 16) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 1 << (i - 8); | ||||
|             GPCRC3 = GPIO_IN; | ||||
|             GPCRC5 = GPIO_IN; | ||||
|         } else if (i == 16) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 0; | ||||
|             GPCRC3 = GPIO_OUT; | ||||
|             GPCRC5 = GPIO_IN; | ||||
|         } else if (i == 17) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 0; | ||||
|             GPCRC3 = GPIO_IN; | ||||
|             GPCRC5 = GPIO_OUT; | ||||
|         } | ||||
|         GPDRC &= ~((1 << 3) | (1 << 5)); | ||||
|  | ||||
|         // TODO: figure out optimal delay | ||||
|         delay_ticks(10); | ||||
|  | ||||
|         uint8_t new = ~KSI; | ||||
|         uint8_t new = kbscan_get_row(i); | ||||
|         uint8_t last = kbscan_last[i]; | ||||
|         if (new != last) { | ||||
|             if (kbscan_has_ghost_in_row(i, new)) { | ||||
|                 kbscan_last[i] = new; | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // A key was pressed or released | ||||
|             int j; | ||||
|             for (j = 0; j < KM_IN; j++) { | ||||
|   | ||||
| @@ -32,6 +32,63 @@ void kbscan_init(void) { | ||||
| // Debounce time in milliseconds | ||||
| #define DEBOUNCE_DELAY 20 | ||||
|  | ||||
| static uint8_t kbscan_get_row(int i) { | ||||
|     // Set current line as output | ||||
|     if (i < 8) { | ||||
|         KSOLGOEN = 1 << i; | ||||
|         KSOHGOEN = 0; | ||||
|     } else if (i < 16) { | ||||
|         KSOLGOEN = 0; | ||||
|         KSOHGOEN = 1 << (i - 8); | ||||
|     } else if (i == 16) { | ||||
|         KSOLGOEN = 0; | ||||
|         KSOHGOEN = 0; | ||||
|     } else if (i == 17) { | ||||
|         KSOLGOEN = 0; | ||||
|         KSOHGOEN = 0; | ||||
|     } | ||||
|  | ||||
|     // TODO: figure out optimal delay | ||||
|     delay_ticks(10); | ||||
|  | ||||
|     return ~KSI; | ||||
| } | ||||
|  | ||||
| static inline bool popcount_more_than_one(uint8_t rowdata) { | ||||
|     return rowdata & (rowdata - 1); | ||||
| } | ||||
|  | ||||
| static uint8_t kbscan_get_real_keys(int row, uint8_t rowdata) { | ||||
|     // Remove any "active" blanks from the matrix. | ||||
|     uint8_t realdata = 0; | ||||
|     for (uint8_t col = 0; col < KM_IN; col++) { | ||||
|         if (KEYMAP[0][row][col] && (rowdata & (1 << col))) { | ||||
|             realdata |=  1 << col; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return realdata; | ||||
| } | ||||
|  | ||||
| static bool kbscan_has_ghost_in_row(int row, uint8_t rowdata) { | ||||
|     rowdata = kbscan_get_real_keys(row, rowdata); | ||||
|  | ||||
|     // No ghosts exist when  less than 2 keys in the row are active. | ||||
|     if (!popcount_more_than_one(rowdata)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Check against other rows to see if more than one column matches. | ||||
|     for (int i = 0; i < KM_OUT; i++) { | ||||
|         uint8_t otherrow = kbscan_get_real_keys(i, kbscan_get_row(i)); | ||||
|         if (i != row && popcount_more_than_one(otherrow & rowdata)) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| bool kbscan_press(uint16_t key, bool pressed, uint8_t * layer) { | ||||
|     if (pressed && | ||||
|         (power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3)) { | ||||
| @@ -150,27 +207,14 @@ void kbscan_event(void) { | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; i < KM_OUT; i++) { | ||||
|         // Set current line as output | ||||
|         if (i < 8) { | ||||
|             KSOLGOEN = 1 << i; | ||||
|             KSOHGOEN = 0; | ||||
|         } else if (i < 16) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 1 << (i - 8); | ||||
|         } else if (i == 16) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 0; | ||||
|         } else if (i == 17) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 0; | ||||
|         } | ||||
|  | ||||
|         // TODO: figure out optimal delay | ||||
|         delay_ticks(10); | ||||
|  | ||||
|         uint8_t new = ~KSI; | ||||
|         uint8_t new = kbscan_get_row(i); | ||||
|         uint8_t last = kbscan_last[i]; | ||||
|         if (new != last) { | ||||
|             if (kbscan_has_ghost_in_row(i, new)) { | ||||
|                 kbscan_last[i] = new; | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // A key was pressed or released | ||||
|             int j; | ||||
|             for (j = 0; j < KM_IN; j++) { | ||||
|   | ||||
| @@ -32,6 +32,63 @@ void kbscan_init(void) { | ||||
| // Debounce time in milliseconds | ||||
| #define DEBOUNCE_DELAY 20 | ||||
|  | ||||
| static uint8_t kbscan_get_row(int i) { | ||||
|         // Set current line as output | ||||
|         if (i < 8) { | ||||
|             KSOLGOEN = 1 << i; | ||||
|             KSOHGOEN = 0; | ||||
|         } else if (i < 16) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 1 << (i - 8); | ||||
|         } else if (i == 16) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 0; | ||||
|         } else if (i == 17) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 0; | ||||
|         } | ||||
|  | ||||
|         // TODO: figure out optimal delay | ||||
|         delay_ticks(10); | ||||
|  | ||||
|         return ~KSI; | ||||
| } | ||||
|  | ||||
| static inline bool popcount_more_than_one(uint8_t rowdata) { | ||||
|     return rowdata & (rowdata - 1); | ||||
| } | ||||
|  | ||||
| static uint8_t kbscan_get_real_keys(int row, uint8_t rowdata) { | ||||
|     // Remove any "active" blanks from the matrix. | ||||
|     uint8_t realdata = 0; | ||||
|     for (uint8_t col = 0; col < KM_IN; col++) { | ||||
|         if (KEYMAP[0][row][col] && (rowdata & (1 << col))) { | ||||
|             realdata |=  1 << col; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return realdata; | ||||
| } | ||||
|  | ||||
| static bool kbscan_has_ghost_in_row(int row, uint8_t rowdata) { | ||||
|     rowdata = kbscan_get_real_keys(row, rowdata); | ||||
|  | ||||
|     // No ghosts exist when  less than 2 keys in the row are active. | ||||
|     if (!popcount_more_than_one(rowdata)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     // Check against other rows to see if more than one column matches. | ||||
|     for (int i = 0; i < KM_OUT; i++) { | ||||
|         uint8_t otherrow = kbscan_get_real_keys(i, kbscan_get_row(i)); | ||||
|         if (i != row && popcount_more_than_one(otherrow & rowdata)) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| bool kbscan_press(uint16_t key, bool pressed, uint8_t * layer) { | ||||
|     if (pressed && | ||||
|         (power_state == POWER_STATE_S3 || power_state == POWER_STATE_DS3)) { | ||||
| @@ -150,27 +207,14 @@ void kbscan_event(void) { | ||||
|  | ||||
|     int i; | ||||
|     for (i = 0; i < KM_OUT; i++) { | ||||
|         // Set current line as output | ||||
|         if (i < 8) { | ||||
|             KSOLGOEN = 1 << i; | ||||
|             KSOHGOEN = 0; | ||||
|         } else if (i < 16) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 1 << (i - 8); | ||||
|         } else if (i == 16) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 0; | ||||
|         } else if (i == 17) { | ||||
|             KSOLGOEN = 0; | ||||
|             KSOHGOEN = 0; | ||||
|         } | ||||
|  | ||||
|         // TODO: figure out optimal delay | ||||
|         delay_ticks(10); | ||||
|  | ||||
|         uint8_t new = ~KSI; | ||||
|         uint8_t new = kbscan_get_row(i); | ||||
|         uint8_t last = kbscan_last[i]; | ||||
|         if (new != last) { | ||||
|             if (kbscan_has_ghost_in_row(i, new)) { | ||||
|                 kbscan_last[i] = new; | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // A key was pressed or released | ||||
|             int j; | ||||
|             for (j = 0; j < KM_IN; j++) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user