implemented algorithm to prevent ghost-keys

This commit is contained in:
Ronald Schaten 2008-07-19 20:17:43 +00:00
parent 4b417440c5
commit c016304100

View File

@ -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,8 +774,17 @@ uint8_t scankeys(void) {
retval |= 0x02; // continue decoding to get modifiers
}
} else {
reportBuffer[reportIndex] = key; // set next available entry
reportIndex++;
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
@ -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;