ESPHome  2024.4.0
xpt2046.cpp
Go to the documentation of this file.
1 #include "xpt2046.h"
2 #include "esphome/core/log.h"
3 #include "esphome/core/helpers.h"
4 
5 #include <algorithm>
6 
7 namespace esphome {
8 namespace xpt2046 {
9 
10 static const char *const TAG = "xpt2046";
11 
13  if (this->irq_pin_ != nullptr) {
14  // The pin reports a touch with a falling edge. Unfortunately the pin goes also changes state
15  // while the channels are read and wiring it as an interrupt is not straightforward and would
16  // need careful masking. A GPIO poll is cheap so we'll just use that.
17 
18  this->irq_pin_->setup(); // INPUT
20  this->irq_pin_->setup();
22  }
23  this->spi_setup();
24  this->read_adc_(0xD0); // ADC powerdown, enable PENIRQ pin
25 }
26 
28  int16_t data[6], x_raw, y_raw, z_raw;
29  bool touch = false;
30 
31  enable();
32 
33  int16_t touch_pressure_1 = this->read_adc_(0xB1 /* touch_pressure_1 */);
34  int16_t touch_pressure_2 = this->read_adc_(0xC1 /* touch_pressure_2 */);
35  z_raw = touch_pressure_1 + 0Xfff - touch_pressure_2;
36  ESP_LOGVV(TAG, "Touchscreen Update z = %d", z_raw);
37  touch = (z_raw >= this->threshold_);
38  if (touch) {
39  read_adc_(0xD1 /* X */); // dummy Y measure, 1st is always noisy
40  data[0] = this->read_adc_(0x91 /* Y */);
41  data[1] = this->read_adc_(0xD1 /* X */); // make 3 x-y measurements
42  data[2] = this->read_adc_(0x91 /* Y */);
43  data[3] = this->read_adc_(0xD1 /* X */);
44  data[4] = this->read_adc_(0x91 /* Y */);
45  }
46 
47  data[5] = this->read_adc_(0xD0 /* X */); // Last X touch power down
48 
49  disable();
50 
51  if (touch) {
52  x_raw = best_two_avg(data[1], data[3], data[5]);
53  y_raw = best_two_avg(data[0], data[2], data[4]);
54 
55  ESP_LOGD(TAG, "Touchscreen Update [%d, %d], z = %d", x_raw, y_raw, z_raw);
56 
57  this->add_raw_touch_position_(0, x_raw, y_raw, z_raw);
58  }
59 }
60 
62  ESP_LOGCONFIG(TAG, "XPT2046:");
63 
64  LOG_PIN(" IRQ Pin: ", this->irq_pin_);
65  ESP_LOGCONFIG(TAG, " X min: %d", this->x_raw_min_);
66  ESP_LOGCONFIG(TAG, " X max: %d", this->x_raw_max_);
67  ESP_LOGCONFIG(TAG, " Y min: %d", this->y_raw_min_);
68  ESP_LOGCONFIG(TAG, " Y max: %d", this->y_raw_max_);
69 
70  ESP_LOGCONFIG(TAG, " Swap X/Y: %s", YESNO(this->swap_x_y_));
71  ESP_LOGCONFIG(TAG, " Invert X: %s", YESNO(this->invert_x_));
72  ESP_LOGCONFIG(TAG, " Invert Y: %s", YESNO(this->invert_y_));
73 
74  ESP_LOGCONFIG(TAG, " threshold: %d", this->threshold_);
75 
76  LOG_UPDATE_INTERVAL(this);
77 }
78 
79 // float XPT2046Component::get_setup_priority() const { return setup_priority::DATA; }
80 
81 int16_t XPT2046Component::best_two_avg(int16_t value1, int16_t value2, int16_t value3) {
82  int16_t delta_a, delta_b, delta_c;
83  int16_t reta = 0;
84 
85  delta_a = (value1 > value2) ? value1 - value2 : value2 - value1;
86  delta_b = (value1 > value3) ? value1 - value3 : value3 - value1;
87  delta_c = (value3 > value2) ? value3 - value2 : value2 - value3;
88 
89  if (delta_a <= delta_b && delta_a <= delta_c) {
90  reta = (value1 + value2) >> 1;
91  } else if (delta_b <= delta_a && delta_b <= delta_c) {
92  reta = (value1 + value3) >> 1;
93  } else {
94  reta = (value2 + value3) >> 1;
95  }
96 
97  return reta;
98 }
99 
100 int16_t XPT2046Component::read_adc_(uint8_t ctrl) { // NOLINT
101  uint8_t data[2];
102 
103  this->write_byte(ctrl);
104  delay(1);
105  data[0] = this->read_byte();
106  data[1] = this->read_byte();
107 
108  return ((data[0] << 8) | data[1]) >> 3;
109 }
110 
111 } // namespace xpt2046
112 } // namespace esphome
int16_t read_adc_(uint8_t ctrl)
Definition: xpt2046.cpp:100
virtual void pin_mode(gpio::Flags flags)=0
static int16_t best_two_avg(int16_t value1, int16_t value2, int16_t value3)
Definition: xpt2046.cpp:81
virtual void setup()=0
void attach_interrupt_(InternalGPIOPin *irq_pin, esphome::gpio::InterruptType type)
Call this function to send touch points to the on_touch listener and the binary_sensors.
Definition: touchscreen.cpp:12
void add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw=0)
Definition: touchscreen.cpp:74
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26
InternalGPIOPin * irq_pin_
Definition: xpt2046.h:37