1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-17 21:30:14 +00:00

Keep track of state separately from scanning.

This commit is contained in:
Thomas Harte 2024-05-16 22:18:51 -04:00
parent ef03ddf2ae
commit 8d0d7abd5a

View File

@ -20,19 +20,18 @@ struct Keyboard {
Keyboard(HalfDuplexSerial &serial) : serial_(serial), mouse_(*this) {}
void set_key_state(int row, int column, bool is_pressed) {
states_[row][column] = is_pressed;
if(!scan_keyboard_) {
logger_.info().append("Ignored key event as key scanning disabled");
return;
}
// Don't waste bandwidth on repeating facts.
if(states_[row][column] == is_pressed) return;
states_[row][column] = is_pressed;
if(posted_states_[row][column] == is_pressed) return;
// Post new key event.
logger_.info().append("Posting row %d, column %d is now %s", row, column, is_pressed ? "pressed" : "released");
const uint8_t prefix = is_pressed ? 0b1100'0000 : 0b1101'0000;
enqueue(static_cast<uint8_t>(prefix | row), static_cast<uint8_t>(prefix | column));
enqueue_key_event(row, column, is_pressed);
consider_dequeue();
}
@ -141,7 +140,17 @@ struct Keyboard {
void consider_dequeue() {
if(state_ == State::Idle) {
// If the key event queue is empty, grab as much mouse motion
// If the key event queue is empty but keyboard scanning is enabled, check for
// any disparity between posted keys states and actuals.
for(int row = 0; row < 16 && event_queue_.empty(); row++) {
for(int column = 0; column < 16 && event_queue_.empty(); column++) {
if(posted_states_[row][column] != states_[row][column]) {
enqueue_key_event(row, column, states_[row][column]);
}
}
}
// If the key event queue is _still_ empty, grab as much mouse motion
// as available.
if(event_queue_.empty()) {
const int x = std::clamp(mouse_x_, -0x3f, 0x3f);
@ -169,6 +178,7 @@ private:
Log::Logger<Log::Source::Keyboard> logger_;
bool states_[16][16]{};
bool posted_states_[16][16]{};
bool scan_keyboard_ = false;
bool scan_mouse_ = false;
@ -196,6 +206,12 @@ private:
event_queue_.erase(event_queue_.begin());
return true;
}
void enqueue_key_event(int row, int column, bool is_pressed) {
logger_.info().append("Posting row %d, column %d is now %s", row, column, is_pressed ? "pressed" : "released");
posted_states_[row][column] = is_pressed;
const uint8_t prefix = is_pressed ? 0b1100'0000 : 0b1101'0000;
enqueue(static_cast<uint8_t>(prefix | row), static_cast<uint8_t>(prefix | column));
}
static constexpr uint8_t HRST = 0b1111'1111; // Keyboard reset.
static constexpr uint8_t RAK1 = 0b1111'1110; // Reset response #1.