mirror of
https://github.com/meshtastic/firmware.git
synced 2025-08-03 04:15:53 +00:00
add PCF8574(A) port expander as passive 4x4 keyboard
This commit is contained in:
parent
5de0c71a3e
commit
a4efa30799
@ -77,6 +77,7 @@ lib_deps =
|
||||
jgromes/RadioLib@~6.5.0
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306
|
||||
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
|
||||
robtillaart/I2CKeyPad@^0.4.0 ; port extender with keymatrix
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
||||
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
|
||||
|
@ -105,10 +105,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// Define if screen should be mirrored left to right
|
||||
// #define SCREEN_MIRROR
|
||||
|
||||
// I2C Keyboards (M5Stack, RAK14004, T-Deck)
|
||||
// I2C Keyboards (M5Stack, RAK14004, T-Deck, PCF8574A passive)
|
||||
#define CARDKB_ADDR 0x5F
|
||||
#define TDECK_KB_ADDR 0x55
|
||||
#define BBQ10_KB_ADDR 0x1F
|
||||
#define PCF8574A_ADDRESS 0x20
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SENSOR
|
||||
|
@ -30,8 +30,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004};
|
||||
return firstOfOrNONE(4, types);
|
||||
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, PCF8574A};
|
||||
return firstOfOrNONE(5, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||
|
@ -19,6 +19,7 @@ class ScanI2C
|
||||
TDECKKB,
|
||||
BBQ10KB,
|
||||
RAK14004,
|
||||
PCF8574A,
|
||||
PMU_AXP192_AXP2101,
|
||||
BME_680,
|
||||
BME_280,
|
||||
|
@ -229,6 +229,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found\n");
|
||||
SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found\n");
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n");
|
||||
SCAN_SIMPLE_CASE(PCF8574A_ADDRESS, PCF8574A, "PCF8574A based keyboard found\n");
|
||||
#ifdef HAS_NCP5623
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n");
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
|
||||
|
||||
void CardKbI2cImpl::init()
|
||||
{
|
||||
if (cardkb_found.address == 0x00) {
|
||||
if ((cardkb_found.address == 0x00) || (kb_model == 0x12)) {
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
84
src/input/peMatrixBase.cpp
Normal file
84
src/input/peMatrixBase.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "peMatrixBase.h"
|
||||
|
||||
#include "configuration.h"
|
||||
#include "detect/ScanI2C.h"
|
||||
|
||||
extern ScanI2C::DeviceAddress cardkb_found;
|
||||
extern uint8_t kb_model;
|
||||
|
||||
I2CKeyPad keyPad(cardkb_found.address);
|
||||
|
||||
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\n");
|
||||
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 50; // Keyscan every 50msec to avoid key bounce
|
||||
}
|
22
src/input/peMatrixBase.h
Normal file
22
src/input/peMatrixBase.h
Normal 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;
|
||||
};
|
16
src/input/peMatrixImpl.cpp
Normal file
16
src/input/peMatrixImpl.cpp
Normal 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
19
src/input/peMatrixImpl.h
Normal 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;
|
@ -486,6 +486,9 @@ void setup()
|
||||
// assign an arbitrary value to distinguish from other models
|
||||
kb_model = 0x11;
|
||||
break;
|
||||
case ScanI2C::DeviceType::PCF8574A:
|
||||
kb_model = 0x12;
|
||||
break;
|
||||
default:
|
||||
// use this as default since it's also just zero
|
||||
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00\n", kb_info.type);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "input/UpDownInterruptImpl1.h"
|
||||
#include "input/cardKbI2cImpl.h"
|
||||
#include "input/kbMatrixImpl.h"
|
||||
#include "input/peMatrixImpl.h"
|
||||
#endif
|
||||
#include "modules/AdminModule.h"
|
||||
#if !MESHTASTIC_EXCLUDE_ATAK
|
||||
@ -125,6 +126,8 @@ void setupModules()
|
||||
kbMatrixImpl = new KbMatrixImpl();
|
||||
kbMatrixImpl->init();
|
||||
#endif // INPUTBROKER_MATRIX_TYPE
|
||||
peMatrixImpl = new PeMatrixImpl();
|
||||
peMatrixImpl->init();
|
||||
#endif // HAS_BUTTON
|
||||
#if ARCH_PORTDUINO
|
||||
aLinuxInputImpl = new LinuxInputImpl();
|
||||
|
Loading…
Reference in New Issue
Block a user