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 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 idleRate; ///< in 4ms units
|
||||||
static uint8_t protocolVer = 1; ///< 0 = boot protocol, 1 = report protocol
|
static uint8_t protocolVer = 1; ///< 0 = boot protocol, 1 = report protocol
|
||||||
uint8_t expectReport = 0; ///< flag to indicate if we expect an USB-report
|
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 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
|
* 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
|
* Convert an ASCII-character to the corresponding key-code and modifier-code
|
||||||
* combination.
|
* combination.
|
||||||
* \parm character ASCII-character to convert
|
* \param character ASCII-character to convert
|
||||||
* \return structure containing the combination
|
* \return structure containing the combination
|
||||||
*/
|
*/
|
||||||
Key charToKey(char character) {
|
Key charToKey(char character) {
|
||||||
@ -670,6 +672,31 @@ void printMatrix(void) {
|
|||||||
sendString("---");
|
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
|
* Scan and debounce keypresses. This is the main worker function for normal
|
||||||
* keyboard operation, the code contains lot of comments. Basically, it first
|
* 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
|
* 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
|
* 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
|
* 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
|
* \return flag to indicate whether something has changed
|
||||||
*/
|
*/
|
||||||
uint8_t scankeys(void) {
|
uint8_t scankeys(void) {
|
||||||
@ -703,6 +731,14 @@ uint8_t scankeys(void) {
|
|||||||
}
|
}
|
||||||
_delay_us(30);
|
_delay_us(30);
|
||||||
uint8_t data = ~PINCOLUMNS;
|
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 (data != curmatrix[row]) {
|
||||||
// if a change was detected
|
// if a change was detected
|
||||||
debounce = 10; // activate debounce counter
|
debounce = 10; // activate debounce counter
|
||||||
@ -721,13 +757,15 @@ uint8_t scankeys(void) {
|
|||||||
uint8_t data = curmatrix[row]; // restore buffer
|
uint8_t data = curmatrix[row]; // restore buffer
|
||||||
if (data != 0xff) { // anything on this row? - optimization
|
if (data != 0xff) { // anything on this row? - optimization
|
||||||
for (uint8_t col = 0; col <= 7; col++) { // check every bit on this row
|
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)) {
|
if (data & (1 << col)) {
|
||||||
key = pgm_read_byte(&keymatrix[row][col]);
|
key = pgm_read_byte(&keymatrix[row][col]);
|
||||||
modifier = pgm_read_byte(&modmatrix[row][col]);
|
modifier = pgm_read_byte(&modmatrix[row][col]);
|
||||||
|
isghostkey = ghostmatrix[row] & (1 << col);
|
||||||
} else {
|
} else {
|
||||||
key = KEY_Reserved;
|
key = KEY_Reserved;
|
||||||
modifier = MOD_NONE;
|
modifier = MOD_NONE;
|
||||||
|
isghostkey = 0x00;
|
||||||
}
|
}
|
||||||
if (key != KEY_Reserved) { // keycode should be added to report
|
if (key != KEY_Reserved) { // keycode should be added to report
|
||||||
if (reportIndex >= sizeof(reportBuffer)) { // too many keycodes
|
if (reportIndex >= sizeof(reportBuffer)) { // too many keycodes
|
||||||
@ -736,9 +774,18 @@ uint8_t scankeys(void) {
|
|||||||
retval |= 0x02; // continue decoding to get modifiers
|
retval |= 0x02; // continue decoding to get modifiers
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
reportBuffer[reportIndex] = key; // set next available entry
|
||||||
reportIndex++;
|
reportIndex++;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
reportBuffer[reportIndex] = key; // set next available entry
|
||||||
|
reportIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (modifier != MOD_NONE) { // modifier should be added to report
|
if (modifier != MOD_NONE) { // modifier should be added to report
|
||||||
reportBuffer[0] |= modifier;
|
reportBuffer[0] |= modifier;
|
||||||
@ -766,6 +813,8 @@ int main(void) {
|
|||||||
usbInit();
|
usbInit();
|
||||||
sei();
|
sei();
|
||||||
|
|
||||||
|
memset(oldReportBuffer, 0, sizeof(oldReportBuffer)); // clear old report buffer
|
||||||
|
|
||||||
scankeys();
|
scankeys();
|
||||||
while (1) {
|
while (1) {
|
||||||
// main event loop
|
// main event loop
|
||||||
@ -790,6 +839,7 @@ int main(void) {
|
|||||||
if (updateNeeded && usbInterruptIsReady()) {
|
if (updateNeeded && usbInterruptIsReady()) {
|
||||||
updateNeeded = 0;
|
updateNeeded = 0;
|
||||||
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
||||||
|
memcpy(oldReportBuffer, reportBuffer, sizeof(oldReportBuffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user