From 05b85e5c33b014d7d53e86ab5d3efd21c29853cb Mon Sep 17 00:00:00 2001 From: quo Date: Sat, 20 Aug 2022 13:39:22 +0200 Subject: [PATCH 1/5] Add tilt support to DFT processor --- src/config/config.cpp | 9 +++++++++ src/config/config.hpp | 3 +++ src/daemon/dft.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/config/config.cpp b/src/config/config.cpp index 818a2302..020a6e40 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -128,6 +128,15 @@ static int parse_conf(void *user, const char *c_section, const char *c_name, con if (section == "DFT" && name == "FreqMinMag") config->dft_freq_min_mag = std::stoi(value); + if (section == "DFT" && name == "TiltMinMag") + config->dft_tilt_min_mag = std::stoi(value); + + if (section == "DFT" && name == "TiltDistance") + config->dft_tilt_distance = std::stof(value); + + if (section == "DFT" && name == "TipDistance") + config->dft_tip_distance = std::stof(value); + return 1; } diff --git a/src/config/config.hpp b/src/config/config.hpp index 9f12bc9e..ce9763af 100644 --- a/src/config/config.hpp +++ b/src/config/config.hpp @@ -50,6 +50,9 @@ class Config { f32 dft_position_exp = -0.7; u16 dft_button_min_mag = 1000; u16 dft_freq_min_mag = 10000; + u16 dft_tilt_min_mag = 10000; + f32 dft_tilt_distance = 6; + f32 dft_tip_distance = 2; public: Config(i16 vendor, i16 product); diff --git a/src/daemon/dft.cpp b/src/daemon/dft.cpp index e969a92c..6fa3dd82 100644 --- a/src/daemon/dft.cpp +++ b/src/daemon/dft.cpp @@ -129,7 +129,7 @@ static f64 iptsd_dft_interpolate_frequency(const Context &ctx, const ipts::DftWi static void iptsd_dft_handle_position(Context &ctx, const ipts::DftWindow &dft, ipts::StylusData &stylus) { - if (dft.rows <= 0) { + if (dft.rows <= 1) { iptsd_dft_lift(stylus); return; } @@ -160,6 +160,47 @@ static void iptsd_dft_handle_position(Context &ctx, const ipts::DftWindow &dft, if (ctx.config.invert_y) y = 1 - y; + if (dft.x[1].magnitude > ctx.config.dft_tilt_min_mag && + dft.y[1].magnitude > ctx.config.dft_tilt_min_mag) { + + // calculate tilt angle from relative position of secondary transmitter + + auto [pxt, xt] = iptsd_dft_interpolate_position(ctx, dft.x[1]); + auto [pyt, yt] = iptsd_dft_interpolate_position(ctx, dft.y[1]); + + if (pxt && pyt) { + + xt /= dft.dim.width - 1; + yt /= dft.dim.height - 1; + + if (ctx.config.invert_x) + xt = 1 - xt; + + if (ctx.config.invert_y) + yt = 1 - yt; + + xt -= x; + yt -= y; + + if (ctx.config.dft_tip_distance) { + // correct tip position using tilt data + auto r = ctx.config.dft_tip_distance / ctx.config.dft_tilt_distance; + x -= xt * r; + y -= yt * r; + } + + xt *= ctx.config.width / (ctx.config.dft_tilt_distance * 10); + yt *= ctx.config.height / (ctx.config.dft_tilt_distance * 10); + + auto azm = std::max(0., std::fmod(std::atan2(-yt, xt) / M_PI + 2, 2)) * 18000; + auto alt = (.5 - std::acos(std::min(1., std::hypot(xt, yt))) / M_PI) * 18000; + stylus.azimuth = gsl::narrow(std::round(azm)); + stylus.altitude = gsl::narrow(std::round(alt)); + + } + + } + x = std::round(std::clamp(x, 0.0, 1.0) * IPTS_MAX_X); y = std::round(std::clamp(y, 0.0, 1.0) * IPTS_MAX_Y); From 850cd4561eae05e2eaf698cdd78cf80166f4da3d Mon Sep 17 00:00:00 2001 From: quo Date: Wed, 24 Aug 2022 20:43:45 +0200 Subject: [PATCH 2/5] DFT tilt: config.width/height is now in cm --- src/daemon/dft.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/daemon/dft.cpp b/src/daemon/dft.cpp index 6fa3dd82..0558de27 100644 --- a/src/daemon/dft.cpp +++ b/src/daemon/dft.cpp @@ -189,8 +189,8 @@ static void iptsd_dft_handle_position(Context &ctx, const ipts::DftWindow &dft, y -= yt * r; } - xt *= ctx.config.width / (ctx.config.dft_tilt_distance * 10); - yt *= ctx.config.height / (ctx.config.dft_tilt_distance * 10); + xt *= ctx.config.width * 10 / ctx.config.dft_tilt_distance; + yt *= ctx.config.height * 10 / ctx.config.dft_tilt_distance; auto azm = std::max(0., std::fmod(std::atan2(-yt, xt) / M_PI + 2, 2)) * 18000; auto alt = (.5 - std::acos(std::min(1., std::hypot(xt, yt))) / M_PI) * 18000; From 0f08b6f86af079cfdcea0a514fa9ce99923b9a21 Mon Sep 17 00:00:00 2001 From: quo Date: Sat, 27 Aug 2022 13:43:34 +0200 Subject: [PATCH 3/5] DFT tilt: simplify azimuth/altitude calculations --- src/daemon/dft.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/daemon/dft.cpp b/src/daemon/dft.cpp index 0558de27..29bef8c5 100644 --- a/src/daemon/dft.cpp +++ b/src/daemon/dft.cpp @@ -192,8 +192,8 @@ static void iptsd_dft_handle_position(Context &ctx, const ipts::DftWindow &dft, xt *= ctx.config.width * 10 / ctx.config.dft_tilt_distance; yt *= ctx.config.height * 10 / ctx.config.dft_tilt_distance; - auto azm = std::max(0., std::fmod(std::atan2(-yt, xt) / M_PI + 2, 2)) * 18000; - auto alt = (.5 - std::acos(std::min(1., std::hypot(xt, yt))) / M_PI) * 18000; + auto azm = std::fmod(std::atan2(-yt, xt) / M_PI + 2, 2) * 18000; + auto alt = std::asin(std::min(1.0, std::hypot(xt, yt))) / M_PI * 18000; stylus.azimuth = gsl::narrow(std::round(azm)); stylus.altitude = gsl::narrow(std::round(alt)); From d7cab17723c635848f086e65924c24709e2637f5 Mon Sep 17 00:00:00 2001 From: quo Date: Sat, 27 Aug 2022 13:47:11 +0200 Subject: [PATCH 4/5] DFT: make sure iptsd_dft_interpolate_position never returns {true,NAN} (e.g. when both arguments to pow are negative) --- src/daemon/dft.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/daemon/dft.cpp b/src/daemon/dft.cpp index 29bef8c5..e7782c76 100644 --- a/src/daemon/dft.cpp +++ b/src/daemon/dft.cpp @@ -63,6 +63,9 @@ iptsd_dft_interpolate_position(const Context &ctx, const struct ipts_pen_dft_win // find critical point of fitted parabola f64 d = (x[0] - x[2]) / (2 * (x[0] - 2 * x[1] + x[2])); + if (std::isnan(d)) + return std::tuple {false, 0}; + return std::tuple {true, row.first + maxi + std::clamp(d, mind, maxd)}; } From e2ecfa043611adde010c57f8bf078ba5be99c171 Mon Sep 17 00:00:00 2001 From: quo Date: Sun, 28 Aug 2022 18:37:37 +0200 Subject: [PATCH 5/5] DFT tilt: change distance config values to cm, and disable tip position correction by default --- src/config/config.hpp | 4 ++-- src/daemon/dft.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/config/config.hpp b/src/config/config.hpp index ce9763af..b163dd90 100644 --- a/src/config/config.hpp +++ b/src/config/config.hpp @@ -51,8 +51,8 @@ class Config { u16 dft_button_min_mag = 1000; u16 dft_freq_min_mag = 10000; u16 dft_tilt_min_mag = 10000; - f32 dft_tilt_distance = 6; - f32 dft_tip_distance = 2; + f32 dft_tilt_distance = 0.6; + f32 dft_tip_distance = 0; public: Config(i16 vendor, i16 product); diff --git a/src/daemon/dft.cpp b/src/daemon/dft.cpp index e7782c76..2ae5643c 100644 --- a/src/daemon/dft.cpp +++ b/src/daemon/dft.cpp @@ -192,8 +192,8 @@ static void iptsd_dft_handle_position(Context &ctx, const ipts::DftWindow &dft, y -= yt * r; } - xt *= ctx.config.width * 10 / ctx.config.dft_tilt_distance; - yt *= ctx.config.height * 10 / ctx.config.dft_tilt_distance; + xt *= ctx.config.width / ctx.config.dft_tilt_distance; + yt *= ctx.config.height / ctx.config.dft_tilt_distance; auto azm = std::fmod(std::atan2(-yt, xt) / M_PI + 2, 2) * 18000; auto alt = std::asin(std::min(1.0, std::hypot(xt, yt))) / M_PI * 18000;