pw_ft6236: Initial implementation
Change-Id: I25f5d0c5b12c04b1af0bf7565255b93108911c42
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/experimental/+/171603
Reviewed-by: Armando Montanez <amontanez@google.com>
Commit-Queue: Anthony DiGirolamo <tonymd@google.com>
diff --git a/applications/app_common_impl/BUILD.gn b/applications/app_common_impl/BUILD.gn
index df20efb..9e05df3 100644
--- a/applications/app_common_impl/BUILD.gn
+++ b/applications/app_common_impl/BUILD.gn
@@ -136,6 +136,7 @@
"$dir_pw_digital_io_pico",
"$dir_pw_display",
"$dir_pw_framebuffer_pool",
+ "$dir_pw_ft6236",
"$dir_pw_i2c_rp2040",
"$dir_pw_log",
"$dir_pw_spi_pico",
diff --git a/applications/app_common_impl/common_pico.cc b/applications/app_common_impl/common_pico.cc
index 8abc503..bc35519 100644
--- a/applications/app_common_impl/common_pico.cc
+++ b/applications/app_common_impl/common_pico.cc
@@ -23,6 +23,7 @@
#include "hardware/vreg.h"
#include "pico/stdlib.h"
#include "pw_digital_io_pico/digital_io.h"
+#include "pw_ft6236/device.h"
#include "pw_i2c_rp2040/initiator.h"
#include "pw_log/log.h"
#include "pw_pixel_pusher_rp2040_pio/pixel_pusher.h"
@@ -219,6 +220,10 @@
i2c_bus.Enable();
+ pw::ft6236::Device touch_screen(i2c_bus);
+ touch_screen.Enable();
+ touch_screen.LogControllerInfo();
+
#if BACKLIGHT_GPIO != -1
SetBacklight(0xffff); // Full brightness.
#endif
diff --git a/build_overrides/pigweed.gni b/build_overrides/pigweed.gni
index 210f6f9..bdf8f80 100644
--- a/build_overrides/pigweed.gni
+++ b/build_overrides/pigweed.gni
@@ -152,4 +152,6 @@
dir_pw_pixel_pusher_rp2040_pio =
get_path_info("$dir_pigweed_experimental/pw_pixel_pusher_rp2040_pio",
"abspath")
+ dir_pw_ft6236 =
+ get_path_info("$dir_pigweed_experimental/pw_ft6236", "abspath")
}
diff --git a/pw_ft6236/BUILD.gn b/pw_ft6236/BUILD.gn
new file mode 100644
index 0000000..1e78995
--- /dev/null
+++ b/pw_ft6236/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2023 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+import("//build_overrides/pi_pico.gni")
+import("//build_overrides/pigweed.gni")
+import("$dir_pw_build/target_types.gni")
+
+config("default_config") {
+ include_dirs = [ "public" ]
+}
+
+pw_source_set("pw_ft6236") {
+ public_configs = [ ":default_config" ]
+ public_deps = [
+ "$dir_pw_i2c:initiator",
+ "$dir_pw_status",
+ ]
+ deps = [
+ "$dir_pw_digital_io",
+ "$dir_pw_i2c:register_device",
+ "$dir_pw_log",
+ ]
+ sources = [ "device.cc" ]
+ remove_configs = [ "$dir_pw_build:strict_warnings" ]
+}
diff --git a/pw_ft6236/device.cc b/pw_ft6236/device.cc
new file mode 100644
index 0000000..4d19079
--- /dev/null
+++ b/pw_ft6236/device.cc
@@ -0,0 +1,162 @@
+// Copyright 2023 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include "pw_ft6236/device.h"
+
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
+
+#include "pw_bytes/bit.h"
+#include "pw_i2c/address.h"
+#include "pw_i2c/register_device.h"
+#include "pw_log/log.h"
+#include "pw_status/status.h"
+
+using ::pw::Status;
+using namespace std::chrono_literals;
+
+namespace pw::ft6236 {
+
+namespace {
+
+#define FT62XX_REG_THRESHHOLD 0x80
+#define FT62XX_REG_POINTRATE 0x88
+#define FT62XX_REG_CHIPID 0xA3
+#define FT62XX_REG_FIRMVERS 0xA6
+#define FT62XX_REG_VENDID 0xA8
+
+constexpr pw::i2c::Address kAddress = pw::i2c::Address::SevenBit<0x38>();
+
+} // namespace
+
+Device::Device(pw::i2c::Initiator& initiator)
+ : initiator_(initiator),
+ device_(initiator,
+ kAddress,
+ endian::little,
+ pw::i2c::RegisterAddressSize::k1Byte) {
+ delta_micros_ = 0;
+ this_update_micros_ = 0;
+ last_update_micros_ = 0;
+}
+Device::~Device() = default;
+
+Status Device::Enable() {
+ Result<std::byte> vendor_id_result = device_.ReadRegister(
+ FT62XX_REG_VENDID, pw::chrono::SystemClock::for_at_least(10ms));
+ if (vendor_id_result.value_or(std::byte{0}) != std::byte{0x11}) {
+ return Status::NotFound();
+ }
+
+ SetThreshhold(128);
+
+ return OkStatus();
+}
+
+Status Device::SetThreshhold(uint8_t threshhold) {
+ PW_TRY(device_.WriteRegister(FT62XX_REG_THRESHHOLD,
+ std::byte{threshhold},
+ pw::chrono::SystemClock::for_at_least(10ms)));
+ return OkStatus();
+}
+
+Status Device::Probe() {
+ pw::Status probe_result(initiator_.ProbeDeviceFor(
+ kAddress, pw::chrono::SystemClock::for_at_least(10ms)));
+
+ if (probe_result != pw::OkStatus()) {
+ PW_LOG_DEBUG("FT6236 Probe Failed");
+ }
+ PW_LOG_DEBUG("FT6236 Probe Ok");
+ return probe_result;
+}
+
+void Device::LogControllerInfo() {
+ Result<std::byte> result = device_.ReadRegister(
+ FT62XX_REG_VENDID, pw::chrono::SystemClock::for_at_least(10ms));
+ PW_LOG_DEBUG("Vend ID: 0x%x", (uint8_t)result.value_or(std::byte{0}));
+
+ result = device_.ReadRegister(FT62XX_REG_CHIPID,
+ pw::chrono::SystemClock::for_at_least(10ms));
+ PW_LOG_DEBUG("Chip ID: 0x%x (0x36==FT6236)",
+ (uint8_t)result.value_or(std::byte{0}));
+
+ result = device_.ReadRegister(FT62XX_REG_FIRMVERS,
+ pw::chrono::SystemClock::for_at_least(10ms));
+ PW_LOG_DEBUG("Firmware Version: %u", (uint8_t)result.value_or(std::byte{0}));
+
+ result = device_.ReadRegister(FT62XX_REG_POINTRATE,
+ pw::chrono::SystemClock::for_at_least(10ms));
+ PW_LOG_DEBUG("Point Rate Hz: %u", (uint8_t)result.value_or(std::byte{0}));
+
+ result = device_.ReadRegister(FT62XX_REG_THRESHHOLD,
+ pw::chrono::SystemClock::for_at_least(10ms));
+ PW_LOG_DEBUG("Threshhold: %u", (uint8_t)result.value_or(std::byte{0}));
+}
+
+void Device::LogTouchInfo() {
+ if (touch_count_ == 0) {
+ return;
+ }
+
+ PW_LOG_DEBUG("Touches: %d", touch_count_);
+
+ for (int i = 0; i < touch_count_; i++) {
+ PW_LOG_DEBUG("(x,y)=(%d, %d) weight=%d area=%d",
+ touches_[i].x,
+ touches_[i].y,
+ touches_[i].weight,
+ touches_[i].area);
+ }
+}
+
+bool Device::ReadData() {
+ // Read 16 registers starting from 0x00.
+ std::array<std::byte, 16> rx_buffer;
+ device_.ReadRegisters(
+ 0, rx_buffer, pw::chrono::SystemClock::for_at_least(10ms));
+
+ // Number of touches (0, 1 or 2) is at 0x02.
+ touch_count_ = (uint8_t)rx_buffer[0x02];
+
+ // Return false if no new touches are present.
+ if (touch_count_ == 0) {
+ return false;
+ }
+
+ // Read Touch #1 X coordinate high and low registers.
+ touches_[0].x =
+ (((uint8_t)rx_buffer[0x03] & 0x0F) << 8) | (uint8_t)rx_buffer[0x04];
+ // Read Touch #1 Y coordinate high and low registers.
+ touches_[0].y =
+ (((uint8_t)rx_buffer[0x05] & 0x0F) << 8) | (uint8_t)rx_buffer[0x06];
+ // Read Touch #1 Misc data
+ touches_[0].weight = (uint8_t)rx_buffer[0x07];
+ touches_[0].area = (uint8_t)rx_buffer[0x08] & 0x0F;
+
+ // Read Touch #2 X coordinate high and low registers.
+ touches_[1].x =
+ (((uint8_t)rx_buffer[0x09] & 0x0F) << 8) | (uint8_t)rx_buffer[0x0A];
+ // Read Touch #2 Y coordinate high and low registers.
+ touches_[1].y =
+ (((uint8_t)rx_buffer[0x0B] & 0x0F) << 8) | (uint8_t)rx_buffer[0x0C];
+ // Read Touch #2 Misc data
+ touches_[0].weight = (uint8_t)rx_buffer[0x0D];
+ touches_[0].area = (uint8_t)rx_buffer[0x0E] & 0x0F;
+
+ return true;
+}
+
+} // namespace pw::ft6236
diff --git a/pw_ft6236/public/pw_ft6236/device.h b/pw_ft6236/public/pw_ft6236/device.h
new file mode 100644
index 0000000..649aa85
--- /dev/null
+++ b/pw_ft6236/public/pw_ft6236/device.h
@@ -0,0 +1,57 @@
+// Copyright 2023 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include <array>
+#include <cstdint>
+
+#include "pw_i2c/address.h"
+#include "pw_i2c/initiator.h"
+#include "pw_i2c/register_device.h"
+#include "pw_status/status.h"
+
+namespace pw::ft6236 {
+
+struct Touch {
+ uint16_t x;
+ uint16_t y;
+ uint8_t weight;
+ uint8_t area;
+};
+
+class Device {
+ public:
+ Device(pw::i2c::Initiator& initiator);
+ ~Device();
+
+ Status Enable();
+ Status Probe();
+ void LogControllerInfo();
+ void LogTouchInfo();
+ Status SetThreshhold(uint8_t threshhold);
+ bool ReadData();
+
+ private:
+ pw::i2c::Initiator& initiator_;
+ pw::i2c::RegisterDevice device_;
+
+ std::array<Touch, 2> touches_;
+ uint8_t touch_count_;
+
+ uint32_t delta_micros_ = 0;
+ uint32_t this_update_micros_ = 0;
+ uint32_t last_update_micros_ = 0;
+};
+
+} // namespace pw::ft6236