2015-07-08 11:39:24 -04:00
/*
* Copyright ( C ) 2015 Jared Boone , ShareBrained Technology , Inc .
2016-12-09 12:21:47 -05:00
* Copyright ( C ) 2016 Furrtek
2023-05-22 16:17:28 -04:00
* Copyright ( C ) 2023 gullradriel , Nilorea Studio Inc .
2023-09-10 20:04:20 -04:00
* Copyright ( C ) 2023 Kyle Reed
2024-02-10 03:32:03 -05:00
* Copyright ( C ) 2024 Mark Thompson
2024-03-10 15:49:36 -04:00
* Copyright ( C ) 2024 u - foka
2024-10-06 15:58:03 -04:00
* Copyright ( C ) 2024 HTotoo
2024-02-07 03:07:30 -05:00
* Copyleft ( ɔ ) 2024 zxkmm under GPL license
2015-07-08 11:39:24 -04:00
*
* This file is part of PortaPack .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; see the file COPYING . If not , write to
* the Free Software Foundation , Inc . , 51 Franklin Street ,
* Boston , MA 02110 - 1301 , USA .
*/
2018-05-16 04:45:13 -04:00
# include "ui_settings.hpp"
2016-02-04 04:27:53 -05:00
2016-12-26 07:49:23 -05:00
# include "ui_navigation.hpp"
2023-06-23 19:13:39 -04:00
# include "ui_receiver.hpp"
2016-07-27 17:15:21 -04:00
# include "ui_touch_calibration.hpp"
2024-01-12 07:41:13 -05:00
# include "ui_text_editor.hpp"
2024-04-03 10:27:13 -04:00
# include "ui_external_items_menu_loader.hpp"
2016-07-27 17:15:21 -04:00
2015-08-04 13:03:18 -04:00
# include "portapack_persistent_memory.hpp"
2015-07-08 11:39:24 -04:00
# include "lpc43xx_cpp.hpp"
using namespace lpc43xx ;
2016-01-31 03:34:24 -05:00
2020-06-07 19:23:23 -04:00
# include "audio.hpp"
2016-01-31 03:34:24 -05:00
# include "portapack.hpp"
2016-07-26 21:03:40 -04:00
using namespace portapack ;
2016-01-23 14:32:10 -05:00
2023-07-02 12:35:34 -04:00
# include "file.hpp"
2024-03-25 03:44:49 -04:00
# include "file_path.hpp"
2023-07-02 12:35:34 -04:00
namespace fs = std : : filesystem ;
2016-07-26 21:03:40 -04:00
# include "string_format.hpp"
2024-02-16 01:19:43 -05:00
# include "ui_font_fixed_8x16.hpp"
2016-07-17 18:56:24 -04:00
# include "cpld_update.hpp"
2024-01-17 00:59:35 -05:00
# include "config_mode.hpp"
2024-10-06 16:14:27 -04:00
# include "i2cdevmanager.hpp"
# include "i2cdev_max17055.hpp"
2015-07-08 11:39:24 -04:00
2024-05-27 15:02:52 -04:00
extern ui : : SystemView * system_view_ptr ;
2023-06-23 19:13:39 -04:00
namespace pmem = portapack : : persistent_memory ;
2023-03-22 03:46:58 -04:00
2015-07-08 11:39:24 -04:00
namespace ui {
2023-06-23 19:13:39 -04:00
/* Sends a UI refresh message to cause the status bar to redraw. */
static void send_system_refresh ( ) {
StatusRefreshMessage message { } ;
EventDispatcher : : send_message ( message ) ;
}
/* SetDateTimeView ***************************************/
2023-05-18 16:16:05 -04:00
SetDateTimeView : : SetDateTimeView (
NavigationView & nav ) {
button_save . on_select = [ & nav , this ] ( Button & ) {
const auto model = this - > form_collect ( ) ;
2024-01-21 13:47:28 -05:00
rtc : : RTC new_datetime { model . year , model . month , model . day , model . hour , model . minute , model . second } ;
pmem : : set_config_dst ( model . dst ) ;
rtc_time : : set ( new_datetime ) ; // NB: 1 hour will be subtracted if value is stored in RTC during DST
2023-05-18 16:16:05 -04:00
nav . pop ( ) ;
} ,
button_cancel . on_select = [ & nav ] ( Button & ) {
nav . pop ( ) ;
} ,
add_children ( {
& labels ,
& field_year ,
& field_month ,
& field_day ,
& field_hour ,
& field_minute ,
& field_second ,
2024-01-21 13:47:28 -05:00
& text_weekday ,
& text_day_of_year ,
2024-02-06 15:25:44 -05:00
& text_in_dst_range ,
2024-01-21 13:47:28 -05:00
& checkbox_dst_enable ,
& options_dst_start_which ,
& options_dst_start_weekday ,
& options_dst_start_month ,
& options_dst_end_which ,
& options_dst_end_weekday ,
& options_dst_end_month ,
2023-05-18 16:16:05 -04:00
& button_save ,
& button_cancel ,
} ) ;
2024-01-21 13:47:28 -05:00
// Populate DST options (same string text for start & end)
options_dst_start_which . set_options ( which_options ) ;
options_dst_end_which . set_options ( which_options ) ;
options_dst_start_weekday . set_options ( weekday_options ) ;
options_dst_end_weekday . set_options ( weekday_options ) ;
options_dst_start_month . set_options ( month_options ) ;
options_dst_end_month . set_options ( month_options ) ;
2024-02-06 15:25:44 -05:00
const auto dst_changed_fn = [ this ] ( size_t , uint32_t ) {
handle_date_field_update ( ) ;
} ;
2024-01-21 13:47:28 -05:00
const auto date_changed_fn = [ this ] ( int32_t ) {
2024-02-06 15:25:44 -05:00
handle_date_field_update ( ) ;
2024-01-21 13:47:28 -05:00
} ;
field_year . on_change = date_changed_fn ;
field_month . on_change = date_changed_fn ;
field_day . on_change = date_changed_fn ;
2024-02-06 15:25:44 -05:00
options_dst_start_which . on_change = dst_changed_fn ;
options_dst_start_weekday . on_change = dst_changed_fn ;
options_dst_start_month . on_change = dst_changed_fn ;
options_dst_end_which . on_change = dst_changed_fn ;
options_dst_end_weekday . on_change = dst_changed_fn ;
options_dst_end_month . on_change = dst_changed_fn ;
2023-05-18 16:16:05 -04:00
rtc : : RTC datetime ;
2024-01-21 13:47:28 -05:00
rtc_time : : now ( datetime ) ;
2023-05-18 16:16:05 -04:00
SetDateTimeModel model {
datetime . year ( ) ,
datetime . month ( ) ,
datetime . day ( ) ,
datetime . hour ( ) ,
datetime . minute ( ) ,
2024-01-21 13:47:28 -05:00
datetime . second ( ) ,
pmem : : config_dst ( ) } ;
2023-05-18 16:16:05 -04:00
form_init ( model ) ;
}
void SetDateTimeView : : focus ( ) {
button_cancel . focus ( ) ;
}
void SetDateTimeView : : form_init ( const SetDateTimeModel & model ) {
field_year . set_value ( model . year ) ;
field_month . set_value ( model . month ) ;
field_day . set_value ( model . day ) ;
field_hour . set_value ( model . hour ) ;
field_minute . set_value ( model . minute ) ;
field_second . set_value ( model . second ) ;
2024-01-21 13:47:28 -05:00
checkbox_dst_enable . set_value ( model . dst . b . dst_enabled ) ;
options_dst_start_which . set_by_value ( model . dst . b . start_which ) ;
options_dst_start_weekday . set_by_value ( model . dst . b . start_weekday ) ;
options_dst_start_month . set_by_value ( model . dst . b . start_month ) ;
options_dst_end_which . set_by_value ( model . dst . b . end_which ) ;
options_dst_end_weekday . set_by_value ( model . dst . b . end_weekday ) ;
options_dst_end_month . set_by_value ( model . dst . b . end_month ) ;
2023-05-18 16:16:05 -04:00
}
SetDateTimeModel SetDateTimeView : : form_collect ( ) {
2024-02-06 15:25:44 -05:00
return {
. year = static_cast < uint16_t > ( field_year . value ( ) ) ,
. month = static_cast < uint8_t > ( field_month . value ( ) ) ,
. day = static_cast < uint8_t > ( field_day . value ( ) ) ,
. hour = static_cast < uint8_t > ( field_hour . value ( ) ) ,
. minute = static_cast < uint8_t > ( field_minute . value ( ) ) ,
. second = static_cast < uint8_t > ( field_second . value ( ) ) ,
. dst = dst_collect ( ) } ;
}
pmem : : dst_config_t SetDateTimeView : : dst_collect ( ) {
2024-01-21 13:47:28 -05:00
pmem : : dst_config_t dst ;
dst . b . dst_enabled = static_cast < uint8_t > ( checkbox_dst_enable . value ( ) ) ;
dst . b . start_which = static_cast < uint8_t > ( options_dst_start_which . selected_index_value ( ) ) ;
dst . b . start_weekday = static_cast < uint8_t > ( options_dst_start_weekday . selected_index_value ( ) ) ;
dst . b . start_month = static_cast < uint8_t > ( options_dst_start_month . selected_index_value ( ) ) ;
dst . b . end_which = static_cast < uint8_t > ( options_dst_end_which . selected_index_value ( ) ) ;
dst . b . end_weekday = static_cast < uint8_t > ( options_dst_end_weekday . selected_index_value ( ) ) ;
dst . b . end_month = static_cast < uint8_t > ( options_dst_end_month . selected_index_value ( ) ) ;
2024-02-06 15:25:44 -05:00
return dst ;
}
void SetDateTimeView : : handle_date_field_update ( ) {
auto weekday = rtc_time : : day_of_week ( field_year . value ( ) , field_month . value ( ) , field_day . value ( ) ) ;
auto doy = rtc_time : : day_of_year ( field_year . value ( ) , field_month . value ( ) , field_day . value ( ) ) ;
bool valid_date = ( field_day . value ( ) < = rtc_time : : days_per_month ( field_year . value ( ) , field_month . value ( ) ) ) ;
text_weekday . set ( valid_date ? weekday_options [ weekday ] . first : " - " ) ;
text_day_of_year . set ( valid_date ? to_string_dec_uint ( doy , 3 ) : " - " ) ;
text_in_dst_range . set ( checkbox_dst_enable . value ( ) & & rtc_time : : dst_test_date_range ( field_year . value ( ) , doy , dst_collect ( ) ) ? " DST " : " " ) ;
2023-05-18 16:16:05 -04:00
}
2023-06-23 19:13:39 -04:00
/* SetRadioView ******************************************/
2023-05-18 16:16:05 -04:00
SetRadioView : : SetRadioView (
NavigationView & nav ) {
button_cancel . on_select = [ & nav ] ( Button & ) {
nav . pop ( ) ;
} ;
2023-09-10 20:04:20 -04:00
add_children ( {
& label_source ,
& value_source ,
& value_source_frequency ,
& check_clkout ,
& field_clkout_freq ,
& labels_clkout_khz ,
& labels_bias ,
& check_bias ,
& disable_external_tcxo , // TODO: always show?
& button_save ,
& button_cancel ,
} ) ;
2023-06-23 19:13:39 -04:00
const auto reference = clock_manager . get_reference ( ) ;
2023-05-18 16:16:05 -04:00
2023-09-10 20:04:20 -04:00
if ( reference . source = = ClockManager : : ReferenceSource : : Xtal ) {
add_children ( {
& labels_correction ,
& field_ppm ,
} ) ;
}
2024-01-01 13:25:36 -05:00
std : : string source_name = clock_manager . get_source ( ) ;
2023-05-18 16:16:05 -04:00
value_source . set ( source_name ) ;
2024-01-01 13:25:36 -05:00
value_source_frequency . set ( clock_manager . get_freq ( ) ) ;
2023-05-18 16:16:05 -04:00
2023-09-10 20:04:20 -04:00
// Make these Text controls look like Labels.
2024-05-27 15:02:52 -04:00
label_source . set_style ( Theme : : getInstance ( ) - > fg_light ) ;
value_source . set_style ( Theme : : getInstance ( ) - > fg_light ) ;
value_source_frequency . set_style ( Theme : : getInstance ( ) - > fg_light ) ;
2023-05-18 16:16:05 -04:00
SetFrequencyCorrectionModel model {
2023-06-23 19:13:39 -04:00
static_cast < int8_t > ( pmem : : correction_ppb ( ) / 1000 ) , 0 } ;
2023-05-18 16:16:05 -04:00
form_init ( model ) ;
2023-06-23 19:13:39 -04:00
check_clkout . set_value ( pmem : : clkout_enabled ( ) ) ;
2023-05-18 16:16:05 -04:00
check_clkout . on_select = [ this ] ( Checkbox & , bool v ) {
clock_manager . enable_clock_output ( v ) ;
2023-06-23 19:13:39 -04:00
pmem : : set_clkout_enabled ( v ) ;
send_system_refresh ( ) ;
2023-05-18 16:16:05 -04:00
} ;
2023-12-24 11:28:22 -05:00
// Disallow CLKOUT freq change on hackrf_r9 due to dependencies on GP_CLKIN (same Si5351A clock);
// see comments in ClockManager::enable_clock_output()
if ( hackrf_r9 ) {
if ( pmem : : clkout_freq ( ) ! = 10000 )
pmem : : set_clkout_freq ( 10000 ) ;
field_clkout_freq . set_focusable ( false ) ;
}
2023-06-23 19:13:39 -04:00
field_clkout_freq . set_value ( pmem : : clkout_freq ( ) ) ;
2023-12-24 02:55:15 -05:00
field_clkout_freq . on_change = [ this ] ( SymField & ) {
2023-12-26 01:11:14 -05:00
if ( field_clkout_freq . to_integer ( ) < 4 ) // Min. CLK out of Si5351A/B/C-B is 2.5khz , but in our application -intermediate freq 800Mhz-,Min working CLK=4khz.
field_clkout_freq . set_value ( 4 ) ;
2023-12-24 02:55:15 -05:00
if ( field_clkout_freq . to_integer ( ) > 60000 )
field_clkout_freq . set_value ( 60000 ) ;
2023-05-18 16:16:05 -04:00
} ;
2023-06-23 19:13:39 -04:00
check_bias . set_value ( get_antenna_bias ( ) ) ;
2023-05-18 16:16:05 -04:00
check_bias . on_select = [ this ] ( Checkbox & , bool v ) {
2023-06-23 19:13:39 -04:00
set_antenna_bias ( v ) ;
2023-05-24 00:22:30 -04:00
// Update the radio.
receiver_model . set_antenna_bias ( ) ;
transmitter_model . set_antenna_bias ( ) ;
// The models won't actually disable this if they are not 'enabled_'.
// Be extra sure this is turned off.
if ( ! v )
radio : : set_antenna_bias ( false ) ;
2023-06-23 19:13:39 -04:00
send_system_refresh ( ) ;
2023-05-18 16:16:05 -04:00
} ;
2023-09-04 11:46:07 -04:00
disable_external_tcxo . set_value ( pmem : : config_disable_external_tcxo ( ) ) ;
2023-05-18 16:16:05 -04:00
button_save . on_select = [ this , & nav ] ( Button & ) {
const auto model = this - > form_collect ( ) ;
2023-06-23 19:13:39 -04:00
pmem : : set_correction_ppb ( model . ppm * 1000 ) ;
pmem : : set_clkout_freq ( model . freq ) ;
2023-09-04 11:46:07 -04:00
pmem : : set_config_disable_external_tcxo ( disable_external_tcxo . value ( ) ) ;
2023-06-23 19:13:39 -04:00
clock_manager . enable_clock_output ( pmem : : clkout_enabled ( ) ) ;
2023-05-18 16:16:05 -04:00
nav . pop ( ) ;
} ;
}
void SetRadioView : : focus ( ) {
button_save . focus ( ) ;
}
void SetRadioView : : form_init ( const SetFrequencyCorrectionModel & model ) {
field_ppm . set_value ( model . ppm ) ;
}
SetFrequencyCorrectionModel SetRadioView : : form_collect ( ) {
return {
. ppm = static_cast < int8_t > ( field_ppm . value ( ) ) ,
2023-12-24 02:55:15 -05:00
. freq = static_cast < uint32_t > ( field_clkout_freq . to_integer ( ) ) ,
2023-05-18 16:16:05 -04:00
} ;
}
2023-06-23 19:13:39 -04:00
/* SetUIView *********************************************/
2023-05-18 16:16:05 -04:00
SetUIView : : SetUIView ( NavigationView & nav ) {
add_children ( { & checkbox_disable_touchscreen ,
& checkbox_bloff ,
& options_bloff ,
& checkbox_showsplash ,
& checkbox_showclock ,
& options_clockformat ,
& checkbox_guireturnflag ,
2023-06-23 19:13:39 -04:00
& labels ,
& toggle_camera ,
& toggle_sleep ,
& toggle_stealth ,
& toggle_converter ,
& toggle_bias_tee ,
& toggle_clock ,
2023-06-26 02:08:09 -04:00
& toggle_mute ,
2023-06-23 19:13:39 -04:00
& toggle_sd_card ,
2023-05-18 16:16:05 -04:00
& button_save ,
& button_cancel } ) ;
2023-06-26 02:08:09 -04:00
// Display "Disable speaker" option only if AK4951 Codec which has separate speaker/headphone control
if ( audio : : speaker_disable_supported ( ) ) {
add_child ( & toggle_speaker ) ;
}
2024-04-29 11:38:27 -04:00
if ( battery : : BatteryManagement : : isDetected ( ) ) {
add_child ( & toggle_battery_icon ) ;
add_child ( & toggle_battery_text ) ;
}
2023-06-26 02:08:09 -04:00
2023-06-23 19:13:39 -04:00
checkbox_disable_touchscreen . set_value ( pmem : : disable_touchscreen ( ) ) ;
checkbox_showsplash . set_value ( pmem : : config_splash ( ) ) ;
checkbox_showclock . set_value ( ! pmem : : hide_clock ( ) ) ;
checkbox_guireturnflag . set_value ( pmem : : show_gui_return_icon ( ) ) ;
2023-05-18 16:16:05 -04:00
2023-06-23 19:13:39 -04:00
const auto backlight_config = pmem : : config_backlight_timer ( ) ;
2023-05-18 16:16:05 -04:00
checkbox_bloff . set_value ( backlight_config . timeout_enabled ( ) ) ;
options_bloff . set_by_value ( backlight_config . timeout_enum ( ) ) ;
2023-06-23 19:13:39 -04:00
if ( pmem : : clock_with_date ( ) ) {
2023-05-18 16:16:05 -04:00
options_clockformat . set_selected_index ( 1 ) ;
} else {
options_clockformat . set_selected_index ( 0 ) ;
}
2023-06-23 19:13:39 -04:00
// NB: Invert so "active" == "not hidden"
toggle_camera . set_value ( ! pmem : : ui_hide_camera ( ) ) ;
toggle_sleep . set_value ( ! pmem : : ui_hide_sleep ( ) ) ;
toggle_stealth . set_value ( ! pmem : : ui_hide_stealth ( ) ) ;
toggle_converter . set_value ( ! pmem : : ui_hide_converter ( ) ) ;
toggle_bias_tee . set_value ( ! pmem : : ui_hide_bias_tee ( ) ) ;
toggle_clock . set_value ( ! pmem : : ui_hide_clock ( ) ) ;
toggle_speaker . set_value ( ! pmem : : ui_hide_speaker ( ) ) ;
2023-06-26 02:08:09 -04:00
toggle_mute . set_value ( ! pmem : : ui_hide_mute ( ) ) ;
2024-04-29 11:38:27 -04:00
toggle_battery_icon . set_value ( ! pmem : : ui_hide_battery_icon ( ) ) ;
toggle_battery_text . set_value ( ! pmem : : ui_hide_numeric_battery ( ) ) ;
2023-06-23 19:13:39 -04:00
toggle_sd_card . set_value ( ! pmem : : ui_hide_sd_card ( ) ) ;
2023-05-18 16:16:05 -04:00
button_save . on_select = [ & nav , this ] ( Button & ) {
2023-06-23 19:13:39 -04:00
pmem : : set_config_backlight_timer ( { ( pmem : : backlight_timeout_t ) options_bloff . selected_index_value ( ) ,
checkbox_bloff . value ( ) } ) ;
2023-05-18 16:16:05 -04:00
if ( checkbox_showclock . value ( ) ) {
if ( options_clockformat . selected_index ( ) = = 1 )
2023-06-23 19:13:39 -04:00
pmem : : set_clock_with_date ( true ) ;
2023-05-18 16:16:05 -04:00
else
2023-06-23 19:13:39 -04:00
pmem : : set_clock_with_date ( false ) ;
2023-05-18 16:16:05 -04:00
}
2023-06-23 19:13:39 -04:00
pmem : : set_config_splash ( checkbox_showsplash . value ( ) ) ;
pmem : : set_clock_hidden ( ! checkbox_showclock . value ( ) ) ;
pmem : : set_gui_return_icon ( checkbox_guireturnflag . value ( ) ) ;
pmem : : set_disable_touchscreen ( checkbox_disable_touchscreen . value ( ) ) ;
pmem : : set_ui_hide_camera ( ! toggle_camera . value ( ) ) ;
pmem : : set_ui_hide_sleep ( ! toggle_sleep . value ( ) ) ;
pmem : : set_ui_hide_stealth ( ! toggle_stealth . value ( ) ) ;
pmem : : set_ui_hide_converter ( ! toggle_converter . value ( ) ) ;
pmem : : set_ui_hide_bias_tee ( ! toggle_bias_tee . value ( ) ) ;
pmem : : set_ui_hide_clock ( ! toggle_clock . value ( ) ) ;
pmem : : set_ui_hide_speaker ( ! toggle_speaker . value ( ) ) ;
2023-06-26 02:08:09 -04:00
pmem : : set_ui_hide_mute ( ! toggle_mute . value ( ) ) ;
2024-04-29 11:38:27 -04:00
pmem : : set_ui_hide_battery_icon ( ! toggle_battery_icon . value ( ) ) ;
pmem : : set_ui_hide_numeric_battery ( ! toggle_battery_text . value ( ) ) ;
2023-06-23 19:13:39 -04:00
pmem : : set_ui_hide_sd_card ( ! toggle_sd_card . value ( ) ) ;
send_system_refresh ( ) ;
2023-05-18 16:16:05 -04:00
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetUIView : : focus ( ) {
button_save . focus ( ) ;
}
2023-11-19 09:08:29 -05:00
/* SetSDCardView *********************************************/
SetSDCardView : : SetSDCardView ( NavigationView & nav ) {
add_children ( { & labels ,
& checkbox_sdcard_speed ,
& button_test_sdcard_high_speed ,
& text_sdcard_test_status ,
& button_save ,
& button_cancel } ) ;
checkbox_sdcard_speed . set_value ( pmem : : config_sdcard_high_speed_io ( ) ) ;
button_test_sdcard_high_speed . on_select = [ & nav , this ] ( Button & ) {
pmem : : set_config_sdcard_high_speed_io ( true , false ) ;
text_sdcard_test_status . set ( " !! HIGH SPEED MODE ON !! " ) ;
} ;
button_save . on_select = [ & nav , this ] ( Button & ) {
pmem : : set_config_sdcard_high_speed_io ( checkbox_sdcard_speed . value ( ) , true ) ;
send_system_refresh ( ) ;
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetSDCardView : : focus ( ) {
button_save . focus ( ) ;
}
2023-06-23 19:13:39 -04:00
/* SetConverterSettingsView ******************************/
2023-05-18 16:16:05 -04:00
SetConverterSettingsView : : SetConverterSettingsView ( NavigationView & nav ) {
2023-09-10 20:04:20 -04:00
add_children ( {
& labels ,
& check_show_converter ,
& check_converter ,
& opt_converter_mode ,
& field_converter_freq ,
& button_return ,
} ) ;
2023-05-18 16:16:05 -04:00
2023-06-23 19:13:39 -04:00
check_show_converter . set_value ( ! pmem : : ui_hide_converter ( ) ) ;
2023-05-18 16:16:05 -04:00
check_show_converter . on_select = [ this ] ( Checkbox & , bool v ) {
2023-06-23 19:13:39 -04:00
pmem : : set_ui_hide_converter ( ! v ) ;
2023-05-18 16:16:05 -04:00
if ( ! v ) {
check_converter . set_value ( false ) ;
}
2023-06-11 14:47:13 -04:00
// Retune to take converter change in account.
receiver_model . set_target_frequency ( receiver_model . target_frequency ( ) ) ;
2023-09-10 20:04:20 -04:00
// Refresh status bar converter icon.
2023-06-23 19:13:39 -04:00
send_system_refresh ( ) ;
2023-05-18 16:16:05 -04:00
} ;
2023-06-23 19:13:39 -04:00
check_converter . set_value ( pmem : : config_converter ( ) ) ;
2023-05-18 16:16:05 -04:00
check_converter . on_select = [ this ] ( Checkbox & , bool v ) {
if ( v ) {
check_show_converter . set_value ( true ) ;
2023-06-23 19:13:39 -04:00
pmem : : set_ui_hide_converter ( false ) ;
2023-05-18 16:16:05 -04:00
}
2023-06-23 19:13:39 -04:00
pmem : : set_config_converter ( v ) ;
2023-09-10 20:04:20 -04:00
// Retune to take converter change in account.
2023-06-11 14:47:13 -04:00
receiver_model . set_target_frequency ( receiver_model . target_frequency ( ) ) ;
2023-09-10 20:04:20 -04:00
// Refresh status bar converter icon.
2023-06-23 19:13:39 -04:00
send_system_refresh ( ) ;
2023-05-18 16:16:05 -04:00
} ;
2023-09-10 20:04:20 -04:00
opt_converter_mode . set_by_value ( pmem : : config_updown_converter ( ) ) ;
opt_converter_mode . on_change = [ this ] ( size_t , OptionsField : : value_t v ) {
2023-06-23 19:13:39 -04:00
pmem : : set_config_updown_converter ( v ) ;
2023-09-10 20:04:20 -04:00
// Refresh status bar with up or down icon.
2023-06-23 19:13:39 -04:00
send_system_refresh ( ) ;
2023-05-18 16:16:05 -04:00
} ;
2023-09-10 20:04:20 -04:00
field_converter_freq . set_step ( 1'000'000 ) ;
field_converter_freq . set_value ( pmem : : config_converter_freq ( ) ) ;
field_converter_freq . on_change = [ this ] ( rf : : Frequency f ) {
pmem : : set_config_converter_freq ( f ) ;
// Retune to take converter change in account.
receiver_model . set_target_frequency ( receiver_model . target_frequency ( ) ) ;
} ;
field_converter_freq . on_edit = [ this , & nav ] ( ) {
auto new_view = nav . push < FrequencyKeypadView > ( field_converter_freq . value ( ) ) ;
new_view - > on_changed = [ this ] ( rf : : Frequency f ) {
field_converter_freq . set_value ( f ) ;
2023-05-18 16:16:05 -04:00
} ;
} ;
2023-05-20 03:30:08 -04:00
button_return . on_select = [ & nav , this ] ( Button & ) {
2023-05-18 16:16:05 -04:00
nav . pop ( ) ;
} ;
2023-05-20 03:30:08 -04:00
}
void SetConverterSettingsView : : focus ( ) {
button_return . focus ( ) ;
}
2023-06-23 19:13:39 -04:00
/* SetFrequencyCorrectionView ****************************/
2023-05-20 03:30:08 -04:00
SetFrequencyCorrectionView : : SetFrequencyCorrectionView ( NavigationView & nav ) {
2023-09-10 20:04:20 -04:00
add_children ( {
& labels ,
& opt_rx_correction_mode ,
& field_rx_correction ,
& opt_tx_correction_mode ,
& field_tx_correction ,
& button_return ,
} ) ;
opt_rx_correction_mode . set_by_value ( pmem : : config_freq_rx_correction_updown ( ) ) ;
opt_rx_correction_mode . on_change = [ this ] ( size_t , OptionsField : : value_t v ) {
2023-06-23 19:13:39 -04:00
pmem : : set_freq_rx_correction_updown ( v ) ;
2023-05-20 03:30:08 -04:00
} ;
2023-12-17 19:47:20 -05:00
opt_tx_correction_mode . set_by_value ( pmem : : config_freq_tx_correction_updown ( ) ) ;
2023-09-10 20:04:20 -04:00
opt_tx_correction_mode . on_change = [ this ] ( size_t , OptionsField : : value_t v ) {
2023-06-23 19:13:39 -04:00
pmem : : set_freq_tx_correction_updown ( v ) ;
2023-05-20 03:30:08 -04:00
} ;
2023-09-10 20:04:20 -04:00
field_rx_correction . set_step ( 100'000 ) ;
field_rx_correction . set_value ( pmem : : config_freq_rx_correction ( ) ) ;
field_rx_correction . on_change = [ this ] ( rf : : Frequency f ) {
pmem : : set_config_freq_rx_correction ( f ) ;
// Retune to take converter change in account.
receiver_model . set_target_frequency ( receiver_model . target_frequency ( ) ) ;
} ;
field_rx_correction . on_edit = [ this , & nav ] ( ) {
auto new_view = nav . push < FrequencyKeypadView > ( field_rx_correction . value ( ) ) ;
new_view - > on_changed = [ this ] ( rf : : Frequency f ) {
field_rx_correction . set_value ( f ) ;
2023-05-20 03:30:08 -04:00
} ;
} ;
2023-09-10 20:04:20 -04:00
field_tx_correction . set_step ( 100'000 ) ;
field_tx_correction . set_value ( pmem : : config_freq_tx_correction ( ) ) ;
field_tx_correction . on_change = [ this ] ( rf : : Frequency f ) {
pmem : : set_config_freq_tx_correction ( f ) ;
// Retune to take converter change in account. NB: receiver_model.
receiver_model . set_target_frequency ( receiver_model . target_frequency ( ) ) ;
} ;
field_tx_correction . on_edit = [ this , & nav ] ( ) {
auto new_view = nav . push < FrequencyKeypadView > ( field_tx_correction . value ( ) ) ;
new_view - > on_changed = [ this ] ( rf : : Frequency f ) {
field_tx_correction . set_value ( f ) ;
2023-05-20 03:30:08 -04:00
} ;
} ;
button_return . on_select = [ & nav , this ] ( Button & ) {
2023-05-18 16:16:05 -04:00
nav . pop ( ) ;
} ;
}
2023-05-20 03:30:08 -04:00
void SetFrequencyCorrectionView : : focus ( ) {
button_return . focus ( ) ;
2023-05-18 16:16:05 -04:00
}
2023-06-23 19:13:39 -04:00
/* SetPersistentMemoryView *******************************/
2023-05-18 16:16:05 -04:00
SetPersistentMemoryView : : SetPersistentMemoryView ( NavigationView & nav ) {
2023-09-10 20:04:20 -04:00
add_children ( {
& labels ,
& text_pmem_status ,
& check_use_sdcard_for_pmem ,
& button_save_mem_to_file ,
& button_load_mem_from_file ,
& button_load_mem_defaults ,
& button_return ,
} ) ;
2024-05-27 15:02:52 -04:00
text_pmem_status . set_style ( Theme : : getInstance ( ) - > fg_yellow ) ;
2023-05-18 16:16:05 -04:00
2023-06-23 19:13:39 -04:00
check_use_sdcard_for_pmem . set_value ( pmem : : should_use_sdcard_for_pmem ( ) ) ;
2023-06-04 15:25:25 -04:00
check_use_sdcard_for_pmem . on_select = [ this ] ( Checkbox & , bool v ) {
2023-05-18 16:16:05 -04:00
File pmem_flag_file_handle ;
if ( v ) {
2024-03-25 03:44:49 -04:00
if ( fs : : file_exists ( settings_dir / PMEM_FILEFLAG ) ) {
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " P.Mem flag file present. " ) ;
2023-07-02 12:35:34 -04:00
} else {
2024-03-25 03:44:49 -04:00
auto error = pmem_flag_file_handle . create ( settings_dir / PMEM_FILEFLAG ) ;
2023-07-02 12:35:34 -04:00
if ( error )
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " Error creating P.Mem File! " ) ;
2023-07-02 12:35:34 -04:00
else
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " P.Mem flag file created. " ) ;
2023-05-18 16:16:05 -04:00
}
} else {
2024-03-25 03:44:49 -04:00
auto result = delete_file ( settings_dir / PMEM_FILEFLAG ) ;
2023-07-02 12:35:34 -04:00
if ( result . code ( ) ! = FR_OK )
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " Error deleting P.Mem flag! " ) ;
2023-07-02 12:35:34 -04:00
else
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " P.Mem flag file deleted. " ) ;
2023-05-18 16:16:05 -04:00
}
} ;
button_save_mem_to_file . on_select = [ & nav , this ] ( Button & ) {
2023-07-02 12:35:34 -04:00
if ( ! pmem : : save_persistent_settings_to_file ( ) )
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " Error saving settings! " ) ;
2023-07-02 12:35:34 -04:00
else
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " Settings saved. " ) ;
2023-05-18 16:16:05 -04:00
} ;
button_load_mem_from_file . on_select = [ & nav , this ] ( Button & ) {
2023-06-23 19:13:39 -04:00
if ( ! pmem : : load_persistent_settings_from_file ( ) ) {
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " Error loading settings! " ) ;
2023-05-18 16:16:05 -04:00
} else {
2023-09-10 20:04:20 -04:00
text_pmem_status . set ( " Settings loaded. " ) ;
2023-05-18 16:16:05 -04:00
// Refresh status bar with icon up or down
2023-06-23 19:13:39 -04:00
send_system_refresh ( ) ;
2023-05-18 16:16:05 -04:00
}
} ;
button_load_mem_defaults . on_select = [ & nav , this ] ( Button & ) {
nav . push < ModalMessageView > (
" Warning! " ,
2023-09-10 20:04:20 -04:00
" This will reset the P.Mem \n to default settings. " ,
2023-05-18 16:16:05 -04:00
YESNO ,
[ this ] ( bool choice ) {
if ( choice ) {
2023-06-23 19:13:39 -04:00
pmem : : cache : : defaults ( ) ;
2024-02-15 09:00:25 -05:00
// Refresh status bar
send_system_refresh ( ) ;
2023-05-18 16:16:05 -04:00
}
} ) ;
} ;
button_return . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetPersistentMemoryView : : focus ( ) {
button_return . focus ( ) ;
}
2023-06-23 19:13:39 -04:00
/* SetAudioView ******************************************/
2023-05-18 16:16:05 -04:00
SetAudioView : : SetAudioView ( NavigationView & nav ) {
add_children ( { & labels ,
& field_tone_mix ,
2024-03-29 14:26:45 -04:00
& checkbox_beep_on_packets ,
2023-05-18 16:16:05 -04:00
& button_save ,
& button_cancel } ) ;
2023-06-23 19:13:39 -04:00
field_tone_mix . set_value ( pmem : : tone_mix ( ) ) ;
2023-05-18 16:16:05 -04:00
2024-03-29 14:26:45 -04:00
checkbox_beep_on_packets . set_value ( pmem : : beep_on_packets ( ) ) ;
2023-05-18 16:16:05 -04:00
button_save . on_select = [ & nav , this ] ( Button & ) {
2023-06-23 19:13:39 -04:00
pmem : : set_tone_mix ( field_tone_mix . value ( ) ) ;
2024-03-29 14:26:45 -04:00
pmem : : set_beep_on_packets ( checkbox_beep_on_packets . value ( ) ) ;
2023-06-19 15:06:07 -04:00
audio : : output : : update_audio_mute ( ) ;
2023-05-18 16:16:05 -04:00
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetAudioView : : focus ( ) {
button_save . focus ( ) ;
}
2023-06-23 19:13:39 -04:00
/* SetQRCodeView *****************************************/
2023-05-18 16:16:05 -04:00
SetQRCodeView : : SetQRCodeView ( NavigationView & nav ) {
2023-09-10 20:04:20 -04:00
add_children ( {
& labels ,
& checkbox_bigger_qr ,
& button_save ,
& button_cancel ,
} ) ;
2023-05-18 16:16:05 -04:00
2023-06-23 19:13:39 -04:00
checkbox_bigger_qr . set_value ( pmem : : show_bigger_qr_code ( ) ) ;
2023-05-18 16:16:05 -04:00
button_save . on_select = [ & nav , this ] ( Button & ) {
2023-06-23 19:13:39 -04:00
pmem : : set_show_bigger_qr_code ( checkbox_bigger_qr . value ( ) ) ;
2023-05-18 16:16:05 -04:00
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetQRCodeView : : focus ( ) {
button_save . focus ( ) ;
}
2023-06-23 19:13:39 -04:00
/* SetEncoderDialView ************************************/
Support for Rotary Encoder Dial sensitivity levels, issue #965 (#1057)
* Support for 3 levels of rotary encoder sensitivity #965
Backend support; UI will still need to call set function to configure.
* Support for 3 levels of rotary encoder sensitivity #965
Backend support only. UI will still need to be changed to call the set_sensitivity() function to configure.
* Removed trailing space
* Deleted blank lines to see if format checker will be happier
* Simpler support for multiple levels of encoder sensitivity, for issue #965
Removed the convoluted code :-) and instead just using a 2-dimensional array to choose which transition map to use. For now I only have 2 (vs 3) levels enabled as well, to save code space and because high-sensitivity is very touchy.
* Simpler version of configurable encoder sensitivity, issue #965
* Formatting
* Formatting test for Clang
* Formatting test
* Formatting (removed helpful comment)
* Formatting test (remove commented-out code)
* Formatting & swapping medium/low so default mode=0
* Swapped medium/low so default mode=0
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Removed unneeded range check (trusting in pmem checksum)
2023-05-24 22:32:12 -04:00
SetEncoderDialView : : SetEncoderDialView ( NavigationView & nav ) {
add_children ( { & labels ,
& field_encoder_dial_sensitivity ,
2024-02-10 03:32:03 -05:00
& field_encoder_rate_multiplier ,
Support for Rotary Encoder Dial sensitivity levels, issue #965 (#1057)
* Support for 3 levels of rotary encoder sensitivity #965
Backend support; UI will still need to call set function to configure.
* Support for 3 levels of rotary encoder sensitivity #965
Backend support only. UI will still need to be changed to call the set_sensitivity() function to configure.
* Removed trailing space
* Deleted blank lines to see if format checker will be happier
* Simpler support for multiple levels of encoder sensitivity, for issue #965
Removed the convoluted code :-) and instead just using a 2-dimensional array to choose which transition map to use. For now I only have 2 (vs 3) levels enabled as well, to save code space and because high-sensitivity is very touchy.
* Simpler version of configurable encoder sensitivity, issue #965
* Formatting
* Formatting test for Clang
* Formatting test
* Formatting (removed helpful comment)
* Formatting test (remove commented-out code)
* Formatting & swapping medium/low so default mode=0
* Swapped medium/low so default mode=0
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Removed unneeded range check (trusting in pmem checksum)
2023-05-24 22:32:12 -04:00
& button_save ,
& button_cancel } ) ;
2024-02-10 03:32:03 -05:00
field_encoder_dial_sensitivity . set_by_value ( pmem : : encoder_dial_sensitivity ( ) ) ;
field_encoder_rate_multiplier . set_value ( pmem : : encoder_rate_multiplier ( ) ) ;
Support for Rotary Encoder Dial sensitivity levels, issue #965 (#1057)
* Support for 3 levels of rotary encoder sensitivity #965
Backend support; UI will still need to call set function to configure.
* Support for 3 levels of rotary encoder sensitivity #965
Backend support only. UI will still need to be changed to call the set_sensitivity() function to configure.
* Removed trailing space
* Deleted blank lines to see if format checker will be happier
* Simpler support for multiple levels of encoder sensitivity, for issue #965
Removed the convoluted code :-) and instead just using a 2-dimensional array to choose which transition map to use. For now I only have 2 (vs 3) levels enabled as well, to save code space and because high-sensitivity is very touchy.
* Simpler version of configurable encoder sensitivity, issue #965
* Formatting
* Formatting test for Clang
* Formatting test
* Formatting (removed helpful comment)
* Formatting test (remove commented-out code)
* Formatting & swapping medium/low so default mode=0
* Swapped medium/low so default mode=0
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Removed unneeded range check (trusting in pmem checksum)
2023-05-24 22:32:12 -04:00
button_save . on_select = [ & nav , this ] ( Button & ) {
2023-06-23 19:13:39 -04:00
pmem : : set_encoder_dial_sensitivity ( field_encoder_dial_sensitivity . selected_index_value ( ) ) ;
2024-02-10 03:32:03 -05:00
pmem : : set_encoder_rate_multiplier ( field_encoder_rate_multiplier . value ( ) ) ;
Support for Rotary Encoder Dial sensitivity levels, issue #965 (#1057)
* Support for 3 levels of rotary encoder sensitivity #965
Backend support; UI will still need to call set function to configure.
* Support for 3 levels of rotary encoder sensitivity #965
Backend support only. UI will still need to be changed to call the set_sensitivity() function to configure.
* Removed trailing space
* Deleted blank lines to see if format checker will be happier
* Simpler support for multiple levels of encoder sensitivity, for issue #965
Removed the convoluted code :-) and instead just using a 2-dimensional array to choose which transition map to use. For now I only have 2 (vs 3) levels enabled as well, to save code space and because high-sensitivity is very touchy.
* Simpler version of configurable encoder sensitivity, issue #965
* Formatting
* Formatting test for Clang
* Formatting test
* Formatting (removed helpful comment)
* Formatting test (remove commented-out code)
* Formatting & swapping medium/low so default mode=0
* Swapped medium/low so default mode=0
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Adding UI & PMEM support to make encoder dial sensitivity configurable, issue #965
* Removed unneeded range check (trusting in pmem checksum)
2023-05-24 22:32:12 -04:00
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetEncoderDialView : : focus ( ) {
button_save . focus ( ) ;
}
2024-01-12 07:41:13 -05:00
/* AppSettingsView ************************************/
AppSettingsView : : AppSettingsView (
NavigationView & nav )
: nav_ { nav } {
add_children ( { & labels ,
& menu_view } ) ;
menu_view . set_parent_rect ( { 0 , 3 * 8 , 240 , 33 * 8 } ) ;
2024-03-25 03:44:49 -04:00
ensure_directory ( settings_dir ) ;
2024-01-12 07:41:13 -05:00
2024-03-25 03:44:49 -04:00
for ( const auto & entry : std : : filesystem : : directory_iterator ( settings_dir , u " *.ini " ) ) {
auto path = settings_dir / entry . path ( ) ;
2024-01-12 07:41:13 -05:00
menu_view . add_item ( { path . filename ( ) . string ( ) . substr ( 0 , 26 ) ,
2024-05-27 15:02:52 -04:00
ui : : Theme : : getInstance ( ) - > fg_darkcyan - > foreground ,
2024-01-12 07:41:13 -05:00
& bitmap_icon_file_text ,
[ this , path ] ( KeyEvent ) {
nav_ . push < TextEditorView > ( path ) ;
} } ) ;
}
}
void AppSettingsView : : focus ( ) {
menu_view . focus ( ) ;
}
2024-01-17 00:59:35 -05:00
/* SetConfigModeView ************************************/
SetConfigModeView : : SetConfigModeView ( NavigationView & nav ) {
add_children ( { & labels ,
& checkbox_config_mode_enabled ,
& button_save ,
& button_cancel } ) ;
checkbox_config_mode_enabled . set_value ( ! pmem : : config_disable_config_mode ( ) ) ;
button_save . on_select = [ & nav , this ] ( Button & ) {
pmem : : set_config_disable_config_mode ( ! checkbox_config_mode_enabled . value ( ) ) ;
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetConfigModeView : : focus ( ) {
button_save . focus ( ) ;
}
2024-09-07 04:58:57 -04:00
/* SetDisplayView ************************************/
2024-02-07 03:07:30 -05:00
2024-09-07 04:58:57 -04:00
SetDisplayView : : SetDisplayView ( NavigationView & nav ) {
2024-11-08 02:47:22 -05:00
add_children ( { & button_save ,
2024-02-07 03:07:30 -05:00
& button_cancel ,
2024-11-08 02:47:22 -05:00
& checkbox_invert_switch } ) ;
2024-02-07 03:07:30 -05:00
2024-09-07 04:58:57 -04:00
checkbox_invert_switch . set_value ( pmem : : config_lcd_inverted_mode ( ) ) ;
2024-02-07 03:07:30 -05:00
button_save . on_select = [ & nav , this ] ( Button & ) {
2024-09-07 04:58:57 -04:00
if ( checkbox_invert_switch . value ( ) ! = pmem : : config_lcd_inverted_mode ( ) ) {
display . set_inverted ( checkbox_invert_switch . value ( ) ) ;
pmem : : set_lcd_inverted_mode ( checkbox_invert_switch . value ( ) ) ;
}
2024-02-08 12:28:49 -05:00
send_system_refresh ( ) ;
2024-02-07 03:07:30 -05:00
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
2024-09-07 04:58:57 -04:00
void SetDisplayView : : focus ( ) {
2024-02-07 03:07:30 -05:00
button_save . focus ( ) ;
}
2024-10-16 12:39:59 -04:00
/* 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 ;
}
2024-02-16 01:19:43 -05:00
/* SetMenuColorView ************************************/
void SetMenuColorView : : paint_sample ( ) {
Color c = Color ( field_red_level . value ( ) , field_green_level . value ( ) , field_blue_level . value ( ) ) ;
button_sample . set_bg_color ( c ) ;
}
SetMenuColorView : : SetMenuColorView ( NavigationView & nav ) {
add_children ( { & labels ,
& button_sample ,
& field_red_level ,
& field_green_level ,
& field_blue_level ,
& button_save ,
2024-04-29 11:38:27 -04:00
& button_reset ,
2024-02-16 01:19:43 -05:00
& button_cancel } ) ;
button_sample . set_focusable ( false ) ;
Color c = pmem : : menu_color ( ) ;
field_red_level . set_value ( c . r ( ) ) ;
field_green_level . set_value ( c . g ( ) ) ;
field_blue_level . set_value ( c . b ( ) ) ;
paint_sample ( ) ;
const auto color_changed_fn = [ this ] ( int32_t ) {
paint_sample ( ) ;
} ;
field_red_level . on_change = color_changed_fn ;
field_green_level . on_change = color_changed_fn ;
field_blue_level . on_change = color_changed_fn ;
2024-04-29 11:38:27 -04:00
button_reset . on_select = [ & nav , this ] ( Button & ) {
field_red_level . set_value ( 127 ) ;
field_green_level . set_value ( 127 ) ;
field_blue_level . set_value ( 127 ) ;
set_dirty ( ) ;
} ;
2024-02-16 01:19:43 -05:00
button_save . on_select = [ & nav , this ] ( Button & ) {
Color c = Color ( field_red_level . value ( ) , field_green_level . value ( ) , field_blue_level . value ( ) ) ;
pmem : : set_menu_color ( c ) ;
send_system_refresh ( ) ;
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetMenuColorView : : focus ( ) {
button_save . focus ( ) ;
}
2024-04-05 10:04:39 -04:00
/* SetAutoStartView ************************************/
2024-04-03 10:27:13 -04:00
SetAutostartView : : SetAutostartView ( NavigationView & nav ) {
add_children ( { & labels ,
& button_save ,
& button_cancel ,
2024-10-06 15:58:03 -04:00
& button_reset ,
2024-04-03 10:27:13 -04:00
& options } ) ;
button_save . on_select = [ & nav , this ] ( Button & ) {
2024-04-05 10:04:39 -04:00
autostart_app = " " ;
if ( selected ! = 0 ) {
auto it = full_app_list . find ( selected ) ;
if ( it ! = full_app_list . end ( ) )
autostart_app = it - > second ;
}
2024-04-03 10:27:13 -04:00
nav . pop ( ) ;
} ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
2024-10-06 15:58:03 -04:00
button_reset . on_select = [ this ] ( Button & ) {
selected = 0 ;
options . set_selected_index ( 0 ) ;
autostart_app = " " ;
} ;
2024-04-03 10:27:13 -04:00
// options
i = 0 ;
OptionsField : : option_t o { " -none- " , i } ;
opts . emplace_back ( o ) ;
for ( auto & app : NavigationView : : appList ) {
if ( app . id = = nullptr ) continue ;
i + + ;
o = { app . displayName , i } ;
opts . emplace_back ( o ) ;
full_app_list . emplace ( i , app . id ) ;
if ( autostart_app = = app . id ) selected = i ;
}
ExternalItemsMenuLoader : : load_all_external_items_callback ( [ this ] ( ui : : AppInfoConsole & app ) {
if ( app . appCallName = = nullptr ) return ;
i + + ;
OptionsField : : option_t o = { app . appFriendlyName , i } ;
opts . emplace_back ( o ) ;
full_app_list . emplace ( i , app . appCallName ) ;
if ( autostart_app = = app . appCallName ) selected = i ;
} ) ;
options . set_options ( opts ) ;
options . on_change = [ this ] ( size_t , OptionsField : : value_t v ) {
2024-04-05 10:04:39 -04:00
selected = v ;
2024-04-03 10:27:13 -04:00
} ;
options . set_selected_index ( selected ) ;
}
void SetAutostartView : : focus ( ) {
options . focus ( ) ;
}
2024-05-27 15:02:52 -04:00
/* SetThemeView ************************************/
SetThemeView : : SetThemeView ( NavigationView & nav ) {
add_children ( { & labels ,
& button_save ,
& button_cancel ,
& options ,
& checkbox_menuset } ) ;
button_save . on_select = [ & nav , this ] ( Button & ) {
if ( selected < Theme : : ThemeId : : MAX & & ( uint8_t ) selected ! = portapack : : persistent_memory : : ui_theme_id ( ) ) {
portapack : : persistent_memory : : set_ui_theme_id ( ( uint8_t ) selected ) ;
Theme : : SetTheme ( ( Theme : : ThemeId ) selected ) ;
if ( checkbox_menuset . value ( ) ) {
pmem : : set_menu_color ( Theme : : getInstance ( ) - > bg_medium - > background ) ;
}
send_system_refresh ( ) ;
}
nav . pop ( ) ;
} ;
checkbox_menuset . set_value ( true ) ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
options . on_change = [ this ] ( size_t , OptionsField : : value_t v ) {
selected = v ;
} ;
options . set_selected_index ( portapack : : persistent_memory : : ui_theme_id ( ) ) ;
}
void SetThemeView : : focus ( ) {
options . focus ( ) ;
}
2024-08-28 05:32:24 -04:00
/* SetBatteryView ************************************/
SetBatteryView : : SetBatteryView ( NavigationView & nav ) {
add_children ( { & labels ,
& button_save ,
& button_cancel ,
& checkbox_overridebatt } ) ;
2024-10-06 16:14:27 -04:00
if ( i2cdev : : I2CDevManager : : get_dev_by_model ( I2C_DEVMDL : : I2CDEVMDL_MAX17055 ) ) add_children ( { & button_reset , & labels2 } ) ;
2024-09-20 05:59:17 -04:00
2024-08-28 05:32:24 -04:00
button_save . on_select = [ & nav , this ] ( Button & ) {
pmem : : set_ui_override_batt_calc ( checkbox_overridebatt . value ( ) ) ;
battery : : BatteryManagement : : set_calc_override ( checkbox_overridebatt . value ( ) ) ;
send_system_refresh ( ) ;
nav . pop ( ) ;
} ;
2024-09-20 05:59:17 -04:00
button_reset . on_select = [ & nav , this ] ( Button & ) {
2024-10-06 16:14:27 -04:00
auto dev = ( i2cdev : : I2cDev_MAX17055 * ) i2cdev : : I2CDevManager : : get_dev_by_model ( I2C_DEVMDL : : I2CDEVMDL_MAX17055 ) ;
if ( dev - > reset_learned ( ) )
2024-09-20 05:59:17 -04:00
nav . display_modal ( " Reset " , " Battery parameters reset " ) ;
else
nav . display_modal ( " Error " , " Error parameter reset " ) ;
} ;
2024-08-28 05:32:24 -04:00
checkbox_overridebatt . set_value ( pmem : : ui_override_batt_calc ( ) ) ;
button_cancel . on_select = [ & nav , this ] ( Button & ) {
nav . pop ( ) ;
} ;
}
void SetBatteryView : : focus ( ) {
button_cancel . focus ( ) ;
}
2023-06-23 19:13:39 -04:00
/* SettingsMenuView **************************************/
2024-03-10 15:49:36 -04:00
SettingsMenuView : : SettingsMenuView ( NavigationView & nav )
: nav_ ( nav ) {
set_max_rows ( 2 ) ; // allow wider buttons
}
void SettingsMenuView : : on_populate ( ) {
2023-06-23 19:13:39 -04:00
if ( pmem : : show_gui_return_icon ( ) ) {
2024-03-10 15:49:36 -04:00
add_items ( { { " .. " , ui : : Color : : light_grey ( ) , & bitmap_icon_previous , [ this ] ( ) { nav_ . pop ( ) ; } } } ) ;
2023-05-18 16:16:05 -04:00
}
add_items ( {
2024-03-10 15:49:36 -04:00
{ " App Settings " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_notepad , [ this ] ( ) { nav_ . push < AppSettingsView > ( ) ; } } ,
{ " Audio " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_speaker , [ this ] ( ) { nav_ . push < SetAudioView > ( ) ; } } ,
{ " Calibration " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_touch , [ this ] ( ) { nav_ . push < TouchCalibrationView > ( ) ; } } ,
2024-10-16 12:39:59 -04:00
{ " TouchThreshold " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_touch , [ this ] ( ) { nav_ . push < SetTouchscreenThresholdView > ( ) ; } } ,
2024-03-10 15:49:36 -04:00
{ " Config Mode " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_clk_ext , [ this ] ( ) { nav_ . push < SetConfigModeView > ( ) ; } } ,
{ " Converter " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_radio , [ this ] ( ) { nav_ . push < SetConverterSettingsView > ( ) ; } } ,
{ " Date/Time " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_datetime , [ this ] ( ) { nav_ . push < SetDateTimeView > ( ) ; } } ,
{ " Encoder Dial " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_setup , [ this ] ( ) { nav_ . push < SetEncoderDialView > ( ) ; } } ,
{ " Freq. Correct " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_radio , [ this ] ( ) { nav_ . push < SetFrequencyCorrectionView > ( ) ; } } ,
{ " P.Memory Mgmt " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_memory , [ this ] ( ) { nav_ . push < SetPersistentMemoryView > ( ) ; } } ,
{ " Radio " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_radio , [ this ] ( ) { nav_ . push < SetRadioView > ( ) ; } } ,
{ " SD Card " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_sdcard , [ this ] ( ) { nav_ . push < SetSDCardView > ( ) ; } } ,
{ " User Interface " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_ui , [ this ] ( ) { nav_ . push < SetUIView > ( ) ; } } ,
2024-03-21 11:56:06 -04:00
//{"QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [this]() { nav_.push<SetQRCodeView>(); }},
2024-09-07 04:58:57 -04:00
{ " Display " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_brightness , [ this ] ( ) { nav_ . push < SetDisplayView > ( ) ; } } ,
2024-03-10 15:49:36 -04:00
{ " Menu Color " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_brightness , [ this ] ( ) { nav_ . push < SetMenuColorView > ( ) ; } } ,
2024-05-27 15:02:52 -04:00
{ " Theme " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_setup , [ this ] ( ) { nav_ . push < SetThemeView > ( ) ; } } ,
2024-04-03 10:27:13 -04:00
{ " Autostart " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_setup , [ this ] ( ) { nav_ . push < SetAutostartView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
} ) ;
2024-09-20 05:59:17 -04:00
if ( battery : : BatteryManagement : : isDetected ( ) ) add_item ( { " Battery " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_batt_icon , [ this ] ( ) { nav_ . push < SetBatteryView > ( ) ; } } ) ;
2023-05-18 16:16:05 -04:00
}
2015-07-08 11:39:24 -04:00
} /* namespace ui */