Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Buildscripts/sdkconfig/default.properties
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ CONFIG_FATFS_SECTOR_512=y
CONFIG_WL_SECTOR_SIZE_512=y
CONFIG_WL_SECTOR_SIZE=512
CONFIG_WL_SECTOR_MODE_SAFE=y
CONFIG_WL_SECTOR_MODE=1
CONFIG_WL_SECTOR_MODE=1
# Allow new i2c_master API (used by Tab5Keyboard for LP_I2C_NUM_0) to coexist with legacy i2c driver
CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK=y
3 changes: 2 additions & 1 deletion Devices/m5stack-tab5/Source/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ using namespace tt::hal;
static constexpr auto* TAG = "Tab5";

static DeviceVector createDevices() {
::Device* i2c2 = device_find_by_name("i2c2");
return {
createPower(),
createDisplay(),
createSdCard(),
std::make_shared<Tab5Keyboard>()
std::make_shared<Tab5Keyboard>(i2c2)
};
Comment thread
KenVanHoeylandt marked this conversation as resolved.
}

Expand Down
4 changes: 3 additions & 1 deletion Devices/m5stack-tab5/Source/devices/Display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

static const auto LOGGER = tt::Logger("Tab5Display");

constexpr auto LCD_PIN_RESET = GPIO_NUM_0; // Match P4 EV board reset line
// LCD reset is wired to the PI4IOE5V6408 IO expander (io_expander0, bit 4), pulsed in
// Configuration.cpp's initExpander0() before display creation - not a direct SoC GPIO.
constexpr auto LCD_PIN_RESET = GPIO_NUM_NC;
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_22;

