diff --git a/boards/t-deck-pro.json b/boards/t-deck-pro.json
new file mode 100644
index 000000000..2f4bd594a
--- /dev/null
+++ b/boards/t-deck-pro.json
@@ -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"
+}
diff --git a/src/configuration.h b/src/configuration.h
index 32d99295e..c5519a54b 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -158,6 +158,9 @@ along with this program. If not, see .
#define LTR390UV_ADDR 0x53
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418
#define PCT2075_ADDR 0x37
+#define BQ27220_ADDR 0x55 // same address as TDECK_KB
+#define BQ25896_ADDR 0x6B
+#define LTR553ALS_ADDR 0x23
// -----------------------------------------------------------------------------
// ACCELEROMETER
@@ -171,6 +174,7 @@ along with this program. If not, see .
#define BMX160_ADDR 0x69
#define ICM20948_ADDR 0x69
#define ICM20948_ADDR_ALT 0x68
+#define BHI260AP_ADDR 0x28
// -----------------------------------------------------------------------------
// LED
@@ -192,6 +196,7 @@ along with this program. If not, see .
// Touchscreen
// -----------------------------------------------------------------------------
#define FT6336U_ADDR 0x48
+#define CST328_ADDR 0x1A
// -----------------------------------------------------------------------------
// BIAS-T Generator
diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h
index 72184db69..3cabc6341 100644
--- a/src/detect/ScanI2C.h
+++ b/src/detect/ScanI2C.h
@@ -72,6 +72,11 @@ class ScanI2C
LTR390UV,
TCA8418KB,
PCT2075,
+ CST328,
+ BQ25896,
+ BQ27220,
+ LTR553ALS,
+ BHI260AP
} DeviceType;
// typedef uint8_t DeviceAddress;
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index e2ba78a92..60a429ec7 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -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
diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp
index 5a2749482..260df2a8d 100644
--- a/src/graphics/EInkDisplay2.cpp
+++ b/src/graphics/EInkDisplay2.cpp
@@ -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(*lowLevel);
adafruitDisplay->init(115200, true, 40, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
diff --git a/src/input/TCA8418Keyboard.cpp b/src/input/TCA8418Keyboard.cpp
index 21cd7b2d5..86263a1b5 100644
--- a/src/input/TCA8418Keyboard.cpp
+++ b/src/input/TCA8418Keyboard.cpp
@@ -103,10 +103,70 @@ enum {
_TCA8418_COL9 // Pin ID for column 9
};
+#if defined(T_DECK_PRO)
+#define _TCA8418_COLS 10
+#define _TCA8418_ROWS 4
+#define _TCA8418_NUM_KEYS 35
+
+#define _TCA8418_LONG_PRESS_THRESHOLD 2000
+#define _TCA8418_MULTI_TAP_THRESHOLD 1500
+
+// Num chars per key, Modulus for rotating through characters
+uint8_t TCA8418TapMod[_TCA8418_NUM_KEYS] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
+
+// https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
+unsigned char TCA8418TapMap[_TCA8418_NUM_KEYS][3] = {{'p', 'P', '@'},
+ {'o', 'O', '+'},
+ {'i', 'I', '-'},
+ {'u', 'U', '_'},
+ {'y', 'Y', ')'},
+ {'t', 'T', '('},
+ {'r', 'R', '3'},
+ {'e', 'E', '2'},
+ {'w', 'W', '1'},
+ {'q', 'Q', '#'},
+ {_TCA8418_BSP, 0x00, 0x00},
+ {'l', 'L', '"'},
+ {'k', 'K', '\''},
+ {'j', 'J', ';'},
+ {'h', 'H', ':'},
+ {'g', 'G', '/'},
+ {'f', 'F', '6'},
+ {'d', 'D', '5'},
+ {'s', 'S', '4'},
+ {'a', 'A', '*'},
+ {0x0d, 0x00, 0x00},
+ {'$', 0x00, 0x00},
+ {'m', 'M', '.'},
+ {'n', 'N', ','},
+ {'b', 'B', '!'},
+ {'v', 'V', '?'},
+ {'c', 'C', '9'},
+ {'x', 'X', '8'},
+ {'z', 'Z', '7'},
+ {0xa4, 0x00, 0x00},
+ {0xa1, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x20, 0x00, 0x00},
+ {0x00, 0x00, '0'},
+ {0xa0, 0x00, 0x00}};
+
+unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, _TCA8418_ESC, // p,o,i,u,y,t,r,e,w,q
+ 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bsp,l,k,j,h,g,f,d,s,a
+ 0x00, 0x00, 0xb7, 0xb6, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, // ent,$,m,n,b,v,c,x,z,alt
+ 0x00, 0x00, 0x00, 0x00, 0x00 // rShift,sym,space,mic,lShift
+};
+
+#else
#define _TCA8418_COLS 3
#define _TCA8418_ROWS 4
#define _TCA8418_NUM_KEYS 12
+#define _TCA8418_LONG_PRESS_THRESHOLD 2000
+#define _TCA8418_MULTI_TAP_THRESHOLD 750
+
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
@@ -139,9 +199,7 @@ unsigned char TCA8418LongPressMap[_TCA8418_NUM_KEYS] = {
_TCA8418_NONE, // 0
_TCA8418_NONE, // #
};
-
-#define _TCA8418_LONG_PRESS_THRESHOLD 2000
-#define _TCA8418_MULTI_TAP_THRESHOLD 750
+#endif
TCA8418Keyboard::TCA8418Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr)
{
@@ -182,10 +240,14 @@ void TCA8418Keyboard::reset()
// set default all GIO pins to INPUT
writeRegister(_TCA8418_REG_GPIO_DIR_1, 0x00);
writeRegister(_TCA8418_REG_GPIO_DIR_2, 0x00);
+#ifndef T_DECK_PRO
// Set COL9 as GPIO output
writeRegister(_TCA8418_REG_GPIO_DIR_3, 0x02);
// Switch off keyboard backlight (COL9 = LOW)
writeRegister(_TCA8418_REG_GPIO_DAT_OUT_3, 0x00);
+#else
+ writeRegister(_TCA8418_REG_GPIO_DIR_3, 0x00);
+#endif
// add all pins to key events
writeRegister(_TCA8418_REG_GPI_EM_1, 0xFF);
@@ -516,11 +578,19 @@ void TCA8418Keyboard::disableDebounce()
void TCA8418Keyboard::setBacklight(bool on)
{
+#ifdef T_DECK_PRO
+ if (on) {
+ digitalWrite(KB_BL_PIN, HIGH);
+ } else {
+ digitalWrite(KB_BL_PIN, LOW);
+ }
+#else
if (on) {
digitalWrite(_TCA8418_COL9, HIGH);
} else {
digitalWrite(_TCA8418_COL9, LOW);
}
+#endif
}
uint8_t TCA8418Keyboard::readRegister(uint8_t reg) const
diff --git a/src/main.cpp b/src/main.cpp
index 2d49b2fbe..9fe9acd0a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -363,6 +363,19 @@ 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(BOARD_1V8_EN, OUTPUT);
+ // digitalWrite(BOARD_1V8_EN, HIGH);
+ // pinMode(BOARD_6609_EN, OUTPUT);
+ // digitalWrite(BOARD_6609_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;
diff --git a/src/platform/extra_variants/t_deck_pro/variant.cpp b/src/platform/extra_variants/t_deck_pro/variant.cpp
new file mode 100644
index 000000000..abf9a6e40
--- /dev/null
+++ b/src/platform/extra_variants/t_deck_pro/variant.cpp
@@ -0,0 +1,46 @@
+#include "configuration.h"
+
+#ifdef T_DECK_PRO
+
+#include "input/TouchScreenImpl1.h"
+#include
+#include
+
+CSE_CST328 tsPanel = CSE_CST328(EINK_WIDTH, EINK_HEIGHT, &Wire, CST328_PIN_RST, CST328_PIN_INT);
+
+volatile bool intReceived = false;
+
+void touchISR()
+{
+ // Detach the interrupt to prevent multiple interrupts
+ detachInterrupt(digitalPinToInterrupt(CST328_PIN_INT));
+ intReceived = true;
+}
+
+bool readTouch(int16_t *x, int16_t *y)
+{
+ if (1 /* intReceived */) {
+ intReceived = false;
+ // Reattach the interrupt for the next touch
+ // attachInterrupt (digitalPinToInterrupt(CST328_PIN_INT), touchISR, FALLING);
+
+ // Read the touch point
+ // if (tsPanel.isTouched(0)) {
+ 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();
+ // attachInterrupt (digitalPinToInterrupt(CST328_PIN_INT), touchISR, FALLING);
+ touchScreenImpl1 = new TouchScreenImpl1(EINK_WIDTH, EINK_HEIGHT, readTouch);
+ touchScreenImpl1->init();
+}
+#endif
\ No newline at end of file
diff --git a/variants/t-deck-pro/pins_arduino.h b/variants/t-deck-pro/pins_arduino.h
new file mode 100644
index 000000000..af0ba80b3
--- /dev/null
+++ b/variants/t-deck-pro/pins_arduino.h
@@ -0,0 +1,19 @@
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include
+
+#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 */
diff --git a/variants/t-deck-pro/platformio.ini b/variants/t-deck-pro/platformio.ini
new file mode 100644
index 000000000..8c0f54748
--- /dev/null
+++ b/variants/t-deck-pro/platformio.ini
@@ -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
diff --git a/variants/t-deck-pro/variant.h b/variants/t-deck-pro/variant.h
new file mode 100644
index 000000000..730c0533b
--- /dev/null
+++ b/variants/t-deck-pro/variant.h
@@ -0,0 +1,86 @@
+// 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 CST328_PIN_INT 12
+#define CST328_PIN_RST 45
+
+#define USE_POWERSAVE
+#define SLEEP_TIME 120
+
+// GNNS
+#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
+
+// 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
+
+// T-Deck Pro PMU
+
+// 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 quality sensor BQ25896
+#define HAS_BQ25896
+
+// battery quality sensor BQ27220
+#define HAS_BQ27220
+
+// 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)