mirror of
https://github.com/esphome/esphome.git
synced 2026-09-17 18:18:43 +00:00
[icnt86] Support ICNT86 touch driver (#18331)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
co-authored by
pre-commit-ci-lite[bot]
Clyde Stubbs
J. Nick Koston
parent
711733f9af
commit
417b841db7
@@ -265,6 +265,7 @@ esphome/components/i2s_audio/* @jesserockz
|
||||
esphome/components/i2s_audio/microphone/* @jesserockz
|
||||
esphome/components/i2s_audio/speaker/* @jesserockz @kahrendt
|
||||
esphome/components/iaqcore/* @yozik04
|
||||
esphome/components/icnt86/* @danepowell
|
||||
esphome/components/ili9xxx/* @clydebarrow @nielsnl68
|
||||
esphome/components/improv_base/* @esphome/core
|
||||
esphome/components/improv_ble/* @jesserockz
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
CODEOWNERS = ["@danepowell"]
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "icnt86.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::icnt86 {
|
||||
|
||||
static const char *const TAG = "icnt86";
|
||||
static constexpr uint16_t REG_TOUCH_NUM = 0x1001;
|
||||
static constexpr uint16_t REG_POINT1 = 0x1002;
|
||||
static constexpr uint8_t MAX_TOUCHES = 5;
|
||||
static constexpr uint8_t POINT_SIZE = 7;
|
||||
|
||||
void ICNT86Touchscreen::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up icnt86 Touchscreen...");
|
||||
|
||||
// Register interrupt pin
|
||||
if (this->interrupt_pin_ != nullptr) {
|
||||
this->interrupt_pin_->setup();
|
||||
this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE);
|
||||
}
|
||||
|
||||
// Perform reset if necessary
|
||||
if (this->reset_pin_ != nullptr) {
|
||||
this->reset_pin_->setup();
|
||||
this->reset_pin_->digital_write(false);
|
||||
delay(10);
|
||||
this->reset_pin_->digital_write(true);
|
||||
}
|
||||
|
||||
if (this->x_raw_max_ == this->x_raw_min_) {
|
||||
this->x_raw_max_ = this->display_->get_native_width();
|
||||
}
|
||||
if (this->y_raw_max_ == this->y_raw_min_) {
|
||||
this->y_raw_max_ = this->display_->get_native_height();
|
||||
}
|
||||
}
|
||||
|
||||
void ICNT86Touchscreen::update_touches() {
|
||||
uint8_t buf[MAX_TOUCHES * POINT_SIZE] = {0};
|
||||
uint8_t mask[1] = {0x00};
|
||||
|
||||
if (this->read_register16(REG_TOUCH_NUM, buf, 1) != i2c::ERROR_OK) {
|
||||
this->status_set_warning();
|
||||
this->skip_update_ = true;
|
||||
ESP_LOGW(TAG, "Failed to read touch count");
|
||||
return;
|
||||
}
|
||||
uint8_t touch_count = buf[0];
|
||||
|
||||
if (touch_count == 0x00 || touch_count > MAX_TOUCHES) { // No new touch
|
||||
this->status_clear_warning();
|
||||
return;
|
||||
}
|
||||
if (this->read_register16(REG_POINT1, buf, touch_count * POINT_SIZE) != i2c::ERROR_OK) {
|
||||
this->status_set_warning();
|
||||
this->skip_update_ = true;
|
||||
ESP_LOGW(TAG, "Failed to read touch points");
|
||||
return;
|
||||
}
|
||||
this->write_register16(REG_TOUCH_NUM, mask, 1);
|
||||
ESP_LOGV(TAG, "Touch count: %d", touch_count);
|
||||
this->status_clear_warning();
|
||||
|
||||
for (uint8_t i = 0; i < touch_count; i++) {
|
||||
uint16_t x = ((uint16_t) buf[2 + 7 * i] << 8) + buf[1 + 7 * i];
|
||||
uint16_t y = ((uint16_t) buf[4 + 7 * i] << 8) + buf[3 + 7 * i];
|
||||
uint8_t pressure = buf[5 + 7 * i];
|
||||
uint8_t touch_id = buf[6 + 7 * i];
|
||||
|
||||
// A zero-pressure report just means this point is no longer touched; skipping it here leaves is_touched_
|
||||
// false (when no other point is active) so send_touches_() reports the release as normal.
|
||||
if (pressure != 0) {
|
||||
this->add_raw_touch_position_(touch_id, x, y, pressure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ICNT86Touchscreen::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "icnt86 Touchscreen:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
}
|
||||
|
||||
} // namespace esphome::icnt86
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/components/touchscreen/touchscreen.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
|
||||
namespace esphome::icnt86 {
|
||||
|
||||
class ICNT86Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
|
||||
void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
|
||||
void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; }
|
||||
|
||||
protected:
|
||||
void update_touches() override;
|
||||
InternalGPIOPin *interrupt_pin_{};
|
||||
GPIOPin *reset_pin_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace esphome::icnt86
|
||||
@@ -0,0 +1,40 @@
|
||||
from esphome import pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c, touchscreen
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@danepowell"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
icnt86_ns = cg.esphome_ns.namespace("icnt86")
|
||||
ICNT86Touchscreen = icnt86_ns.class_(
|
||||
"ICNT86Touchscreen",
|
||||
touchscreen.Touchscreen,
|
||||
i2c.I2CDevice,
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = touchscreen.touchscreen_schema("250ms").extend(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(ICNT86Touchscreen),
|
||||
cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
|
||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||
}
|
||||
).extend(i2c.i2c_device_schema(0x48))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await touchscreen.register_touchscreen(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
if interrupt_pin_config := config.get(CONF_INTERRUPT_PIN):
|
||||
cg.add(
|
||||
var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin_config))
|
||||
)
|
||||
|
||||
if reset_pin_config := config.get(CONF_RESET_PIN):
|
||||
cg.add(var.set_reset_pin(await cg.gpio_pin_expression(reset_pin_config)))
|
||||
@@ -0,0 +1,24 @@
|
||||
touchscreen:
|
||||
- platform: icnt86
|
||||
i2c_id: i2c_bus
|
||||
interrupt_pin: ${interrupt_pin_touch}
|
||||
reset_pin: ${reset_pin_touch}
|
||||
display: epaper
|
||||
on_touch:
|
||||
- logger.log:
|
||||
format: Touch at (%d, %d)
|
||||
args: [touch.x, touch.y]
|
||||
|
||||
display:
|
||||
- platform: waveshare_epaper
|
||||
id: epaper
|
||||
rotation: 90
|
||||
cs_pin: ${cs_pin_display}
|
||||
dc_pin: ${dc_pin_display}
|
||||
busy_pin: ${busy_pin_display}
|
||||
reset_pin: ${reset_pin_display}
|
||||
model: 2.90inv2-r2
|
||||
pages:
|
||||
- id: icnt86_page
|
||||
lambda: |-
|
||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||
@@ -0,0 +1,14 @@
|
||||
substitutions:
|
||||
interrupt_pin_touch: GPIO4
|
||||
reset_pin_touch: GPIO32
|
||||
cs_pin_display: GPIO33
|
||||
dc_pin_display: GPIO21
|
||||
busy_pin_display: GPIO27
|
||||
reset_pin_display: GPIO14
|
||||
clk_pin: GPIO25
|
||||
mosi_pin: GPIO26
|
||||
|
||||
packages:
|
||||
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
||||
spi: !include ../../test_build_components/common/spi/esp32-idf.yaml
|
||||
icnt86: !include common.yaml
|
||||
Reference in New Issue
Block a user