Compare commits

...

9 Commits

Author SHA1 Message Date
Manuel
cad86b1ee9
Merge 70ec2c84ed into ba296db701 2025-06-06 07:49:41 +02:00
mverch67
70ec2c84ed refactored TCA8418Keyboard 2025-06-05 14:53:06 +02:00
mverch67
0ccce5e991 enable vibration motor 2025-06-05 14:53:06 +02:00
mverch67
d93d5205f2 cleanup comments 2025-06-05 14:53:06 +02:00
mverch67
1296d4d989 battery management 2025-06-05 14:53:06 +02:00
mverch67
1dc887ab6e optimize GPS 2025-06-05 14:53:06 +02:00
mverch67
4f4d55e7c9 fix touchscreen 2025-06-05 14:53:06 +02:00
mverch67
212839bdd3 fix touchscreen 2025-06-05 14:53:06 +02:00
mverch67
f6ee533f41 initial draft 2025-06-05 14:53:06 +02:00
23 changed files with 1248 additions and 549 deletions

43
boards/t-deck-pro.json Normal file
View File

@ -0,0 +1,43 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_qspi",
"partitions": "default_16MB.csv"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "esp32s3"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "LilyGo T-Deck Pro S3 (16M Flash 8M QSPI PSRAM )",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 921600
},
"monitor": {
"speed": 115200
},
"url": "https://lilygo.cc/products/t-deck-pro",
"vendor": "LilyGo"
}

View File

@ -120,6 +120,11 @@ NullSensor max17048Sensor;
RAK9154Sensor rak9154Sensor;
#endif
#ifdef HAS_PPM
// note: XPOWERS_CHIP_XXX must be defined in variant.h
#include <XPowersLib.h>
#endif
#ifdef HAS_PMU
XPowersLibInterface *PMU = NULL;
#else
@ -665,6 +670,8 @@ bool Power::setup()
bool found = axpChipInit();
if (!found)
found = lipoInit();
if (!found)
found = lipoChargerInit();
if (!found)
found = analogInit();
@ -1235,3 +1242,111 @@ bool Power::lipoInit()
return false;
}
#endif
#if defined(HAS_PPM) && HAS_PPM
/**
* Adapter class for BQ25896 Lipo battery charger.
*/
class LipoCharger : public HasBatteryLevel
{
private:
XPowersPPM *ppm = nullptr;
public:
/**
* Init the I2C BQ25896 Lipo battery charger
*/
bool runOnce()
{
if (ppm == nullptr) {
ppm = new XPowersPPM;
bool result = ppm->init(Wire, I2C_SDA, I2C_SCL, BQ25896_ADDR);
if (result) {
LOG_INFO("PPM BQ25896 init succeeded");
// Set the minimum operating voltage. Below this voltage, the PPM will protect
ppm->setSysPowerDownVoltage(3100);
// Set input current limit, default is 500mA
ppm->setInputCurrentLimit(3250);
// Disable current limit pin
ppm->disableCurrentLimitPin();
// Set the charging target voltage, Range:3840 ~ 4608mV ,step:16 mV
ppm->setChargeTargetVoltage(4208);
// Set the precharge current , Range: 64mA ~ 1024mA ,step:64mA
ppm->setPrechargeCurr(64);
// The premise is that limit pin is disabled, or it will
// only follow the maximum charging current set by limit pin.
// Set the charging current , Range:0~5056mA ,step:64mA
ppm->setChargerConstantCurr(1024);
// To obtain voltage data, the ADC must be enabled first
ppm->enableMeasure();
// Turn on charging function
// If there is no battery connected, do not turn on the charging function
ppm->enableCharge();
return true;
} else {
LOG_WARN("PPM BQ25896 init failed");
delete ppm;
ppm = nullptr;
}
}
return false;
}
/**
* Battery state of charge, from 0 to 100 or -1 for unknown
*/
virtual int getBatteryPercent() override { return -1; }
/**
* The raw voltage of the battery in millivolts, or NAN if unknown
*/
virtual uint16_t getBattVoltage() override { return ppm->getBattVoltage(); }
/**
* return true if there is a battery installed in this unit
*/
virtual bool isBatteryConnect() override { return ppm->getBattVoltage() > 0; }
/**
* return true if there is an external power source detected
*/
virtual bool isVbusIn() override { return ppm->isVbusIn(); }
/**
* return true if the battery is currently charging
*/
virtual bool isCharging() override { return ppm->isCharging(); }
};
LipoCharger lipoCharger;
/**
* Init the Lipo battery charger
*/
bool Power::lipoChargerInit()
{
bool result = lipoCharger.runOnce();
LOG_DEBUG("Power::lipoChargerInit lipo sensor is %s", result ? "ready" : "not ready yet");
if (!result)
return false;
batteryLevel = &lipoCharger;
return true;
}
#else
/**
* The Lipo battery level sensor is unavailable - default to AnalogBatteryLevel
*/
bool Power::lipoChargerInit()
{
return false;
}
#endif

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 SCREEN_MIRROR
// I2C Keyboards (M5Stack, RAK14004, T-Deck)
// I2C Keyboards (M5Stack, RAK14004, T-Deck, T-Deck Pro, T-Lora Pager, CardKB, BBQ10, MPR121, TCA8418)
#define CARDKB_ADDR 0x5F
#define TDECK_KB_ADDR 0x55
#define BBQ10_KB_ADDR 0x1F
#define MPR121_KB_ADDR 0x5A
#define TCA8418_KB_ADDR 0x34
// -----------------------------------------------------------------------------
// SENSOR
@ -156,8 +157,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MLX90614_ADDR_DEF 0x5A
#define CGRADSENS_ADDR 0x66
#define LTR390UV_ADDR 0x53
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418_KB
#define PCT2075_ADDR 0x37
#define BQ27220_ADDR 0x55 // same address as TDECK_KB
#define BQ25896_ADDR 0x6B
#define LTR553ALS_ADDR 0x23
// -----------------------------------------------------------------------------
// ACCELEROMETER
@ -171,6 +175,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BMX160_ADDR 0x69
#define ICM20948_ADDR 0x69
#define ICM20948_ADDR_ALT 0x68
#define BHI260AP_ADDR 0x28
// -----------------------------------------------------------------------------
// LED
@ -192,6 +197,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Touchscreen
// -----------------------------------------------------------------------------
#define FT6336U_ADDR 0x48
#define CST328_ADDR 0x1A
// -----------------------------------------------------------------------------
// BIAS-T Generator

View File

@ -72,6 +72,11 @@ class ScanI2C
LTR390UV,
TCA8418KB,
PCT2075,
CST328,
BQ25896,
BQ27220,
LTR553ALS,
BHI260AP
} DeviceType;
// typedef uint8_t DeviceAddress;

View File

@ -206,7 +206,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
}
break;
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address);
case TDECK_KB_ADDR:
// Do we have the T-Deck keyboard or the T-Deck Pro battery sensor?
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x40), 2); // MACData
if (registerValue != 0) {
logFoundDevice("BQ27220", (uint8_t)addr.address);
type = BQ27220;
} else {
logFoundDevice("TDECKKB", (uint8_t)addr.address);
type = TDECKKB;
}
break;
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);
@ -396,6 +406,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
logFoundDevice("BQ24295", (uint8_t)addr.address);
break;
}
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x14), 1); // get ID
if ((registerValue & 0b00000011) == 0b00000010) {
type = BQ25896;
logFoundDevice("BQ25896", (uint8_t)addr.address);
break;
}
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID
if (registerValue == 0x6A) {
type = LSM6DS3;
@ -435,6 +451,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(CST328_ADDR, CST328, "CST328", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(LTR553ALS_ADDR, LTR553ALS, "LTR553ALS", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(BHI260AP_ADDR, BHI260AP, "BHI260AP", (uint8_t)addr.address);
#ifdef HAS_TPS65233
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
#endif

View File

@ -203,7 +203,7 @@ bool EInkDisplay::connect()
adafruitDisplay->setRotation(0);
adafruitDisplay->setPartialWindow(0, 0, EINK_WIDTH, EINK_HEIGHT);
}
#elif defined(M5_COREINK)
#elif defined(M5_COREINK) || defined(T_DECK_PRO)
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init(115200, true, 40, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));

View File

@ -1795,7 +1795,7 @@ void Screen::setup()
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
touchScreenImpl1->init();
}
#elif HAS_TOUCHSCREEN
#elif HAS_TOUCHSCREEN && !defined(USE_EINK)
touchScreenImpl1 =
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
touchScreenImpl1->init();

View File

