2015-12-01 22:04:04 -08:00
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
2018-05-21 18:46:48 +01:00
* Copyright (C) 2018 Furrtek
2015-12-01 22:04:04 -08: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.
*/
2015-12-08 15:28:33 -08:00
#include "analog_audio_app.hpp"
2015-12-01 22:04:04 -08:00
2023-06-18 22:48:29 -07:00
#include "audio.hpp"
2016-06-24 11:30:54 -07:00
#include "baseband_api.hpp"
2023-06-18 22:48:29 -07:00
#include "file.hpp"
2015-12-01 22:04:04 -08:00
#include "portapack.hpp"
2016-02-10 15:34:33 -08:00
#include "portapack_persistent_memory.hpp"
2023-06-18 22:48:29 -07:00
#include "string_format.hpp"
2023-07-17 11:43:37 -07:00
#include "ui_freqman.hpp"
2015-12-01 22:04:04 -08:00
#include "utility.hpp"
2024-03-09 23:46:38 +01:00
#include "radio.hpp"
2015-12-01 22:04:04 -08:00
2023-06-18 22:48:29 -07:00
using namespace portapack ;
using namespace tonekey ;
2023-05-10 13:16:23 +02:00
2016-01-31 09:13:44 -08:00
namespace ui {
2016-02-02 13:42:00 -08:00
/* AMOptionsView *********************************************************/
AMOptionsView :: AMOptionsView (
2025-03-23 23:08:12 +01:00
AnalogAudioView * view ,
2023-06-18 22:48:29 -07:00
Rect parent_rect ,
const Style * style )
2023-05-19 08:16:05 +12:00
: View { parent_rect } {
set_style ( style );
2016-02-02 13:42:00 -08:00
2023-05-19 08:16:05 +12:00
add_children ({
& label_config ,
& options_config ,
2025-03-23 23:08:12 +01:00
& zoom_config ,
2023-05-19 08:16:05 +12:00
});
2016-02-02 13:42:00 -08:00
2025-04-04 15:43:26 +02:00
zoom_config . on_change = [ this , view ]( size_t , OptionsField :: value_t n ) { // n , has two option values. when GUI =zoom+1 => (0), when GUI=zoom+2 (6)
receiver_model . set_am_configuration ( view -> get_previous_AM_mode_option () + n ); // n (0 or 6)
2025-03-23 23:08:12 +01:00
view -> set_zoom_factor ( AM_MODULATION , n );
2025-04-04 15:43:26 +02:00
view -> set_previous_zoom_option ( n );
2025-03-23 23:08:12 +01:00
};
// restore zoom selection
zoom_config . set_by_value ( view -> get_zoom_factor ( AM_MODULATION ));
2025-04-04 15:43:26 +02:00
freqman_set_bandwidth_option ( AM_MODULATION , options_config ); // freqman.cpp to the options_config, only allowing 5 modes freqman_bandwidths[AM] {"DSB 9k", 0}, {"DSB 6k", 1}, {"USB+3k", 2}, {"LSB-3k", 3}, {"CW", 4},
options_config . set_by_value ( receiver_model . am_configuration () - view -> get_previous_zoom_option ()); // restore AM GUI option mode , AM FIR index filters (0..11) values , <baseband::AMConfig, 12> am_configs has 12 fir index elements.
2025-03-23 23:08:12 +01:00
options_config . on_change = [ this , view ]( size_t , OptionsField :: value_t n ) {
2025-04-04 15:43:26 +02:00
receiver_model . set_am_configuration ( n + view -> get_previous_zoom_option ()); // we select proper FIR AM filter (0..11), = 0..4 GUI AM modes + offset +6 (if zoom+2)
view -> set_previous_AM_mode_option ( n ); // (0..4) allowing 5 AM modes (DSB9K, DSB6K, USB,LSB, CW)
2023-05-19 08:16:05 +12:00
};
2016-02-02 13:42:00 -08:00
}
/* NBFMOptionsView *******************************************************/
NBFMOptionsView :: NBFMOptionsView (
2023-06-18 22:48:29 -07:00
Rect parent_rect ,
const Style * style )
2023-05-19 08:16:05 +12:00
: View { parent_rect } {
set_style ( style );
2016-02-02 13:42:00 -08:00
2023-05-19 08:16:05 +12:00
add_children ({ & label_config ,
& options_config ,
& text_squelch ,
& field_squelch });
2016-02-02 13:42:00 -08:00
2023-05-19 08:16:05 +12:00
freqman_set_bandwidth_option ( NFM_MODULATION , options_config ); // adding the common message from freqman.cpp to the options_config
2023-06-06 11:46:08 -05:00
options_config . set_by_value ( receiver_model . nbfm_configuration ());
options_config . on_change = [ this ]( size_t , OptionsField :: value_t n ) {
2023-05-19 08:16:05 +12:00
receiver_model . set_nbfm_configuration ( n );
};
field_squelch . set_value ( receiver_model . squelch_level ());
field_squelch . on_change = [ this ]( int32_t v ) {
receiver_model . set_squelch_level ( v );
};
2016-02-02 13:42:00 -08:00
}
2023-05-07 16:08:45 +02:00
/* WFMOptionsView *******************************************************/
WFMOptionsView :: WFMOptionsView (
2023-06-18 22:48:29 -07:00
Rect parent_rect ,
const Style * style )
2023-05-19 08:16:05 +12:00
: View { parent_rect } {
set_style ( style );
2023-05-07 16:08:45 +02:00
2023-05-19 08:16:05 +12:00
add_children ({
& label_config ,
& options_config ,
});
2023-05-07 16:08:45 +02:00
2023-05-19 08:16:05 +12:00
freqman_set_bandwidth_option ( WFM_MODULATION , options_config ); // adding the common message from freqman.cpp to the options_config
2023-06-06 11:46:08 -05:00
options_config . set_by_value ( receiver_model . wfm_configuration ());
options_config . on_change = [ this ]( size_t , OptionsField :: value_t n ) {
2023-05-19 08:16:05 +12:00
receiver_model . set_wfm_configuration ( n );
};
2023-05-07 16:08:45 +02:00
}
2025-05-05 17:48:01 +02:00
/* WFMAMAptOptionsView *******************************************************/
WFMAMAptOptionsView :: WFMAMAptOptionsView (
Rect parent_rect ,
const Style * style )
: View { parent_rect } {
set_style ( style );
add_children ({
& label_config ,
& options_config ,
});
freqman_set_bandwidth_option ( WFMAM_MODULATION , options_config ); // adding the common message from freqman.cpp to the options_config
options_config . set_by_value ( receiver_model . wfmam_configuration ());
options_config . on_change = [ this ]( size_t , OptionsField :: value_t n ) {
receiver_model . set_wfmam_configuration ( n );
};
}
2025-03-05 04:27:18 +01:00
/* AMFMAptOptionsView *********************************************************/
AMFMAptOptionsView :: AMFMAptOptionsView (
2025-03-23 23:08:12 +01:00
AnalogAudioView * view ,
2025-03-05 04:27:18 +01:00
Rect parent_rect ,
const Style * style )
: View { parent_rect } {
set_style ( style );
add_children ({
& label_config ,
& options_config ,
2025-03-23 23:08:12 +01:00
& zoom_config ,
2025-03-05 04:27:18 +01:00
});
freqman_set_bandwidth_option ( AMFM_MODULATION , options_config ); // adding the common message from freqman.cpp to the options_config
2025-03-07 17:28:11 +01:00
receiver_model . set_amfm_configuration ( 5 ); // Fix index 5 manually, not from freqman: set to RX AM (USB+FM) mode to demod audio tone, and get Wefax_APT signal.
2025-03-05 04:27:18 +01:00
options_config . set_by_value ( receiver_model . amfm_configuration ());
2025-03-23 23:08:12 +01:00
zoom_config . on_change = [ this , view ]( size_t , OptionsField :: value_t n ) {
receiver_model . set_amfm_configuration ( 5 + n );
view -> set_zoom_factor ( AMFM_MODULATION , n );
};
// restore zoom selection
zoom_config . set_by_value ( view -> get_zoom_factor ( AMFM_MODULATION ));
2025-03-05 04:27:18 +01:00
}
2020-07-31 13:47:40 +03:00
/* SPECOptionsView *******************************************************/
SPECOptionsView :: SPECOptionsView (
2023-05-19 08:16:05 +12:00
AnalogAudioView * view ,
2023-06-18 22:48:29 -07:00
Rect parent_rect ,
const Style * style )
2023-05-19 08:16:05 +12:00
: View { parent_rect } {
set_style ( style );
2020-07-31 13:47:40 +03:00
2024-03-09 23:46:38 +01:00
add_children ({
& label_config ,
& options_config ,
& text_speed ,
& field_speed ,
& text_rx_cal ,
2024-03-09 17:36:48 -06:00
& field_rx_iq_phase_cal ,
2024-03-09 23:46:38 +01:00
});
2020-07-31 13:47:40 +03:00
2023-05-19 08:16:05 +12:00
options_config . set_selected_index ( view -> get_spec_bw_index ());
options_config . on_change = [ this , view ]( size_t n , OptionsField :: value_t bw ) {
view -> set_spec_bw ( n , bw );
};
2020-07-31 13:47:40 +03:00
2023-05-19 08:16:05 +12:00
field_speed . set_value ( view -> get_spec_trigger ());
field_speed . on_change = [ this , view ]( int32_t v ) {
view -> set_spec_trigger ( v );
};
2024-03-09 23:46:38 +01:00
2024-03-09 17:36:48 -06:00
field_rx_iq_phase_cal . set_range ( 0 , hackrf_r9 ? 63 : 31 ); // max2839 has 6 bits [0..63], max2837 has 5 bits [0..31]
field_rx_iq_phase_cal . set_value ( view -> get_spec_iq_phase_calibration_value ()); // using accessor function of AnalogAudioView to read iq_phase_calibration_value from rx_audio.ini
field_rx_iq_phase_cal . on_change = [ this , view ]( int32_t v ) {
view -> set_spec_iq_phase_calibration_value ( v ); // using accessor function of AnalogAudioView to write inside SPEC submenu, register value to max283x and save it to rx_audio.ini
};
2024-03-10 14:50:48 -05:00
view -> set_spec_iq_phase_calibration_value ( view -> get_spec_iq_phase_calibration_value ()); // initialize iq_phase_calibration in radio
2020-07-31 13:47:40 +03:00
}
2016-01-31 09:13:44 -08:00
/* AnalogAudioView *******************************************************/
AnalogAudioView :: AnalogAudioView (
2023-05-19 08:16:05 +12:00
NavigationView & nav )
: nav_ ( nav ) {
2023-07-04 16:26:26 -07:00
// A baseband image _must_ be running before add waterfall view.
2023-06-18 22:48:29 -07:00
baseband :: run_image ( portapack :: spi_flash :: image_tag_wideband_spectrum );
2023-05-19 08:16:05 +12:00
add_children ({ & rssi ,
& channel ,
& audio ,
& field_frequency ,
& field_lna ,
& field_vga ,
& options_modulation ,
& field_volume ,
& text_ctcss ,
& record_view ,
& waterfall });
2016-01-31 09:13:44 -08:00
2023-05-19 08:16:05 +12:00
// Filename Datetime and Frequency
record_view . set_filename_date_frequency ( true );
2016-01-31 09:13:44 -08:00
2023-05-19 08:16:05 +12:00
field_frequency . on_show_options = [ this ]() {
this -> on_show_options_frequency ();
};
2016-01-31 09:13:44 -08:00
2023-05-19 08:16:05 +12:00
field_lna . on_show_options = [ this ]() {
this -> on_show_options_rf_gain ();
};
2016-01-31 09:13:44 -08:00
2023-05-19 08:16:05 +12:00
field_vga . on_show_options = [ this ]() {
this -> on_show_options_rf_gain ();
};
2022-05-13 08:38:04 -04:00
2023-06-18 22:48:29 -07:00
auto modulation = receiver_model . modulation ();
2025-03-07 17:28:11 +01:00
2023-06-18 22:48:29 -07:00
// This app doesn't handle "Capture" mode.
2025-03-07 17:28:11 +01:00
if ( modulation == ReceiverModel :: Mode :: Capture )
modulation = ReceiverModel :: Mode :: SpectrumAnalysis ;
2016-01-31 09:13:44 -08:00
2023-06-18 22:48:29 -07:00
options_modulation . set_by_value ( toUType ( modulation ));
2023-05-19 08:16:05 +12:00
options_modulation . on_change = [ this ]( size_t , OptionsField :: value_t v ) {
this -> on_modulation_changed ( static_cast < ReceiverModel :: Mode > ( v ));
};
options_modulation . on_show_options = [ this ]() {
this -> on_show_options_modulation ();
};
2016-01-31 09:13:44 -08:00
2023-05-19 08:16:05 +12:00
record_view . on_error = [ & nav ]( std :: string message ) {
nav . display_modal ( "Error" , message );
};
2016-02-05 16:25:43 -08:00
2023-05-19 08:16:05 +12:00
waterfall . on_select = [ this ]( int32_t offset ) {
2023-06-11 11:47:13 -07:00
field_frequency . set_value ( receiver_model . target_frequency () + offset );
2023-05-19 08:16:05 +12:00
};
audio :: output :: start ();
2023-06-18 22:48:29 -07:00
// This call starts the correct baseband image to run
// and sets the radio up as necessary for the given modulation.
on_modulation_changed ( modulation );
2016-01-31 09:13:44 -08:00
}
2023-07-04 16:26:26 -07:00
AnalogAudioView :: AnalogAudioView (
NavigationView & nav ,
ReceiverModel :: settings_t override )
: AnalogAudioView ( nav ) {
2024-03-30 12:57:43 -05:00
// Settings to override when launched from another app (versus from AppSettings .ini file)
2023-07-04 16:26:26 -07:00
// TODO: Which other settings make sense to override?
2024-03-30 12:57:43 -05:00
field_frequency . set_value ( override . frequency_app_override );
2023-07-04 16:26:26 -07:00
on_frequency_step_changed ( override . frequency_step );
options_modulation . set_by_value ( toUType ( override . mode ));
}
2020-07-31 13:47:40 +03:00
size_t AnalogAudioView :: get_spec_bw_index () {
2023-05-19 08:16:05 +12:00
return spec_bw_index ;
2020-07-31 13:47:40 +03:00
}
void AnalogAudioView :: set_spec_bw ( size_t index , uint32_t bw ) {
2023-05-19 08:16:05 +12:00
spec_bw_index = index ;
spec_bw = bw ;
2020-07-31 13:47:40 +03:00
2023-05-19 08:16:05 +12:00
baseband :: set_spectrum ( bw , spec_trigger );
receiver_model . set_sampling_rate ( bw );
receiver_model . set_baseband_bandwidth ( bw / 2 );
2020-07-31 13:47:40 +03:00
}
2025-03-23 23:08:12 +01:00
uint8_t AnalogAudioView :: get_zoom_factor ( uint8_t mode ) { // define accessor functions inside AnalogAudioView to read zoom value
if ( mode == AM_MODULATION )
return zoom_factor_am ;
else if ( mode == AMFM_MODULATION )
return zoom_factor_amfm ;
return 0 ; // default if unsupported mode
}
void AnalogAudioView :: set_zoom_factor ( uint8_t mode , uint8_t zoom ) { // define accessor functions inside AnalogAudioView to write zoom value
if ( mode == AM_MODULATION )
zoom_factor_am = zoom ;
else if ( mode == AMFM_MODULATION )
zoom_factor_amfm = zoom ;
}
2025-04-04 15:43:26 +02:00
uint8_t AnalogAudioView :: get_previous_AM_mode_option () {
return previous_AM_mode_option ;
}
void AnalogAudioView :: set_previous_AM_mode_option ( uint8_t mode ) {
previous_AM_mode_option = mode ;
}
uint8_t AnalogAudioView :: get_previous_zoom_option () {
return previous_zoom ;
}
void AnalogAudioView :: set_previous_zoom_option ( uint8_t zoom ) {
previous_zoom = zoom ;
}
2025-03-23 23:08:12 +01:00
uint8_t AnalogAudioView :: get_spec_iq_phase_calibration_value () { // define accessor functions inside AnalogAudioView to read iq_phase_calibration_value
2024-03-09 23:46:38 +01:00
return iq_phase_calibration_value ;
}
2025-03-23 23:08:12 +01:00
void AnalogAudioView :: set_spec_iq_phase_calibration_value ( uint8_t cal_value ) { // define accessor functions inside AnalogAudioView to write iq_phase_calibration_value
2024-03-09 23:46:38 +01:00
iq_phase_calibration_value = cal_value ;
radio :: set_rx_max283x_iq_phase_calibration ( iq_phase_calibration_value );
}
2020-07-31 13:47:40 +03:00
uint16_t AnalogAudioView :: get_spec_trigger () {
2023-05-19 08:16:05 +12:00
return spec_trigger ;
2020-07-31 13:47:40 +03:00
}
void AnalogAudioView :: set_spec_trigger ( uint16_t trigger ) {
2023-05-19 08:16:05 +12:00
spec_trigger = trigger ;
2020-07-31 13:47:40 +03:00
2023-05-19 08:16:05 +12:00
baseband :: set_spectrum ( spec_bw , spec_trigger );
2020-07-31 13:47:40 +03:00
}
2016-01-31 09:13:44 -08:00
AnalogAudioView ::~ AnalogAudioView () {
2025-03-19 23:03:04 +01:00
receiver_model . set_hidden_offset ( 0 );
2023-05-19 08:16:05 +12:00
audio :: output :: stop ();
receiver_model . disable ();
baseband :: shutdown ();
2016-01-31 09:13:44 -08:00
}
2023-06-18 22:48:29 -07:00
void AnalogAudioView :: set_parent_rect ( Rect new_parent_rect ) {
2023-05-19 08:16:05 +12:00
View :: set_parent_rect ( new_parent_rect );
2023-06-18 22:48:29 -07:00
ui :: Rect waterfall_rect { 0 , header_height , new_parent_rect . width (), new_parent_rect . height () - header_height };
2023-05-19 08:16:05 +12:00
waterfall . set_parent_rect ( waterfall_rect );
2016-01-31 09:13:44 -08:00
}
void AnalogAudioView :: focus () {
2023-05-19 08:16:05 +12:00
field_frequency . focus ();
2016-01-31 09:13:44 -08:00
}
void AnalogAudioView :: on_baseband_bandwidth_changed ( uint32_t bandwidth_hz ) {
2023-05-19 08:16:05 +12:00
receiver_model . set_baseband_bandwidth ( bandwidth_hz );
2016-01-31 09:13:44 -08:00
}
2023-06-18 22:48:29 -07:00
void AnalogAudioView :: on_modulation_changed ( ReceiverModel :: Mode modulation ) {
baseband :: spectrum_streaming_stop ();
2023-05-19 08:16:05 +12:00
update_modulation ( modulation );
on_show_options_modulation ();
2023-06-18 22:48:29 -07:00
baseband :: spectrum_streaming_start ();
2016-01-31 09:13:44 -08:00
}
2016-02-02 14:26:00 -08:00
void AnalogAudioView :: remove_options_widget () {
2023-05-19 08:16:05 +12:00
if ( options_widget ) {
remove_child ( options_widget . get ());
options_widget . reset ();
}
field_lna . set_style ( nullptr );
options_modulation . set_style ( nullptr );
field_frequency . set_style ( nullptr );
2016-02-02 14:26:00 -08:00
}
2016-01-31 09:13:44 -08:00
2016-02-02 14:26:00 -08:00
void AnalogAudioView :: set_options_widget ( std :: unique_ptr < Widget > new_widget ) {
2023-05-19 08:16:05 +12:00
remove_options_widget ();
2016-04-22 10:01:17 -07:00
2023-05-19 08:16:05 +12:00
if ( new_widget ) {
options_widget = std :: move ( new_widget );
} else {
// TODO: Lame hack to hide options view due to my bad paint/damage algorithm.
2024-05-27 21:02:52 +02:00
options_widget = std :: make_unique < Rectangle > ( options_view_rect , Theme :: getInstance () -> option_active -> background );
2023-05-19 08:16:05 +12:00
}
add_child ( options_widget . get ());
2016-02-02 14:26:00 -08:00
}
void AnalogAudioView :: on_show_options_frequency () {
2024-05-27 21:02:52 +02:00
auto widget = std :: make_unique < FrequencyOptionsView > ( options_view_rect , Theme :: getInstance () -> option_active );
2016-02-02 14:26:00 -08:00
2023-05-19 08:16:05 +12:00
widget -> set_step ( receiver_model . frequency_step ());
widget -> on_change_step = [ this ]( rf :: Frequency f ) {
this -> on_frequency_step_changed ( f );
};
widget -> set_reference_ppm_correction ( persistent_memory :: correction_ppb () / 1000 );
widget -> on_change_reference_ppm_correction = [ this ]( int32_t v ) {
this -> on_reference_ppm_correction_changed ( v );
};
2016-02-02 14:26:00 -08:00
2023-05-19 08:16:05 +12:00
set_options_widget ( std :: move ( widget ));
2024-05-27 21:02:52 +02:00
field_frequency . set_style ( Theme :: getInstance () -> option_active );
2016-01-31 09:13:44 -08:00
}
void AnalogAudioView :: on_show_options_rf_gain () {
2024-05-27 21:02:52 +02:00
auto widget = std :: make_unique < RadioGainOptionsView > ( options_view_rect , Theme :: getInstance () -> option_active );
2016-02-02 14:26:00 -08:00
2023-05-19 08:16:05 +12:00
set_options_widget ( std :: move ( widget ));
2024-05-27 21:02:52 +02:00
field_lna . set_style ( Theme :: getInstance () -> option_active );
2016-01-31 09:13:44 -08:00
}
2016-02-02 13:42:00 -08:00
void AnalogAudioView :: on_show_options_modulation () {
2023-05-19 08:16:05 +12:00
std :: unique_ptr < Widget > widget ;
2016-04-22 10:22:47 -07:00
2023-06-18 22:48:29 -07:00
const auto modulation = receiver_model . modulation ();
2023-05-19 08:16:05 +12:00
switch ( modulation ) {
case ReceiverModel :: Mode :: AMAudio :
2025-03-23 23:08:12 +01:00
widget = std :: make_unique < AMOptionsView > ( this , options_view_rect , Theme :: getInstance () -> option_active );
2023-05-19 08:16:05 +12:00
waterfall . show_audio_spectrum_view ( false );
text_ctcss . hidden ( true );
break ;
2016-04-22 10:22:47 -07:00
2023-05-19 08:16:05 +12:00
case ReceiverModel :: Mode :: NarrowbandFMAudio :
2024-05-27 21:02:52 +02:00
widget = std :: make_unique < NBFMOptionsView > ( nbfm_view_rect , Theme :: getInstance () -> option_active );
2023-05-19 08:16:05 +12:00
waterfall . show_audio_spectrum_view ( false );
text_ctcss . hidden ( false );
break ;
2016-04-22 10:22:47 -07:00
2023-05-19 08:16:05 +12:00
case ReceiverModel :: Mode :: WidebandFMAudio :
2024-05-27 21:02:52 +02:00
widget = std :: make_unique < WFMOptionsView > ( options_view_rect , Theme :: getInstance () -> option_active );
2023-05-19 08:16:05 +12:00
waterfall . show_audio_spectrum_view ( true );
text_ctcss . hidden ( true );
break ;
2025-05-05 17:48:01 +02:00
case ReceiverModel :: Mode :: WFMAudioAMApt :
widget = std :: make_unique < WFMAMAptOptionsView > ( options_view_rect , Theme :: getInstance () -> option_active );
waterfall . show_audio_spectrum_view ( true );
text_ctcss . hidden ( true );
break ;
2025-03-05 04:27:18 +01:00
case ReceiverModel :: Mode :: AMAudioFMApt :
2025-03-23 23:08:12 +01:00
widget = std :: make_unique < AMFMAptOptionsView > ( this , options_view_rect , Theme :: getInstance () -> option_active );
2025-03-05 04:27:18 +01:00
waterfall . show_audio_spectrum_view ( false );
text_ctcss . hidden ( true );
break ;
2023-05-19 08:16:05 +12:00
case ReceiverModel :: Mode :: SpectrumAnalysis :
2024-05-27 21:02:52 +02:00
widget = std :: make_unique < SPECOptionsView > ( this , nbfm_view_rect , Theme :: getInstance () -> option_active );
2023-05-19 08:16:05 +12:00
waterfall . show_audio_spectrum_view ( false );
text_ctcss . hidden ( true );
break ;
default :
2023-06-18 22:48:29 -07:00
chDbgPanic ( "Unhandled Mode" );
2023-05-19 08:16:05 +12:00
break ;
}
set_options_widget ( std :: move ( widget ));
2024-05-27 21:02:52 +02:00
options_modulation . set_style ( Theme :: getInstance () -> option_active );
2016-02-02 13:42:00 -08:00
}
2016-01-31 09:13:44 -08:00
void AnalogAudioView :: on_frequency_step_changed ( rf :: Frequency f ) {
2023-05-19 08:16:05 +12:00
receiver_model . set_frequency_step ( f );
field_frequency . set_step ( f );
2016-01-31 09:13:44 -08:00
}
void AnalogAudioView :: on_reference_ppm_correction_changed ( int32_t v ) {
2023-05-19 08:16:05 +12:00
persistent_memory :: set_correction_ppb ( v * 1000 );
2016-01-31 09:13:44 -08:00
}
2023-06-18 22:48:29 -07:00
void AnalogAudioView :: update_modulation ( ReceiverModel :: Mode modulation ) {
2023-05-19 08:16:05 +12:00
audio :: output :: mute ();
record_view . stop ();
2016-02-05 16:25:43 -08:00
2023-05-19 08:16:05 +12:00
baseband :: shutdown ();
2016-07-02 16:12:36 -07:00
2023-05-19 08:16:05 +12:00
portapack :: spi_flash :: image_tag_t image_tag ;
switch ( modulation ) {
case ReceiverModel :: Mode :: AMAudio :
image_tag = portapack :: spi_flash :: image_tag_am_audio ;
break ;
case ReceiverModel :: Mode :: NarrowbandFMAudio :
image_tag = portapack :: spi_flash :: image_tag_nfm_audio ;
break ;
case ReceiverModel :: Mode :: WidebandFMAudio :
image_tag = portapack :: spi_flash :: image_tag_wfm_audio ;
break ;
2025-05-05 17:48:01 +02:00
case ReceiverModel :: Mode :: WFMAudioAMApt :
image_tag = portapack :: spi_flash :: image_tag_wfm_audio ;
break ;
case ReceiverModel :: Mode :: AMAudioFMApt :
2025-03-05 04:27:18 +01:00
image_tag = portapack :: spi_flash :: image_tag_am_audio ;
break ;
2023-05-19 08:16:05 +12:00
case ReceiverModel :: Mode :: SpectrumAnalysis :
image_tag = portapack :: spi_flash :: image_tag_wideband_spectrum ;
break ;
default :
2023-06-18 22:48:29 -07:00
chDbgPanic ( "Unhandled Mode" );
break ;
2023-05-19 08:16:05 +12:00
}
2016-07-01 10:37:22 -07:00
2023-05-19 08:16:05 +12:00
baseband :: run_image ( image_tag );
2020-07-31 13:47:40 +03:00
2023-05-19 08:16:05 +12:00
if ( modulation == ReceiverModel :: Mode :: SpectrumAnalysis ) {
baseband :: set_spectrum ( spec_bw , spec_trigger );
}
2016-07-01 10:37:22 -07:00
2023-05-19 08:16:05 +12:00
const auto is_wideband_spectrum_mode = ( modulation == ReceiverModel :: Mode :: SpectrumAnalysis );
receiver_model . set_modulation ( modulation );
2020-07-31 13:47:40 +03:00
2023-05-19 08:16:05 +12:00
receiver_model . set_sampling_rate ( is_wideband_spectrum_mode ? spec_bw : 3072000 );
receiver_model . set_baseband_bandwidth ( is_wideband_spectrum_mode ? spec_bw / 2 : 1750000 );
2020-07-31 13:47:40 +03:00
2025-03-19 23:03:04 +01:00
receiver_model . set_hidden_offset ( modulation == ReceiverModel :: Mode :: AMAudioFMApt ? - 2200 : 0 ); // wefax needs to be shifted, see wefax rx app.
2023-05-19 08:16:05 +12:00
receiver_model . enable ();
2016-02-05 15:22:28 -08:00
2023-05-19 08:16:05 +12:00
// TODO: This doesn't belong here! There's a better way.
size_t sampling_rate = 0 ;
switch ( modulation ) {
case ReceiverModel :: Mode :: AMAudio :
sampling_rate = 12000 ;
break ;
case ReceiverModel :: Mode :: NarrowbandFMAudio :
sampling_rate = 24000 ;
break ;
case ReceiverModel :: Mode :: WidebandFMAudio :
sampling_rate = 48000 ;
break ;
2025-05-05 17:48:01 +02:00
case ReceiverModel :: Mode :: WFMAudioAMApt :
sampling_rate = 12000 ;
break ;
case ReceiverModel :: Mode :: AMAudioFMApt :
2025-03-05 04:27:18 +01:00
sampling_rate = 12000 ;
break ;
2023-05-19 08:16:05 +12:00
default :
break ;
}
record_view . set_sampling_rate ( sampling_rate );
2016-04-30 11:25:04 -07:00
2023-05-19 08:16:05 +12:00
if ( ! is_wideband_spectrum_mode ) {
audio :: output :: unmute ();
}
2016-04-30 11:25:04 -07:00
}
2023-06-18 22:48:29 -07:00
void AnalogAudioView :: handle_coded_squelch ( uint32_t value ) {
2023-07-02 18:53:51 -05:00
text_ctcss . set ( tone_key_string_by_value ( value , text_ctcss . parent_rect (). width () / 8 ));
2017-11-28 08:52:04 +01:00
}
2024-09-04 20:26:31 +02:00
void AnalogAudioView :: on_freqchg ( int64_t freq ) {
field_frequency . set_value ( freq );
}
2016-01-31 09:13:44 -08:00
} /* namespace ui */