From 8e945024c5103061b8b284a6f02f51b4c198bac2 Mon Sep 17 00:00:00 2001 From: sommermorgentraum <24917424+zxkmm@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:39:59 +0800 Subject: [PATCH] touchscreen threshold (sensitivity) auto detect (#2306) * gui * worked but slow * not do the auto detect * worked * remove debug thing * format * remove uneeded thing * fix hackrf submodule bump * clean up * format * format * format * remve batt * add hint text and eta * code clean up by @HTotoo * work around to resolve not clear enough * correct comments --- firmware/application/apps/ui_settings.cpp | 102 ++++++++++++++++++ firmware/application/apps/ui_settings.hpp | 72 +++++++++++++ firmware/application/irq_controls.cpp | 2 +- firmware/application/portapack.cpp | 6 ++ firmware/application/portapack.hpp | 1 + firmware/application/touch.hpp | 8 -- .../common/portapack_persistent_memory.cpp | 11 ++ .../common/portapack_persistent_memory.hpp | 4 + 8 files changed, 197 insertions(+), 9 deletions(-) diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index 2174c1644..edad2c39d 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -818,6 +818,107 @@ void SetDisplayView::focus() { button_save.focus(); } +/* SetTouchscreenSensitivityView ************************************/ +/* sample max: 1023 sample_t AKA uint16_t + * touch_sensitivity: range: 1 to 128 + * threshold = 1023 / sensitive + * threshold range: 1023/1 to 1023/128 = 1023 to 8 + */ +SetTouchscreenThresholdView::SetTouchscreenThresholdView(NavigationView& nav) { + add_children({&labels, + &field_threshold, + &button_autodetect, + &button_reset, + &button_save, + &button_cancel, + &text_hint, + &text_wait_timer}); + + set_dirty(); + org_threshold = portapack::touch_threshold; + field_threshold.set_value(pmem::touchscreen_threshold()); + text_hint.set_style(Theme::getInstance()->error_dark); + text_hint.hidden(true); + text_wait_timer.set_style(Theme::getInstance()->error_dark); + text_wait_timer.hidden(true); + // clang-format off + button_autodetect.on_select = [this, &nav](Button&) { + nav.display_modal("NOTICE", + "Now on don't touch screen;\n" + "Use arrow keys to operate.\n" + "Follow instructions.\n" + "Press YES to continue", + YESNO, [this, &nav](bool choice) { + if (choice){ + time_start_auto_detect = chTimeNow(); + text_hint.hidden(false); + text_wait_timer.hidden(false); + text_wait_timer.set("ETA " + to_string_dec_uint(10) + "s"); + in_auto_detect = true; + field_threshold.set_value(1); + portapack::touch_threshold = 1; + set_dirty(); } }, TRUE); + }; + // clang-format on + + button_reset.on_select = [this](Button&) { + field_threshold.set_value(32); + portapack::touch_threshold = 32; + }; + + button_save.on_select = [&nav, this](Button&) { + pmem::set_touchscreen_threshold(field_threshold.value()); + portapack::touch_threshold = field_threshold.value(); + send_system_refresh(); + nav.pop(); + }; + + button_cancel.on_select = [&nav, this](Button&) { + portapack::touch_threshold = org_threshold; + nav.pop(); + }; +} + +void SetTouchscreenThresholdView::focus() { + button_autodetect.focus(); + set_dirty(); +} + +void SetTouchscreenThresholdView::on_frame_sync() { + if (!in_auto_detect) return; + uint32_t time_now = chTimeNow(); + int32_t time_diff = time_now - time_start_auto_detect; + text_wait_timer.set("ETA " + to_string_dec_uint((10 - time_diff / 1000) <= 0 ? 0 : 10 - time_diff / 1000) + "s"); + if (time_diff >= 10001 && !auto_detect_succeed_consumed) { // 10s + in_auto_detect = false; + text_wait_timer.hidden(true); + text_hint.set("OK, press save and reboot"); + portapack::touch_threshold = org_threshold; + pmem::set_touchscreen_threshold(org_threshold); + set_dirty(); + auto_detect_succeed_consumed = true; + button_save.focus(); + return; + } + if (get_touch_frame().touch) { + if (in_auto_detect) { + uint16_t sen = field_threshold.value(); + sen++; + portapack::touch_threshold = sen; + field_threshold.set_value(sen); + } + } +} + +SetTouchscreenThresholdView::~SetTouchscreenThresholdView() { + // it seems that sometimes in the msg handler func it would enter the condi that not possible to entered, + // so added this workaround. + // TODO: find out why + in_auto_detect = false; + auto_detect_succeed_consumed = false; + time_start_auto_detect = 0; +} + /* SetMenuColorView ************************************/ void SetMenuColorView::paint_sample() { @@ -1022,6 +1123,7 @@ void SettingsMenuView::on_populate() { {"App Settings", ui::Color::dark_cyan(), &bitmap_icon_notepad, [this]() { nav_.push(); }}, {"Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [this]() { nav_.push(); }}, {"Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [this]() { nav_.push(); }}, + {"TouchThreshold", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [this]() { nav_.push(); }}, {"Config Mode", ui::Color::dark_cyan(), &bitmap_icon_clk_ext, [this]() { nav_.push(); }}, {"Converter", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [this]() { nav_.push(); }}, {"Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [this]() { nav_.push(); }}, diff --git a/firmware/application/apps/ui_settings.hpp b/firmware/application/apps/ui_settings.hpp index b3e215e87..cf6849a73 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -35,6 +35,7 @@ #include "bitmap.hpp" #include "ff.h" #include "portapack_persistent_memory.hpp" +#include "irq_controls.hpp" #include @@ -754,6 +755,77 @@ class SetDisplayView : public View { }; }; +using portapack::persistent_memory::touchscreen_threshold; + +class SetTouchscreenThresholdView : public View { + public: + SetTouchscreenThresholdView(NavigationView& nav); + ~SetTouchscreenThresholdView(); + + void focus() override; + + std::string title() const override { return "Touch S"; }; + + private: + bool in_auto_detect = false; + uint16_t org_threshold = 0; + uint8_t auto_detect_succeed_consumed = false; // prevent screen flash but can still change text content + uint32_t time_start_auto_detect = 0; + + Labels labels{ + {{1 * 8, 1 * 16}, "Set touchscreen sensitivity", Theme::getInstance()->fg_light->foreground}, + {{1 * 8, 2 * 16}, "Or press auto detect button", Theme::getInstance()->fg_light->foreground}, + {{1 * 8, 3 * 16}, "FOLLOW INSTRUCTIONS", Theme::getInstance()->fg_light->foreground}, + {{1 * 8, 4 * 16}, "REBOOT TO APPLY", Theme::getInstance()->fg_light->foreground}, + {{1 * 8, 11 * 16}, "Threshold:", Theme::getInstance()->fg_light->foreground}, + }; + + Text text_hint{ + {1 * 8, 7 * 16, screen_width - 2 * 8, 1 * 16}, + "DON'T TOUCH SCREEN"}; + + Text text_wait_timer{ + {1 * 8, 8 * 16, screen_width - 2 * 8, 1 * 16}, + "ETA 00:00"}; + + void on_frame_sync(); + + /* sample max: 1023 sample_t AKA uint16_t + * touch_sensitivity: range: 1 to 128 + * threshold range: 1023/1 to 1023/128 = 1023 to 8 + */ + NumberField field_threshold{ + {1 * 8 + sizeof("Threshold:") * 8 + 8, 11 * 16}, + 4, + {1, 1023}, + 1, + ' ', + }; + + Button button_autodetect{ + {2 * 8, 13 * 16, 12 * 8, 32}, + "Auto Detect"}; + Button button_reset{ + {16 * 8, 13 * 16, 12 * 8, 32}, + "Reset", + }; + + Button button_save{ + {2 * 8, 16 * 16, 12 * 8, 32}, + "Save"}; + + Button button_cancel{ + {16 * 8, 16 * 16, 12 * 8, 32}, + "Cancel", + }; + + MessageHandlerRegistration message_handler_frame_sync{ + Message::ID::DisplayFrameSync, + [this](const Message* const) { + this->on_frame_sync(); + }}; +}; + class SetMenuColorView : public View { public: SetMenuColorView(NavigationView& nav); diff --git a/firmware/application/irq_controls.cpp b/firmware/application/irq_controls.cpp index 06a1d21f1..f9b53321a 100644 --- a/firmware/application/irq_controls.cpp +++ b/firmware/application/irq_controls.cpp @@ -85,7 +85,7 @@ static bool touch_update() { case IO::TouchPinsConfig::SensePressure: { const auto z1 = samples.xp - samples.xn; const auto z2 = samples.yp - samples.yn; - const auto touch_raw = (z1 > touch::touch_threshold) || (z2 > touch::touch_threshold); + const auto touch_raw = (z1 > portapack::touch_threshold) || (z2 > portapack::touch_threshold); touch_debounce = (touch_debounce << 1) | (touch_raw ? 1U : 0U); touch_detected = ((touch_debounce & touch_debounce_mask) == touch_debounce_mask); if (!touch_detected && !touch_cycle) { diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 9f5e51cff..251a265ad 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -95,6 +95,7 @@ TemperatureLogger temperature_logger; bool antenna_bias{false}; uint32_t bl_tick_counter{0}; +uint16_t touch_threshold{32}; void set_antenna_bias(const bool v) { antenna_bias = v; @@ -538,6 +539,11 @@ init_status_t init() { set_cpu_clock_speed(); if (persistent_memory::config_lcd_inverted_mode()) display.set_inverted(true); + /* sample max: 1023 sample_t AKA uint16_t + * touch_sensitivity: range: 1 to 128 + * threshold range: 1023/1 to 1023/128 = 1023 to 8 + */ + touch_threshold = portapack::persistent_memory::touchscreen_threshold(); if (lcd_fast_setup) draw_splash_screen_icon(0, ui::bitmap_icon_memory); diff --git a/firmware/application/portapack.hpp b/firmware/application/portapack.hpp index 6273c7ce4..a13b987b3 100644 --- a/firmware/application/portapack.hpp +++ b/firmware/application/portapack.hpp @@ -68,6 +68,7 @@ extern TransmitterModel transmitter_model; extern uint32_t bl_tick_counter; extern bool antenna_bias; +extern uint16_t touch_threshold; extern TemperatureLogger temperature_logger; diff --git a/firmware/application/touch.hpp b/firmware/application/touch.hpp index 2594d40a2..91758dfcd 100644 --- a/firmware/application/touch.hpp +++ b/firmware/application/touch.hpp @@ -36,14 +36,6 @@ namespace touch { using sample_t = uint16_t; -constexpr sample_t sample_max = 1023; - -// If you have a dead bottom-left corner try to increase the sensitivity, -// but look for flickering touch indicator in the Buttons test screen -// in which case decrease sensitivity to avoid killing backlight timeout -constexpr sample_t touch_sensitivity = 32; -constexpr sample_t touch_threshold = sample_max / touch_sensitivity; - struct Samples { sample_t xp; sample_t xn; diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 42c3411f5..6c655e237 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -252,6 +252,8 @@ struct data_t { // Menu Color Scheme Color menu_color; + uint16_t touchscreen_threshold; + uint16_t UNUSED_16; constexpr data_t() @@ -310,6 +312,7 @@ struct data_t { config_mode_storage(CONFIG_MODE_NORMAL_VALUE), dst_config(), menu_color(Color::grey()), + touchscreen_threshold(32), UNUSED_16() { } }; @@ -1140,6 +1143,13 @@ void set_menu_color(Color v) { data->menu_color = v; } +uint16_t touchscreen_threshold() { + return data->touchscreen_threshold; +} +void set_touchscreen_threshold(uint16_t v) { + data->touchscreen_threshold = v; +} + // PMem to sdcard settings bool should_use_sdcard_for_pmem() { @@ -1244,6 +1254,7 @@ bool debug_dump() { pmem_dump_file.write_line("dst_config: 0x" + to_string_hex((uint32_t)data->dst_config.v, 8)); pmem_dump_file.write_line("fake_brightness_level: " + to_string_dec_uint(data->fake_brightness_level)); pmem_dump_file.write_line("menu_color: 0x" + to_string_hex(data->menu_color.v, 4)); + pmem_dump_file.write_line("touchscreen_threshold: " + to_string_dec_uint(data->touchscreen_threshold)); // ui_config bits const auto backlight_timer = portapack::persistent_memory::config_backlight_timer(); diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index e13d0b5ad..93da33ad1 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -282,6 +282,10 @@ uint8_t fake_brightness_level(); void set_fake_brightness_level(uint8_t v); void toggle_fake_brightness_level(); +/* Touchscreen threshold */ +uint16_t touchscreen_threshold(); +void set_touchscreen_threshold(uint16_t v); + Color menu_color(); void set_menu_color(Color v);