2015-07-08 08:39:24 -07:00
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
2016-12-09 18:21:47 +01:00
* Copyright (C) 2016 Furrtek
2023-05-22 22:17:28 +02:00
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
2023-09-10 17:04:20 -07:00
* Copyright (C) 2023 Kyle Reed
2024-02-10 02:32:03 -06:00
* Copyright (C) 2024 Mark Thompson
2024-03-10 14:49:36 -05:00
* Copyright (C) 2024 u-foka
2024-10-07 03:58:03 +08:00
* Copyright (C) 2024 HTotoo
2025-08-26 19:56:39 +08:00
* copyleft 2024 zxkmm AKA zix aka sommermorgentraum
2015-07-08 08:39:24 -07: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 09:45:13 +01:00
#include "ui_settings.hpp"
2016-02-04 10:27:53 +01:00
2016-12-26 13:49:23 +01:00
#include "ui_navigation.hpp"
2023-06-23 16:13:39 -07:00
#include "ui_receiver.hpp"
2016-07-27 14:15:21 -07:00
#include "ui_touch_calibration.hpp"
2024-01-12 06:41:13 -06:00
#include "ui_text_editor.hpp"
2024-04-03 16:27:13 +02:00
#include "ui_external_items_menu_loader.hpp"
2016-07-27 14:15:21 -07:00
2015-08-04 10:03:18 -07:00
#include "portapack_persistent_memory.hpp"
2015-07-08 08:39:24 -07:00
#include "lpc43xx_cpp.hpp"
using namespace lpc43xx ;
2016-01-31 09:34:24 +01:00
2020-06-08 01:23:23 +02:00
#include "audio.hpp"
2016-01-31 09:34:24 +01:00
#include "portapack.hpp"
2025-10-03 19:10:10 +02:00
#include "portapack_io.hpp"
2016-07-27 03:03:40 +02:00
using namespace portapack ;
2016-01-23 11:32:10 -08:00
2023-07-02 09:35:34 -07:00
#include "file.hpp"
2024-03-25 02:44:49 -05:00
#include "file_path.hpp"
2023-07-02 09:35:34 -07:00
namespace fs = std :: filesystem ;
2016-07-27 03:03:40 +02:00
#include "string_format.hpp"
2024-02-16 00:19:43 -06:00
#include "ui_font_fixed_8x16.hpp"
2016-07-17 15:56:24 -07:00
#include "cpld_update.hpp"
2024-01-16 23:59:35 -06:00
#include "config_mode.hpp"
2024-10-06 22:14:27 +02:00
#include "i2cdevmanager.hpp"
#include "i2cdev_max17055.hpp"
2015-07-08 08:39:24 -07:00
2024-12-27 19:01:33 +08:00
#include "file_reader.hpp"
2024-05-27 21:02:52 +02:00
extern ui :: SystemView * system_view_ptr ;
2023-06-23 16:13:39 -07:00
namespace pmem = portapack :: persistent_memory ;
2023-03-22 08:46:58 +01:00
2015-07-08 08:39:24 -07:00
namespace ui {
2023-06-23 16:13:39 -07: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-19 08:16:05 +12:00
SetDateTimeView :: SetDateTimeView (
NavigationView & nav ) {
button_save . on_select = [ & nav , this ]( Button & ) {
const auto model = this -> form_collect ();
2024-01-21 12:47:28 -06: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-19 08:16:05 +12: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 12:47:28 -06:00
& text_weekday ,
& text_day_of_year ,
2024-02-06 14:25:44 -06:00
& text_in_dst_range ,
2024-01-21 12:47:28 -06: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-19 08:16:05 +12:00
& button_save ,
& button_cancel ,
});
2024-01-21 12:47:28 -06: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 14:25:44 -06:00
const auto dst_changed_fn = [ this ]( size_t , uint32_t ) {
handle_date_field_update ();
};
2024-01-21 12:47:28 -06:00
const auto date_changed_fn = [ this ]( int32_t ) {
2024-02-06 14:25:44 -06:00
handle_date_field_update ();
2024-01-21 12:47:28 -06: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 14:25:44 -06: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-19 08:16:05 +12:00
rtc :: RTC datetime ;
2024-01-21 12:47:28 -06:00
rtc_time :: now ( datetime );
2023-05-19 08:16:05 +12:00
SetDateTimeModel model {
datetime . year (),
datetime . month (),
datetime . day (),
datetime . hour (),
datetime . minute (),
2024-01-21 12:47:28 -06:00
datetime . second (),
pmem :: config_dst ()};
2023-05-19 08:16:05 +12: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 12:47:28 -06: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-19 08:16:05 +12:00
}
SetDateTimeModel SetDateTimeView :: form_collect () {
2024-02-06 14:25:44 -06: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 12:47:28 -06: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 14:25:44 -06: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-19 08:16:05 +12:00
}
2023-06-23 16:13:39 -07:00
/* SetRadioView ******************************************/
2023-05-19 08:16:05 +12:00
SetRadioView :: SetRadioView (
NavigationView & nav ) {
button_cancel . on_select = [ & nav ]( Button & ) {
nav . pop ();
};
2023-09-10 17:04:20 -07: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 16:13:39 -07:00
const auto reference = clock_manager . get_reference ();
2023-05-19 08:16:05 +12:00
2023-09-10 17:04:20 -07:00
if ( reference . source == ClockManager :: ReferenceSource :: Xtal ) {
add_children ({
& labels_correction ,
& field_ppm ,
});
}
2024-01-02 07:25:36 +13:00
std :: string source_name = clock_manager . get_source ();
2023-05-19 08:16:05 +12:00
value_source . set ( source_name );
2024-01-02 07:25:36 +13:00
value_source_frequency . set ( clock_manager . get_freq ());
2023-05-19 08:16:05 +12:00
2023-09-10 17:04:20 -07:00
// Make these Text controls look like Labels.
2024-05-27 21:02:52 +02: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-19 08:16:05 +12:00
SetFrequencyCorrectionModel model {
2023-06-23 16:13:39 -07:00
static_cast < int8_t > ( pmem :: correction_ppb () / 1000 ), 0 };
2023-05-19 08:16:05 +12:00
form_init ( model );
2023-06-23 16:13:39 -07:00
check_clkout . set_value ( pmem :: clkout_enabled ());
2023-05-19 08:16:05 +12:00
check_clkout . on_select = [ this ]( Checkbox & , bool v ) {
clock_manager . enable_clock_output ( v );
2023-06-23 16:13:39 -07:00
pmem :: set_clkout_enabled ( v );
send_system_refresh ();
2023-05-19 08:16:05 +12:00
};
2023-12-24 10:28:22 -06: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 16:13:39 -07:00
field_clkout_freq . set_value ( pmem :: clkout_freq ());
2023-12-24 01:55:15 -06:00
field_clkout_freq . on_change = [ this ]( SymField & ) {
2023-12-26 07:11:14 +01: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 01:55:15 -06:00
if ( field_clkout_freq . to_integer () > 60000 )
field_clkout_freq . set_value ( 60000 );
2023-05-19 08:16:05 +12:00
};
2023-06-23 16:13:39 -07:00
check_bias . set_value ( get_antenna_bias ());
2023-05-19 08:16:05 +12:00
check_bias . on_select = [ this ]( Checkbox & , bool v ) {
2023-06-23 16:13:39 -07:00
set_antenna_bias ( v );
2023-05-23 21:22:30 -07: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 16:13:39 -07:00
send_system_refresh ();
2023-05-19 08:16:05 +12:00
};
2023-09-04 17:46:07 +02:00
disable_external_tcxo . set_value ( pmem :: config_disable_external_tcxo ());
2023-05-19 08:16:05 +12:00
button_save . on_select = [ this , & nav ]( Button & ) {
const auto model = this -> form_collect ();
2023-06-23 16:13:39 -07:00
pmem :: set_correction_ppb ( model . ppm * 1000 );
pmem :: set_clkout_freq ( model . freq );
2023-09-04 17:46:07 +02:00
pmem :: set_config_disable_external_tcxo ( disable_external_tcxo . value ());
2023-06-23 16:13:39 -07:00
clock_manager . enable_clock_output ( pmem :: clkout_enabled ());
2023-05-19 08:16:05 +12: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 01:55:15 -06:00
. freq = static_cast < uint32_t > ( field_clkout_freq . to_integer ()),
2023-05-19 08:16:05 +12:00
};
}
2023-06-23 16:13:39 -07:00
/* SetUIView *********************************************/
2023-05-19 08:16:05 +12: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 16:13:39 -07:00
& labels ,
& toggle_camera ,
& toggle_sleep ,
& toggle_stealth ,
& toggle_converter ,
& toggle_bias_tee ,
& toggle_clock ,
2023-06-26 01:08:09 -05:00
& toggle_mute ,
2024-12-26 23:23:02 +01:00
& toggle_fake_brightness ,
2023-06-23 16:13:39 -07:00
& toggle_sd_card ,
2023-05-19 08:16:05 +12:00
& button_save ,
& button_cancel });
2023-06-26 01:08:09 -05: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 17:38:27 +02:00
if ( battery :: BatteryManagement :: isDetected ()) {
add_child ( & toggle_battery_icon );
add_child ( & toggle_battery_text );
}
2023-06-26 01:08:09 -05:00
2023-06-23 16:13:39 -07: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-19 08:16:05 +12:00
2023-06-23 16:13:39 -07:00
const auto backlight_config = pmem :: config_backlight_timer ();
2023-05-19 08:16:05 +12:00
checkbox_bloff . set_value ( backlight_config . timeout_enabled ());
options_bloff . set_by_value ( backlight_config . timeout_enum ());
2023-06-23 16:13:39 -07:00
if ( pmem :: clock_with_date ()) {
2023-05-19 08:16:05 +12:00
options_clockformat . set_selected_index ( 1 );
} else {
options_clockformat . set_selected_index ( 0 );
}
2023-06-23 16:13:39 -07: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 01:08:09 -05:00
toggle_mute . set_value ( ! pmem :: ui_hide_mute ());
2024-12-26 23:23:02 +01:00
toggle_fake_brightness . set_value ( ! pmem :: ui_hide_fake_brightness ());
2024-04-29 17:38:27 +02:00
toggle_battery_icon . set_value ( ! pmem :: ui_hide_battery_icon ());
toggle_battery_text . set_value ( ! pmem :: ui_hide_numeric_battery ());
2023-06-23 16:13:39 -07:00
toggle_sd_card . set_value ( ! pmem :: ui_hide_sd_card ());
2023-05-19 08:16:05 +12:00
button_save . on_select = [ & nav , this ]( Button & ) {
2023-06-23 16:13:39 -07:00
pmem :: set_config_backlight_timer ({( pmem :: backlight_timeout_t ) options_bloff . selected_index_value (),
checkbox_bloff . value ()});
2023-05-19 08:16:05 +12:00
if ( checkbox_showclock . value ()) {
if ( options_clockformat . selected_index () == 1 )
2023-06-23 16:13:39 -07:00
pmem :: set_clock_with_date ( true );
2023-05-19 08:16:05 +12:00
else
2023-06-23 16:13:39 -07:00
pmem :: set_clock_with_date ( false );
2023-05-19 08:16:05 +12:00
}
2023-06-23 16:13:39 -07: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 01:08:09 -05:00
pmem :: set_ui_hide_mute ( ! toggle_mute . value ());
2024-12-26 23:23:02 +01:00
pmem :: set_ui_hide_fake_brightness ( ! toggle_fake_brightness . value ());
2024-04-29 17:38:27 +02:00
pmem :: set_ui_hide_battery_icon ( ! toggle_battery_icon . value ());
pmem :: set_ui_hide_numeric_battery ( ! toggle_battery_text . value ());
2023-06-23 16:13:39 -07:00
pmem :: set_ui_hide_sd_card ( ! toggle_sd_card . value ());
send_system_refresh ();
2023-05-19 08:16:05 +12:00
nav . pop ();
};
button_cancel . on_select = [ & nav , this ]( Button & ) {
nav . pop ();
};
}
void SetUIView :: focus () {
button_save . focus ();
}
2023-11-19 15:08:29 +01: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 16:13:39 -07:00
/* SetConverterSettingsView ******************************/
2023-05-19 08:16:05 +12:00
SetConverterSettingsView :: SetConverterSettingsView ( NavigationView & nav ) {
2023-09-10 17:04:20 -07:00
add_children ({
& labels ,
& check_show_converter ,
& check_converter ,
& opt_converter_mode ,
& field_converter_freq ,
& button_return ,
});
2023-05-19 08:16:05 +12:00
2023-06-23 16:13:39 -07:00
check_show_converter . set_value ( ! pmem :: ui_hide_converter ());
2023-05-19 08:16:05 +12:00
check_show_converter . on_select = [ this ]( Checkbox & , bool v ) {
2023-06-23 16:13:39 -07:00
pmem :: set_ui_hide_converter ( ! v );
2023-05-19 08:16:05 +12:00
if ( ! v ) {
check_converter . set_value ( false );
}
2023-06-11 11:47:13 -07:00
// Retune to take converter change in account.
receiver_model . set_target_frequency ( receiver_model . target_frequency ());
2023-09-10 17:04:20 -07:00
// Refresh status bar converter icon.
2023-06-23 16:13:39 -07:00
send_system_refresh ();
2023-05-19 08:16:05 +12:00
};
2023-06-23 16:13:39 -07:00
check_converter . set_value ( pmem :: config_converter ());
2023-05-19 08:16:05 +12:00
check_converter . on_select = [ this ]( Checkbox & , bool v ) {
if ( v ) {
check_show_converter . set_value ( true );
2023-06-23 16:13:39 -07:00
pmem :: set_ui_hide_converter ( false );
2023-05-19 08:16:05 +12:00
}
2023-06-23 16:13:39 -07:00
pmem :: set_config_converter ( v );
2023-09-10 17:04:20 -07:00
// Retune to take converter change in account.
2023-06-11 11:47:13 -07:00
receiver_model . set_target_frequency ( receiver_model . target_frequency ());
2023-09-10 17:04:20 -07:00
// Refresh status bar converter icon.
2023-06-23 16:13:39 -07:00
send_system_refresh ();
2023-05-19 08:16:05 +12:00
};
2023-09-10 17:04:20 -07: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 16:13:39 -07:00
pmem :: set_config_updown_converter ( v );
2023-09-10 17:04:20 -07:00
// Refresh status bar with up or down icon.
2023-06-23 16:13:39 -07:00
send_system_refresh ();
2023-05-19 08:16:05 +12:00
};
2023-09-10 17:04:20 -07: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-19 08:16:05 +12:00
};
};
2023-05-20 09:30:08 +02:00
button_return . on_select = [ & nav , this ]( Button & ) {
2023-05-19 08:16:05 +12:00
nav . pop ();
};
}
void SetConverterSettingsView :: focus () {
2023-05-20 09:30:08 +02:00
button_return . focus ();
}
2023-06-23 16:13:39 -07:00
/* SetFrequencyCorrectionView ****************************/
2023-05-20 09:30:08 +02:00
SetFrequencyCorrectionView :: SetFrequencyCorrectionView ( NavigationView & nav ) {
2023-09-10 17:04:20 -07:00
add_children ({
& labels ,
& opt_rx_correction_mode ,
& field_rx_correction ,
& opt_tx_correction_mode ,
& field_tx_correction ,
& button_return ,
});
2023-05-20 09:30:08 +02:00
2023-09-10 17:04:20 -07:00
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 16:13:39 -07:00
pmem :: set_freq_rx_correction_updown ( v );
2023-05-20 09:30:08 +02:00
};
2023-12-18 01:47:20 +01:00
opt_tx_correction_mode . set_by_value ( pmem :: config_freq_tx_correction_updown ());
2023-09-10 17:04:20 -07:00
opt_tx_correction_mode . on_change = [ this ]( size_t , OptionsField :: value_t v ) {
2023-06-23 16:13:39 -07:00
pmem :: set_freq_tx_correction_updown ( v );
2023-05-20 09:30:08 +02:00
};
2023-09-10 17:04:20 -07: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 09:30:08 +02:00
};
};
2023-09-10 17:04:20 -07: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 09:30:08 +02:00
};
};
button_return . on_select = [ & nav , this ]( Button & ) {
nav . pop ();
};
}
void SetFrequencyCorrectionView :: focus () {
button_return . focus ();
2023-05-19 08:16:05 +12:00
}
2023-06-23 16:13:39 -07:00
/* SetPersistentMemoryView *******************************/
2023-05-19 08:16:05 +12:00
SetPersistentMemoryView :: SetPersistentMemoryView ( NavigationView & nav ) {
2023-09-10 17:04:20 -07: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 21:02:52 +02:00
text_pmem_status . set_style ( Theme :: getInstance () -> fg_yellow );
2023-05-19 08:16:05 +12:00
2023-06-23 16:13:39 -07:00
check_use_sdcard_for_pmem . set_value ( pmem :: should_use_sdcard_for_pmem ());
2023-06-04 21:25:25 +02:00
check_use_sdcard_for_pmem . on_select = [ this ]( Checkbox & , bool v ) {
2023-05-19 08:16:05 +12:00
File pmem_flag_file_handle ;
if ( v ) {
2024-03-25 02:44:49 -05:00
if ( fs :: file_exists ( settings_dir / PMEM_FILEFLAG )) {
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "P.Mem flag file present." );
2023-07-02 09:35:34 -07:00
} else {
2024-03-25 02:44:49 -05:00
auto error = pmem_flag_file_handle . create ( settings_dir / PMEM_FILEFLAG );
2023-07-02 09:35:34 -07:00
if ( error )
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "Error creating P.Mem File!" );
2023-07-02 09:35:34 -07:00
else
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "P.Mem flag file created." );
2023-05-19 08:16:05 +12:00
}
} else {
2024-03-25 02:44:49 -05:00
auto result = delete_file ( settings_dir / PMEM_FILEFLAG );
2023-07-02 09:35:34 -07:00
if ( result . code () != FR_OK )
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "Error deleting P.Mem flag!" );
2023-07-02 09:35:34 -07:00
else
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "P.Mem flag file deleted." );
2023-05-19 08:16:05 +12:00
}
};
button_save_mem_to_file . on_select = [ & nav , this ]( Button & ) {
2023-07-02 09:35:34 -07:00
if ( ! pmem :: save_persistent_settings_to_file ())
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "Error saving settings!" );
2023-07-02 09:35:34 -07:00
else
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "Settings saved." );
2023-05-19 08:16:05 +12:00
};
button_load_mem_from_file . on_select = [ & nav , this ]( Button & ) {
2023-06-23 16:13:39 -07:00
if ( ! pmem :: load_persistent_settings_from_file ()) {
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "Error loading settings!" );
2023-05-19 08:16:05 +12:00
} else {
2023-09-10 17:04:20 -07:00
text_pmem_status . set ( "Settings loaded." );
2023-05-19 08:16:05 +12:00
// Refresh status bar with icon up or down
2023-06-23 16:13:39 -07:00
send_system_refresh ();
2023-05-19 08:16:05 +12:00
}
};
button_load_mem_defaults . on_select = [ & nav , this ]( Button & ) {
nav . push < ModalMessageView > (
"Warning!" ,
2023-09-10 17:04:20 -07:00
"This will reset the P.Mem \n to default settings." ,
2023-05-19 08:16:05 +12:00
YESNO ,
[ this ]( bool choice ) {
if ( choice ) {
2023-06-23 16:13:39 -07:00
pmem :: cache :: defaults ();
2024-02-15 08:00:25 -06:00
// Refresh status bar
send_system_refresh ();
2023-05-19 08:16:05 +12:00
}
});
};
button_return . on_select = [ & nav , this ]( Button & ) {
nav . pop ();
};
}
void SetPersistentMemoryView :: focus () {
button_return . focus ();
}
2023-06-23 16:13:39 -07:00
/* SetAudioView ******************************************/
2023-05-19 08:16:05 +12:00
SetAudioView :: SetAudioView ( NavigationView & nav ) {
add_children ({ & labels ,
& field_tone_mix ,
2024-03-29 13:26:45 -05:00
& checkbox_beep_on_packets ,
2023-05-19 08:16:05 +12:00
& button_save ,
& button_cancel });
2023-06-23 16:13:39 -07:00
field_tone_mix . set_value ( pmem :: tone_mix ());
2023-05-19 08:16:05 +12:00
2024-03-29 13:26:45 -05:00
checkbox_beep_on_packets . set_value ( pmem :: beep_on_packets ());
2023-05-19 08:16:05 +12:00
button_save . on_select = [ & nav , this ]( Button & ) {
2023-06-23 16:13:39 -07:00
pmem :: set_tone_mix ( field_tone_mix . value ());
2024-03-29 13:26:45 -05:00
pmem :: set_beep_on_packets ( checkbox_beep_on_packets . value ());
2023-06-19 14:06:07 -05:00
audio :: output :: update_audio_mute ();
2023-05-19 08:16:05 +12:00
nav . pop ();
};
button_cancel . on_select = [ & nav , this ]( Button & ) {
nav . pop ();
};
}
void SetAudioView :: focus () {
button_save . focus ();
}
2023-06-23 16:13:39 -07:00
/* SetEncoderDialView ************************************/
2023-05-24 21:32:12 -05:00
SetEncoderDialView :: SetEncoderDialView ( NavigationView & nav ) {
add_children ({ & labels ,
& field_encoder_dial_sensitivity ,
2024-02-10 02:32:03 -06:00
& field_encoder_rate_multiplier ,
2023-05-24 21:32:12 -05:00
& button_save ,
2025-10-28 10:34:14 +01:00
& button_cancel ,
& button_dial_sensitivity_plus ,
& button_dial_sensitivity_minus ,
& button_rate_multiplier_plus ,
& button_rate_multiplier_minus ,
& field_encoder_dial_direction });
2023-05-24 21:32:12 -05:00
2024-02-10 02:32:03 -06:00
field_encoder_dial_sensitivity . set_by_value ( pmem :: encoder_dial_sensitivity ());
field_encoder_rate_multiplier . set_value ( pmem :: encoder_rate_multiplier ());
2025-01-09 04:02:05 +08:00
field_encoder_dial_direction . set_by_value ( pmem :: encoder_dial_direction ());
2025-10-28 10:34:14 +01:00
button_dial_sensitivity_plus . on_select = [ this ]( Button & ) {
field_encoder_dial_sensitivity . on_encoder ( 1 );
};
button_dial_sensitivity_minus . on_select = [ this ]( Button & ) {
field_encoder_dial_sensitivity . on_encoder ( - 1 );
};
button_rate_multiplier_plus . on_select = [ this ]( Button & ) {
field_encoder_rate_multiplier . on_encoder ( 1 );
};
button_rate_multiplier_minus . on_select = [ this ]( Button & ) {
field_encoder_rate_multiplier . on_encoder ( - 1 );
};
2024-12-28 05:04:11 +08:00
2023-05-24 21:32:12 -05:00
button_save . on_select = [ & nav , this ]( Button & ) {
2023-06-23 16:13:39 -07:00
pmem :: set_encoder_dial_sensitivity ( field_encoder_dial_sensitivity . selected_index_value ());
2024-02-10 02:32:03 -06:00
pmem :: set_encoder_rate_multiplier ( field_encoder_rate_multiplier . value ());
2025-01-09 04:02:05 +08:00
pmem :: set_encoder_dial_direction ( field_encoder_dial_direction . selected_index_value ());
2023-05-24 21:32:12 -05:00
nav . pop ();
};
button_cancel . on_select = [ & nav , this ]( Button & ) {
nav . pop ();
};
}
void SetEncoderDialView :: focus () {
button_save . focus ();
}
2025-03-11 09:13:41 -05:00
/* SetButtonsView ************************************/
SetButtonsView :: SetButtonsView ( NavigationView & nav ) {
add_children ({ & labels ,
& button_save ,
& button_cancel ,
& field_repeat_delay ,
& field_repeat_speed ,
& field_long_press_delay });
field_repeat_delay . set_by_value ( pmem :: ui_button_repeat_delay ());
field_repeat_speed . set_by_value ( pmem :: ui_button_repeat_speed ());
field_long_press_delay . set_by_value ( pmem :: ui_button_long_press_delay ());
button_save . on_select = [ & nav , this ]( Button & ) {
pmem :: set_ui_button_repeat_delay ( field_repeat_delay . selected_index_value ());
pmem :: set_ui_button_repeat_speed ( field_repeat_speed . selected_index_value ());
pmem :: set_ui_button_long_press_delay ( field_long_press_delay . selected_index_value ());
nav . pop ();
};
button_cancel . on_select = [ & nav , this ]( Button & ) {
nav . pop ();
};
}
void SetButtonsView :: focus () {
button_save . focus ();
}
2024-01-12 06:41:13 -06:00
/* AppSettingsView ************************************/
AppSettingsView :: AppSettingsView (
NavigationView & nav )
: nav_ { nav } {
add_children ({ & labels ,
& menu_view });
2025-10-03 19:10:10 +02:00
menu_view . set_parent_rect ({ 0 , 3 * 8 , screen_width , UI_POS_HEIGHT_REMAINING ( 3 )});
2024-01-12 06:41:13 -06:00
2024-03-25 02:44:49 -05:00
ensure_directory ( settings_dir );
2024-01-12 06:41:13 -06:00
2024-03-25 02:44:49 -05:00
for ( const auto & entry : std :: filesystem :: directory_iterator ( settings_dir , u "*.ini" )) {
auto path = settings_dir / entry . path ();
2024-01-12 06:41:13 -06:00
menu_view . add_item ({ path . filename (). string (). substr ( 0 , 26 ),
2024-05-27 21:02:52 +02:00
ui :: Theme :: getInstance () -> fg_darkcyan -> foreground ,
2024-01-12 06:41:13 -06:00
& bitmap_icon_file_text ,
[ this , path ]( KeyEvent ) {
nav_ . push < TextEditorView > ( path );
}});
}
}
void AppSettingsView :: focus () {
menu_view . focus ();
}
2024-01-16 23:59:35 -06: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 10:58:57 +02:00
/* SetDisplayView ************************************/
2024-02-07 16:07:30 +08:00
2024-09-07 10:58:57 +02:00
SetDisplayView :: SetDisplayView ( NavigationView & nav ) {
2024-12-26 23:23:02 +01:00
add_children ({ & labels ,
& field_fake_brightness ,
& button_save ,
2024-02-07 16:07:30 +08:00
& button_cancel ,
2024-12-26 23:23:02 +01:00
& checkbox_brightness_switch });
2024-02-07 16:07:30 +08:00
2025-10-03 19:10:10 +02:00
if ( portapack :: device_type == portapack :: DeviceType :: DEV_PORTAPACK ) {
add_child ( & checkbox_ips_screen_switch );
}
2024-12-26 23:23:02 +01:00
field_fake_brightness . set_by_value ( pmem :: fake_brightness_level ());
checkbox_brightness_switch . set_value ( pmem :: apply_fake_brightness ());
2025-04-17 13:40:28 +08:00
checkbox_ips_screen_switch . set_value ( pmem :: config_lcd_normally_black ());
2024-02-07 16:07:30 +08:00
button_save . on_select = [ & nav , this ]( Button & ) {
2024-12-26 23:23:02 +01:00
pmem :: set_apply_fake_brightness ( checkbox_brightness_switch . value ());
pmem :: set_fake_brightness_level ( field_fake_brightness . selected_index_value ());
2025-04-17 13:40:28 +08:00
if ( checkbox_ips_screen_switch . value () != pmem :: config_lcd_normally_black ()) {
pmem :: set_lcd_normally_black ( checkbox_ips_screen_switch . value ());
2024-09-07 10:58:57 +02:00
}
2024-02-08 18:28:49 +01:00
send_system_refresh ();
2024-02-07 16:07:30 +08:00
nav . pop ();
};
2024-12-26 23:23:02 +01:00
// only enable invert OR fake brightness
2025-04-17 13:40:28 +08:00
checkbox_ips_screen_switch . on_select = [ this ]( Checkbox & , bool v ) {
2024-12-26 23:23:02 +01:00
if ( v ) checkbox_brightness_switch . set_value ( false );
};
checkbox_brightness_switch . on_select = [ this ]( Checkbox & , bool v ) {
2025-04-17 13:40:28 +08:00
if ( v ) checkbox_ips_screen_switch . set_value ( false );
2024-12-26 23:23:02 +01:00
};
2024-02-07 16:07:30 +08:00
button_cancel . on_select = [ & nav , this ]( Button & ) {
nav . pop ();
};
}
2024-09-07 10:58:57 +02:00
void SetDisplayView :: focus () {
2024-02-07 16:07:30 +08:00
button_save . focus ();
}
2024-10-17 00:39:59 +08: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 00:19:43 -06: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 17:38:27 +02:00
& button_reset ,
2024-02-16 00:19:43 -06: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 17:38:27 +02: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 00:19:43 -06: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-05-27 21:02:52 +02: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 11:32:24 +02:00
/* SetBatteryView ************************************/
SetBatteryView :: SetBatteryView ( NavigationView & nav ) {
add_children ({ & labels ,
& button_save ,
& button_cancel ,
2025-04-06 10:24:50 +08:00
& checkbox_overridebatt ,
& checkbox_battery_charge_hint });
2024-08-28 11:32:24 +02:00
2024-10-06 22:14:27 +02:00
if ( i2cdev :: I2CDevManager :: get_dev_by_model ( I2C_DEVMDL :: I2CDEVMDL_MAX17055 )) add_children ({ & button_reset , & labels2 });
2024-09-20 21:59:17 +12:00
2024-08-28 11:32:24 +02:00
button_save . on_select = [ & nav , this ]( Button & ) {
pmem :: set_ui_override_batt_calc ( checkbox_overridebatt . value ());
2025-04-06 10:24:50 +08:00
pmem :: set_ui_battery_charge_hint ( checkbox_battery_charge_hint . value ());
2024-08-28 11:32:24 +02:00
battery :: BatteryManagement :: set_calc_override ( checkbox_overridebatt . value ());
send_system_refresh ();
nav . pop ();
};
2024-09-20 21:59:17 +12:00
button_reset . on_select = [ & nav , this ]( Button & ) {
2024-10-06 22:14:27 +02:00
auto dev = ( i2cdev :: I2cDev_MAX17055 * ) i2cdev :: I2CDevManager :: get_dev_by_model ( I2C_DEVMDL :: I2CDEVMDL_MAX17055 );
if ( dev -> reset_learned ())
2024-09-20 21:59:17 +12:00
nav . display_modal ( "Reset" , "Battery parameters reset" );
else
nav . display_modal ( "Error" , "Error parameter reset" );
};
2024-08-28 11:32:24 +02:00
checkbox_overridebatt . set_value ( pmem :: ui_override_batt_calc ());
2025-04-06 10:24:50 +08:00
checkbox_battery_charge_hint . set_value ( pmem :: ui_battery_charge_hint ());
2024-08-28 11:32:24 +02:00
button_cancel . on_select = [ & nav , this ]( Button & ) {
nav . pop ();
};
}
void SetBatteryView :: focus () {
button_cancel . focus ();
}
2023-06-23 16:13:39 -07:00
/* SettingsMenuView **************************************/
2024-03-10 14:49:36 -05:00
SettingsMenuView :: SettingsMenuView ( NavigationView & nav )
: nav_ ( nav ) {
2023-05-19 08:16:05 +12:00
set_max_rows ( 2 ); // allow wider buttons
}
2015-07-08 08:39:24 -07:00
2024-03-10 14:49:36 -05:00
void SettingsMenuView :: on_populate () {
2024-12-27 19:01:33 +08:00
const bool return_icon = pmem :: show_gui_return_icon ();
if ( return_icon ) {
2024-03-10 14:49:36 -05:00
add_items ({{ ".." , ui :: Color :: light_grey (), & bitmap_icon_previous , [ this ]() { nav_ . pop (); }}});
}
2024-12-27 19:01:33 +08:00
2024-03-10 14:49:36 -05:00
add_items ({
{ "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-17 00:39:59 +08:00
{ "TouchThreshold" , ui :: Color :: dark_cyan (), & bitmap_icon_options_touch , [ this ]() { nav_ . push < SetTouchscreenThresholdView > (); }},
2024-03-10 14:49:36 -05: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 > (); }},
2025-03-11 09:13:41 -05:00
{ "Button Speed" , ui :: Color :: dark_cyan (), & bitmap_icon_controls , [ this ]() { nav_ . push < SetButtonsView > (); }},
2024-03-10 14:49:36 -05:00
{ "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-09-07 10:58:57 +02:00
{ "Display" , ui :: Color :: dark_cyan (), & bitmap_icon_brightness , [ this ]() { nav_ . push < SetDisplayView > (); }},
2024-03-10 14:49:36 -05:00
{ "Menu Color" , ui :: Color :: dark_cyan (), & bitmap_icon_brightness , [ this ]() { nav_ . push < SetMenuColorView > (); }},
2024-05-27 21:02:52 +02:00
{ "Theme" , ui :: Color :: dark_cyan (), & bitmap_icon_setup , [ this ]() { nav_ . push < SetThemeView > (); }},
2024-03-10 14:49:36 -05:00
});
2024-12-27 19:01:33 +08:00
2024-09-20 21:59:17 +12:00
if ( battery :: BatteryManagement :: isDetected ()) add_item ({ "Battery" , ui :: Color :: dark_cyan (), & bitmap_icon_batt_icon , [ this ]() { nav_ . push < SetBatteryView > (); }});
2024-12-27 19:01:33 +08:00
add_external_items ( nav_ , app_location_t :: SETTINGS , * this , return_icon ? 1 : 0 );
2024-03-10 14:49:36 -05:00
}
2015-07-08 08:39:24 -07:00
} /* namespace ui */