From e17869e1a10e58e91031027c77840e32fc1cb8c0 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 14 Mar 2018 09:20:47 +0100 Subject: [PATCH] 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 --- src/Kaleidoscope-Hardware-Model01.cpp | 30 +++++++++++++++++---------- src/Kaleidoscope-Hardware-Model01.h | 2 ++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Kaleidoscope-Hardware-Model01.cpp b/src/Kaleidoscope-Hardware-Model01.cpp index cbf6d0c8..90c9ef84 100644 --- a/src/Kaleidoscope-Hardware-Model01.cpp +++ b/src/Kaleidoscope-Hardware-Model01.cpp @@ -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() { 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) | - (bitRead(leftHandState.all, keynum) << 1); - handleKeyswitchEvent(Key_NoKey, row, 7 - col, keyState); + colState = rightHandState.rows[row]; + colPrevState = previousRightHandState.rows[row]; - keyState = (bitRead(previousRightHandState.all, keynum) << 0) | - (bitRead(rightHandState.all, keynum) << 1); - - handleKeyswitchEvent(Key_NoKey, row, (15 - col), keyState); - } + actOnHalfRow(row, colState, colPrevState, 15); } } diff --git a/src/Kaleidoscope-Hardware-Model01.h b/src/Kaleidoscope-Hardware-Model01.h index 0f02ac37..107e4435 100644 --- a/src/Kaleidoscope-Hardware-Model01.h +++ b/src/Kaleidoscope-Hardware-Model01.h @@ -55,6 +55,8 @@ class Model01 { keydata_t previousRightHandState; private: + static void actOnHalfRow(byte row, byte colState, byte colPrevState, byte startPos); + static bool isLEDChanged; static KeyboardioScanner leftHand; static KeyboardioScanner rightHand;