static std::shared_ptr<tt::hal::touch::TouchDevice> createGt911Touch() {
Expand Down
89 changes: 9 additions & 80 deletions Devices/m5stack-tab5/Source/devices/Tab5Keyboard.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "Tab5Keyboard.h"
#include <Tactility/app/App.h>
#include <tactility/drivers/i2c_controller.h>
#include <tactility/log.h>
#include <esp_timer.h>
#include <lvgl.h>

Expand Down Expand Up @@ -135,19 +137,14 @@ static uint32_t tab5TranslateKey(uint8_t keycode, uint8_t modifier, bool ctrl) {
}

// ---------------------------------------------------------------------------
// I2C helpers - direct i2c_master API (LP_I2C_NUM_0, GPIO 0/1)
// I2C helpers - use Tactility I2C controller API
// ---------------------------------------------------------------------------
bool Tab5Keyboard::readReg(uint8_t reg, uint8_t& value) const {
if (!i2cDev) return false;
const esp_err_t err = i2c_master_transmit_receive(i2cDev, &reg, 1, &value, 1, pdMS_TO_TICKS(50));
return err == ESP_OK;
bool Tab5Keyboard::readReg(uint8_t reg, uint8_t& value) {
return i2c_controller_read_register(i2cController, I2C_ADDRESS, reg, &value, 1, pdMS_TO_TICKS(50)) == ERROR_NONE;
}

bool Tab5Keyboard::writeReg(uint8_t reg, uint8_t value) const {
if (!i2cDev) return false;
const uint8_t buf[2] = { reg, value };
const esp_err_t err = i2c_master_transmit(i2cDev, buf, 2, pdMS_TO_TICKS(50));
return err == ESP_OK;
bool Tab5Keyboard::writeReg(uint8_t reg, uint8_t value) {
return i2c_controller_write_register(i2cController, I2C_ADDRESS, reg, &value, 1, pdMS_TO_TICKS(50)) == ERROR_NONE;
}

// ---------------------------------------------------------------------------
Expand All @@ -161,11 +158,7 @@ void Tab5Keyboard::updateLeds() {
0x00, 0x00, aaSticky ? uint8_t(0xA0) : uint8_t(0x00), // LED1: red if Aa latched
};
// Write 7-byte block starting at REG_RGB_BASE
const uint8_t reg = REG_RGB_BASE;
uint8_t tx[8];
tx[0] = reg;
for (int i = 0; i < 7; i++) tx[i + 1] = buf[i];
i2c_master_transmit(i2cDev, tx, 8, pdMS_TO_TICKS(50));
i2c_controller_write_register(i2cController, I2C_ADDRESS, REG_RGB_BASE, buf, 7, pdMS_TO_TICKS(50));
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -371,41 +364,10 @@ bool Tab5Keyboard::startLvgl(lv_display_t* display) {
LOG_E("Tab5Keyboard", "Input queue allocation failed — cannot start");
return false;
}
// Create LP I2C master bus (LP_I2C_NUM_0, GPIO 0/1) via new i2c_master API
i2c_master_bus_config_t bus_cfg = {
.i2c_port = LP_I2C_NUM_0,
.sda_io_num = GPIO_NUM_0,
.scl_io_num = GPIO_NUM_1,
.clk_source = static_cast<i2c_clock_source_t>(LP_I2C_SCLK_DEFAULT),
.glitch_ignore_cnt = 7,
.intr_priority = 0,
.trans_queue_depth = 0,
.flags = { .enable_internal_pullup = true },
};
if (i2c_new_master_bus(&bus_cfg, &i2cBus) != ESP_OK) {
LOG_E("Tab5Keyboard", "Failed to create LP I2C master bus");
return false;
}

i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = I2C_ADDRESS,
.scl_speed_hz = 100000,
};
if (i2c_master_bus_add_device(i2cBus, &dev_cfg, &i2cDev) != ESP_OK) {
LOG_E("Tab5Keyboard", "Failed to add keyboard device to LP I2C bus");
i2c_del_master_bus(i2cBus);
i2cBus = nullptr;
return false;
}

// Set Normal mode explicitly — device may power up in a different mode
if (!writeReg(REG_KEYBOARD_MODE, 0x00)) {
LOG_E("Tab5Keyboard", "Failed to set keyboard mode");
i2c_master_bus_rm_device(i2cDev);
i2c_del_master_bus(i2cBus);
i2cDev = nullptr;
i2cBus = nullptr;
return false;
}
writeReg(REG_EVENT_NUM, 0x00); // flush event queue
Expand All @@ -426,10 +388,6 @@ bool Tab5Keyboard::startLvgl(lv_display_t* display) {
// Enable Normal-mode interrupt (bit 0)
if (!writeReg(REG_INT_CFG, 0x01)) {
LOG_E("Tab5Keyboard", "Failed to configure interrupt register");
i2c_master_bus_rm_device(i2cDev);
i2c_del_master_bus(i2cBus);
i2cDev = nullptr;
i2cBus = nullptr;
return false;
}

Expand Down Expand Up @@ -470,38 +428,9 @@ bool Tab5Keyboard::stopLvgl() {
lv_indev_delete(kbHandle);
kbHandle = nullptr;

if (i2cDev) {
i2c_master_bus_rm_device(i2cDev);
i2cDev = nullptr;
}
if (i2cBus) {
i2c_del_master_bus(i2cBus);
i2cBus = nullptr;
}
return true;
}

bool Tab5Keyboard::isAttached() const {
// If already started, just probe via the open bus handle
if (i2cBus) {
return i2c_master_probe(i2cBus, I2C_ADDRESS, pdMS_TO_TICKS(100)) == ESP_OK;
}
// Otherwise open a temporary bus to probe (LP I2C is not accessible via legacy API)
i2c_master_bus_config_t bus_cfg = {
.i2c_port = LP_I2C_NUM_0,
.sda_io_num = GPIO_NUM_0,
.scl_io_num = GPIO_NUM_1,
.clk_source = static_cast<i2c_clock_source_t>(LP_I2C_SCLK_DEFAULT),
.glitch_ignore_cnt = 7,
.intr_priority = 0,
.trans_queue_depth = 0,
.flags = { .enable_internal_pullup = true },
};
i2c_master_bus_handle_t probe_bus = nullptr;
if (i2c_new_master_bus(&bus_cfg, &probe_bus) != ESP_OK) {
return false;
}
const esp_err_t ret = i2c_master_probe(probe_bus, I2C_ADDRESS, pdMS_TO_TICKS(100));
i2c_del_master_bus(probe_bus);
return ret == ESP_OK;
return i2c_controller_has_device_at_address(i2cController, I2C_ADDRESS, pdMS_TO_TICKS(100)) == ERROR_NONE;
}
Comment thread
KenVanHoeylandt marked this conversation as resolved.
11 changes: 5 additions & 6 deletions Devices/m5stack-tab5/Source/devices/Tab5Keyboard.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once
#include <Tactility/hal/keyboard/KeyboardDevice.h>
#include <Tactility/Timer.h>
#include <driver/i2c_master.h>
#include <tactility/device.h>
#include <driver/gpio.h>
#include <freertos/queue.h>

Expand All @@ -13,8 +13,7 @@ class Tab5Keyboard final : public tt::hal::keyboard::KeyboardDevice {
static constexpr uint32_t REPEAT_INITIAL_MS = 400;
static constexpr uint32_t REPEAT_RATE_MS = 80;

i2c_master_bus_handle_t i2cBus = nullptr;
i2c_master_dev_handle_t i2cDev = nullptr;
::Device* i2cController = nullptr;

lv_indev_t* kbHandle = nullptr;
QueueHandle_t queue = nullptr;
Expand All @@ -37,8 +36,8 @@ class Tab5Keyboard final : public tt::hal::keyboard::KeyboardDevice {
uint32_t repeatStartMs = 0;
uint32_t repeatLastMs = 0;

bool readReg(uint8_t reg, uint8_t& value) const;
bool writeReg(uint8_t reg, uint8_t value) const;
bool readReg(uint8_t reg, uint8_t& value);
bool writeReg(uint8_t reg, uint8_t value);
void updateLeds();

bool configureIrqPin();
Expand All @@ -50,7 +49,7 @@ class Tab5Keyboard final : public tt::hal::keyboard::KeyboardDevice {
static void readCallback(lv_indev_t* indev, lv_indev_data_t* data);

public:
Tab5Keyboard() {
explicit Tab5Keyboard(::Device* i2cController) : i2cController(i2cController) {
queue = xQueueCreate(20, sizeof(uint32_t));
// queue == nullptr on OOM; startLvgl() checks and refuses to start
}
Expand Down
2 changes: 0 additions & 2 deletions Devices/m5stack-tab5/device.properties
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,3 @@ CONFIG_CACHE_L2_CACHE_256KB=y
CONFIG_LVGL_PORT_ENABLE_PPA=y
CONFIG_LV_DRAW_BUF_ALIGN=64
CONFIG_LV_DEF_REFR_PERIOD=15
# Allow new i2c_master API (used by Tab5Keyboard for LP_I2C_NUM_0) to coexist with legacy i2c driver
CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK=y
10 changes: 10 additions & 0 deletions Devices/m5stack-tab5/m5stack,tab5.dts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <tactility/bindings/esp32_ble.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_i2c_master.h>
#include <tactility/bindings/esp32_i2s.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_uart.h>
Expand Down Expand Up @@ -68,6 +69,15 @@
pin-scl = <&gpio0 54 GPIO_FLAG_NONE>;
};

i2c_keyboard: i2c2 {
compatible = "espressif,esp32-i2c-master";
port = <LP_I2C_NUM_0>;
clock-frequency = <100000>;
clock-source = <LP_I2C_SCLK_DEFAULT>;
pin-sda = <&gpio0 0 GPIO_FLAG_PULL_UP>;
pin-scl = <&gpio0 1 GPIO_FLAG_PULL_UP>;
};

sdcard_spi: spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
Expand Down
2 changes: 1 addition & 1 deletion Platforms/platform-esp32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ idf_component_register(
SRCS ${SOURCES}
INCLUDE_DIRS "include/"
PRIV_INCLUDE_DIRS "private/"
REQUIRES TactilityKernel driver vfs fatfs
REQUIRES TactilityKernel driver esp_driver_i2c vfs fatfs
)

idf_component_optional_requires(PRIVATE bt usb espressif__usb_host_hid espressif__usb_host_msc)
29 changes: 29 additions & 0 deletions Platforms/platform-esp32/bindings/espressif,esp32-i2c-master.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
description: ESP32 I2C Controller

include: ["i2c-controller.yaml"]

compatible: "espressif,esp32-i2c-master"

properties:
port:
type: int
required: true
description: |
The port number, defined by i2c_port_t.
Depending on the hardware, these values are available: I2C_NUM_0, I2C_NUM_1, LP_I2C_NUM_0
clock-frequency:
type: int
required: true
description: Initial clock frequency in Hz
clock-source:
type: int
default: 0
description: |
Clock source for the I2C peripheral.
If not specified, a default clock source will be used.
pin-sda:
type: phandle-array
required: true
pin-scl:
type: phandle-array
required: true
2 changes: 1 addition & 1 deletion Platforms/platform-esp32/bindings/espressif,esp32-i2c.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ properties:
required: true
description: |
The port number, defined by i2c_port_t.
Depending on the hardware, these values are available: I2C_NUM_0, I2C_NUM_1, LP_I2C_NUM_0
Depending on the hardware, these values are available: I2C_NUM_0, I2C_NUM_1
clock-frequency:
type: int
required: true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once

#include <tactility/bindings/bindings.h>
#include <tactility/drivers/esp32_i2c_master.h>

#ifdef __cplusplus
extern "C" {
#endif

DEFINE_DEVICETREE(esp32_i2c_master, struct Esp32I2cMasterConfig)

#ifdef __cplusplus
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once

#include <tactility/drivers/gpio.h>
#include <driver/i2c_types.h>

#ifdef __cplusplus
extern "C" {
#endif

struct Esp32I2cMasterConfig {
i2c_port_num_t port;
uint32_t clockFrequency;
int32_t clkSource;
struct GpioPinSpec pinSda;
struct GpioPinSpec pinScl;
};

#ifdef __cplusplus
}
#endif
8 changes: 2 additions & 6 deletions Platforms/platform-esp32/source/drivers/esp32_i2c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,12 @@ static error_t start(Device* device) {
check(gpio_descriptor_get_native_pin_number(sda_descriptor, &sda_pin) == ERROR_NONE);
check(gpio_descriptor_get_native_pin_number(scl_descriptor, &scl_pin) == ERROR_NONE);

gpio_flags_t sda_flags, scl_flags;
check(gpio_descriptor_get_flags(sda_descriptor, &sda_flags) == ERROR_NONE);
check(gpio_descriptor_get_flags(scl_descriptor, &scl_flags) == ERROR_NONE);

i2c_config_t esp_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = sda_pin,
.scl_io_num = scl_pin,
.sda_pullup_en = (sda_flags & GPIO_FLAG_PULL_UP) != 0,
.scl_pullup_en = (scl_flags & GPIO_FLAG_PULL_UP) != 0,
.sda_pullup_en = (sda_spec.flags & GPIO_FLAG_PULL_UP) != 0,
.scl_pullup_en = (scl_spec.flags & GPIO_FLAG_PULL_UP) != 0,
.master {
.clk_speed = dts_config->clockFrequency
},
Expand Down
Loading
Loading