Updating the touchscreen interface structure (#4596)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: NP v/d Spek <github_mail@lumensoft.nl> Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: Gustavo Ambrozio <gustavo@gustavo.eng.br>
This commit is contained in:
35 files changed
+997
-836
No files matched your search
@@ -7,27 +7,128 @@ namespace touchscreen {
|
||||
|
||||
static const char *const TAG = "touchscreen";
|
||||
|
||||
void Touchscreen::set_display(display::Display *display) {
|
||||
this->display_ = display;
|
||||
this->display_width_ = display->get_width();
|
||||
this->display_height_ = display->get_height();
|
||||
this->rotation_ = static_cast<TouchRotation>(display->get_rotation());
|
||||
void TouchscreenInterrupt::gpio_intr(TouchscreenInterrupt *store) { store->touched = true; }
|
||||
|
||||
if (this->rotation_ == ROTATE_90_DEGREES || this->rotation_ == ROTATE_270_DEGREES) {
|
||||
std::swap(this->display_width_, this->display_height_);
|
||||
void Touchscreen::attach_interrupt_(InternalGPIOPin *irq_pin, esphome::gpio::InterruptType type) {
|
||||
irq_pin->attach_interrupt(TouchscreenInterrupt::gpio_intr, &this->store_, type);
|
||||
this->store_.init = true;
|
||||
this->store_.touched = false;
|
||||
}
|
||||
|
||||
void Touchscreen::update() {
|
||||
if (!this->store_.init) {
|
||||
this->store_.touched = true;
|
||||
} else {
|
||||
// no need to poll if we have interrupts.
|
||||
this->stop_poller();
|
||||
}
|
||||
}
|
||||
|
||||
void Touchscreen::send_release_() {
|
||||
for (auto *listener : this->touch_listeners_)
|
||||
listener->release();
|
||||
void Touchscreen::loop() {
|
||||
if (this->store_.touched) {
|
||||
this->first_touch_ = this->touches_.empty();
|
||||
this->need_update_ = false;
|
||||
this->is_touched_ = false;
|
||||
this->skip_update_ = false;
|
||||
for (auto &tp : this->touches_) {
|
||||
if (tp.second.state == STATE_PRESSED || tp.second.state == STATE_UPDATED) {
|
||||
tp.second.state = tp.second.state | STATE_RELEASING;
|
||||
} else {
|
||||
tp.second.state = STATE_RELEASED;
|
||||
}
|
||||
tp.second.x_prev = tp.second.x;
|
||||
tp.second.y_prev = tp.second.y;
|
||||
}
|
||||
this->update_touches();
|
||||
if (this->skip_update_) {
|
||||
for (auto &tp : this->touches_) {
|
||||
tp.second.state = tp.second.state & -STATE_RELEASING;
|
||||
}
|
||||
} else {
|
||||
this->store_.touched = false;
|
||||
this->defer([this]() { this->send_touches_(); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Touchscreen::send_touch_(TouchPoint tp) {
|
||||
ESP_LOGV(TAG, "Touch (x=%d, y=%d)", tp.x, tp.y);
|
||||
this->touch_trigger_.trigger(tp);
|
||||
for (auto *listener : this->touch_listeners_)
|
||||
listener->touch(tp);
|
||||
void Touchscreen::set_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw) {
|
||||
TouchPoint tp;
|
||||
uint16_t x, y;
|
||||
if (this->touches_.count(id) == 0) {
|
||||
tp.state = STATE_PRESSED;
|
||||
tp.id = id;
|
||||
} else {
|
||||
tp = this->touches_[id];
|
||||
tp.state = STATE_UPDATED;
|
||||
}
|
||||
tp.x_raw = x_raw;
|
||||
tp.y_raw = y_raw;
|
||||
tp.z_raw = z_raw;
|
||||
|
||||
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_);
|
||||
|
||||
if (this->swap_x_y_) {
|
||||
std::swap(x, y);
|
||||
}
|
||||
|
||||
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) {
|
||||
tp.x_org = tp.x;
|
||||
tp.y_org = tp.y;
|
||||
}
|
||||
|
||||
this->touches_[id] = tp;
|
||||
|
||||
this->is_touched_ = true;
|
||||
if ((tp.x != tp.x_prev) || (tp.y != tp.y_prev)) {
|
||||
this->need_update_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Touchscreen::send_touches_() {
|
||||
if (!this->is_touched_) {
|
||||
this->release_trigger_.trigger();
|
||||
for (auto *listener : this->touch_listeners_)
|
||||
listener->release();
|
||||
this->touches_.clear();
|
||||
} else {
|
||||
TouchPoints_t touches;
|
||||
for (auto tp : this->touches_) {
|
||||
touches.push_back(tp.second);
|
||||
}
|
||||
if (this->first_touch_) {
|
||||
TouchPoint tp = this->touches_.begin()->second;
|
||||
this->touch_trigger_.trigger(tp, touches);
|
||||
for (auto *listener : this->touch_listeners_) {
|
||||
listener->touch(tp);
|
||||
}
|
||||
}
|
||||
if (this->need_update_) {
|
||||
this->update_trigger_.trigger(touches);
|
||||
for (auto *listener : this->touch_listeners_) {
|
||||
listener->update(touches);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t Touchscreen::normalize_(int16_t val, int16_t min_val, int16_t max_val, bool inverted) {
|
||||
int16_t ret;
|
||||
|
||||
if (val <= min_val) {
|
||||
ret = 0;
|
||||
} else if (val >= max_val) {
|
||||
ret = 0xfff;
|
||||
} else {
|
||||
ret = (int16_t) ((int) 0xfff * (val - min_val) / (max_val - min_val));
|
||||
}
|
||||
|
||||
ret = (inverted) ? 0xfff - ret : ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace touchscreen
|
||||
|
||||
Reference in new issue
Block a user