actOnMatrixScan: Optimize the idle case

When there are no state changes, and no keys pressed on a row, instead of
iterating through a byte bit-by-bit, just fire idle events without checking the
bits. In all other cases, do the bit-walking like we did before.

The reason this is useful is because bit-walking is costly, and slow. If we can
avoid that, we win quite a lot of performance. Since rows being idle is the most
common case on a keyboard, this is a huge net win. Even in the worst case, where
no rows are idle, this is just one byte comparison and a branch slower than our
previous implementation.

As part of this optimization, `actOnHalfRow` was lifted out into its own
function, to reduce code duplication.

Many thanks to @gedankenexperimenter for the original idea!

Signed-off-by: Gergely Nagy <algernon@keyboard.io>
pull/365/head
Gergely Nagy 7 years ago
parent 9578dc1d73
commit e17869e1a1

@ -157,23 +157,31 @@ void Model01::readMatrix() {
} }
} }
void Model01::actOnHalfRow(byte row, byte colState, byte colPrevState, byte startPos) {
if ((colState == colPrevState) && (colState == 0)) {
for (byte col = 0; col < 8; col++) {
handleKeyswitchEvent(Key_NoKey, row, startPos - col, 0);
}
} else {
for (byte col = 0; col < 8; col++) {
uint8_t keyState = (bitRead(colPrevState, col) << 0) |
(bitRead(colState, col) << 1);
handleKeyswitchEvent(Key_NoKey, row, startPos - col, keyState);
}
}
}
void Model01::actOnMatrixScan() { void Model01::actOnMatrixScan() {
for (byte row = 0; row < 4; row++) { for (byte row = 0; row < 4; row++) {
for (byte col = 0; col < 8; col++) { uint8_t colState = leftHandState.rows[row];
uint8_t colPrevState = previousLeftHandState.rows[row];
uint8_t keynum = (row * 8) + (col); actOnHalfRow(row, colState, colPrevState, 7);
uint8_t keyState = (bitRead(previousLeftHandState.all, keynum) << 0) | colState = rightHandState.rows[row];
(bitRead(leftHandState.all, keynum) << 1); colPrevState = previousRightHandState.rows[row];
handleKeyswitchEvent(Key_NoKey, row, 7 - col, keyState);
keyState = (bitRead(previousRightHandState.all, keynum) << 0) | actOnHalfRow(row, colState, colPrevState, 15);
(bitRead(rightHandState.all, keynum) << 1);
handleKeyswitchEvent(Key_NoKey, row, (15 - col), keyState);
}
} }
} }

@ -55,6 +55,8 @@ class Model01 {
keydata_t previousRightHandState; keydata_t previousRightHandState;
private: private:
static void actOnHalfRow(byte row, byte colState, byte colPrevState, byte startPos);
static bool isLEDChanged; static bool isLEDChanged;
static KeyboardioScanner leftHand; static KeyboardioScanner leftHand;
static KeyboardioScanner rightHand; static KeyboardioScanner rightHand;

Loading…
Cancel
Save