gd32: matrix-based keyscanner

Signed-off-by: Gergely Nagy <algernon@keyboard.io>
pull/1086/head
Gergely Nagy 3 years ago committed by Jesse Vincent
parent 88a1d86079
commit 541e77cfc9
No known key found for this signature in database
GPG Key ID: 122F5DF7108E4046

@ -26,16 +26,20 @@ namespace device {
namespace gd32 { namespace gd32 {
namespace eval { namespace eval {
uint8_t KeyScanner::keyState; KeyScanner::col_state_t KeyScanner::matrix_state_[KeyScannerProps::matrix_columns];
uint8_t KeyScanner::previousKeyState; const uint8_t KeyScannerProps::matrix_rows;
int KeyScanner::prevPinState[2]; const uint8_t KeyScannerProps::matrix_columns;
constexpr uint8_t KeyScannerProps::matrix_row_pins[matrix_rows];
constexpr uint8_t KeyScannerProps::matrix_col_pins[matrix_columns];
void KeyScanner::setup() { void KeyScanner::setup() {
pinMode(PA3, INPUT); for (uint8_t i = 0; i < Props_::matrix_columns; i++) {
pinMode(PB13, INPUT); pinMode(Props_::matrix_row_pins[i], INPUT_PULLUP);
}
prevPinState[0] = HIGH; for (uint8_t i = 0; i < Props_::matrix_rows; i++) {
prevPinState[1] = HIGH; pinMode(Props_::matrix_row_pins[i], INPUT);
}
} }
void KeyScanner::scanMatrix() { void KeyScanner::scanMatrix() {
@ -43,39 +47,73 @@ void KeyScanner::scanMatrix() {
actOnMatrixScan(); actOnMatrixScan();
} }
uint16_t KeyScanner::readRows() {
uint16_t hot_pins = 0;
for (uint8_t i = 0; i < Props_::matrix_rows; i++) {
uint8_t rowPin = Props_::matrix_row_pins[i];
pinMode(rowPin, INPUT_PULLUP);
uint8_t v = !!digitalRead(rowPin);
pinMode(rowPin, INPUT);
hot_pins |= v << i;
}
return hot_pins;
}
uint16_t KeyScanner::debounce(uint16_t sample, debounce_t *debouncer) {
uint16_t delta, changes;
// Use xor to detect changes from last stable state:
// if a key has changed, it's bit will be 1, otherwise 0
delta = sample ^ debouncer->debounced_state;
// Increment counters and reset any unchanged bits:
// increment bit 1 for all changed keys
debouncer->db1 = ((debouncer->db1) ^ (debouncer->db0)) & delta;
// increment bit 0 for all changed keys
debouncer->db0 = ~(debouncer->db0) & delta;
// Calculate returned change set: if delta is still true
// and the counter has wrapped back to 0, the key is changed.
changes = ~(~delta | (debouncer->db0) | (debouncer->db1));
// Update state: in this case use xor to flip any bit that is true in changes.
debouncer->debounced_state ^= changes;
return changes;
}
void KeyScanner::readMatrix() { void KeyScanner::readMatrix() {
int b1, b2; uint16_t any_debounced_changes = 0;
b1 = digitalRead(PA3); for (uint8_t col = 0; col < Props_::matrix_columns; col++) {
b2 = digitalRead(PB13); uint8_t colPin = Props_::matrix_col_pins[col];
pinMode(colPin, OUTPUT);
digitalWrite(colPin, LOW);
previousKeyState = keyState; uint16_t hot_pins = readRows();
pinMode(colPin, INPUT);
if ((b1 != prevPinState[0]) && (b1 == HIGH)) { any_debounced_changes |= debounce(hot_pins, &matrix_state_[col].debouncer);
bitSet(keyState, 0);
}
prevPinState[0] = b1;
if ((b2 != prevPinState[1]) && (b2 == HIGH)) { if (any_debounced_changes) {
bitSet(keyState, 1); for (uint8_t i = 0; i < Props_::matrix_columns; i++) {
matrix_state_[i].current = matrix_state_[i].debouncer.debounced_state;
}
}
} }
prevPinState[1] = b2;
} }
void KeyScanner::actOnMatrixScan() { void KeyScanner::actOnMatrixScan() {
if (bitRead(keyState, 0) != bitRead(previousKeyState, 0)) { for (byte col = 0; col < Props_::matrix_columns; col++) {
ThisType::handleKeyswitchEvent( for (byte row = 0; row < Props_::matrix_rows; row++) {
Key_NoKey, uint8_t keyState = (bitRead(matrix_state_[col].previous, row) << 0) | (bitRead(matrix_state_[col].current, row) << 1);
typename Props_::KeyAddr(0, 0), if (keyState) {
keyState ThisType::handleKeyswitchEvent(Key_NoKey, typename Props_::KeyAddr(row, col), keyState);
); }
} }
if (bitRead(keyState, 1) != bitRead(previousKeyState, 1)) { matrix_state_[col].previous = matrix_state_[col].current;
ThisType::handleKeyswitchEvent(
Key_NoKey,
typename Props_::KeyAddr(0, 1),
keyState
);
} }
} }

@ -31,6 +31,10 @@ namespace eval {
struct KeyScannerProps : public kaleidoscope::driver::keyscanner::BaseProps { struct KeyScannerProps : public kaleidoscope::driver::keyscanner::BaseProps {
static constexpr uint8_t matrix_rows = 1; static constexpr uint8_t matrix_rows = 1;
static constexpr uint8_t matrix_columns = 2; static constexpr uint8_t matrix_columns = 2;
static constexpr uint8_t matrix_row_pins[] = { PA3 };
static constexpr uint8_t matrix_col_pins[] = { PE4, PD12 };
typedef MatrixAddr<matrix_rows, matrix_columns> KeyAddr; typedef MatrixAddr<matrix_rows, matrix_columns> KeyAddr;
}; };
@ -45,25 +49,44 @@ class KeyScanner: public kaleidoscope::driver::keyscanner::Base<KeyScannerProps>
static void actOnMatrixScan(); static void actOnMatrixScan();
static bool isKeyswitchPressed(KeyAddr key_addr) { static bool isKeyswitchPressed(KeyAddr key_addr) {
if (key_addr.row() != 0) //return bitRead(keyState, key_addr.col());
return false; return false;
return bitRead(keyState, key_addr.col());
} }
static uint8_t pressedKeyswitchCount() { static uint8_t pressedKeyswitchCount() {
return __builtin_popcount(keyState); //return __builtin_popcount(keyState);
return 0;
} }
static bool wasKeyswitchPressed(KeyAddr key_addr) { static bool wasKeyswitchPressed(KeyAddr key_addr) {
if (key_addr.row() != 0) //return bitRead(previousKeyState, key_addr.col());
return false; return false;
return bitRead(previousKeyState, key_addr.col());
} }
static uint8_t previousPressedKeyswitchCount() { static uint8_t previousPressedKeyswitchCount() {
return __builtin_popcount(previousKeyState); //return __builtin_popcount(previousKeyState);
return 0;
} }
protected: private:
static uint8_t keyState, previousKeyState; /*
static int prevPinState[2]; each of these variables are storing the state for a row of keys
so for key 0, the counter is represented by db0[0] and db1[0]
and the state in debounced_state[0].
*/
struct debounce_t {
uint16_t db0; // counter bit 0
uint16_t db1; // counter bit 1
uint16_t debounced_state; // debounced state
};
struct col_state_t {
uint16_t previous;
uint16_t current;
debounce_t debouncer;
};
static col_state_t matrix_state_[Props_::matrix_columns];
static inline uint16_t debounce(uint16_t sample, debounce_t *debouncer);
static uint16_t readRows();
}; };
} // namespace eval } // namespace eval

Loading…
Cancel
Save