This commit is contained in:
Thomas Göttgens 2025-06-07 23:09:19 +02:00 committed by GitHub
commit da08ba5fb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 173 additions and 6 deletions

View File

@ -28,9 +28,8 @@ build_flags =
-fmerge-all-constants -fmerge-all-constants
-ffunction-sections -ffunction-sections
-fdata-sections -fdata-sections
build_src_filter = build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp> ${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp> -<.pio/*/*/I2CKeyPad/*>
board_upload.offset_address = 0x08000000 board_upload.offset_address = 0x08000000
upload_protocol = stlink upload_protocol = stlink
@ -43,5 +42,6 @@ lib_deps =
https://github.com/caveman99/Crypto/archive/eae9c768054118a9399690f8af202853d1ae8516.zip https://github.com/caveman99/Crypto/archive/eae9c768054118a9399690f8af202853d1ae8516.zip
lib_ignore = lib_ignore =
mathertel/OneButton@2.6.1
Wire Wire
I2CKeyPad
mathertel/OneButton@2.6.1

View File

@ -71,6 +71,7 @@ lib_deps =
nanopb/Nanopb@0.4.91 nanopb/Nanopb@0.4.91
# renovate: datasource=custom.pio depName=ErriezCRC32 packageName=erriez/library/ErriezCRC32 # renovate: datasource=custom.pio depName=ErriezCRC32 packageName=erriez/library/ErriezCRC32
erriez/ErriezCRC32@1.0.1 erriez/ErriezCRC32@1.0.1
robtillaart/I2CKeyPad@0.5.0
; Used for the code analysis in PIO Home / Inspect ; Used for the code analysis in PIO Home / Inspect
check_tool = cppcheck check_tool = cppcheck

View File

@ -114,11 +114,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Define if screen should be mirrored left to right // Define if screen should be mirrored left to right
// #define SCREEN_MIRROR // #define SCREEN_MIRROR
// I2C Keyboards (M5Stack, RAK14004, T-Deck) // I2C Keyboards (M5Stack, RAK14004, T-Deck, PCF8574A passive)
#define CARDKB_ADDR 0x5F #define CARDKB_ADDR 0x5F
#define TDECK_KB_ADDR 0x55 #define TDECK_KB_ADDR 0x55
#define BBQ10_KB_ADDR 0x1F #define BBQ10_KB_ADDR 0x1F
#define MPR121_KB_ADDR 0x5A #define MPR121_KB_ADDR 0x5A
#define PCF8574A_ADDRESS 0x20
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// SENSOR // SENSOR

View File

@ -31,8 +31,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
{ {
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB, TCA8418KB}; ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, PCF8574A, MPR121KB, TCA8418KB};
return firstOfOrNONE(6, types); return firstOfOrNONE(7, types);
} }
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const

View File

@ -18,6 +18,7 @@ class ScanI2C
TDECKKB, TDECKKB,
BBQ10KB, BBQ10KB,
RAK14004, RAK14004,
PCF8574A,
PMU_AXP192_AXP2101, // has the same adress as the TCA8418KB PMU_AXP192_AXP2101, // has the same adress as the TCA8418KB
BME_680, BME_680,
BME_280, BME_280,

View File

@ -210,6 +210,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address); SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address); SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address);
#ifndef HAS_TCA9535
SCAN_SIMPLE_CASE(PCF8574A_ADDRESS, PCF8574A, "PCF8574A", (uint8_t)addr.address);
#endif
#ifdef HAS_NCP5623 #ifdef HAS_NCP5623
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address); SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address);
#endif #endif

View File

@ -9,6 +9,10 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
void CardKbI2cImpl::init() void CardKbI2cImpl::init()
{ {
if (kb_model == 0x12) {
disable();
return;
}
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN) #if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(I2C_NO_RESCAN)
if (cardkb_found.address == 0x00) { if (cardkb_found.address == 0x00) {
LOG_DEBUG("Rescan for I2C keyboard"); LOG_DEBUG("Rescan for I2C keyboard");

View File

@ -0,0 +1,88 @@
#include "peMatrixBase.h"
#include "configuration.h"
#include "detect/ScanI2C.h"
extern ScanI2C::DeviceAddress cardkb_found;
extern uint8_t kb_model;
#if WIRE_INTERFACES_COUNT == 2 // defined in architecture.h
I2CKeyPad keyPad(cardkb_found.address, cardkb_found.port == ScanI2C::WIRE1 ? &Wire1 : &Wire);
#else
I2CKeyPad keyPad(cardkb_found.address, &Wire);
#endif
PeMatrixBase::PeMatrixBase(const char *name) : concurrency::OSThread(name)
{
this->_originName = name;
}
int32_t PeMatrixBase::runOnce()
{
if (kb_model != 0x12) {
// Input device is not detected.
return disable();
}
if (firstTime) {
// This is the first time the OSThread library has called this function, so do port setup
firstTime = 0;
if (!keyPad.begin()) {
LOG_ERROR("Failed to initialize I2C keypad");
return disable();
}
keyPad.loadKeyMap(keymap);
} else {
if (keyPad.isPressed()) {
key = keyPad.getChar();
// debounce
if (key != prevkey) {
if (key != 0) {
LOG_DEBUG("Key 0x%x pressed\n", key);
// reset shift now that we have a keypress
InputEvent e;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.source = this->_originName;
switch (key) {
case 0x1b: // ESC
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
break;
case 0x08: // Back
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
e.kbchar = key;
break;
case 0xb5: // Up
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
break;
case 0xb6: // Down
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
break;
case 0xb4: // Left
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
e.kbchar = key;
break;
case 0xb7: // Right
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = key;
break;
case 0x0d: // Enter
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;
case 0x00: // nopress
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
break;
default: // all other keys
e.inputEvent = ANYKEY;
e.kbchar = key;
break;
}
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
this->notifyObservers(&e);
}
}
prevkey = key;
}
}
}
return 100; // Keyscan every 100msec to avoid key bounce
}

22
src/input/peMatrixBase.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "InputBroker.h"
#include "concurrency/OSThread.h"
#include <I2CKeyPad.h>
class PeMatrixBase : public Observable<const InputEvent *>, public concurrency::OSThread
{
public:
explicit PeMatrixBase(const char *name);
protected:
virtual int32_t runOnce() override;
private:
const char *_originName;
bool firstTime = 1;
// char keymap[19] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
char keymap[19] = {0x1b, 0xb5, '3', 'A', 0xb4, 0x0d, 0xb7, 'B', '7', 0xb6, '9', 'C', 0x09, '0', 0x08, 'D', 'N', 'F'};
char key = 0;
char prevkey = 0;
};

View File

@ -0,0 +1,16 @@
#include "peMatrixImpl.h"
#include "InputBroker.h"
PeMatrixImpl *peMatrixImpl;
PeMatrixImpl::PeMatrixImpl() : PeMatrixBase("matrixPE") {}
void PeMatrixImpl::init()
{
if (kb_model != 0x12) {
disable();
return;
}
inputBroker->registerSource(this);
}

19
src/input/peMatrixImpl.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include "main.h"
#include "peMatrixBase.h"
/**
* @brief The idea behind this class to have static methods for the event handlers.
* Check attachInterrupt() at RotaryEncoderInteruptBase.cpp
* Technically you can have as many rotary encoders hardver attached
* to your device as you wish, but you always need to have separate event
* handlers, thus you need to have a RotaryEncoderInterrupt implementation.
*/
class PeMatrixImpl : public PeMatrixBase
{
public:
PeMatrixImpl();
void init();
};
extern PeMatrixImpl *peMatrixImpl;

View File

@ -636,6 +636,9 @@ void setup()
// assign an arbitrary value to distinguish from other models // assign an arbitrary value to distinguish from other models
kb_model = 0x11; kb_model = 0x11;
break; break;
case ScanI2C::DeviceType::PCF8574A:
kb_model = 0x12;
break;
case ScanI2C::DeviceType::MPR121KB: case ScanI2C::DeviceType::MPR121KB:
// assign an arbitrary value to distinguish from other models // assign an arbitrary value to distinguish from other models
kb_model = 0x37; kb_model = 0x37;

View File

@ -11,6 +11,7 @@
#include "input/cardKbI2cImpl.h" #include "input/cardKbI2cImpl.h"
#endif #endif
#include "input/kbMatrixImpl.h" #include "input/kbMatrixImpl.h"
#include "input/peMatrixImpl.h"
#endif #endif
#if !MESHTASTIC_EXCLUDE_ADMIN #if !MESHTASTIC_EXCLUDE_ADMIN
#include "modules/AdminModule.h" #include "modules/AdminModule.h"
@ -178,10 +179,15 @@ void setupModules()
kbMatrixImpl = new KbMatrixImpl(); kbMatrixImpl = new KbMatrixImpl();
kbMatrixImpl->init(); kbMatrixImpl->init();
#endif // INPUTBROKER_MATRIX_TYPE #endif // INPUTBROKER_MATRIX_TYPE
peMatrixImpl = new PeMatrixImpl();
peMatrixImpl->init();
#ifdef INPUTBROKER_SERIAL_TYPE #ifdef INPUTBROKER_SERIAL_TYPE
aSerialKeyboardImpl = new SerialKeyboardImpl(); aSerialKeyboardImpl = new SerialKeyboardImpl();
aSerialKeyboardImpl->init(); aSerialKeyboardImpl->init();
#endif // INPUTBROKER_MATRIX_TYPE #endif // INPUTBROKER_MATRIX_TYPE
#endif // HAS_BUTTON #endif // HAS_BUTTON
#if ARCH_PORTDUINO && !HAS_TFT #if ARCH_PORTDUINO && !HAS_TFT
aLinuxInputImpl = new LinuxInputImpl(); aLinuxInputImpl = new LinuxInputImpl();

View File

@ -16,6 +16,9 @@
// #define ADC_CHANNEL ADC1_GPIO27_CHANNEL // #define ADC_CHANNEL ADC1_GPIO27_CHANNEL
// #define ADC_MULTIPLIER 2 // #define ADC_MULTIPLIER 2
// Portexpander
#define HAS_TCA9535
// ST7701 TFT LCD // ST7701 TFT LCD
#define ST7701_CS (4 | IO_EXPANDER) #define ST7701_CS (4 | IO_EXPANDER)
#define ST7701_RS -1 // DC #define ST7701_RS -1 // DC