@ -1,116 +1,18 @@
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
#include "TCA8418Keyboard.h"
#include "configuration.h"
#include <Arduino.h>
// REGISTERS
// #define _TCA8418_REG_RESERVED 0x00
#define _TCA8418_REG_CFG 0x01 // Configuration register
#define _TCA8418_REG_INT_STAT 0x02 // Interrupt status
#define _TCA8418_REG_KEY_LCK_EC 0x03 // Key lock and event counter
#define _TCA8418_REG_KEY_EVENT_A 0x04 // Key event register A
#define _TCA8418_REG_KEY_EVENT_B 0x05 // Key event register B
#define _TCA8418_REG_KEY_EVENT_C 0x06 // Key event register C
#define _TCA8418_REG_KEY_EVENT_D 0x07 // Key event register D
#define _TCA8418_REG_KEY_EVENT_E 0x08 // Key event register E
#define _TCA8418_REG_KEY_EVENT_F 0x09 // Key event register F
#define _TCA8418_REG_KEY_EVENT_G 0x0A // Key event register G
#define _TCA8418_REG_KEY_EVENT_H 0x0B // Key event register H
#define _TCA8418_REG_KEY_EVENT_I 0x0C // Key event register I
#define _TCA8418_REG_KEY_EVENT_J 0x0D // Key event register J
#define _TCA8418_REG_KP_LCK_TIMER 0x0E // Keypad lock1 to lock2 timer
#define _TCA8418_REG_UNLOCK_1 0x0F // Unlock register 1
#define _TCA8418_REG_UNLOCK_2 0x10 // Unlock register 2
#define _TCA8418_REG_GPIO_INT_STAT_1 0x11 // GPIO interrupt status 1
#define _TCA8418_REG_GPIO_INT_STAT_2 0x12 // GPIO interrupt status 2
#define _TCA8418_REG_GPIO_INT_STAT_3 0x13 // GPIO interrupt status 3
#define _TCA8418_REG_GPIO_DAT_STAT_1 0x14 // GPIO data status 1
#define _TCA8418_REG_GPIO_DAT_STAT_2 0x15 // GPIO data status 2
#define _TCA8418_REG_GPIO_DAT_STAT_3 0x16 // GPIO data status 3
#define _TCA8418_REG_GPIO_DAT_OUT_1 0x17 // GPIO data out 1
#define _TCA8418_REG_GPIO_DAT_OUT_2 0x18 // GPIO data out 2
#define _TCA8418_REG_GPIO_DAT_OUT_3 0x19 // GPIO data out 3
#define _TCA8418_REG_GPIO_INT_EN_1 0x1A // GPIO interrupt enable 1
#define _TCA8418_REG_GPIO_INT_EN_2 0x1B // GPIO interrupt enable 2
#define _TCA8418_REG_GPIO_INT_EN_3 0x1C // GPIO interrupt enable 3
#define _TCA8418_REG_KP_GPIO_1 0x1D // Keypad/GPIO select 1
#define _TCA8418_REG_KP_GPIO_2 0x1E // Keypad/GPIO select 2
#define _TCA8418_REG_KP_GPIO_3 0x1F // Keypad/GPIO select 3
#define _TCA8418_REG_GPI_EM_1 0x20 // GPI event mode 1
#define _TCA8418_REG_GPI_EM_2 0x21 // GPI event mode 2
#define _TCA8418_REG_GPI_EM_3 0x22 // GPI event mode 3
#define _TCA8418_REG_GPIO_DIR_1 0x23 // GPIO data direction 1
#define _TCA8418_REG_GPIO_DIR_2 0x24 // GPIO data direction 2
#define _TCA8418_REG_GPIO_DIR_3 0x25 // GPIO data direction 3
#define _TCA8418_REG_GPIO_INT_LVL_1 0x26 // GPIO edge/level detect 1
#define _TCA8418_REG_GPIO_INT_LVL_2 0x27 // GPIO edge/level detect 2
#define _TCA8418_REG_GPIO_INT_LVL_3 0x28 // GPIO edge/level detect 3
#define _TCA8418_REG_DEBOUNCE_DIS_1 0x29 // Debounce disable 1
#define _TCA8418_REG_DEBOUNCE_DIS_2 0x2A // Debounce disable 2
#define _TCA8418_REG_DEBOUNCE_DIS_3 0x2B // Debounce disable 3
#define _TCA8418_REG_GPIO_PULL_1 0x2C // GPIO pull-up disable 1
#define _TCA8418_REG_GPIO_PULL_2 0x2D // GPIO pull-up disable 2
#define _TCA8418_REG_GPIO_PULL_3 0x2E // GPIO pull-up disable 3
// #define _TCA8418_REG_RESERVED 0x2F
// FIELDS CONFIG REGISTER 1
#define _TCA8418_REG_CFG_AI 0x80 // Auto-increment for read/write
#define _TCA8418_REG_CFG_GPI_E_CGF 0x40 // Event mode config
#define _TCA8418_REG_CFG_OVR_FLOW_M 0x20 // Overflow mode enable
#define _TCA8418_REG_CFG_INT_CFG 0x10 // Interrupt config
#define _TCA8418_REG_CFG_OVR_FLOW_IEN 0x08 // Overflow interrupt enable
#define _TCA8418_REG_CFG_K_LCK_IEN 0x04 // Keypad lock interrupt enable
#define _TCA8418_REG_CFG_GPI_IEN 0x02 // GPI interrupt enable
#define _TCA8418_REG_CFG_KE_IEN 0x01 // Key events interrupt enable
// FIELDS INT_STAT REGISTER 2
#define _TCA8418_REG_STAT_CAD_INT 0x10 // Ctrl-alt-del seq status
#define _TCA8418_REG_STAT_OVR_FLOW_INT 0x08 // Overflow interrupt status
#define _TCA8418_REG_STAT_K_LCK_INT 0x04 // Key lock interrupt status
#define _TCA8418_REG_STAT_GPI_INT 0x02 // GPI interrupt status
#define _TCA8418_REG_STAT_K_INT 0x01 // Key events interrupt status
// FIELDS KEY_LCK_EC REGISTER 3
#define _TCA8418_REG_LCK_EC_K_LCK_EN 0x40 // Key lock enable
#define _TCA8418_REG_LCK_EC_LCK_2 0x20 // Keypad lock status 2
#define _TCA8418_REG_LCK_EC_LCK_1 0x10 // Keypad lock status 1
#define _TCA8418_REG_LCK_EC_KLEC_3 0x08 // Key event count bit 3
#define _TCA8418_REG_LCK_EC_KLEC_2 0x04 // Key event count bit 2
#define _TCA8418_REG_LCK_EC_KLEC_1 0x02 // Key event count bit 1
#define _TCA8418_REG_LCK_EC_KLEC_0 0x01 // Key event count bit 0
// Pin IDs for matrix rows/columns
enum {
_TCA8418_ROW0, // Pin ID for row 0
_TCA8418_ROW1, // Pin ID for row 1
_TCA8418_ROW2, // Pin ID for row 2
_TCA8418_ROW3, // Pin ID for row 3
_TCA8418_ROW4, // Pin ID for row 4
_TCA8418_ROW5, // Pin ID for row 5
_TCA8418_ROW6, // Pin ID for row 6
_TCA8418_ROW7, // Pin ID for row 7
_TCA8418_COL0, // Pin ID for column 0
_TCA8418_COL1, // Pin ID for column 1
_TCA8418_COL2, // Pin ID for column 2
_TCA8418_COL3, // Pin ID for column 3
_TCA8418_COL4, // Pin ID for column 4
_TCA8418_COL5, // Pin ID for column 5
_TCA8418_COL6, // Pin ID for column 6
_TCA8418_COL7, // Pin ID for column 7
_TCA8418_COL8, // Pin ID for column 8
_TCA8418_COL9 // Pin ID for column 9
};
#define _TCA8418_COLS 3
#define _TCA8418_ROWS 4
#define _TCA8418_NUM_KEYS 12
uint8_t TCA8418TapMod[_TCA8418_NUM_KEYS] = {13, 7, 7, 7, 7, 7,
9, 7, 9, 2, 2, 2}; // Num chars per key, Modulus for rotating through characters
#define _TCA8418_LONG_PRESS_THRESHOLD 2000
#define _TCA8418_MULTI_TAP_THRESHOLD 750
unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = {
using Key = TCA8418KeyboardBase::TCA8418Key;
// Num chars per key, Modulus for rotating through characters
static uint8_t TCA8418TapMod[_TCA8418_NUM_KEYS] = {13, 7, 7, 7, 7, 7, 9, 7, 9, 2, 2, 2};
static unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = {
{'1', '.', ',', '?', '!', ':', ';', '-', '_', '\\', '/', '(', ')'}, // 1
{'2', 'a', 'b', 'c', 'A', 'B', 'C'}, // 2
{'3', 'd', 'e', 'f', 'D', 'E', 'F'}, // 3
@ -125,177 +27,35 @@ unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][13] = {
{'#', '@'}, // #
};
unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = {
_TCA8418_ESC, // 1
_TCA8418_UP, // 2
_TCA8418_NONE, // 3
_TCA8418_LEFT, // 4
_TCA8418_NONE, // 5
_TCA8418_RIGHT, // 6
_TCA8418_NONE, // 7
_TCA8418_DOWN, // 8
_TCA8418_NONE, // 9
_TCA8418_BSP, // *
_TCA8418_NONE, // 0
_TCA8418_NONE, // #
static unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = {
Key::ESC, // 1
Key::UP, // 2
Key::NONE, // 3
Key::LEFT, // 4
Key::NONE, // 5
Key::RIGHT, // 6
Key::NONE, // 7
Key::DOWN, // 8
Key::NONE, // 9
Key::BSP, // *
Key::NONE, // 0
Key::NONE, // #
};
#define _TCA8418_LONG_PRESS_THRESHOLD 2000
#define _TCA8418_MULTI_TAP_THRESHOLD 750
TCA8418Keyboard::TCA8418Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr)
TCA8418Keyboard::TCA8418Keyboard()
: TCA8418KeyboardBase(_TCA8418_ROWS, _TCA8418_COLS), last_key(-1), next_key(-1), last_tap(0L), char_idx(0), tap_interval(0),
should_backspace(false)
{
state = Init;
last_key = -1;
next_key = -1;
should_backspace = false;
last_tap = 0L;
char_idx = 0;
tap_interval = 0;
backlight_on = true;
queue = "";
}
void TCA8418Keyboard::begin(uint8_t addr, TwoWire *wire)
{
m_addr = addr;
m_wire = wire;
m_wire->begin();
reset();
}
void TCA8418Keyboard::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
{
m_addr = addr;
m_wire = nullptr;
writeCallback = w;
readCallback = r;
reset();
}
void TCA8418Keyboard::reset()
{
LOG_DEBUG("TCA8418 Reset");
// GPIO
// set default all GIO pins to INPUT
writeRegister(_TCA8418_REG_GPIO_DIR_1, 0x00);
writeRegister(_TCA8418_REG_GPIO_DIR_2, 0x00);
TCA8418KeyboardBase::reset();
// Set COL9 as GPIO output
writeRegister(_TCA8418_REG_GPIO_DIR_3, 0x02);
writeRegister(TCA8418_REG_GPIO_DIR_3, 0x02);
// Switch off keyboard backlight (COL9 = LOW)
writeRegister(_TCA8418_REG_GPIO_DAT_OUT_3, 0x00);
// add all pins to key events
writeRegister(_TCA8418_REG_GPI_EM_1, 0xFF);
writeRegister(_TCA8418_REG_GPI_EM_2, 0xFF);
writeRegister(_TCA8418_REG_GPI_EM_3, 0xFF);
// set all pins to FALLING interrupts
writeRegister(_TCA8418_REG_GPIO_INT_LVL_1, 0x00);
writeRegister(_TCA8418_REG_GPIO_INT_LVL_2, 0x00);
writeRegister(_TCA8418_REG_GPIO_INT_LVL_3, 0x00);
// add all pins to interrupts
writeRegister(_TCA8418_REG_GPIO_INT_EN_1, 0xFF);
writeRegister(_TCA8418_REG_GPIO_INT_EN_2, 0xFF);
writeRegister(_TCA8418_REG_GPIO_INT_EN_3, 0xFF);
// Set keyboard matrix size
matrix(_TCA8418_ROWS, _TCA8418_COLS);
enableDebounce();
flush();
state = Idle;
}
bool TCA8418Keyboard::matrix(uint8_t rows, uint8_t columns)
{
if ((rows > 8) || (columns > 10))
return false;
// Skip zero size matrix
if ((rows != 0) && (columns != 0)) {
// Setup the keypad matrix.
uint8_t mask = 0x00;
for (int r = 0; r < rows; r++) {
mask <<= 1;
mask |= 1;
}
writeRegister(_TCA8418_REG_KP_GPIO_1, mask);
mask = 0x00;
for (int c = 0; c < columns && c < 8; c++) {
mask <<= 1;
mask |= 1;
}
writeRegister(_TCA8418_REG_KP_GPIO_2, mask);
if (columns > 8) {
if (columns == 9)
mask = 0x01;
else
mask = 0x03;
writeRegister(_TCA8418_REG_KP_GPIO_3, mask);
}
}
return true;
}
uint8_t TCA8418Keyboard::keyCount() const
{
uint8_t eventCount = readRegister(_TCA8418_REG_KEY_LCK_EC);
eventCount &= 0x0F; // lower 4 bits only
return eventCount;
}
bool TCA8418Keyboard::hasEvent()
{
return queue.length() > 0;
}
void TCA8418Keyboard::queueEvent(char next)
{
if (next == _TCA8418_NONE) {
return;
}
queue.concat(next);
}
char TCA8418Keyboard::dequeueEvent()
{
if (queue.length() < 1) {
return _TCA8418_NONE;
}
char next = queue.charAt(0);
queue.remove(0, 1);
return next;
}
void TCA8418Keyboard::trigger()
{
if (keyCount() == 0) {
return;
}
if (state != Init) {
// Read the key register
uint8_t k = readRegister(_TCA8418_REG_KEY_EVENT_A);
uint8_t key = k & 0x7F;
if (k & 0x80) {
if (state == Idle)
pressed(key);
return;
} else {
if (state == Held) {
released();
}
state = Idle;
return;
}
} else {
reset();
}
writeRegister(TCA8418_REG_GPIO_DAT_OUT_3, 0x00);
}
void TCA8418Keyboard::pressed(uint8_t key)
@ -355,7 +115,7 @@ void TCA8418Keyboard::released()
int32_t held_interval = now - last_tap;
last_tap = now;
if (tap_interval < _TCA8418_MULTI_TAP_THRESHOLD && should_backspace) {
queueEvent(_TCA8418_BSP);
queueEvent(BSP);
}
if (held_interval > _TCA8418_LONG_PRESS_THRESHOLD) {
queueEvent(TCA8418LongPressMap[last_key]);
@ -367,195 +127,11 @@ void TCA8418Keyboard::released()
}
}
uint8_t TCA8418Keyboard::flush()
{
// Flush key events
uint8_t count = 0;
while (readRegister(_TCA8418_REG_KEY_EVENT_A) != 0)
count++;
// Flush gpio events
readRegister(_TCA8418_REG_GPIO_INT_STAT_1);
readRegister(_TCA8418_REG_GPIO_INT_STAT_2);
readRegister(_TCA8418_REG_GPIO_INT_STAT_3);
// Clear INT_STAT register
writeRegister(_TCA8418_REG_INT_STAT, 3);
return count;
}
uint8_t TCA8418Keyboard::digitalRead(uint8_t pinnum) const
{
if (pinnum > _TCA8418_COL9)
return 0xFF;
uint8_t reg = _TCA8418_REG_GPIO_DAT_STAT_1 + pinnum / 8;
uint8_t mask = (1 << (pinnum % 8));
// Level 0 = low other = high
uint8_t value = readRegister(reg);
if (value & mask)
return HIGH;
return LOW;
}
bool TCA8418Keyboard::digitalWrite(uint8_t pinnum, uint8_t level)
{
if (pinnum > _TCA8418_COL9)
return false;
uint8_t reg = _TCA8418_REG_GPIO_DAT_OUT_1 + pinnum / 8;
uint8_t mask = (1 << (pinnum % 8));
// Level 0 = low other = high
uint8_t value = readRegister(reg);
if (level == LOW)
value &= ~mask;
else
value |= mask;
writeRegister(reg, value);
return true;
}
bool TCA8418Keyboard::pinMode(uint8_t pinnum, uint8_t mode)
{
if (pinnum > _TCA8418_COL9)
return false;
uint8_t idx = pinnum / 8;
uint8_t reg = _TCA8418_REG_GPIO_DIR_1 + idx;
uint8_t mask = (1 << (pinnum % 8));
// Mode 0 = input 1 = output
uint8_t value = readRegister(reg);
if (mode == OUTPUT)
value |= mask;
else
value &= ~mask;
writeRegister(reg, value);
// Pullup 0 = enabled 1 = disabled
reg = _TCA8418_REG_GPIO_PULL_1 + idx;
value = readRegister(reg);
if (mode == INPUT_PULLUP)
value &= ~mask;
else
value |= mask;
writeRegister(reg, value);
return true;
}
bool TCA8418Keyboard::pinIRQMode(uint8_t pinnum, uint8_t mode)
{
if (pinnum > _TCA8418_COL9)
return false;
if ((mode != RISING) && (mode != FALLING))
return false;
// Mode 0 = falling 1 = rising
uint8_t idx = pinnum / 8;
uint8_t reg = _TCA8418_REG_GPIO_INT_LVL_1 + idx;
uint8_t mask = (1 << (pinnum % 8));
uint8_t value = readRegister(reg);
if (mode == RISING)
value |= mask;
else
value &= ~mask;
writeRegister(reg, value);
// Enable interrupt
reg = _TCA8418_REG_GPIO_INT_EN_1 + idx;
value = readRegister(reg);
value |= mask;
writeRegister(reg, value);
return true;
}
void TCA8418Keyboard::enableInterrupts()
{
uint8_t value = readRegister(_TCA8418_REG_CFG);
value |= (_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
writeRegister(_TCA8418_REG_CFG, value);
};
void TCA8418Keyboard::disableInterrupts()
{
uint8_t value = readRegister(_TCA8418_REG_CFG);
value &= ~(_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
writeRegister(_TCA8418_REG_CFG, value);
};
void TCA8418Keyboard::enableMatrixOverflow()
{
uint8_t value = readRegister(_TCA8418_REG_CFG);
value |= _TCA8418_REG_CFG_OVR_FLOW_M;
writeRegister(_TCA8418_REG_CFG, value);
};
void TCA8418Keyboard::disableMatrixOverflow()
{
uint8_t value = readRegister(_TCA8418_REG_CFG);
value &= ~_TCA8418_REG_CFG_OVR_FLOW_M;
writeRegister(_TCA8418_REG_CFG, value);
};
void TCA8418Keyboard::enableDebounce()
{
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0x00);
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0x00);
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0x00);
}
void TCA8418Keyboard::disableDebounce()
{
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_1, 0xFF);
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_2, 0xFF);
writeRegister(_TCA8418_REG_DEBOUNCE_DIS_3, 0xFF);
}
void TCA8418Keyboard::setBacklight(bool on)
{
if (on) {
digitalWrite(_TCA8418_COL9, HIGH);
digitalWrite(TCA8418_COL9, HIGH);
} else {
digitalWrite(_TCA8418_COL9, LOW);
digitalWrite(TCA8418_COL9, LOW);
}
}
uint8_t TCA8418Keyboard::readRegister(uint8_t reg) const
{
if (m_wire) {
m_wire->beginTransmission(m_addr);
m_wire->write(reg);
m_wire->endTransmission();
m_wire->requestFrom(m_addr, (uint8_t)1);
if (m_wire->available() < 1)
return 0;
return m_wire->read();
}
if (readCallback) {
uint8_t data;
readCallback(m_addr, reg, &data, 1);
return data;
}
return 0;
}
void TCA8418Keyboard::writeRegister(uint8_t reg, uint8_t value)
{
uint8_t data[2];
data[0] = reg;
data[1] = value;
if (m_wire) {
m_wire->beginTransmission(m_addr);
m_wire->write(data, sizeof(uint8_t) * 2);
m_wire->endTransmission();
}
if (writeCallback) {
writeCallback(m_addr, data[0], &(data[1]), 1);
}
}

