namespace ISR {
void panic(Error::ErrorType err) {
Timer1::stop();
detachInterrupt(digitalPinToInterrupt(K_IN_PIN));
Error::errno = err;
}
static volatile enum : uint8_t {
IDLE,
WAIT_FOR_KEYBOARD,
WAIT_AFTER_WRITE,
WAIT_AFTER_READ
} state = IDLE;
void onKCleared() {
switch (state) {
case IDLE: return;
case WAIT_AFTER_WRITE: setIOPinsToInput(); break;
case WAIT_AFTER_READ: break;
default: return panic(Error::REACHED_DEFAULT_1);
}
state = IDLE;
Timer1::restart();
}
void writeByteToBusAndWait(uint8_t const value) {
Timer1::stop();
setIOPinsToOutput();
writeByteToBus(value);
setK();
state = WAIT_AFTER_WRITE;
};
void enqueueByteFromBusAndWait() {
Timer1::stop();
lcdBuffer.enqueue(readByteFromBus());
setK();
state = WAIT_AFTER_READ;
};
void onTimer() {
switch (state) {
case IDLE: break;
case WAIT_FOR_KEYBOARD: {
if (kbBuffer.available()) {
writeByteToBusAndWait(kbBuffer.get());
}
return;
}
default: return panic(Error::REACHED_DEFAULT_2);
}
bool const EN_OUT = digitalRead<DISPLAY_ENABLE_PIN>();
bool const EN_IN = digitalRead<KEYBOARD_ENABLE_PIN>();
switch (EN_IN << 1 | EN_OUT) {
case 0b00: return;
case 0b01: return enqueueByteFromBusAndWait();
case 0b10: {
if (settings.inputMode == IMMEDIATE || kbBuffer.available()) {
return writeByteToBusAndWait(kbBuffer.get());
} else {
state = WAIT_FOR_KEYBOARD;
return;
}
}
case 0b11: return writeByteToBusAndWait(rng.get());
default: return panic(Error::REACHED_DEFAULT_3);
}
}
} // namespace ISRAppendix