Merge pull request #40 from system76/wip/ghost

Ignore key presses that trigger ghost keys
This commit is contained in:
Jeremy Soller
2020-03-31 16:29:42 -06:00
committed by GitHub
3 changed files with 198 additions and 66 deletions

View File

@ -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++) {

View File

@ -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++) {

View File

@ -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++) {