View File

@ -1,83 +1,23 @@
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
#include "configuration.h"
#include <Wire.h>
#include "TCA8418KeyboardBase.h"
#define _TCA8418_NONE 0x00
#define _TCA8418_REBOOT 0x90
#define _TCA8418_LEFT 0xb4
#define _TCA8418_UP 0xb5
#define _TCA8418_DOWN 0xb6
#define _TCA8418_RIGHT 0xb7
#define _TCA8418_ESC 0x1b
#define _TCA8418_BSP 0x08
#define _TCA8418_SELECT 0x0d
class TCA8418Keyboard
/**
* @brief 3x4 keypad with 3 columns and 4 rows
*/
class TCA8418Keyboard : public TCA8418KeyboardBase
{
public:
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
TCA8418Keyboard();
void reset(void) override;
void setBacklight(bool on) override;
enum KeyState { Init = 0, Idle, Held, Busy };
protected:
void pressed(uint8_t key) override;
void released(void) override;
KeyState state;
int8_t last_key;
int8_t next_key;
bool should_backspace;
uint32_t last_tap;
uint8_t char_idx;
int32_t tap_interval;
bool backlight_on;
String queue;
TCA8418Keyboard();
void begin(uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS, TwoWire *wire = &Wire);
void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = XPOWERS_AXP192_AXP2101_ADDRESS);
void reset(void);
// Configure the size of the keypad.
// All other rows and columns are set as inputs.
bool matrix(uint8_t rows, uint8_t columns);
// Flush all events in the FIFO buffer + GPIO events.
uint8_t flush(void);
// Key events available in the internal FIFO buffer.
uint8_t keyCount(void) const;
void trigger(void);
void pressed(uint8_t key);
void released(void);
bool hasEvent(void);
char dequeueEvent(void);
void queueEvent(char);
uint8_t digitalRead(uint8_t pinnum) const;
bool digitalWrite(uint8_t pinnum, uint8_t level);
bool pinMode(uint8_t pinnum, uint8_t mode);
bool pinIRQMode(uint8_t pinnum, uint8_t mode); // MODE FALLING or RISING
// enable / disable interrupts for matrix and GPI pins
void enableInterrupts();
void disableInterrupts();
// ignore key events when FIFO buffer is full or not.
void enableMatrixOverflow();
void disableMatrixOverflow();
// debounce keys.
void enableDebounce();
void disableDebounce();
void setBacklight(bool on);
uint8_t readRegister(uint8_t reg) const;
void writeRegister(uint8_t reg, uint8_t value);
private:
TwoWire *m_wire;
uint8_t m_addr;
i2c_com_fptr_t readCallback;
i2c_com_fptr_t writeCallback;
bool should_backspace;
};

