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
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"
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"
namespace fs = std : : filesystem ;
2016-07-26 21:03:40 -04:00
# include "string_format.hpp"
2023-06-07 11:33:32 -04:00
# include "ui_styles.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"
2015-07-08 11:39:24 -04:00
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 ,
& 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 ) ;
const auto date_changed_fn = [ this ] ( int32_t ) {
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 ) : " - " ) ;
} ;
field_year . on_change = date_changed_fn ;
field_month . on_change = date_changed_fn ;
field_day . on_change = date_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-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 ( ) ) ;
2023-05-18 16:16:05 -04: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 ( ) ) ,
2024-01-21 13:47:28 -05:00
. second = static_cast < uint8_t > ( field_second . value ( ) ) ,
. dst = 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.
2023-06-07 11:33:32 -04:00
label_source . set_style ( & Styles : : light_grey ) ;
value_source . set_style ( & Styles : : light_grey ) ;
value_source_frequency . set_style ( & Styles : : light_grey ) ;
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 ) ;
}
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 ( ) ) ;
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 ( ) ) ;
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 ,
} ) ;
text_pmem_status . set_style ( & Styles : : 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 ) {
2023-07-02 12:35:34 -04:00
if ( fs : : file_exists ( 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 {
auto error = pmem_flag_file_handle . create ( PMEM_FILEFLAG ) ;
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 {
2023-07-02 12:35:34 -04:00
auto result = delete_file ( PMEM_FILEFLAG ) ;
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 ( ) ;
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 ,
& 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
button_save . on_select = [ & nav , this ] ( Button & ) {
2023-06-23 19:13:39 -04:00
pmem : : set_tone_mix ( field_tone_mix . 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 ,
& button_save ,
& button_cancel } ) ;
2023-06-23 19:13:39 -04:00
field_encoder_dial_sensitivity . set_by_value ( pmem : : config_encoder_dial_sensitivity ( ) ) ;
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 ( ) ) ;
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 } ) ;
ensure_directory ( SETTINGS_DIR ) ;
for ( const auto & entry : std : : filesystem : : directory_iterator ( SETTINGS_DIR , u " *.ini " ) ) {
auto path = ( std : : filesystem : : path ) SETTINGS_DIR / entry . path ( ) ;
menu_view . add_item ( { path . filename ( ) . string ( ) . substr ( 0 , 26 ) ,
ui : : Color : : dark_cyan ( ) ,
& 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 ( ) ;
}
2023-06-23 19:13:39 -04:00
/* SettingsMenuView **************************************/
2023-05-18 16:16:05 -04:00
SettingsMenuView : : SettingsMenuView ( NavigationView & nav ) {
2023-06-23 19:13:39 -04:00
if ( pmem : : show_gui_return_icon ( ) ) {
2023-05-18 16:16:05 -04:00
add_items ( { { " .. " , ui : : Color : : light_grey ( ) , & bitmap_icon_previous , [ & nav ] ( ) { nav . pop ( ) ; } } } ) ;
}
add_items ( {
2024-01-12 07:41:13 -05:00
{ " App Settings " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_notepad , [ & nav ] ( ) { nav . push < AppSettingsView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
{ " Audio " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_speaker , [ & nav ] ( ) { nav . push < SetAudioView > ( ) ; } } ,
{ " Calibration " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_touch , [ & nav ] ( ) { nav . push < TouchCalibrationView > ( ) ; } } ,
2024-01-17 00:59:35 -05:00
{ " Config Mode " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_clk_ext , [ & nav ] ( ) { nav . push < SetConfigModeView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
{ " Converter " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_radio , [ & nav ] ( ) { nav . push < SetConverterSettingsView > ( ) ; } } ,
2023-09-18 17:22:46 -04:00
{ " Date/Time " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_datetime , [ & nav ] ( ) { nav . push < SetDateTimeView > ( ) ; } } ,
{ " Encoder Dial " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_setup , [ & nav ] ( ) { nav . push < SetEncoderDialView > ( ) ; } } ,
2023-09-10 20:04:20 -04:00
{ " Freq. Correct " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_radio , [ & nav ] ( ) { nav . push < SetFrequencyCorrectionView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
{ " P.Memory Mgmt " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_memory , [ & nav ] ( ) { nav . push < SetPersistentMemoryView > ( ) ; } } ,
2023-09-18 17:22:46 -04:00
{ " Radio " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_radio , [ & nav ] ( ) { nav . push < SetRadioView > ( ) ; } } ,
2023-11-19 09:08:29 -05:00
{ " SD Card " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_sdcard , [ & nav ] ( ) { nav . push < SetSDCardView > ( ) ; } } ,
2024-01-17 00:59:35 -05:00
{ " User Interface " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_options_ui , [ & nav ] ( ) { nav . push < SetUIView > ( ) ; } } ,
{ " QR Code " , ui : : Color : : dark_cyan ( ) , & bitmap_icon_qr_code , [ & nav ] ( ) { nav . push < SetQRCodeView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
} ) ;
set_max_rows ( 2 ) ; // allow wider buttons
}
2015-07-08 11:39:24 -04:00
} /* namespace ui */