mirror of
https://github.com/esphome/esphome.git
synced 2024-12-27 17:28:01 +01:00
initial cst328
This commit is contained in:
parent
45beea68eb
commit
1805000e9a
6
esphome/components/cst328/__init__.py
Normal file
6
esphome/components/cst328/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
import esphome.codegen as cg
|
||||
|
||||
CODEOWNERS = ["@latonita"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
cst328_ns = cg.esphome_ns.namespace("cst328")
|
36
esphome/components/cst328/touchscreen/__init__.py
Normal file
36
esphome/components/cst328/touchscreen/__init__.py
Normal file
@ -0,0 +1,36 @@
|
||||
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 .. import cst328_ns
|
||||
|
||||
CST328Touchscreen = cst328_ns.class_(
|
||||
"CST328Touchscreen",
|
||||
touchscreen.Touchscreen,
|
||||
i2c.I2CDevice,
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
touchscreen.touchscreen_schema("100ms")
|
||||
.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CST328Touchscreen),
|
||||
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(0x1A))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await touchscreen.register_touchscreen(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
if interrupt_pin := config.get(CONF_INTERRUPT_PIN):
|
||||
cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin)))
|
||||
if reset_pin := config.get(CONF_RESET_PIN):
|
||||
cg.add(var.set_reset_pin(await cg.gpio_pin_expression(reset_pin)))
|
143
esphome/components/cst328/touchscreen/cst328_touchscreen.cpp
Normal file
143
esphome/components/cst328/touchscreen/cst328_touchscreen.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
#include "cst328_touchscreen.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace cst328 {
|
||||
|
||||
void CST328Touchscreen::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up CST328 Touchscreen...");
|
||||
if (this->reset_pin_ != nullptr) {
|
||||
this->reset_pin_->setup();
|
||||
this->reset_pin_->digital_write(true);
|
||||
delay(50);
|
||||
this->reset_pin_->digital_write(false);
|
||||
delay(5);
|
||||
this->reset_pin_->digital_write(true);
|
||||
this->set_timeout(50, [this] { this->continue_setup_(); });
|
||||
} else {
|
||||
this->continue_setup_();
|
||||
}
|
||||
}
|
||||
|
||||
void CST328Touchscreen::continue_setup_() {
|
||||
uint8_t buffer[4];
|
||||
|
||||
if (this->interrupt_pin_ != nullptr) {
|
||||
this->interrupt_pin_->setup();
|
||||
this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE);
|
||||
}
|
||||
|
||||
// buffer[0] = 0xD1;
|
||||
// if (this->write_register16(0xD1, buffer, 1) != i2c::ERROR_OK) {
|
||||
// ESP_LOGE(TAG, "Write byte to 0xD1 failed");
|
||||
// this->mark_failed();
|
||||
// return;
|
||||
// }
|
||||
// delay(10);
|
||||
|
||||
// Enter debug/info mode
|
||||
if (this->write_register16(static_cast<uint16_t>(Cst328WorkModes::DEBUG_INFO_MODE), buffer, 0) != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Failed to enter debug/info mode");
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read chip and project ID
|
||||
if (this->read16_(static_cast<u_int16_t>(Cst328Registers::CHIP_TYPE_AND_PROJECT_ID), buffer, 4)) {
|
||||
this->chip_id_ = buffer[2] + (buffer[3] << 8);
|
||||
this->project_id_ = buffer[0] + (buffer[1] << 8);
|
||||
ESP_LOGV(TAG, "Chip ID %X, project ID %X", this->chip_id_, this->project_id_);
|
||||
}
|
||||
|
||||
// Read FW checksum
|
||||
if (this->read16_(static_cast<uint16_t>(Cst328Registers::FW_CRC_AND_BOOT_TIME), buffer, 4)) {
|
||||
uint16_t fw_crc = buffer[2] + (buffer[3] << 8);
|
||||
if (0xCACA != fw_crc) {
|
||||
ESP_LOGE(TAG, "Invalid FW checksum: %X", fw_crc);
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Read FW version
|
||||
if (this->read16_(static_cast<u_int16_t>(Cst328Registers::FW_REVISION), buffer, 4)) {
|
||||
this->fw_ver_major_ = buffer[3];
|
||||
this->fw_ver_minor_ = buffer[2];
|
||||
this->fw_build_ = buffer[0] + (buffer[1] << 8);
|
||||
ESP_LOGV(TAG, "FW version %d.%d.%d", this->fw_ver_major_, this->fw_ver_minor_, this->fw_build_);
|
||||
}
|
||||
|
||||
// Read X/Y resolution
|
||||
if (this->read16_(static_cast<u_int16_t>(Cst328Registers::X_Y_RESOLUTION), buffer, 4)) {
|
||||
this->x_raw_max_ = buffer[0] + (buffer[1] << 8);
|
||||
this->y_raw_max_ = buffer[2] + (buffer[3] << 8);
|
||||
} else {
|
||||
this->x_raw_max_ = this->display_->get_native_width();
|
||||
this->y_raw_max_ = this->display_->get_native_height();
|
||||
}
|
||||
|
||||
// Enter normal mode
|
||||
this->write_register16(static_cast<uint16_t>(Cst328WorkModes::NORMAL_MODE), buffer, 0);
|
||||
|
||||
this->setup_complete_ = true;
|
||||
|
||||
ESP_LOGV(TAG, "CST328 Touchscreen setup complete");
|
||||
}
|
||||
|
||||
void CST328Touchscreen::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "CST328 Touchscreen:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Chip ID: 0x%04X, Project ID: 0x%04X", this->chip_id_, this->project_id_);
|
||||
ESP_LOGCONFIG(TAG, " FW version: %d.%d.%d", this->fw_ver_major_, this->fw_ver_minor_, this->fw_build_);
|
||||
ESP_LOGCONFIG(TAG, " X/Y resolution: %d/%d", this->x_raw_max_, this->y_raw_max_);
|
||||
}
|
||||
|
||||
void CST328Touchscreen::update_touches() {
|
||||
uint8_t data[CST328_TOUCH_DATA_SIZE];
|
||||
uint8_t clear{0};
|
||||
uint8_t touch_cnt = 0;
|
||||
this->skip_update_ = true;
|
||||
if (!this->read_register16(static_cast<u_int16_t>(Cst328Registers::TOUCH_FINGER_NUMBER), data, 1)) {
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
this->status_clear_warning();
|
||||
|
||||
// number of fingers
|
||||
touch_cnt = data[0] & 0x0F;
|
||||
|
||||
// no touch or error
|
||||
if (touch_cnt == 0 || touch_cnt > CST328_TOUCH_MAX_POINTS) {
|
||||
// clear touch
|
||||
this->write_register16(static_cast<u_int16_t>(Cst328Registers::TOUCH_FINGER_NUMBER), &clear, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// read all points
|
||||
if (!this->read_register16(static_cast<u_int16_t>(Cst328Registers::TOUCH_INFORMATION), data, sizeof(data))) {
|
||||
ESP_LOGV(TAG, "Failed to read touch data");
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
|
||||
// clear touch
|
||||
this->write_register16(static_cast<u_int16_t>(Cst328Registers::TOUCH_FINGER_NUMBER), &clear, 1);
|
||||
|
||||
this->skip_update_ = false;
|
||||
size_t index = 0;
|
||||
for (uint8_t i = 0; i != touch_cnt; i++) {
|
||||
uint8_t id = data[index] >> 4;
|
||||
int16_t x = (data[index + 1] << 4) | ((data[index + 3] >> 4) & 0x0F);
|
||||
int16_t y = (data[index + 2] << 4) | (data[index + 3] & 0x0F);
|
||||
int16_t z = data[index + 4];
|
||||
this->add_raw_touch_position_(id, x, y, z);
|
||||
ESP_LOGV(TAG, "Read touch %d: %d/%d", id, x, y);
|
||||
index += 5;
|
||||
if (i == 0) {
|
||||
index += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace cst328
|
||||
} // namespace esphome
|
76
esphome/components/cst328/touchscreen/cst328_touchscreen.h
Normal file
76
esphome/components/cst328/touchscreen/cst328_touchscreen.h
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/components/touchscreen/touchscreen.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace cst328 {
|
||||
|
||||
static const char *const TAG = "cst328.touchscreen";
|
||||
|
||||
static const uint8_t CST328_REG_STATUS = 0x00;
|
||||
static const uint8_t CST328_TOUCH_MAX_POINTS = 5;
|
||||
static const uint8_t CST328_TOUCH_DATA_SIZE = 27;
|
||||
|
||||
enum class Cst328Registers : uint16_t {
|
||||
TOUCH_INFORMATION = 0xD000,
|
||||
TOUCH_FINGER_NUMBER = 0xD005,
|
||||
KEY_TX_RX_NUMBERS = 0xD1F4,
|
||||
X_Y_RESOLUTION = 0xD1F8,
|
||||
FW_CRC_AND_BOOT_TIME = 0xD1FC,
|
||||
CHIP_TYPE_AND_PROJECT_ID = 0xD204,
|
||||
FW_REVISION = 0xD208,
|
||||
};
|
||||
|
||||
enum class Cst328WorkModes : uint16_t {
|
||||
DEBUG_INFO_MODE = 0xD101,
|
||||
RESET_MODE = 0xD102,
|
||||
RECALIBRATION_MODE = 0xD104,
|
||||
DEEP_SLEEP_MODE = 0xD105,
|
||||
DEBUG_POINT_MODE = 0xD108,
|
||||
NORMAL_MODE = 0xD109,
|
||||
DEBUG_RAWDATA_MODE = 0xD10A,
|
||||
DEBUG_DIFF_MODE = 0xD10D,
|
||||
DEBUG_FACTORY_MODE = 0xD119,
|
||||
DEBUG_FACTORY_MODE_2 = 0xD120,
|
||||
};
|
||||
|
||||
class CST328Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
void update_touches() 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; }
|
||||
|
||||
bool can_proceed() override { return this->setup_complete_ || this->is_failed(); }
|
||||
|
||||
protected:
|
||||
bool read16_(uint16_t addr, uint8_t *data, size_t len) {
|
||||
if (this->read_register16(addr, data, len) != i2c::ERROR_OK) {
|
||||
esph_log_e(TAG, "Read data from 0x%04X failed", addr);
|
||||
this->mark_failed();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void continue_setup_();
|
||||
|
||||
InternalGPIOPin *interrupt_pin_{};
|
||||
GPIOPin *reset_pin_{};
|
||||
|
||||
uint16_t chip_id_{};
|
||||
uint16_t project_id_{};
|
||||
uint8_t fw_ver_major_{};
|
||||
uint8_t fw_ver_minor_{};
|
||||
uint16_t fw_build_{};
|
||||
|
||||
bool setup_complete_{};
|
||||
};
|
||||
|
||||
} // namespace cst328
|
||||
} // namespace esphome
|
Loading…
Reference in New Issue
Block a user