mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 01:07:45 +01:00
Touchscreen component and driver fixes (#5997)
* Introduce calibration settings for all touchscreen drivers. this will override the common values. The x,y coordinates only calculated when the right calibrations are set. * resolve issues reported by CI * remove unneeded spaces and newlines * Forgot to remove some obsolete code * remove get_setup_priority from xpt2046 * remove media_player changes. * media_player: removed to much, * Update suggestions * referd back the `get_setup_priority` removal so it can be moved into a othe PR. * tt21100: restore init read * fix spacing * load native display dimensions instead of using internal dimensons. and load it only onse on setup * moved `update_touches()` to protexted section * adding Clydes PR#6049 * add multitouch test script * Update all Touchscreen replacing `get_*_internal` to `get_native_*` * fixed some CI recomendations * couple of fixes * make sure the display is running before touchscreen is setup * fix clang * revert back last changes * xpt2046: change log level for testing * logging information * add test file * fix polling issue with the for example the xpt2046 * fixed some CI issues * fixed some CI issues * restore mirror parameter discriptions * same for the swap_xy * same for the transform * remove the above const from const.py * and put the above const bacl const.py * Merge branch 'nvds-touchscreen-fix1' of https://github.com/nielsnl68/esphome into nvds-touchscreen-fix1 * and put the above const bacl const.py * [tt21100] making interupt pin optional * [tt21100] making interupt pin optional (now complete) * update the display part based on @clyde' s changes. * fix issue with ft6x36 touvhscreen * reverd back touch check. add comment * add some extra checks to the ft6x36 * add an other log and a typo fixed * okay an other fix. * add an extra check like others do and fix data type * [ft6336] fix update race when ts is touched. * [touchscreen] update some log's with a verbose level. * fix clang issues * fix the clang issues * fix the clang issues * fix virtual issue. * fix the clang issues * an other clang issues * remove anti-aliased fonts support. It does not belong here. * remove anti-aliased fonts support. It does not belong here. * rename test script * Moving the test files to there right location. * rename the test files * clean up the code * add a new line * clang fixings * clang fixings * remove comment * remove comment * Update esphome/components/touchscreen/__init__.py Co-authored-by: guillempages <guillempages@users.noreply.github.com> * Update esphome/components/touchscreen/__init__.py Co-authored-by: guillempages <guillempages@users.noreply.github.com> * Update esphome/components/touchscreen/__init__.py Co-authored-by: guillempages <guillempages@users.noreply.github.com> * Update esphome/components/touchscreen/touchscreen.cpp * Update esphome/components/touchscreen/touchscreen.cpp * [ft63x6] add threshold --------- Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: guillempages <guillempages@users.noreply.github.com>
This commit is contained in:
parent
c43c9ad1c5
commit
5393a09872
21 changed files with 422 additions and 157 deletions
|
@ -175,10 +175,15 @@ class Display : public PollingComponent {
|
||||||
/// Clear the entire screen by filling it with OFF pixels.
|
/// Clear the entire screen by filling it with OFF pixels.
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
/// Get the width of the image in pixels with rotation applied.
|
/// Get the calculated width of the display in pixels with rotation applied.
|
||||||
virtual int get_width() = 0;
|
virtual int get_width() { return this->get_width_internal(); }
|
||||||
/// Get the height of the image in pixels with rotation applied.
|
/// Get the calculated height of the display in pixels with rotation applied.
|
||||||
virtual int get_height() = 0;
|
virtual int get_height() { return this->get_height_internal(); }
|
||||||
|
|
||||||
|
/// Get the native (original) width of the display in pixels.
|
||||||
|
int get_native_width() { return this->get_width_internal(); }
|
||||||
|
/// Get the native (original) height of the display in pixels.
|
||||||
|
int get_native_height() { return this->get_height_internal(); }
|
||||||
|
|
||||||
/// Set a single pixel at the specified coordinates to default color.
|
/// Set a single pixel at the specified coordinates to default color.
|
||||||
inline void draw_pixel_at(int x, int y) { this->draw_pixel_at(x, y, COLOR_ON); }
|
inline void draw_pixel_at(int x, int y) { this->draw_pixel_at(x, y, COLOR_ON); }
|
||||||
|
@ -538,6 +543,9 @@ class Display : public PollingComponent {
|
||||||
void do_update_();
|
void do_update_();
|
||||||
void clear_clipping_();
|
void clear_clipping_();
|
||||||
|
|
||||||
|
virtual int get_height_internal() = 0;
|
||||||
|
virtual int get_width_internal() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method fills a triangle using only integer variables by using a
|
* This method fills a triangle using only integer variables by using a
|
||||||
* modified bresenham algorithm.
|
* modified bresenham algorithm.
|
||||||
|
|
|
@ -22,9 +22,6 @@ class DisplayBuffer : public Display {
|
||||||
/// Set a single pixel at the specified coordinates to the given color.
|
/// Set a single pixel at the specified coordinates to the given color.
|
||||||
void draw_pixel_at(int x, int y, Color color) override;
|
void draw_pixel_at(int x, int y, Color color) override;
|
||||||
|
|
||||||
virtual int get_height_internal() = 0;
|
|
||||||
virtual int get_width_internal() = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void draw_absolute_pixel_internal(int x, int y, Color color) = 0;
|
virtual void draw_absolute_pixel_internal(int x, int y, Color color) = 0;
|
||||||
|
|
||||||
|
|
|
@ -34,24 +34,27 @@ void EKTF2232Touchscreen::setup() {
|
||||||
|
|
||||||
// Get touch resolution
|
// Get touch resolution
|
||||||
uint8_t received[4];
|
uint8_t received[4];
|
||||||
this->write(GET_X_RES, 4);
|
if (this->x_raw_max_ == this->x_raw_min_) {
|
||||||
if (this->read(received, 4)) {
|
this->write(GET_X_RES, 4);
|
||||||
ESP_LOGE(TAG, "Failed to read X resolution!");
|
if (this->read(received, 4)) {
|
||||||
this->interrupt_pin_->detach_interrupt();
|
ESP_LOGE(TAG, "Failed to read X resolution!");
|
||||||
this->mark_failed();
|
this->interrupt_pin_->detach_interrupt();
|
||||||
return;
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->x_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4);
|
||||||
}
|
}
|
||||||
this->x_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4);
|
|
||||||
|
|
||||||
this->write(GET_Y_RES, 4);
|
if (this->y_raw_max_ == this->y_raw_min_) {
|
||||||
if (this->read(received, 4)) {
|
this->write(GET_Y_RES, 4);
|
||||||
ESP_LOGE(TAG, "Failed to read Y resolution!");
|
if (this->read(received, 4)) {
|
||||||
this->interrupt_pin_->detach_interrupt();
|
ESP_LOGE(TAG, "Failed to read Y resolution!");
|
||||||
this->mark_failed();
|
this->interrupt_pin_->detach_interrupt();
|
||||||
return;
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->y_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4);
|
||||||
}
|
}
|
||||||
this->y_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4);
|
|
||||||
|
|
||||||
this->set_power_state(true);
|
this->set_power_state(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,14 @@ class FT5x06Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// reading the chip registers to get max x/y does not seem to work.
|
// reading the chip registers to get max x/y does not seem to work.
|
||||||
this->x_raw_max_ = this->display_->get_width();
|
if (this->display_ != nullptr) {
|
||||||
this->y_raw_max_ = this->display_->get_height();
|
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->x_raw_max_ = this->display_->get_native_height();
|
||||||
|
}
|
||||||
|
}
|
||||||
esph_log_config(TAG, "FT5x06 Touchscreen setup complete");
|
esph_log_config(TAG, "FT5x06 Touchscreen setup complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,21 +12,23 @@
|
||||||
// Reference: https://focuslcds.com/content/FT6236.pdf
|
// Reference: https://focuslcds.com/content/FT6236.pdf
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ft63x6 {
|
namespace ft63x6 {
|
||||||
|
static const uint8_t FT6X36_ADDR_DEVICE_MODE = 0x00;
|
||||||
|
|
||||||
|
static const uint8_t FT63X6_ADDR_TD_STATUS = 0x02;
|
||||||
static const uint8_t FT63X6_ADDR_TOUCH1_STATE = 0x03;
|
static const uint8_t FT63X6_ADDR_TOUCH1_STATE = 0x03;
|
||||||
static const uint8_t FT63X6_ADDR_TOUCH1_X = 0x03;
|
static const uint8_t FT63X6_ADDR_TOUCH1_X = 0x03;
|
||||||
static const uint8_t FT63X6_ADDR_TOUCH1_ID = 0x05;
|
static const uint8_t FT63X6_ADDR_TOUCH1_ID = 0x05;
|
||||||
static const uint8_t FT63X6_ADDR_TOUCH1_Y = 0x05;
|
static const uint8_t FT63X6_ADDR_TOUCH1_Y = 0x05;
|
||||||
|
static const uint8_t FT63X6_ADDR_TOUCH1_WEIGHT = 0x07;
|
||||||
|
static const uint8_t FT63X6_ADDR_TOUCH1_MISC = 0x08;
|
||||||
|
static const uint8_t FT6X36_ADDR_THRESHHOLD = 0x80;
|
||||||
|
static const uint8_t FT6X36_ADDR_TOUCHRATE_ACTIVE = 0x88;
|
||||||
|
static const uint8_t FT63X6_ADDR_CHIP_ID = 0xA3;
|
||||||
|
|
||||||
static const uint8_t FT63X6_ADDR_TOUCH2_STATE = 0x09;
|
static const char *const TAG = "FT63X6";
|
||||||
static const uint8_t FT63X6_ADDR_TOUCH2_X = 0x09;
|
|
||||||
static const uint8_t FT63X6_ADDR_TOUCH2_ID = 0x0B;
|
|
||||||
static const uint8_t FT63X6_ADDR_TOUCH2_Y = 0x0B;
|
|
||||||
|
|
||||||
static const char *const TAG = "FT63X6Touchscreen";
|
|
||||||
|
|
||||||
void FT63X6Touchscreen::setup() {
|
void FT63X6Touchscreen::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Setting up FT63X6Touchscreen Touchscreen...");
|
ESP_LOGCONFIG(TAG, "Setting up FT63X6 Touchscreen...");
|
||||||
if (this->interrupt_pin_ != nullptr) {
|
if (this->interrupt_pin_ != nullptr) {
|
||||||
this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
|
this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
|
||||||
this->interrupt_pin_->setup();
|
this->interrupt_pin_->setup();
|
||||||
|
@ -35,10 +37,9 @@ void FT63X6Touchscreen::setup() {
|
||||||
|
|
||||||
if (this->reset_pin_ != nullptr) {
|
if (this->reset_pin_ != nullptr) {
|
||||||
this->reset_pin_->setup();
|
this->reset_pin_->setup();
|
||||||
|
this->hard_reset_();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->hard_reset_();
|
|
||||||
|
|
||||||
// Get touch resolution
|
// Get touch resolution
|
||||||
if (this->x_raw_max_ == this->x_raw_min_) {
|
if (this->x_raw_max_ == this->x_raw_min_) {
|
||||||
this->x_raw_max_ = 320;
|
this->x_raw_max_ = 320;
|
||||||
|
@ -46,6 +47,15 @@ void FT63X6Touchscreen::setup() {
|
||||||
if (this->y_raw_max_ == this->y_raw_min_) {
|
if (this->y_raw_max_ == this->y_raw_min_) {
|
||||||
this->y_raw_max_ = 480;
|
this->y_raw_max_ = 480;
|
||||||
}
|
}
|
||||||
|
uint8_t chip_id = this->read_byte_(FT63X6_ADDR_CHIP_ID);
|
||||||
|
if (chip_id != 0) {
|
||||||
|
ESP_LOGI(TAG, "FT6336U touch driver started chipid: %d", chip_id);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "FT6336U touch driver failed to start");
|
||||||
|
}
|
||||||
|
this->write_byte(FT6X36_ADDR_DEVICE_MODE, 0x00);
|
||||||
|
this->write_byte(FT6X36_ADDR_THRESHHOLD, this->threshold_);
|
||||||
|
this->write_byte(FT6X36_ADDR_TOUCHRATE_ACTIVE, 0x0E);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FT63X6Touchscreen::hard_reset_() {
|
void FT63X6Touchscreen::hard_reset_() {
|
||||||
|
@ -65,28 +75,61 @@ void FT63X6Touchscreen::dump_config() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FT63X6Touchscreen::update_touches() {
|
void FT63X6Touchscreen::update_touches() {
|
||||||
uint8_t data[15];
|
|
||||||
uint16_t touch_id, x, y;
|
uint16_t touch_id, x, y;
|
||||||
|
|
||||||
if (!this->read_bytes(0x00, (uint8_t *) data, 15)) {
|
uint8_t touches = this->read_touch_number_();
|
||||||
ESP_LOGE(TAG, "Failed to read touch data");
|
if ((touches == 0x00) || (touches == 0xff)) {
|
||||||
this->skip_update_ = true;
|
// ESP_LOGD(TAG, "No touches detected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((data[FT63X6_ADDR_TOUCH1_STATE] >> 6) & 0x01) == 0) {
|
ESP_LOGV(TAG, "Touches found: %d", touches);
|
||||||
touch_id = data[FT63X6_ADDR_TOUCH1_ID] >> 4; // id1 = 0 or 1
|
|
||||||
x = encode_uint16(data[FT63X6_ADDR_TOUCH1_X] & 0x0F, data[FT63X6_ADDR_TOUCH1_X + 1]);
|
for (auto point = 0; point < touches; point++) {
|
||||||
y = encode_uint16(data[FT63X6_ADDR_TOUCH1_Y] & 0x0F, data[FT63X6_ADDR_TOUCH1_Y + 1]);
|
if (((this->read_touch_event_(point)) & 0x01) == 0) { // checking event flag bit 6 if it is null
|
||||||
this->add_raw_touch_position_(touch_id, x, y);
|
touch_id = this->read_touch_id_(point); // id1 = 0 or 1
|
||||||
}
|
x = this->read_touch_x_(point);
|
||||||
if (((data[FT63X6_ADDR_TOUCH2_STATE] >> 6) & 0x01) == 0) {
|
y = this->read_touch_y_(point);
|
||||||
touch_id = data[FT63X6_ADDR_TOUCH2_ID] >> 4; // id1 = 0 or 1
|
if ((x == 0) && (y == 0)) {
|
||||||
x = encode_uint16(data[FT63X6_ADDR_TOUCH2_X] & 0x0F, data[FT63X6_ADDR_TOUCH2_X + 1]);
|
ESP_LOGW(TAG, "Reporting a (0,0) touch on %d", touch_id);
|
||||||
y = encode_uint16(data[FT63X6_ADDR_TOUCH2_Y] & 0x0F, data[FT63X6_ADDR_TOUCH2_Y + 1]);
|
}
|
||||||
this->add_raw_touch_position_(touch_id, x, y);
|
this->add_raw_touch_position_(touch_id, x, y, this->read_touch_weight_(point));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t FT63X6Touchscreen::read_touch_number_() { return this->read_byte_(FT63X6_ADDR_TD_STATUS) & 0x0F; }
|
||||||
|
// Touch 1 functions
|
||||||
|
uint16_t FT63X6Touchscreen::read_touch_x_(uint8_t touch) {
|
||||||
|
uint8_t read_buf[2];
|
||||||
|
read_buf[0] = this->read_byte_(FT63X6_ADDR_TOUCH1_X + (touch * 6));
|
||||||
|
read_buf[1] = this->read_byte_(FT63X6_ADDR_TOUCH1_X + 1 + (touch * 6));
|
||||||
|
return ((read_buf[0] & 0x0f) << 8) | read_buf[1];
|
||||||
|
}
|
||||||
|
uint16_t FT63X6Touchscreen::read_touch_y_(uint8_t touch) {
|
||||||
|
uint8_t read_buf[2];
|
||||||
|
read_buf[0] = this->read_byte_(FT63X6_ADDR_TOUCH1_Y + (touch * 6));
|
||||||
|
read_buf[1] = this->read_byte_(FT63X6_ADDR_TOUCH1_Y + 1 + (touch * 6));
|
||||||
|
return ((read_buf[0] & 0x0f) << 8) | read_buf[1];
|
||||||
|
}
|
||||||
|
uint8_t FT63X6Touchscreen::read_touch_event_(uint8_t touch) {
|
||||||
|
return this->read_byte_(FT63X6_ADDR_TOUCH1_X + (touch * 6)) >> 6;
|
||||||
|
}
|
||||||
|
uint8_t FT63X6Touchscreen::read_touch_id_(uint8_t touch) {
|
||||||
|
return this->read_byte_(FT63X6_ADDR_TOUCH1_ID + (touch * 6)) >> 4;
|
||||||
|
}
|
||||||
|
uint8_t FT63X6Touchscreen::read_touch_weight_(uint8_t touch) {
|
||||||
|
return this->read_byte_(FT63X6_ADDR_TOUCH1_WEIGHT + (touch * 6));
|
||||||
|
}
|
||||||
|
uint8_t FT63X6Touchscreen::read_touch_misc_(uint8_t touch) {
|
||||||
|
return this->read_byte_(FT63X6_ADDR_TOUCH1_MISC + (touch * 6)) >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t FT63X6Touchscreen::read_byte_(uint8_t addr) {
|
||||||
|
uint8_t byte = 0;
|
||||||
|
this->read_byte(addr, &byte);
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ft63x6
|
} // namespace ft63x6
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -16,6 +16,8 @@ namespace ft63x6 {
|
||||||
|
|
||||||
using namespace touchscreen;
|
using namespace touchscreen;
|
||||||
|
|
||||||
|
static const uint8_t FT6X36_DEFAULT_THRESHOLD = 22;
|
||||||
|
|
||||||
class FT63X6Touchscreen : public Touchscreen, public i2c::I2CDevice {
|
class FT63X6Touchscreen : public Touchscreen, public i2c::I2CDevice {
|
||||||
public:
|
public:
|
||||||
void setup() override;
|
void setup() override;
|
||||||
|
@ -23,18 +25,26 @@ class FT63X6Touchscreen : public Touchscreen, public i2c::I2CDevice {
|
||||||
|
|
||||||
void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
|
void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
|
||||||
void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; }
|
void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; }
|
||||||
|
void set_threshold(uint8_t threshold) { this->threshold_ = threshold; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void hard_reset_();
|
void hard_reset_();
|
||||||
uint8_t read_byte_(uint8_t addr);
|
|
||||||
void update_touches() override;
|
void update_touches() override;
|
||||||
|
|
||||||
InternalGPIOPin *interrupt_pin_{nullptr};
|
InternalGPIOPin *interrupt_pin_{nullptr};
|
||||||
GPIOPin *reset_pin_{nullptr};
|
GPIOPin *reset_pin_{nullptr};
|
||||||
|
uint8_t threshold_{FT6X36_DEFAULT_THRESHOLD};
|
||||||
|
|
||||||
uint8_t read_touch_count_();
|
uint8_t read_touch_number_();
|
||||||
uint16_t read_touch_coordinate_(uint8_t coordinate);
|
|
||||||
uint8_t read_touch_id_(uint8_t id_address);
|
uint16_t read_touch_x_(uint8_t touch);
|
||||||
|
uint16_t read_touch_y_(uint8_t touch);
|
||||||
|
uint8_t read_touch_event_(uint8_t touch);
|
||||||
|
uint8_t read_touch_id_(uint8_t touch);
|
||||||
|
uint8_t read_touch_weight_(uint8_t touch);
|
||||||
|
uint8_t read_touch_misc_(uint8_t touch);
|
||||||
|
|
||||||
|
uint8_t read_byte_(uint8_t addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ft63x6
|
} // namespace ft63x6
|
||||||
|
|
|
@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
||||||
|
|
||||||
from esphome import pins
|
from esphome import pins
|
||||||
from esphome.components import i2c, touchscreen
|
from esphome.components import i2c, touchscreen
|
||||||
from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN
|
from esphome.const import CONF_ID, CONF_INTERRUPT_PIN, CONF_RESET_PIN, CONF_THRESHOLD
|
||||||
|
|
||||||
CODEOWNERS = ["@gpambrozio"]
|
CODEOWNERS = ["@gpambrozio"]
|
||||||
DEPENDENCIES = ["i2c"]
|
DEPENDENCIES = ["i2c"]
|
||||||
|
@ -26,6 +26,7 @@ CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend(
|
||||||
pins.internal_gpio_input_pin_schema
|
pins.internal_gpio_input_pin_schema
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||||
|
cv.Optional(CONF_THRESHOLD): cv.uint8_t,
|
||||||
}
|
}
|
||||||
).extend(i2c.i2c_device_schema(0x38))
|
).extend(i2c.i2c_device_schema(0x38))
|
||||||
)
|
)
|
||||||
|
|
|
@ -48,9 +48,13 @@ void GT911Touchscreen::setup() {
|
||||||
if (err == i2c::ERROR_OK) {
|
if (err == i2c::ERROR_OK) {
|
||||||
err = this->read(data, sizeof(data));
|
err = this->read(data, sizeof(data));
|
||||||
if (err == i2c::ERROR_OK) {
|
if (err == i2c::ERROR_OK) {
|
||||||
this->x_raw_max_ = encode_uint16(data[1], data[0]);
|
if (this->x_raw_max_ == this->x_raw_min_) {
|
||||||
this->y_raw_max_ = encode_uint16(data[3], data[2]);
|
this->x_raw_max_ = encode_uint16(data[1], data[0]);
|
||||||
esph_log_d(TAG, "Read max_x/max_y %d/%d", this->x_raw_max_, this->y_raw_max_);
|
}
|
||||||
|
if (this->y_raw_max_ == this->y_raw_min_) {
|
||||||
|
this->y_raw_max_ = encode_uint16(data[3], data[2]);
|
||||||
|
}
|
||||||
|
esph_log_d(TAG, "calibration max_x/max_y %d/%d", this->x_raw_max_, this->y_raw_max_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,14 @@ void LilygoT547Touchscreen::setup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
this->write_register(POWER_REGISTER, WAKEUP_CMD, 1);
|
this->write_register(POWER_REGISTER, WAKEUP_CMD, 1);
|
||||||
|
if (this->display_ != nullptr) {
|
||||||
this->x_raw_max_ = this->get_width_();
|
if (this->x_raw_max_ == this->x_raw_min_) {
|
||||||
this->y_raw_max_ = this->get_height_();
|
this->x_raw_max_ = this->display_->get_native_width();
|
||||||
|
}
|
||||||
|
if (this->y_raw_max_ == this->y_raw_min_) {
|
||||||
|
this->x_raw_max_ = this->display_->get_native_height();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LilygoT547Touchscreen::update_touches() {
|
void LilygoT547Touchscreen::update_touches() {
|
||||||
|
|
|
@ -3,14 +3,17 @@ import esphome.codegen as cg
|
||||||
|
|
||||||
from esphome.components import display
|
from esphome.components import display
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
|
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ON_TOUCH,
|
CONF_ON_TOUCH,
|
||||||
CONF_ON_RELEASE,
|
CONF_ON_RELEASE,
|
||||||
|
CONF_SWAP_XY,
|
||||||
CONF_MIRROR_X,
|
CONF_MIRROR_X,
|
||||||
CONF_MIRROR_Y,
|
CONF_MIRROR_Y,
|
||||||
CONF_SWAP_XY,
|
|
||||||
CONF_TRANSFORM,
|
CONF_TRANSFORM,
|
||||||
|
CONF_CALIBRATION,
|
||||||
)
|
)
|
||||||
|
|
||||||
from esphome.core import coroutine_with_priority
|
from esphome.core import coroutine_with_priority
|
||||||
|
|
||||||
CODEOWNERS = ["@jesserockz", "@nielsnl68"]
|
CODEOWNERS = ["@jesserockz", "@nielsnl68"]
|
||||||
|
@ -34,6 +37,56 @@ CONF_ON_UPDATE = "on_update"
|
||||||
CONF_TOUCH_TIMEOUT = "touch_timeout"
|
CONF_TOUCH_TIMEOUT = "touch_timeout"
|
||||||
|
|
||||||
|
|
||||||
|
CONF_X_MIN = "x_min"
|
||||||
|
CONF_X_MAX = "x_max"
|
||||||
|
CONF_Y_MIN = "y_min"
|
||||||
|
CONF_Y_MAX = "y_max"
|
||||||
|
|
||||||
|
|
||||||
|
def validate_calibration(config):
|
||||||
|
if CONF_CALIBRATION in config:
|
||||||
|
calibration_config = config[CONF_CALIBRATION]
|
||||||
|
if (
|
||||||
|
cv.int_([CONF_X_MIN]) != 0
|
||||||
|
and cv.int_(calibration_config[CONF_X_MAX]) != 0
|
||||||
|
and abs(
|
||||||
|
cv.int_(calibration_config[CONF_X_MIN])
|
||||||
|
- cv.int_(calibration_config[CONF_X_MAX])
|
||||||
|
)
|
||||||
|
< 10
|
||||||
|
):
|
||||||
|
raise cv.Invalid("Calibration X values difference must be more than 10")
|
||||||
|
|
||||||
|
if (
|
||||||
|
cv.int_(calibration_config[CONF_Y_MIN]) != 0
|
||||||
|
and cv.int_(calibration_config[CONF_Y_MAX]) != 0
|
||||||
|
and abs(
|
||||||
|
cv.int_(calibration_config[CONF_Y_MIN])
|
||||||
|
- cv.int_(calibration_config[CONF_Y_MAX])
|
||||||
|
)
|
||||||
|
< 10
|
||||||
|
):
|
||||||
|
raise cv.Invalid("Calibration Y values difference must be more than 10")
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def calibration_schema(default_max_values):
|
||||||
|
return cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_X_MIN, default=0): cv.int_range(min=0, max=4095),
|
||||||
|
cv.Optional(CONF_X_MAX, default=default_max_values): cv.int_range(
|
||||||
|
min=0, max=4095
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_Y_MIN, default=0): cv.int_range(min=0, max=4095),
|
||||||
|
cv.Optional(CONF_Y_MAX, default=default_max_values): cv.int_range(
|
||||||
|
min=0, max=4095
|
||||||
|
),
|
||||||
|
},
|
||||||
|
validate_calibration,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def touchscreen_schema(default_touch_timeout):
|
def touchscreen_schema(default_touch_timeout):
|
||||||
return cv.Schema(
|
return cv.Schema(
|
||||||
{
|
{
|
||||||
|
@ -49,6 +102,7 @@ def touchscreen_schema(default_touch_timeout):
|
||||||
cv.positive_time_period_milliseconds,
|
cv.positive_time_period_milliseconds,
|
||||||
cv.Range(max=cv.TimePeriod(milliseconds=65535)),
|
cv.Range(max=cv.TimePeriod(milliseconds=65535)),
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_CALIBRATION): calibration_schema(0),
|
||||||
cv.Optional(CONF_ON_TOUCH): automation.validate_automation(single=True),
|
cv.Optional(CONF_ON_TOUCH): automation.validate_automation(single=True),
|
||||||
cv.Optional(CONF_ON_UPDATE): automation.validate_automation(single=True),
|
cv.Optional(CONF_ON_UPDATE): automation.validate_automation(single=True),
|
||||||
cv.Optional(CONF_ON_RELEASE): automation.validate_automation(single=True),
|
cv.Optional(CONF_ON_RELEASE): automation.validate_automation(single=True),
|
||||||
|
@ -74,6 +128,17 @@ async def register_touchscreen(var, config):
|
||||||
cg.add(var.set_mirror_x(transform[CONF_MIRROR_X]))
|
cg.add(var.set_mirror_x(transform[CONF_MIRROR_X]))
|
||||||
cg.add(var.set_mirror_y(transform[CONF_MIRROR_Y]))
|
cg.add(var.set_mirror_y(transform[CONF_MIRROR_Y]))
|
||||||
|
|
||||||
|
if CONF_CALIBRATION in config:
|
||||||
|
calibration_config = config[CONF_CALIBRATION]
|
||||||
|
cg.add(
|
||||||
|
var.set_calibration(
|
||||||
|
calibration_config[CONF_X_MIN],
|
||||||
|
calibration_config[CONF_X_MAX],
|
||||||
|
calibration_config[CONF_Y_MIN],
|
||||||
|
calibration_config[CONF_Y_MAX],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if CONF_ON_TOUCH in config:
|
if CONF_ON_TOUCH in config:
|
||||||
await automation.build_automation(
|
await automation.build_automation(
|
||||||
var.get_touch_trigger(),
|
var.get_touch_trigger(),
|
||||||
|
|
|
@ -13,6 +13,15 @@ void Touchscreen::attach_interrupt_(InternalGPIOPin *irq_pin, esphome::gpio::Int
|
||||||
irq_pin->attach_interrupt(TouchscreenInterrupt::gpio_intr, &this->store_, type);
|
irq_pin->attach_interrupt(TouchscreenInterrupt::gpio_intr, &this->store_, type);
|
||||||
this->store_.init = true;
|
this->store_.init = true;
|
||||||
this->store_.touched = false;
|
this->store_.touched = false;
|
||||||
|
ESP_LOGD(TAG, "Attach Touch Interupt");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Touchscreen::call_setup() {
|
||||||
|
if (this->display_ != nullptr) {
|
||||||
|
this->display_width_ = this->display_->get_native_width();
|
||||||
|
this->display_height_ = this->display_->get_native_height();
|
||||||
|
}
|
||||||
|
PollingComponent::call_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Touchscreen::update() {
|
void Touchscreen::update() {
|
||||||
|
@ -20,19 +29,22 @@ void Touchscreen::update() {
|
||||||
this->store_.touched = true;
|
this->store_.touched = true;
|
||||||
} else {
|
} else {
|
||||||
// no need to poll if we have interrupts.
|
// no need to poll if we have interrupts.
|
||||||
|
ESP_LOGW(TAG, "Touch Polling Stopped. You can safely remove the 'update_interval:' variable from the YAML file.");
|
||||||
this->stop_poller();
|
this->stop_poller();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Touchscreen::loop() {
|
void Touchscreen::loop() {
|
||||||
if (this->store_.touched) {
|
if (this->store_.touched) {
|
||||||
|
ESP_LOGVV(TAG, "<< Do Touch loop >>");
|
||||||
this->first_touch_ = this->touches_.empty();
|
this->first_touch_ = this->touches_.empty();
|
||||||
this->need_update_ = false;
|
this->need_update_ = false;
|
||||||
|
this->was_touched_ = this->is_touched_;
|
||||||
this->is_touched_ = false;
|
this->is_touched_ = false;
|
||||||
this->skip_update_ = false;
|
this->skip_update_ = false;
|
||||||
for (auto &tp : this->touches_) {
|
for (auto &tp : this->touches_) {
|
||||||
if (tp.second.state == STATE_PRESSED || tp.second.state == STATE_UPDATED) {
|
if (tp.second.state == STATE_PRESSED || tp.second.state == STATE_UPDATED) {
|
||||||
tp.second.state = tp.second.state | STATE_RELEASING;
|
tp.second.state |= STATE_RELEASING;
|
||||||
} else {
|
} else {
|
||||||
tp.second.state = STATE_RELEASED;
|
tp.second.state = STATE_RELEASED;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +54,7 @@ void Touchscreen::loop() {
|
||||||
this->update_touches();
|
this->update_touches();
|
||||||
if (this->skip_update_) {
|
if (this->skip_update_) {
|
||||||
for (auto &tp : this->touches_) {
|
for (auto &tp : this->touches_) {
|
||||||
tp.second.state = tp.second.state & -STATE_RELEASING;
|
tp.second.state &= ~STATE_RELEASING;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this->store_.touched = false;
|
this->store_.touched = false;
|
||||||
|
@ -65,21 +77,25 @@ void Touchscreen::add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_r
|
||||||
} else {
|
} else {
|
||||||
tp = this->touches_[id];
|
tp = this->touches_[id];
|
||||||
tp.state = STATE_UPDATED;
|
tp.state = STATE_UPDATED;
|
||||||
|
tp.y_prev = tp.y;
|
||||||
|
tp.x_prev = tp.x;
|
||||||
}
|
}
|
||||||
tp.x_raw = x_raw;
|
tp.x_raw = x_raw;
|
||||||
tp.y_raw = y_raw;
|
tp.y_raw = y_raw;
|
||||||
tp.z_raw = z_raw;
|
tp.z_raw = z_raw;
|
||||||
|
if (this->x_raw_max_ != this->x_raw_min_ and this->y_raw_max_ != this->y_raw_min_) {
|
||||||
|
x = this->normalize_(x_raw, this->x_raw_min_, this->x_raw_max_, this->invert_x_);
|
||||||
|
y = this->normalize_(y_raw, this->y_raw_min_, this->y_raw_max_, this->invert_y_);
|
||||||
|
|
||||||
x = this->normalize_(x_raw, this->x_raw_min_, this->x_raw_max_, this->invert_x_);
|
if (this->swap_x_y_) {
|
||||||
y = this->normalize_(y_raw, this->y_raw_min_, this->y_raw_max_, this->invert_y_);
|
std::swap(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->swap_x_y_) {
|
tp.x = (uint16_t) ((int) x * this->display_width_ / 0x1000);
|
||||||
std::swap(x, y);
|
tp.y = (uint16_t) ((int) y * this->display_height_ / 0x1000);
|
||||||
|
} else {
|
||||||
|
tp.state |= STATE_CALIBRATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
tp.x = (uint16_t) ((int) x * this->get_width_() / 0x1000);
|
|
||||||
tp.y = (uint16_t) ((int) y * this->get_height_() / 0x1000);
|
|
||||||
|
|
||||||
if (tp.state == STATE_PRESSED) {
|
if (tp.state == STATE_PRESSED) {
|
||||||
tp.x_org = tp.x;
|
tp.x_org = tp.x;
|
||||||
tp.y_org = tp.y;
|
tp.y_org = tp.y;
|
||||||
|
@ -94,19 +110,30 @@ void Touchscreen::add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_r
|
||||||
}
|
}
|
||||||
|
|
||||||
void Touchscreen::send_touches_() {
|
void Touchscreen::send_touches_() {
|
||||||
|
TouchPoints_t touches;
|
||||||
|
for (auto tp : this->touches_) {
|
||||||
|
ESP_LOGV(TAG, "Touch status: %d/%d: raw:(%4d,%4d,%4d) calc:(%3d,%4d)", tp.second.id, tp.second.state,
|
||||||
|
tp.second.x_raw, tp.second.y_raw, tp.second.z_raw, tp.second.x, tp.second.y);
|
||||||
|
touches.push_back(tp.second);
|
||||||
|
}
|
||||||
|
if (this->need_update_ || (!this->is_touched_ && this->was_touched_)) {
|
||||||
|
this->update_trigger_.trigger(touches);
|
||||||
|
for (auto *listener : this->touch_listeners_) {
|
||||||
|
listener->update(touches);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!this->is_touched_) {
|
if (!this->is_touched_) {
|
||||||
if (this->touch_timeout_ > 0) {
|
if (this->was_touched_) {
|
||||||
this->cancel_timeout(TAG);
|
if (this->touch_timeout_ > 0) {
|
||||||
|
this->cancel_timeout(TAG);
|
||||||
|
}
|
||||||
|
this->release_trigger_.trigger();
|
||||||
|
for (auto *listener : this->touch_listeners_)
|
||||||
|
listener->release();
|
||||||
|
this->touches_.clear();
|
||||||
|
this->was_touched_ = false;
|
||||||
}
|
}
|
||||||
this->release_trigger_.trigger();
|
|
||||||
for (auto *listener : this->touch_listeners_)
|
|
||||||
listener->release();
|
|
||||||
this->touches_.clear();
|
|
||||||
} else {
|
} else {
|
||||||
TouchPoints_t touches;
|
|
||||||
for (auto tp : this->touches_) {
|
|
||||||
touches.push_back(tp.second);
|
|
||||||
}
|
|
||||||
if (this->first_touch_) {
|
if (this->first_touch_) {
|
||||||
TouchPoint tp = this->touches_.begin()->second;
|
TouchPoint tp = this->touches_.begin()->second;
|
||||||
this->touch_trigger_.trigger(tp, touches);
|
this->touch_trigger_.trigger(tp, touches);
|
||||||
|
@ -114,12 +141,6 @@ void Touchscreen::send_touches_() {
|
||||||
listener->touch(tp);
|
listener->touch(tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this->need_update_) {
|
|
||||||
this->update_trigger_.trigger(touches);
|
|
||||||
for (auto *listener : this->touch_listeners_) {
|
|
||||||
listener->update(touches);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ static const uint8_t STATE_RELEASED = 0x00;
|
||||||
static const uint8_t STATE_PRESSED = 0x01;
|
static const uint8_t STATE_PRESSED = 0x01;
|
||||||
static const uint8_t STATE_UPDATED = 0x02;
|
static const uint8_t STATE_UPDATED = 0x02;
|
||||||
static const uint8_t STATE_RELEASING = 0x04;
|
static const uint8_t STATE_RELEASING = 0x04;
|
||||||
|
static const uint8_t STATE_CALIBRATE = 0x07;
|
||||||
|
|
||||||
struct TouchPoint {
|
struct TouchPoint {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
|
@ -68,8 +69,6 @@ class Touchscreen : public PollingComponent {
|
||||||
|
|
||||||
void register_listener(TouchListener *listener) { this->touch_listeners_.push_back(listener); }
|
void register_listener(TouchListener *listener) { this->touch_listeners_.push_back(listener); }
|
||||||
|
|
||||||
virtual void update_touches() = 0;
|
|
||||||
|
|
||||||
optional<TouchPoint> get_touch() { return this->touches_.begin()->second; }
|
optional<TouchPoint> get_touch() { return this->touches_.begin()->second; }
|
||||||
|
|
||||||
TouchPoints_t get_touches() {
|
TouchPoints_t get_touches() {
|
||||||
|
@ -82,6 +81,7 @@ class Touchscreen : public PollingComponent {
|
||||||
|
|
||||||
void update() override;
|
void update() override;
|
||||||
void loop() override;
|
void loop() override;
|
||||||
|
void call_setup() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Call this function to send touch points to the `on_touch` listener and the binary_sensors.
|
/// Call this function to send touch points to the `on_touch` listener and the binary_sensors.
|
||||||
|
@ -90,17 +90,17 @@ class Touchscreen : public PollingComponent {
|
||||||
|
|
||||||
void add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw = 0);
|
void add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw = 0);
|
||||||
|
|
||||||
|
virtual void update_touches() = 0;
|
||||||
|
|
||||||
void send_touches_();
|
void send_touches_();
|
||||||
|
|
||||||
int16_t normalize_(int16_t val, int16_t min_val, int16_t max_val, bool inverted = false);
|
int16_t normalize_(int16_t val, int16_t min_val, int16_t max_val, bool inverted = false);
|
||||||
|
|
||||||
uint16_t get_width_() { return this->display_->get_width(); }
|
|
||||||
|
|
||||||
uint16_t get_height_() { return this->display_->get_height(); }
|
|
||||||
|
|
||||||
display::Display *display_{nullptr};
|
display::Display *display_{nullptr};
|
||||||
|
|
||||||
int16_t x_raw_min_{0}, x_raw_max_{0}, y_raw_min_{0}, y_raw_max_{0};
|
int16_t x_raw_min_{0}, x_raw_max_{0}, y_raw_min_{0}, y_raw_max_{0};
|
||||||
|
int16_t display_width_{0}, display_height_{0};
|
||||||
|
|
||||||
uint16_t touch_timeout_{0};
|
uint16_t touch_timeout_{0};
|
||||||
bool invert_x_{false}, invert_y_{false}, swap_x_y_{false};
|
bool invert_x_{false}, invert_y_{false}, swap_x_y_{false};
|
||||||
|
|
||||||
|
@ -115,6 +115,7 @@ class Touchscreen : public PollingComponent {
|
||||||
bool first_touch_{true};
|
bool first_touch_{true};
|
||||||
bool need_update_{false};
|
bool need_update_{false};
|
||||||
bool is_touched_{false};
|
bool is_touched_{false};
|
||||||
|
bool was_touched_{false};
|
||||||
bool skip_update_{false};
|
bool skip_update_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend(
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(TT21100Touchscreen),
|
cv.GenerateID(): cv.declare_id(TT21100Touchscreen),
|
||||||
cv.Required(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
|
cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
|
||||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||||
}
|
}
|
||||||
).extend(i2c.i2c_device_schema(0x24))
|
).extend(i2c.i2c_device_schema(0x24))
|
||||||
|
@ -32,8 +32,9 @@ async def to_code(config):
|
||||||
await touchscreen.register_touchscreen(var, config)
|
await touchscreen.register_touchscreen(var, config)
|
||||||
await i2c.register_i2c_device(var, config)
|
await i2c.register_i2c_device(var, config)
|
||||||
|
|
||||||
interrupt_pin = await cg.gpio_pin_expression(config[CONF_INTERRUPT_PIN])
|
if CONF_INTERRUPT_PIN in config:
|
||||||
cg.add(var.set_interrupt_pin(interrupt_pin))
|
interrupt_pin = await cg.gpio_pin_expression(config[CONF_INTERRUPT_PIN])
|
||||||
|
cg.add(var.set_interrupt_pin(interrupt_pin))
|
||||||
|
|
||||||
if CONF_RESET_PIN in config:
|
if CONF_RESET_PIN in config:
|
||||||
rts_pin = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
|
rts_pin = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
|
||||||
|
|
|
@ -50,10 +50,11 @@ void TT21100Touchscreen::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Setting up TT21100 Touchscreen...");
|
ESP_LOGCONFIG(TAG, "Setting up TT21100 Touchscreen...");
|
||||||
|
|
||||||
// Register interrupt pin
|
// Register interrupt pin
|
||||||
this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
|
if (this->interrupt_pin_ != nullptr) {
|
||||||
this->interrupt_pin_->setup();
|
this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
|
||||||
|
this->interrupt_pin_->setup();
|
||||||
this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE);
|
this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE);
|
||||||
|
}
|
||||||
|
|
||||||
// Perform reset if necessary
|
// Perform reset if necessary
|
||||||
if (this->reset_pin_ != nullptr) {
|
if (this->reset_pin_ != nullptr) {
|
||||||
|
@ -62,8 +63,14 @@ void TT21100Touchscreen::setup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update display dimensions if they were updated during display setup
|
// Update display dimensions if they were updated during display setup
|
||||||
this->x_raw_max_ = this->get_width_();
|
if (this->display_ != nullptr) {
|
||||||
this->y_raw_max_ = this->get_height_();
|
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->x_raw_max_ = this->display_->get_native_height();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger initial read to activate the interrupt
|
// Trigger initial read to activate the interrupt
|
||||||
this->store_.touched = true;
|
this->store_.touched = true;
|
||||||
|
|
|
@ -15,35 +15,11 @@ XPT2046Component = XPT2046_ns.class_(
|
||||||
spi.SPIDevice,
|
spi.SPIDevice,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
CONF_CALIBRATION_X_MIN = "calibration_x_min"
|
CONF_CALIBRATION_X_MIN = "calibration_x_min"
|
||||||
CONF_CALIBRATION_X_MAX = "calibration_x_max"
|
CONF_CALIBRATION_X_MAX = "calibration_x_max"
|
||||||
CONF_CALIBRATION_Y_MIN = "calibration_y_min"
|
CONF_CALIBRATION_Y_MIN = "calibration_y_min"
|
||||||
CONF_CALIBRATION_Y_MAX = "calibration_y_max"
|
CONF_CALIBRATION_Y_MAX = "calibration_y_max"
|
||||||
|
|
||||||
|
|
||||||
def validate_xpt2046(config):
|
|
||||||
if (
|
|
||||||
abs(
|
|
||||||
cv.int_(config[CONF_CALIBRATION_X_MAX])
|
|
||||||
- cv.int_(config[CONF_CALIBRATION_X_MIN])
|
|
||||||
)
|
|
||||||
< 1000
|
|
||||||
):
|
|
||||||
raise cv.Invalid("Calibration X values difference < 1000")
|
|
||||||
|
|
||||||
if (
|
|
||||||
abs(
|
|
||||||
cv.int_(config[CONF_CALIBRATION_Y_MAX])
|
|
||||||
- cv.int_(config[CONF_CALIBRATION_Y_MIN])
|
|
||||||
)
|
|
||||||
< 1000
|
|
||||||
):
|
|
||||||
raise cv.Invalid("Calibration Y values difference < 1000")
|
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(
|
CONFIG_SCHEMA = cv.All(
|
||||||
touchscreen.TOUCHSCREEN_SCHEMA.extend(
|
touchscreen.TOUCHSCREEN_SCHEMA.extend(
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
|
@ -52,42 +28,41 @@ CONFIG_SCHEMA = cv.All(
|
||||||
cv.Optional(CONF_INTERRUPT_PIN): cv.All(
|
cv.Optional(CONF_INTERRUPT_PIN): cv.All(
|
||||||
pins.internal_gpio_input_pin_schema
|
pins.internal_gpio_input_pin_schema
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_CALIBRATION_X_MIN, default=0): cv.int_range(
|
|
||||||
min=0, max=4095
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_CALIBRATION_X_MAX, default=4095): cv.int_range(
|
|
||||||
min=0, max=4095
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_CALIBRATION_Y_MIN, default=0): cv.int_range(
|
|
||||||
min=0, max=4095
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_CALIBRATION_Y_MAX, default=4095): cv.int_range(
|
|
||||||
min=0, max=4095
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_THRESHOLD, default=400): cv.int_range(min=0, max=4095),
|
cv.Optional(CONF_THRESHOLD, default=400): cv.int_range(min=0, max=4095),
|
||||||
|
cv.Optional(
|
||||||
|
touchscreen.CONF_CALIBRATION
|
||||||
|
): touchscreen.calibration_schema(4095),
|
||||||
|
cv.Optional(CONF_CALIBRATION_X_MIN): cv.invalid(
|
||||||
|
"Deprecated: use the new 'calibration' configuration variable"
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CALIBRATION_X_MAX): cv.invalid(
|
||||||
|
"Deprecated: use the new 'calibration' configuration variable"
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CALIBRATION_Y_MIN): cv.invalid(
|
||||||
|
"Deprecated: use the new 'calibration' configuration variable"
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CALIBRATION_Y_MAX): cv.invalid(
|
||||||
|
"Deprecated: use the new 'calibration' configuration variable"
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CALIBRATION_Y_MAX): cv.invalid(
|
||||||
|
"Deprecated: use the new 'calibration' configuration variable"
|
||||||
|
),
|
||||||
|
cv.Optional("report_interval"): cv.invalid(
|
||||||
|
"Deprecated: use the 'update_interval' configuration variable"
|
||||||
|
),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
).extend(spi.spi_device_schema()),
|
).extend(spi.spi_device_schema()),
|
||||||
validate_xpt2046,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await touchscreen.register_touchscreen(var, config)
|
|
||||||
await spi.register_spi_device(var, config)
|
await spi.register_spi_device(var, config)
|
||||||
|
await touchscreen.register_touchscreen(var, config)
|
||||||
|
|
||||||
cg.add(var.set_threshold(config[CONF_THRESHOLD]))
|
cg.add(var.set_threshold(config[CONF_THRESHOLD]))
|
||||||
|
|
||||||
cg.add(
|
|
||||||
var.set_calibration(
|
|
||||||
config[CONF_CALIBRATION_X_MIN],
|
|
||||||
config[CONF_CALIBRATION_X_MAX],
|
|
||||||
config[CONF_CALIBRATION_Y_MIN],
|
|
||||||
config[CONF_CALIBRATION_Y_MAX],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if CONF_INTERRUPT_PIN in config:
|
if CONF_INTERRUPT_PIN in config:
|
||||||
pin = await cg.gpio_pin_expression(config[CONF_INTERRUPT_PIN])
|
pin = await cg.gpio_pin_expression(config[CONF_INTERRUPT_PIN])
|
||||||
cg.add(var.set_irq_pin(pin))
|
cg.add(var.set_irq_pin(pin))
|
||||||
|
|
|
@ -32,9 +32,8 @@ void XPT2046Component::update_touches() {
|
||||||
|
|
||||||
int16_t touch_pressure_1 = this->read_adc_(0xB1 /* touch_pressure_1 */);
|
int16_t touch_pressure_1 = this->read_adc_(0xB1 /* touch_pressure_1 */);
|
||||||
int16_t touch_pressure_2 = this->read_adc_(0xC1 /* touch_pressure_2 */);
|
int16_t touch_pressure_2 = this->read_adc_(0xC1 /* touch_pressure_2 */);
|
||||||
ESP_LOGVV(TAG, "touch_pressure %d, %d", touch_pressure_1, touch_pressure_2);
|
|
||||||
z_raw = touch_pressure_1 + 0Xfff - touch_pressure_2;
|
z_raw = touch_pressure_1 + 0Xfff - touch_pressure_2;
|
||||||
|
ESP_LOGVV(TAG, "Touchscreen Update z = %d", z_raw);
|
||||||
touch = (z_raw >= this->threshold_);
|
touch = (z_raw >= this->threshold_);
|
||||||
if (touch) {
|
if (touch) {
|
||||||
read_adc_(0xD1 /* X */); // dummy Y measure, 1st is always noisy
|
read_adc_(0xD1 /* X */); // dummy Y measure, 1st is always noisy
|
||||||
|
@ -53,7 +52,7 @@ void XPT2046Component::update_touches() {
|
||||||
x_raw = best_two_avg(data[1], data[3], data[5]);
|
x_raw = best_two_avg(data[1], data[3], data[5]);
|
||||||
y_raw = best_two_avg(data[0], data[2], data[4]);
|
y_raw = best_two_avg(data[0], data[2], data[4]);
|
||||||
|
|
||||||
ESP_LOGV(TAG, "Touchscreen Update [%d, %d], z = %d", x_raw, y_raw, z_raw);
|
ESP_LOGD(TAG, "Touchscreen Update [%d, %d], z = %d", x_raw, y_raw, z_raw);
|
||||||
|
|
||||||
this->add_raw_touch_position_(0, x_raw, y_raw, z_raw);
|
this->add_raw_touch_position_(0, x_raw, y_raw, z_raw);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +76,7 @@ void XPT2046Component::dump_config() {
|
||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
float XPT2046Component::get_setup_priority() const { return setup_priority::DATA; }
|
// float XPT2046Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
|
||||||
int16_t XPT2046Component::best_two_avg(int16_t value1, int16_t value2, int16_t value3) {
|
int16_t XPT2046Component::best_two_avg(int16_t value1, int16_t value2, int16_t value3) {
|
||||||
int16_t delta_a, delta_b, delta_c;
|
int16_t delta_a, delta_b, delta_c;
|
||||||
|
|
|
@ -23,7 +23,7 @@ class XPT2046Component : public Touchscreen,
|
||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
float get_setup_priority() const override;
|
// float get_setup_priority() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static int16_t best_two_avg(int16_t value1, int16_t value2, int16_t value3);
|
static int16_t best_two_avg(int16_t value1, int16_t value2, int16_t value3);
|
||||||
|
|
38
tests/components/ft63x6/test.esp32.yaml
Normal file
38
tests/components/ft63x6/test.esp32.yaml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
spi:
|
||||||
|
clk_pin: 14
|
||||||
|
mosi_pin: 13
|
||||||
|
|
||||||
|
i2c:
|
||||||
|
sda: GPIO18
|
||||||
|
scl: GPIO19
|
||||||
|
|
||||||
|
display:
|
||||||
|
- id: my_display
|
||||||
|
platform: ili9xxx
|
||||||
|
dimensions: 480x320
|
||||||
|
model: ST7796
|
||||||
|
cs_pin: 15
|
||||||
|
dc_pin: 21
|
||||||
|
reset_pin: 22
|
||||||
|
transform:
|
||||||
|
swap_xy: true
|
||||||
|
mirror_x: true
|
||||||
|
mirror_y: true
|
||||||
|
auto_clear_enabled: false
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: ft63x6
|
||||||
|
interrupt_pin: GPIO39
|
||||||
|
transform:
|
||||||
|
swap_xy: true
|
||||||
|
mirror_x: false
|
||||||
|
mirror_y: true
|
||||||
|
on_touch:
|
||||||
|
- logger.log:
|
||||||
|
format: tp touched
|
||||||
|
on_update:
|
||||||
|
- logger.log:
|
||||||
|
format: to updated
|
||||||
|
on_release:
|
||||||
|
- logger.log:
|
||||||
|
format: to released
|
43
tests/components/tt21100/test.esp32-s2.yaml
Normal file
43
tests/components/tt21100/test.esp32-s2.yaml
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
i2c:
|
||||||
|
sda: GPIO8
|
||||||
|
scl: GPIO18
|
||||||
|
|
||||||
|
spi:
|
||||||
|
clk_pin: 7
|
||||||
|
mosi_pin: 11
|
||||||
|
miso_pin: 9
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: ili9xxx
|
||||||
|
id: my_display
|
||||||
|
model: ili9341
|
||||||
|
cs_pin: 5
|
||||||
|
dc_pin: 12
|
||||||
|
reset_pin: 33
|
||||||
|
auto_clear_enabled: false
|
||||||
|
data_rate: 40MHz
|
||||||
|
dimensions: 320x240
|
||||||
|
update_interval: never
|
||||||
|
transform:
|
||||||
|
mirror_y: false
|
||||||
|
mirror_x: false
|
||||||
|
swap_xy: true
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: tt21100
|
||||||
|
address: 0x24
|
||||||
|
interrupt_pin: GPIO3
|
||||||
|
on_touch:
|
||||||
|
- logger.log: "Touchscreen:: Touched"
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: tt21100
|
||||||
|
index: 0
|
||||||
|
name: "Home"
|
||||||
|
|
||||||
|
- platform: touchscreen
|
||||||
|
name: FanLo
|
||||||
|
x_min: 0
|
||||||
|
x_max: 105
|
||||||
|
y_min: 0
|
||||||
|
y_max: 80
|
37
tests/components/xpt2046/test.esp32-s2.yaml
Normal file
37
tests/components/xpt2046/test.esp32-s2.yaml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
spi:
|
||||||
|
clk_pin: 7
|
||||||
|
mosi_pin: 11
|
||||||
|
miso_pin: 9
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: ili9xxx
|
||||||
|
id: my_display
|
||||||
|
model: ili9341
|
||||||
|
cs_pin: 5
|
||||||
|
dc_pin: 12
|
||||||
|
reset_pin: 33
|
||||||
|
auto_clear_enabled: false
|
||||||
|
data_rate: 40MHz
|
||||||
|
dimensions: 320x240
|
||||||
|
update_interval: never
|
||||||
|
transform:
|
||||||
|
mirror_y: false
|
||||||
|
mirror_x: false
|
||||||
|
swap_xy: true
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: xpt2046
|
||||||
|
display: my_display
|
||||||
|
id: my_toucher
|
||||||
|
update_interval: 50ms
|
||||||
|
cs_pin: 18
|
||||||
|
threshold: 300
|
||||||
|
calibration:
|
||||||
|
x_min: 210
|
||||||
|
x_max: 3890
|
||||||
|
y_min: 170
|
||||||
|
y_max: 3730
|
||||||
|
transform:
|
||||||
|
mirror_x: false
|
||||||
|
mirror_y: true
|
||||||
|
swap_xy: true
|
|
@ -976,10 +976,11 @@ touchscreen:
|
||||||
display: inkplate_display
|
display: inkplate_display
|
||||||
update_interval: 50ms
|
update_interval: 50ms
|
||||||
threshold: 400
|
threshold: 400
|
||||||
calibration_x_min: 3860
|
calibration:
|
||||||
calibration_x_max: 280
|
x_min: 3860
|
||||||
calibration_y_min: 340
|
x_max: 280
|
||||||
calibration_y_max: 3860
|
y_min: 340
|
||||||
|
y_max: 3860
|
||||||
on_touch:
|
on_touch:
|
||||||
- logger.log:
|
- logger.log:
|
||||||
format: Touch at (%d, %d)
|
format: Touch at (%d, %d)
|
||||||
|
|
Loading…
Reference in a new issue