TCA8418: Interrupt based notify of new key events

This commit is contained in:
WillyJL 2025-09-13 04:04:40 +02:00
parent 4816f45552
commit 63468df93f
No known key found for this signature in database
5 changed files with 54 additions and 4 deletions

View File

@ -43,6 +43,18 @@ void TCA8418KeyboardBase::begin(uint8_t addr, TwoWire *wire)
m_wire = wire;
m_wire->begin();
reset();
#ifdef KB_INT
interruptInstance = this;
auto interruptHandler = []() {
interruptInstance->notifyObservers(interruptInstance);
};
::pinMode(KB_INT, INPUT_PULLUP);
attachInterrupt(KB_INT, interruptHandler, FALLING);
enableInterrupts();
#endif
}
void TCA8418KeyboardBase::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
@ -157,6 +169,11 @@ void TCA8418KeyboardBase::trigger()
released(key);
}
}
#ifdef KB_INT
// Reset interrupt mask so we can receive future interrupts
writeRegister(TCA8418_REG_INT_STAT, 3);
#endif
}
void TCA8418KeyboardBase::pressed(uint8_t key)
@ -292,6 +309,8 @@ void TCA8418KeyboardBase::disableInterrupts()
writeRegister(TCA8418_REG_CFG, value);
};
TCA8418KeyboardBase* TCA8418KeyboardBase::interruptInstance;
void TCA8418KeyboardBase::enableMatrixOverflow()
{
uint8_t value = readRegister(TCA8418_REG_CFG);

View File

@ -1,6 +1,7 @@
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
#include "configuration.h"
#include <Wire.h>
#include "kbInterrupt.h"
/**
* @brief TCA8418KeyboardBase is the base class for TCA8418 keyboard handling.
@ -8,7 +9,7 @@
* and handling key states. It is designed to be extended for specific keyboard implementations.
* It supports both I2C communication and function pointers for custom I2C operations.
*/
class TCA8418KeyboardBase
class TCA8418KeyboardBase : public KbInterruptObservable
{
public:
enum TCA8418Key : uint8_t {
@ -142,6 +143,7 @@ class TCA8418KeyboardBase
// enable / disable interrupts for matrix and GPI pins
void enableInterrupts();
void disableInterrupts();
static TCA8418KeyboardBase* interruptInstance;
// ignore key events when FIFO buffer is full or not.
void enableMatrixOverflow();

View File

@ -46,6 +46,7 @@ uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t len
int32_t KbI2cBase::runOnce()
{
int32_t interval = 300;
if (!i2cBus) {
switch (cardkb_found.port) {
case ScanI2C::WIRE1:
@ -61,6 +62,7 @@ int32_t KbI2cBase::runOnce()
}
if (cardkb_found.address == TCA8418_KB_ADDR) {
TCAKeyboard.begin(TCA8418_KB_ADDR, &Wire1);
observe(&TCAKeyboard);
}
break;
#endif
@ -76,6 +78,7 @@ int32_t KbI2cBase::runOnce()
}
if (cardkb_found.address == TCA8418_KB_ADDR) {
TCAKeyboard.begin(TCA8418_KB_ADDR, &Wire);
observe(&TCAKeyboard);
}
break;
case ScanI2C::NO_I2C:
@ -249,6 +252,7 @@ int32_t KbI2cBase::runOnce()
break;
}
case 0x84: { // Adafruit TCA8418
interval = 3000; // Less polling, we have interrupts with onNotify()
TCAKeyboard.trigger();
InputEvent e;
while (TCAKeyboard.hasEvent()) {
@ -331,7 +335,6 @@ int32_t KbI2cBase::runOnce()
LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar);
this->notifyObservers(&e);
}
TCAKeyboard.trigger();
}
break;
}
@ -518,5 +521,17 @@ int32_t KbI2cBase::runOnce()
default:
LOG_WARN("Unknown kb_model 0x%02x", kb_model);
}
return 300;
// If new interrupt triggered while we were processing the previous, reinvoke with 0 interval right away
if (pendingInterruptCount) pendingInterruptCount--;
if (pendingInterruptCount) return 0;
return interval;
}
int KbI2cBase::onNotify(KbInterruptObservable* src)
{
pendingInterruptCount++;
setInterval(0);
return 0;
}

View File

@ -5,16 +5,18 @@
#include "MPR121Keyboard.h"
#include "Wire.h"
#include "concurrency/OSThread.h"
#include "kbInterrupt.h"
class TCA8418KeyboardBase;
class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OSThread
class KbI2cBase : public Observable<const InputEvent *>, public KbInterruptObserver, public concurrency::OSThread
{
public:
explicit KbI2cBase(const char *name);
protected:
virtual int32_t runOnce() override;
virtual int onNotify(KbInterruptObservable* src) override;
private:
const char *_originName;
@ -24,5 +26,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
BBQ10Keyboard Q10keyboard;
MPR121Keyboard MPRkeyboard;
TCA8418KeyboardBase &TCAKeyboard;
volatile uint8_t pendingInterruptCount = 0;
bool is_sym = false;
};

11
src/input/kbInterrupt.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "Observer.h"
class KbInterruptObservable : public Observable<KbInterruptObservable*>
{
};
class KbInterruptObserver : public Observer<KbInterruptObservable*>
{
};