implemented algorithm to prevent ghost-keys
This commit is contained in:
parent
4b417440c5
commit
c016304100
@ -289,6 +289,7 @@ static void hardwareInit(void) {
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static uint8_t reportBuffer[8]; ///< buffer for HID reports
|
||||
static uint8_t oldReportBuffer[8]; ///< buffer for the last sent HID report
|
||||
static uint8_t idleRate; ///< in 4ms units
|
||||
static uint8_t protocolVer = 1; ///< 0 = boot protocol, 1 = report protocol
|
||||
uint8_t expectReport = 0; ///< flag to indicate if we expect an USB-report
|
||||
@ -428,6 +429,7 @@ void usbSendReport(uint8_t mode, uint8_t key) {
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
uint8_t curmatrix[16]; ///< contains current state of the keyboard
|
||||
uint8_t ghostmatrix[16]; ///< contains pressed keys that belong to a ghost-key situation
|
||||
|
||||
/**
|
||||
* The keymatrix-array contains positions of keys in the matrix. Here you can
|
||||
@ -493,7 +495,7 @@ typedef struct {
|
||||
/**
|
||||
* Convert an ASCII-character to the corresponding key-code and modifier-code
|
||||
* combination.
|
||||
* \parm character ASCII-character to convert
|
||||
* \param character ASCII-character to convert
|
||||
* \return structure containing the combination
|
||||
*/
|
||||
Key charToKey(char character) {
|
||||
@ -670,6 +672,31 @@ void printMatrix(void) {
|
||||
sendString("---");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if more than one bit in data is set.
|
||||
* \param data value to check
|
||||
* \return true if more than one bit is set
|
||||
*/
|
||||
uint8_t bitcount2(uint16_t data) {
|
||||
data &= (data - 1);
|
||||
return data != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if reportBuffer contains the key
|
||||
* \param buffer buffer to check
|
||||
* \param key key to search
|
||||
* \return 1 if buffer contains key, 0 otherwise
|
||||
*/
|
||||
uint8_t bufferContains(uint8_t* buffer, uint8_t key) {
|
||||
for (uint8_t i = 2; i < sizeof(buffer); i++) {
|
||||
if (buffer[i] == key) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan and debounce keypresses. This is the main worker function for normal
|
||||
* keyboard operation, the code contains lot of comments. Basically, it first
|
||||
@ -679,7 +706,8 @@ void printMatrix(void) {
|
||||
* so we can be pretty sure that the keys are in a certain state (as in: not
|
||||
* bouncing). Then, the codes for keys and modifiers are searched from the two
|
||||
* arrays, the USB-message to send the state is prepared. The return value of
|
||||
* this function indicates if the message has to be sent.
|
||||
*~ this function indicates if the message has to be sent.
|
||||
|
||||
* \return flag to indicate whether something has changed
|
||||
*/
|
||||
uint8_t scankeys(void) {
|
||||
@ -703,6 +731,14 @@ uint8_t scankeys(void) {
|
||||
}
|
||||
_delay_us(30);
|
||||
uint8_t data = ~PINCOLUMNS;
|
||||
// check if we have to prevent ghost-keys
|
||||
uint16_t rows= (PINROWS1 << 8) | PINROWS2;
|
||||
if (bitcount2(~rows) && bitcount2(data)) {
|
||||
// ghost-key situation detected
|
||||
ghostmatrix[row] = data;
|
||||
} else {
|
||||
ghostmatrix[row] = 0x00;
|
||||
}
|
||||
if (data != curmatrix[row]) {
|
||||
// if a change was detected
|
||||
debounce = 10; // activate debounce counter
|
||||
@ -721,13 +757,15 @@ uint8_t scankeys(void) {
|
||||
uint8_t data = curmatrix[row]; // restore buffer
|
||||
if (data != 0xff) { // anything on this row? - optimization
|
||||
for (uint8_t col = 0; col <= 7; col++) { // check every bit on this row
|
||||
uint8_t key, modifier;
|
||||
uint8_t key, modifier, isghostkey;
|
||||
if (data & (1 << col)) {
|
||||
key = pgm_read_byte(&keymatrix[row][col]);
|
||||
modifier = pgm_read_byte(&modmatrix[row][col]);
|
||||
isghostkey = ghostmatrix[row] & (1 << col);
|
||||
} else {
|
||||
key = KEY_Reserved;
|
||||
modifier = MOD_NONE;
|
||||
isghostkey = 0x00;
|
||||
}
|
||||
if (key != KEY_Reserved) { // keycode should be added to report
|
||||
if (reportIndex >= sizeof(reportBuffer)) { // too many keycodes
|
||||
@ -736,9 +774,18 @@ uint8_t scankeys(void) {
|
||||
retval |= 0x02; // continue decoding to get modifiers
|
||||
}
|
||||
} else {
|
||||
if (isghostkey) {
|
||||
// we're in a ghost-key situation
|
||||
if (bufferContains(oldReportBuffer, key)) {
|
||||
// this key has been pressed before, so we still send it
|
||||
reportBuffer[reportIndex] = key; // set next available entry
|
||||
reportIndex++;
|
||||
}
|
||||
} else {
|
||||
reportBuffer[reportIndex] = key; // set next available entry
|
||||
reportIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modifier != MOD_NONE) { // modifier should be added to report
|
||||
reportBuffer[0] |= modifier;
|
||||
@ -766,6 +813,8 @@ int main(void) {
|
||||
usbInit();
|
||||
sei();
|
||||
|
||||
memset(oldReportBuffer, 0, sizeof(oldReportBuffer)); // clear old report buffer
|
||||
|
||||
scankeys();
|
||||
while (1) {
|
||||
// main event loop
|
||||
@ -790,6 +839,7 @@ int main(void) {
|
||||
if (updateNeeded && usbInterruptIsReady()) {
|
||||
updateNeeded = 0;
|
||||
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
||||
memcpy(oldReportBuffer, reportBuffer, sizeof(oldReportBuffer));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user