View File

@ -0,0 +1,372 @@
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
#include "TCA8418KeyboardBase.h"
#include "configuration.h"
#include <Arduino.h>
// FIELDS CONFIG REGISTER 1
#define _TCA8418_REG_CFG_AI 0x80 // Auto-increment for read/write
#define _TCA8418_REG_CFG_GPI_E_CGF 0x40 // Event mode config
#define _TCA8418_REG_CFG_OVR_FLOW_M 0x20 // Overflow mode enable
#define _TCA8418_REG_CFG_INT_CFG 0x10 // Interrupt config
#define _TCA8418_REG_CFG_OVR_FLOW_IEN 0x08 // Overflow interrupt enable
#define _TCA8418_REG_CFG_K_LCK_IEN 0x04 // Keypad lock interrupt enable
#define _TCA8418_REG_CFG_GPI_IEN 0x02 // GPI interrupt enable
#define _TCA8418_REG_CFG_KE_IEN 0x01 // Key events interrupt enable
// FIELDS INT_STAT REGISTER 2
#define _TCA8418_REG_STAT_CAD_INT 0x10 // Ctrl-alt-del seq status
#define _TCA8418_REG_STAT_OVR_FLOW_INT 0x08 // Overflow interrupt status
#define _TCA8418_REG_STAT_K_LCK_INT 0x04 // Key lock interrupt status
#define _TCA8418_REG_STAT_GPI_INT 0x02 // GPI interrupt status
#define _TCA8418_REG_STAT_K_INT 0x01 // Key events interrupt status
// FIELDS KEY_LCK_EC REGISTER 3
#define _TCA8418_REG_LCK_EC_K_LCK_EN 0x40 // Key lock enable
#define _TCA8418_REG_LCK_EC_LCK_2 0x20 // Keypad lock status 2
#define _TCA8418_REG_LCK_EC_LCK_1 0x10 // Keypad lock status 1
#define _TCA8418_REG_LCK_EC_KLEC_3 0x08 // Key event count bit 3
#define _TCA8418_REG_LCK_EC_KLEC_2 0x04 // Key event count bit 2
#define _TCA8418_REG_LCK_EC_KLEC_1 0x02 // Key event count bit 1
#define _TCA8418_REG_LCK_EC_KLEC_0 0x01 // Key event count bit 0
TCA8418KeyboardBase::TCA8418KeyboardBase(uint8_t rows, uint8_t columns)
: rows(rows), columns(columns), state(Init), queue(""), m_wire(nullptr), m_addr(0), readCallback(nullptr),
writeCallback(nullptr)
{
}
void TCA8418KeyboardBase::begin(uint8_t addr, TwoWire *wire)
{
m_addr = addr;
m_wire = wire;
m_wire->begin();
reset();
}
void TCA8418KeyboardBase::begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr)
{
m_addr = addr;
m_wire = nullptr;
writeCallback = w;
readCallback = r;
reset();
}
void TCA8418KeyboardBase::reset()
{
LOG_DEBUG("TCA8418 Reset");
// GPIO
// set default all GIO pins to INPUT
writeRegister(TCA8418_REG_GPIO_DIR_1, 0x00);
writeRegister(TCA8418_REG_GPIO_DIR_2, 0x00);
writeRegister(TCA8418_REG_GPIO_DIR_3, 0x00);
// add all pins to key events
writeRegister(TCA8418_REG_GPI_EM_1, 0xFF);
writeRegister(TCA8418_REG_GPI_EM_2, 0xFF);
writeRegister(TCA8418_REG_GPI_EM_3, 0xFF);
// set all pins to FALLING interrupts
writeRegister(TCA8418_REG_GPIO_INT_LVL_1, 0x00);
writeRegister(TCA8418_REG_GPIO_INT_LVL_2, 0x00);
writeRegister(TCA8418_REG_GPIO_INT_LVL_3, 0x00);
// add all pins to interrupts
writeRegister(TCA8418_REG_GPIO_INT_EN_1, 0xFF);
writeRegister(TCA8418_REG_GPIO_INT_EN_2, 0xFF);
writeRegister(TCA8418_REG_GPIO_INT_EN_3, 0xFF);
// Set keyboard matrix size
matrix(rows, columns);
enableDebounce();
flush();
state = Idle;
}
bool TCA8418KeyboardBase::matrix(uint8_t rows, uint8_t columns)
{
if (rows < 1 || rows > 8 || columns < 1 || columns > 10)
return false;
// Setup the keypad matrix.
uint8_t mask = 0x00;
for (int r = 0; r < rows; r++) {
mask <<= 1;
mask |= 1;
}
writeRegister(TCA8418_REG_KP_GPIO_1, mask);
mask = 0x00;
for (int c = 0; c < columns && c < 8; c++) {
mask <<= 1;
mask |= 1;
}
writeRegister(TCA8418_REG_KP_GPIO_2, mask);
if (columns > 8) {
if (columns == 9)
mask = 0x01;
else
mask = 0x03;
writeRegister(TCA8418_REG_KP_GPIO_3, mask);
}
return true;
}
uint8_t TCA8418KeyboardBase::keyCount() const
{
uint8_t eventCount = readRegister(TCA8418_REG_KEY_LCK_EC);
eventCount &= 0x0F; // lower 4 bits only
return eventCount;
}
bool TCA8418KeyboardBase::hasEvent() const
{
return queue.length() > 0;
}
void TCA8418KeyboardBase::queueEvent(char next)
{
if (next == NONE) {
return;
}
queue.concat(next);
}
char TCA8418KeyboardBase::dequeueEvent()
{
if (queue.length() < 1) {
return NONE;
}
char next = queue.charAt(0);
queue.remove(0, 1);
return next;
}
void TCA8418KeyboardBase::trigger()
{
if (keyCount() == 0) {
return;
}
if (state != Init) {
// Read the key register
uint8_t k = readRegister(TCA8418_REG_KEY_EVENT_A);
uint8_t key = k & 0x7F;
if (k & 0x80) {
if (state == Idle)
pressed(key);
return;
} else {
if (state == Held) {
released();
}
state = Idle;
return;
}
} else {
reset();
}
}
void TCA8418KeyboardBase::pressed(uint8_t key)
{
// must be defined in derived class
LOG_ERROR("pressed() not implemented in derived class");
}
void TCA8418KeyboardBase::released()
{
// must be defined in derived class
LOG_ERROR("released() not implemented in derived class");
}
uint8_t TCA8418KeyboardBase::flush()
{
// Flush key events
uint8_t count = 0;
while (readRegister(TCA8418_REG_KEY_EVENT_A) != 0)
count++;
// Flush gpio events
readRegister(TCA8418_REG_GPIO_INT_STAT_1);
readRegister(TCA8418_REG_GPIO_INT_STAT_2);
readRegister(TCA8418_REG_GPIO_INT_STAT_3);
// Clear INT_STAT register
writeRegister(TCA8418_REG_INT_STAT, 3);
return count;
}
uint8_t TCA8418KeyboardBase::digitalRead(uint8_t pinnum) const
{
if (pinnum > TCA8418_COL9)
return 0xFF;
uint8_t reg = TCA8418_REG_GPIO_DAT_STAT_1 + pinnum / 8;
uint8_t mask = (1 << (pinnum % 8));
// Level 0 = low other = high
uint8_t value = readRegister(reg);
if (value & mask)
return HIGH;
return LOW;
}
bool TCA8418KeyboardBase::digitalWrite(uint8_t pinnum, uint8_t level)
{
if (pinnum > TCA8418_COL9)
return false;
uint8_t reg = TCA8418_REG_GPIO_DAT_OUT_1 + pinnum / 8;
uint8_t mask = (1 << (pinnum % 8));
// Level 0 = low other = high
uint8_t value = readRegister(reg);
if (level == LOW)
value &= ~mask;
else
value |= mask;
writeRegister(reg, value);
return true;
}
bool TCA8418KeyboardBase::pinMode(uint8_t pinnum, uint8_t mode)
{
if (pinnum > TCA8418_COL9)
return false;
uint8_t idx = pinnum / 8;
uint8_t reg = TCA8418_REG_GPIO_DIR_1 + idx;
uint8_t mask = (1 << (pinnum % 8));
// Mode 0 = input 1 = output
uint8_t value = readRegister(reg);
if (mode == OUTPUT)
value |= mask;
else
value &= ~mask;
writeRegister(reg, value);
// Pullup 0 = enabled 1 = disabled
reg = TCA8418_REG_GPIO_PULL_1 + idx;
value = readRegister(reg);
if (mode == INPUT_PULLUP)
value &= ~mask;
else
value |= mask;
writeRegister(reg, value);
return true;
}
bool TCA8418KeyboardBase::pinIRQMode(uint8_t pinnum, uint8_t mode)
{
if (pinnum > TCA8418_COL9)
return false;
if ((mode != RISING) && (mode != FALLING))
return false;
// Mode 0 = falling 1 = rising
uint8_t idx = pinnum / 8;
uint8_t reg = TCA8418_REG_GPIO_INT_LVL_1 + idx;
uint8_t mask = (1 << (pinnum % 8));
uint8_t value = readRegister(reg);
if (mode == RISING)
value |= mask;
else
value &= ~mask;
writeRegister(reg, value);
// Enable interrupt
reg = TCA8418_REG_GPIO_INT_EN_1 + idx;
value = readRegister(reg);
value |= mask;
writeRegister(reg, value);
return true;
}
void TCA8418KeyboardBase::enableInterrupts()
{
uint8_t value = readRegister(TCA8418_REG_CFG);
value |= (_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
writeRegister(TCA8418_REG_CFG, value);
};
void TCA8418KeyboardBase::disableInterrupts()
{
uint8_t value = readRegister(TCA8418_REG_CFG);
value &= ~(_TCA8418_REG_CFG_GPI_IEN | _TCA8418_REG_CFG_KE_IEN);
writeRegister(TCA8418_REG_CFG, value);
};
void TCA8418KeyboardBase::enableMatrixOverflow()
{
uint8_t value = readRegister(TCA8418_REG_CFG);
value |= _TCA8418_REG_CFG_OVR_FLOW_M;
writeRegister(TCA8418_REG_CFG, value);
};
void TCA8418KeyboardBase::disableMatrixOverflow()
{
uint8_t value = readRegister(TCA8418_REG_CFG);
value &= ~_TCA8418_REG_CFG_OVR_FLOW_M;
writeRegister(TCA8418_REG_CFG, value);
};
void TCA8418KeyboardBase::enableDebounce()
{
writeRegister(TCA8418_REG_DEBOUNCE_DIS_1, 0x00);
writeRegister(TCA8418_REG_DEBOUNCE_DIS_2, 0x00);
writeRegister(TCA8418_REG_DEBOUNCE_DIS_3, 0x00);
}
void TCA8418KeyboardBase::disableDebounce()
{
writeRegister(TCA8418_REG_DEBOUNCE_DIS_1, 0xFF);
writeRegister(TCA8418_REG_DEBOUNCE_DIS_2, 0xFF);
writeRegister(TCA8418_REG_DEBOUNCE_DIS_3, 0xFF);
}
void TCA8418KeyboardBase::setBacklight(bool on) {}
uint8_t TCA8418KeyboardBase::readRegister(uint8_t reg) const
{
if (m_wire) {
m_wire->beginTransmission(m_addr);
m_wire->write(reg);
m_wire->endTransmission();
m_wire->requestFrom(m_addr, (uint8_t)1);
if (m_wire->available() < 1)
return 0;
return m_wire->read();
}
if (readCallback) {
uint8_t data;
readCallback(m_addr, reg, &data, 1);
return data;
}
return 0;
}
void TCA8418KeyboardBase::writeRegister(uint8_t reg, uint8_t value)
{
uint8_t data[2];
data[0] = reg;
data[1] = value;
if (m_wire) {
m_wire->beginTransmission(m_addr);
m_wire->write(data, sizeof(uint8_t) * 2);
m_wire->endTransmission();
}
if (writeCallback) {
writeCallback(m_addr, data[0], &(data[1]), 1);
}
}

View File

@ -0,0 +1,170 @@
// Based on the MPR121 Keyboard and Adafruit TCA8418 library
#include "configuration.h"
#include <Wire.h>
/**
* @brief TCA8418KeyboardBase is the base class for TCA8418 keyboard handling.
* It provides basic functionality for reading key events, managing the keyboard matrix,
* 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
{
public:
enum TCA8418Key : uint8_t {
NONE = 0x00,
BSP = 0x08,
TAB = 0x09,
SELECT = 0x0d,
ESC = 0x1b,
REBOOT = 0x90,
LEFT = 0xb4,
UP = 0xb5,
DOWN = 0xb6,
RIGHT = 0xb7,
BT_TOGGLE = 0xAA,
GPS_TOGGLE = 0x9E,
MUTE_TOGGLE = 0xAC,
SEND_PING = 0xAF,
BL_TOGGLE = 0xAB
};
typedef uint8_t (*i2c_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
TCA8418KeyboardBase(uint8_t rows, uint8_t columns);
virtual void begin(uint8_t addr = TCA8418_KB_ADDR, TwoWire *wire = &Wire);
virtual void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = TCA8418_KB_ADDR);
virtual void reset(void);
virtual void trigger(void);
virtual void setBacklight(bool on);
// Key events available
virtual bool hasEvent(void) const;
virtual char dequeueEvent(void);
protected:
enum KeyState { Init, Idle, Held, Busy };
enum TCA8418Register : uint8_t {
TCA8418_REG_RESERVED = 0x00,
TCA8418_REG_CFG = 0x01,
TCA8418_REG_INT_STAT = 0x02,
TCA8418_REG_KEY_LCK_EC = 0x03,
TCA8418_REG_KEY_EVENT_A = 0x04,
TCA8418_REG_KEY_EVENT_B = 0x05,
TCA8418_REG_KEY_EVENT_C = 0x06,
TCA8418_REG_KEY_EVENT_D = 0x07,
TCA8418_REG_KEY_EVENT_E = 0x08,
TCA8418_REG_KEY_EVENT_F = 0x09,
TCA8418_REG_KEY_EVENT_G = 0x0A,
TCA8418_REG_KEY_EVENT_H = 0x0B,
TCA8418_REG_KEY_EVENT_I = 0x0C,
TCA8418_REG_KEY_EVENT_J = 0x0D,
TCA8418_REG_KP_LCK_TIMER = 0x0E,
TCA8418_REG_UNLOCK_1 = 0x0F,
TCA8418_REG_UNLOCK_2 = 0x10,
TCA8418_REG_GPIO_INT_STAT_1 = 0x11,
TCA8418_REG_GPIO_INT_STAT_2 = 0x12,
TCA8418_REG_GPIO_INT_STAT_3 = 0x13,
TCA8418_REG_GPIO_DAT_STAT_1 = 0x14,
TCA8418_REG_GPIO_DAT_STAT_2 = 0x15,
TCA8418_REG_GPIO_DAT_STAT_3 = 0x16,
TCA8418_REG_GPIO_DAT_OUT_1 = 0x17,
TCA8418_REG_GPIO_DAT_OUT_2 = 0x18,
TCA8418_REG_GPIO_DAT_OUT_3 = 0x19,
TCA8418_REG_GPIO_INT_EN_1 = 0x1A,
TCA8418_REG_GPIO_INT_EN_2 = 0x1B,
TCA8418_REG_GPIO_INT_EN_3 = 0x1C,
TCA8418_REG_KP_GPIO_1 = 0x1D,
TCA8418_REG_KP_GPIO_2 = 0x1E,
TCA8418_REG_KP_GPIO_3 = 0x1F,
TCA8418_REG_GPI_EM_1 = 0x20,
TCA8418_REG_GPI_EM_2 = 0x21,
TCA8418_REG_GPI_EM_3 = 0x22,
TCA8418_REG_GPIO_DIR_1 = 0x23,
TCA8418_REG_GPIO_DIR_2 = 0x24,
TCA8418_REG_GPIO_DIR_3 = 0x25,
TCA8418_REG_GPIO_INT_LVL_1 = 0x26,
TCA8418_REG_GPIO_INT_LVL_2 = 0x27,
TCA8418_REG_GPIO_INT_LVL_3 = 0x28,
TCA8418_REG_DEBOUNCE_DIS_1 = 0x29,
TCA8418_REG_DEBOUNCE_DIS_2 = 0x2A,
TCA8418_REG_DEBOUNCE_DIS_3 = 0x2B,
TCA8418_REG_GPIO_PULL_1 = 0x2C,
TCA8418_REG_GPIO_PULL_2 = 0x2D,
TCA8418_REG_GPIO_PULL_3 = 0x2E
};
// Pin IDs for matrix rows/columns
enum TCA8418PinId : uint8_t {
TCA8418_ROW0, // Pin ID for row 0
TCA8418_ROW1, // Pin ID for row 1
TCA8418_ROW2, // Pin ID for row 2
TCA8418_ROW3, // Pin ID for row 3
TCA8418_ROW4, // Pin ID for row 4
TCA8418_ROW5, // Pin ID for row 5
TCA8418_ROW6, // Pin ID for row 6
TCA8418_ROW7, // Pin ID for row 7
TCA8418_COL0, // Pin ID for column 0
TCA8418_COL1, // Pin ID for column 1
TCA8418_COL2, // Pin ID for column 2
TCA8418_COL3, // Pin ID for column 3
TCA8418_COL4, // Pin ID for column 4
TCA8418_COL5, // Pin ID for column 5
TCA8418_COL6, // Pin ID for column 6
TCA8418_COL7, // Pin ID for column 7
TCA8418_COL8, // Pin ID for column 8
TCA8418_COL9 // Pin ID for column 9
};
virtual void pressed(uint8_t key);
virtual void released(void);
virtual void queueEvent(char);
virtual ~TCA8418KeyboardBase() {}
protected:
// Set the size of the keypad matrix
// All other rows and columns are set as inputs.
bool matrix(uint8_t rows, uint8_t columns);
uint8_t keyCount(void) const;
// Flush all events in the FIFO buffer + GPIO events.
uint8_t flush(void);
// debounce keys.
void enableDebounce();
void disableDebounce();
// enable / disable interrupts for matrix and GPI pins
void enableInterrupts();
void disableInterrupts();
// ignore key events when FIFO buffer is full or not.
void enableMatrixOverflow();
void disableMatrixOverflow();
uint8_t digitalRead(uint8_t pinnum) const;
bool digitalWrite(uint8_t pinnum, uint8_t level);
bool pinMode(uint8_t pinnum, uint8_t mode);
bool pinIRQMode(uint8_t pinnum, uint8_t mode); // MODE FALLING or RISING
uint8_t readRegister(uint8_t reg) const;
void writeRegister(uint8_t reg, uint8_t value);
protected:
uint8_t rows;
uint8_t columns;
KeyState state;
String queue;
private:
TwoWire *m_wire;
uint8_t m_addr;
i2c_com_fptr_t readCallback;
i2c_com_fptr_t writeCallback;
};

View File

@ -0,0 +1,196 @@
#if defined(T_DECK_PRO)
#include "TDeckProKeyboard.h"
#define _TCA8418_COLS 10
#define _TCA8418_ROWS 4
#define _TCA8418_NUM_KEYS 35
#define _TCA8418_MULTI_TAP_THRESHOLD 1500
using Key = TCA8418KeyboardBase::TCA8418Key;
constexpr uint8_t modifierRightShiftKey = 31 - 1; // keynum -1
constexpr uint8_t modifierRightShift = 0b0001;
constexpr uint8_t modifierLeftShiftKey = 35 - 1;
constexpr uint8_t modifierLeftShift = 0b0001;
constexpr uint8_t modifierSymKey = 32 - 1;
constexpr uint8_t modifierSym = 0b0010;
constexpr uint8_t modifierAltKey = 30 - 1;
constexpr uint8_t modifierAlt = 0b0100;
// Num chars per key, Modulus for rotating through characters
static uint8_t TDeckProTapMod[_TCA8418_NUM_KEYS] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
static unsigned char TDeckProTapMap[_TCA8418_NUM_KEYS][5] = {
{'p', 'P', '@', 0x00, Key::SEND_PING},
{'o', 'O', '+'},
{'i', 'I', '-'},
{'u', 'U', '_'},
{'y', 'Y', ')'},
{'t', 'T', '(', 0x00, Key::TAB},
{'r', 'R', '3'},
{'e', 'E', '2', 0x00, Key::UP},
{'w', 'W', '1'},
{'q', 'Q', '#', 0x00, Key::ESC}, // p, o, i, u, y, t, r, e, w, q
{Key::BSP, 0x00, 0x00},
{'l', 'L', '"'},
{'k', 'K', '\''},
{'j', 'J', ';'},
{'h', 'H', ':'},
{'g', 'G', '/', 0x00, Key::GPS_TOGGLE},
{'f', 'F', '6', 0x00, Key::RIGHT},
{'d', 'D', '5'},
{'s', 'S', '4', 0x00, Key::LEFT},
{'a', 'A', '*'}, // bsp, l, k, j, h, g, f, d, s, a
{0x0d, 0x00, 0x00},
{'$', 0x00, 0x00},
{'m', 'M', '.', 0x00, Key::MUTE_TOGGLE},
{'n', 'N', ','},
{'b', 'B', '!', 0x00, Key::BL_TOGGLE},
{'v', 'V', '?'},
{'c', 'C', '9'},
{'x', 'X', '8', 0x00, Key::DOWN},
{'z', 'Z', '7'},
{0x00, 0x00, 0x00}, // Ent, $, m, n, b, v, c, x, z, alt
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x20, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00} // R_Shift, sym, space, mic, L_Shift
};
TDeckProKeyboard::TDeckProKeyboard()
: TCA8418KeyboardBase(_TCA8418_ROWS, _TCA8418_COLS), modifierFlag(0), last_modifier_time(0), last_key(-1), next_key(-1),
last_tap(0L), char_idx(0), tap_interval(0)
{
}
void TDeckProKeyboard::reset()
{
TCA8418KeyboardBase::reset();
pinMode(KB_BL_PIN, OUTPUT);
setBacklight(false);
}
// handle multi-key presses (shift and alt)
void TDeckProKeyboard::trigger()
{
uint8_t count = keyCount();
if (count == 0)
return;
for (uint8_t i = 0; i < count; ++i) {
uint8_t k = readRegister(TCA8418_REG_KEY_EVENT_A + i);
uint8_t key = k & 0x7F;
if (k & 0x80) {
pressed(key);
} else {
released();
state = Idle;
}
}
}
void TDeckProKeyboard::pressed(uint8_t key)
{
if (state == Init || state == Busy) {
return;
}
if (modifierFlag && (millis() - last_modifier_time > _TCA8418_MULTI_TAP_THRESHOLD)) {
modifierFlag = 0;
}
uint8_t next_key = 0;
int row = (key - 1) / 10;
int col = (key - 1) % 10;
if (row >= _TCA8418_ROWS || col >= _TCA8418_COLS) {
return; // Invalid key
}
next_key = row * _TCA8418_COLS + col;
state = Held;
uint32_t now = millis();
tap_interval = now - last_tap;
updateModifierFlag(next_key);
if (isModifierKey(next_key)) {
last_modifier_time = now;
}
if (tap_interval < 0) {
last_tap = 0;
state = Busy;
return;
}
if (next_key != last_key || tap_interval > _TCA8418_MULTI_TAP_THRESHOLD) {
char_idx = 0;
} else {
char_idx += 1;
}
last_key = next_key;
last_tap = now;
}
void TDeckProKeyboard::released()
{
if (state != Held) {
return;
}
if (last_key < 0 || last_key >= _TCA8418_NUM_KEYS) {
last_key = -1;
state = Idle;
return;
}
uint32_t now = millis();
last_tap = now;
if (TDeckProTapMap[last_key][modifierFlag % TDeckProTapMod[last_key]] == Key::BL_TOGGLE) {
toggleBacklight();
return;
}
queueEvent(TDeckProTapMap[last_key][modifierFlag % TDeckProTapMod[last_key]]);
if (isModifierKey(last_key) == false)
modifierFlag = 0;
}
void TDeckProKeyboard::setBacklight(bool on)
{
if (on) {
digitalWrite(KB_BL_PIN, HIGH);
} else {
digitalWrite(KB_BL_PIN, LOW);
}
}
void TDeckProKeyboard::toggleBacklight(void)
{
digitalWrite(KB_BL_PIN, !digitalRead(KB_BL_PIN));
}
void TDeckProKeyboard::updateModifierFlag(uint8_t key)
{
if (key == modifierRightShiftKey) {
modifierFlag ^= modifierRightShift;
} else if (key == modifierLeftShiftKey) {
modifierFlag ^= modifierLeftShift;
} else if (key == modifierSymKey) {
modifierFlag ^= modifierSym;
} else if (key == modifierAltKey) {
modifierFlag ^= modifierAlt;
}
}
bool TDeckProKeyboard::isModifierKey(uint8_t key)
{
return (key == modifierRightShiftKey || key == modifierLeftShiftKey || key == modifierAltKey || key == modifierSymKey);
}
#endif // T_DECK_PRO

View File

@ -0,0 +1,27 @@
#include "TCA8418KeyboardBase.h"
class TDeckProKeyboard : public TCA8418KeyboardBase
{
public:
TDeckProKeyboard();
void reset(void) override;
void trigger(void) override;
void setBacklight(bool on) override;
protected:
void pressed(uint8_t key) override;
void released(void) override;
void updateModifierFlag(uint8_t key);
bool isModifierKey(uint8_t key);
void toggleBacklight(void);
private:
uint8_t modifierFlag; // Flag to indicate if a modifier key is pressed
uint32_t last_modifier_time; // Timestamp of the last modifier key press
int8_t last_key;
int8_t next_key;
uint32_t last_tap;
uint8_t char_idx;
int32_t tap_interval;
};

View File

@ -0,0 +1,12 @@
#include "TCA8418KeyboardBase.h"
class TLoraPagerKeyboard : public TCA8418KeyboardBase
{
public:
TLoraPagerKeyboard();
void setBacklight(bool on) override{};
protected:
void pressed(uint8_t key) override{};
void released(void) override{};
};

View File

@ -3,10 +3,26 @@
#include "detect/ScanI2C.h"
#include "detect/ScanI2CTwoWire.h"
#if defined(T_DECK_PRO)
#include "TDeckProKeyboard.h"
#elif defined(T_LORA_PAGER)
#include "TLoraPagerKeyboard.h"
#else
#include "TCA8418Keyboard.h"
#endif
extern ScanI2C::DeviceAddress cardkb_found;
extern uint8_t kb_model;
KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
KbI2cBase::KbI2cBase(const char *name)
: concurrency::OSThread(name),
#if defined(T_DECK_PRO)
TCAKeyboard(*(new TDeckProKeyboard()))
#elif defined(T_LORA_PAGER)
TCAKeyboard(*(new TLoraPagerKeyboard()))
#else
TCAKeyboard(*(new TCA8418Keyboard()))
#endif
{
this->_originName = name;
}
@ -43,8 +59,8 @@ int32_t KbI2cBase::runOnce()
if (cardkb_found.address == MPR121_KB_ADDR) {
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire1);
}
if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) {
TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire1);
if (cardkb_found.address == TCA8418_KB_ADDR) {
TCAKeyboard.begin(TCA8418_KB_ADDR, &Wire1);
}
break;
#endif
@ -58,8 +74,8 @@ int32_t KbI2cBase::runOnce()
if (cardkb_found.address == MPR121_KB_ADDR) {
MPRkeyboard.begin(MPR121_KB_ADDR, &Wire);
}
if (cardkb_found.address == XPOWERS_AXP192_AXP2101_ADDRESS) {
TCAKeyboard.begin(XPOWERS_AXP192_AXP2101_ADDRESS, &Wire);
if (cardkb_found.address == TCA8418_KB_ADDR) {
TCAKeyboard.begin(TCA8418_KB_ADDR, &Wire);
}
break;
case ScanI2C::NO_I2C:
@ -241,42 +257,66 @@ int32_t KbI2cBase::runOnce()
e.kbchar = 0x00;
e.source = this->_originName;
switch (nextEvent) {
case _TCA8418_NONE:
case TCA8418KeyboardBase::NONE:
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.kbchar = 0x00;
break;
case _TCA8418_REBOOT:
case TCA8418KeyboardBase::REBOOT:
e.inputEvent = ANYKEY;
e.kbchar = INPUT_BROKER_MSG_REBOOT;
break;
case _TCA8418_LEFT:
case TCA8418KeyboardBase::LEFT:
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
e.kbchar = 0x00;
break;
case _TCA8418_UP:
case TCA8418KeyboardBase::UP:
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
e.kbchar = 0x00;
break;
case _TCA8418_DOWN:
case TCA8418KeyboardBase::DOWN:
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
e.kbchar = 0x00;
break;
case _TCA8418_RIGHT:
case TCA8418KeyboardBase::RIGHT:
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = 0x00;
break;
case _TCA8418_BSP:
case TCA8418KeyboardBase::BSP:
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
e.kbchar = 0x08;
break;
case _TCA8418_SELECT:
case TCA8418KeyboardBase::SELECT:
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
e.kbchar = 0x0d;
break;
case _TCA8418_ESC:
case TCA8418KeyboardBase::ESC:
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
e.kbchar = 0x1b;
break;
case 0x9E:
e.inputEvent = ANYKEY;
e.kbchar = INPUT_BROKER_MSG_GPS_TOGGLE;
break;
case 0xAF:
e.inputEvent = ANYKEY;
e.kbchar = INPUT_BROKER_MSG_SEND_PING;
break;
case 0xAC:
e.inputEvent = ANYKEY;
e.kbchar = INPUT_BROKER_MSG_MUTE_TOGGLE;
break;
case 0xAA:
e.inputEvent = ANYKEY;
e.kbchar = INPUT_BROKER_MSG_BLUETOOTH_TOGGLE;
break;
case 0xAB:
e.inputEvent = ANYKEY;
e.kbchar = INPUT_BROKER_MSG_BLUETOOTH_TOGGLE;
break;
case 0x09:
e.inputEvent = ANYKEY;
e.kbchar = 0x09; // Tab
break;
default:
if (nextEvent > 127) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
@ -291,6 +331,7 @@ int32_t KbI2cBase::runOnce()
LOG_DEBUG("TCA8418 Notifying: %i Char: %c", e.inputEvent, e.kbchar);
this->notifyObservers(&e);
}
TCAKeyboard.trigger();
}
break;
}

View File

@ -3,10 +3,11 @@
#include "BBQ10Keyboard.h"
#include "InputBroker.h"
#include "MPR121Keyboard.h"
#include "TCA8418Keyboard.h"
#include "Wire.h"
#include "concurrency/OSThread.h"
class TCA8418KeyboardBase;
class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OSThread
{
public:
@ -22,6 +23,6 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
BBQ10Keyboard Q10keyboard;
MPR121Keyboard MPRkeyboard;
TCA8418Keyboard TCAKeyboard;
TCA8418KeyboardBase &TCAKeyboard;
bool is_sym = false;
};

View File

@ -363,6 +363,15 @@ void setup()
pinMode(TFT_CS, OUTPUT);
digitalWrite(TFT_CS, HIGH);
delay(100);
#elif defined(T_DECK_PRO)
pinMode(LORA_EN, OUTPUT);
digitalWrite(LORA_EN, HIGH);
pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
pinMode(PIN_EINK_CS, OUTPUT);
digitalWrite(PIN_EINK_CS, HIGH);
#endif
concurrency::hasBeenSetup = true;

View File

@ -664,7 +664,6 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
config.display.screen_on_secs = 30;
config.display.wake_on_tap_or_motion = true;
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
if (WiFiOTA::isUpdated()) {
WiFiOTA::recoverConfig(&config.network);
@ -720,6 +719,13 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.external_notification.alert_message_buzzer = true;
moduleConfig.external_notification.nag_timeout = 60;
#endif
#if defined(PIN_VIBRATION)
moduleConfig.external_notification.enabled = true;
moduleConfig.external_notification.output_vibra = PIN_VIBRATION;
moduleConfig.external_notification.alert_message_vibra = true;
moduleConfig.external_notification.output_ms = 500;
moduleConfig.external_notification.nag_timeout = 2;
#endif
#if defined(RAK4630) || defined(RAK11310)
// Default to RAK led pin 2 (blue)
moduleConfig.external_notification.enabled = true;

View File

@ -0,0 +1,28 @@
#include "configuration.h"
#ifdef T_DECK_PRO
#include "input/TouchScreenImpl1.h"
#include <CSE_CST328.h>
#include <Wire.h>
CSE_CST328 tsPanel = CSE_CST328(EINK_WIDTH, EINK_HEIGHT, &Wire, CST328_PIN_RST, CST328_PIN_INT);
bool readTouch(int16_t *x, int16_t *y)
{
if (tsPanel.getTouches()) {
*x = tsPanel.getPoint(0).x;
*y = tsPanel.getPoint(0).y;
return true;
}
return false;
}
// T-Deck Pro specific init
void lateInitVariant()
{
tsPanel.begin();
touchScreenImpl1 = new TouchScreenImpl1(EINK_WIDTH, EINK_HEIGHT, readTouch);
touchScreenImpl1->init();
}
#endif

View File

@ -122,6 +122,8 @@ class Power : private concurrency::OSThread
bool analogInit();
/// Setup a Lipo battery level sensor
bool lipoInit();
/// Setup a Lipo charger
bool lipoChargerInit();
private:
// open circuit voltage lookup table

View File

@ -0,0 +1,19 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define USB_VID 0x303a
#define USB_PID 0x1001
// used for keyboard, touch controller, beam sensor, and gyroscope
static const uint8_t SDA = 13;
static const uint8_t SCL = 14;
// Default SPI will be mapped to Radio
static const uint8_t SS = 3;
static const uint8_t MOSI = 33;
static const uint8_t MISO = 47;
static const uint8_t SCK = 36;
#endif /* Pins_Arduino_h */

View File

@ -0,0 +1,24 @@
[env:t-deck-pro]
extends = esp32s3_base
board = t-deck-pro
board_check = true
upload_protocol = esptool
build_flags =
${esp32_base.build_flags} -I variants/t-deck-pro
-D T_DECK_PRO
-D PRIVATE_HW ; TODO: remove me
-D GPS_POWER_TOGGLE
-D USE_EINK
-D EINK_DISPLAY_MODEL=GxEPD2_310_GDEQ031T10
-D EINK_WIDTH=240
-D EINK_HEIGHT=320
;-D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk
-D EINK_LIMIT_FASTREFRESH=10 ; How many consecutive fast-refreshes are permitted
-D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated
lib_deps =
${esp32s3_base.lib_deps}
https://github.com/ZinggJM/GxEPD2/archive/refs/tags/1.6.4.zip
https://github.com/CIRCUITSTATE/CSE_Touch/archive/b44f23b6f870b848f1fbe453c190879bc6cfaafa.zip
https://github.com/CIRCUITSTATE/CSE_CST328/archive/refs/tags/v0.0.4.zip

View File

@ -0,0 +1,88 @@
// Display (E-Ink)
#define PIN_EINK_CS 34
#define PIN_EINK_BUSY 37
#define PIN_EINK_DC 35
#define PIN_EINK_RES -1
#define PIN_EINK_SCLK 36
#define PIN_EINK_MOSI 47
#define I2C_SDA SDA
#define I2C_SCL SCL
// CST328 touch screen (implementation in src/platform/extra_variants/t_deck_pro/variant.cpp)
#define HAS_TOUCHSCREEN 1
#define CST328_PIN_INT 12
#define CST328_PIN_RST 45
#define USE_POWERSAVE
#define SLEEP_TIME 120
// GNNS
#define HAS_GPS 1
#define GPS_BAUDRATE 38400
#define PIN_GPS_EN 15
#define GPS_EN_ACTIVE 1
#define GPS_RX_PIN 44
#define GPS_TX_PIN 43
#define PIN_GPS_PPS 1
#define BUTTON_PIN 0
// vibration motor
#define PIN_VIBRATION 2
// Have SPI interface SD card slot
#define HAS_SDCARD
#define SDCARD_USE_SPI1
#define SPI_MOSI (33)
#define SPI_SCK (36)
#define SPI_MISO (47)
#define SPI_CS (48)
#define SDCARD_CS SPI_CS
#define SD_SPI_FREQUENCY 75000000U
// TCA8418 keyboard
#define KB_BL_PIN 42
#define CANNED_MESSAGE_MODULE_ENABLE 1
// microphone PCM5102A
#define PCM5102A_SCK 47
#define PCM5102A_DIN 17
#define PCM5102A_LRCK 18
// LTR_553ALS light sensor
#define HAS_LTR553ALS
// gyroscope BHI260AP
#define BOARD_1V8_EN 38
#define HAS_BHI260AP
// battery charger BQ25896
#define HAS_PPM 1
#define XPOWERS_CHIP_BQ25896
// LoRa
#define USE_SX1262
#define USE_SX1268
#define LORA_EN 46 // LoRa enable pin
#define LORA_SCK 36
#define LORA_MISO 47
#define LORA_MOSI 33
#define LORA_CS 3
#define LORA_DIO0 -1 // a No connect on the SX1262 module
#define LORA_RESET 4
#define LORA_DIO1 5 // SX1262 IRQ
#define LORA_DIO2 6 // SX1262 BUSY
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
#define SX126X_CS LORA_CS // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
// Not really an E22 but TTGO seems to be trying to clone that
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 2.4
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)