diff --git a/firmware/application/apps/ui_mictx.cpp b/firmware/application/apps/ui_mictx.cpp index d5c3525d0..ee5f2aee9 100644 --- a/firmware/application/apps/ui_mictx.cpp +++ b/firmware/application/apps/ui_mictx.cpp @@ -269,16 +269,24 @@ void MicTXView::set_rxbw_options(void) { } } -void MicTXView::set_rxbw_defaults(bool use_app_settings) { +void MicTXView::set_rxbw_defaults(bool use_app_settings) { // Initially in that function we set up rxbw, but now also txbw. if (use_app_settings) { field_bw.set_value(transmitter_model.channel_bandwidth() / 1000); field_rxbw.set_by_value(rxbw_index); } else if (mic_mod_index == MIC_MOD_NFM) { - field_bw.set_value(10); // NFM TX bw 10k, RX bw 16k (2) default - field_rxbw.set_by_value(2); + field_bw.set_value(10); // NFM TX bw 10k, RX bw 16k (index 2) default + field_bw.set_range(1, 60); // In NFM , FM , we are limitting index modulation range (0.08 ..5) ; (Ex max dev 60khz/12k = 5) + field_bw.set_step(1); + field_rxbw.set_by_value(2); // 16k from the three options (8k5,11k,16k) } else if (mic_mod_index == MIC_MOD_WFM) { - field_bw.set_value(75); // WFM TX bw 75K, RX bw 200k (0) default + field_bw.set_value(75); // WFM TX bw 75K, RX bw 200k (index 0) default + field_bw.set_range(1, 150); // In our case Mod. Index range (1,67 ...12,5) ; 150k/12k=12,5 + field_bw.set_step(1); field_rxbw.set_by_value(0); + } else if ((mic_mod_index == MIC_MOD_USB) | (mic_mod_index == MIC_MOD_LSB)) { + field_bw.set_value(3); // In SSB by default let's limit TX_BW to 3kHz. + field_bw.set_range(2, 3); // User range to modify that TX_BW. (TODO pending to investigate 4khz). + field_bw.set_step(1); } // field_bw is hidden in other modulation cases } @@ -482,7 +490,11 @@ MicTXView::MicTXView( field_bw.hidden(false); options_tone_key.hidden(false); } else { - field_bw.hidden(true); + if ((mic_mod_index == MIC_MOD_USB) || (mic_mod_index == MIC_MOD_LSB)) { + field_bw.hidden(false); + } else { + field_bw.hidden(true); + } options_tone_key.set_selected_index(0); options_tone_key.hidden(true); } diff --git a/firmware/application/apps/ui_mictx.hpp b/firmware/application/apps/ui_mictx.hpp index 15cc4e7a6..6b61a8f0b 100644 --- a/firmware/application/apps/ui_mictx.hpp +++ b/firmware/application/apps/ui_mictx.hpp @@ -148,10 +148,10 @@ class MicTXView : public View { Labels labels_both{ {{3 * 8, 1 * 8}, "MIC-GAIN:", Theme::getInstance()->fg_light->foreground}, - {{3 * 8, 3 * 8}, "F:", Theme::getInstance()->fg_light->foreground}, - {{15 * 8, 3 * 8}, "FM TXBW: kHz", Theme::getInstance()->fg_light->foreground}, // to be more symetric and consistent to the below FM RXBW - {{18 * 8, (5 * 8)}, "Mode:", Theme::getInstance()->fg_light->foreground}, // now, no need to handle GAIN, Amp here It is handled by ui_transmitter.cpp - {{4 * 8, 10 * 8}, "LVL:", Theme::getInstance()->fg_light->foreground}, // we delete { {11 * 8, 5 * 8 }, "Amp:", Theme::getInstance()->fg_light->foreground }, + {{3 * 8, 3 * 8}, "F: MHz", Theme::getInstance()->fg_light->foreground}, + {{18 * 8, 3 * 8}, "TXBW: kHz", Theme::getInstance()->fg_light->foreground}, // to be more symetric and consistent to the below FM RXBW + {{18 * 8, (5 * 8)}, "Mode:", Theme::getInstance()->fg_light->foreground}, // now, no need to handle GAIN, Amp here It is handled by ui_transmitter.cpp + {{4 * 8, 10 * 8}, "LVL:", Theme::getInstance()->fg_light->foreground}, // we delete { {11 * 8, 5 * 8 }, "Amp:", Theme::getInstance()->fg_light->foreground }, {{12 * 8, 10 * 8}, "ATT:", Theme::getInstance()->fg_light->foreground}, {{20 * 8, 10 * 8}, "DEC:", Theme::getInstance()->fg_light->foreground}, {{3 * 8, (13 * 8) - 5}, "TONE KEY:", Theme::getInstance()->fg_light->foreground}, diff --git a/firmware/baseband/dsp_hilbert.cpp b/firmware/baseband/dsp_hilbert.cpp index b858c8fa6..e2ac5a3de 100644 --- a/firmware/baseband/dsp_hilbert.cpp +++ b/firmware/baseband/dsp_hilbert.cpp @@ -27,6 +27,7 @@ namespace dsp { HilbertTransform::HilbertTransform() { n = 0; + sos_input.configure(half_band_lpf_config); sos_i.configure(half_band_lpf_config); sos_q.configure(half_band_lpf_config); } @@ -34,22 +35,26 @@ HilbertTransform::HilbertTransform() { void HilbertTransform::execute(float in, float& out_i, float& out_q) { float a = 0, b = 0; + float in_filtered = sos_input.execute(in) * 1.0f; // Anti-aliasing LPF at fs/4 mic audio filter front-end. + // it is exactly matching with the usefull mic BW_cut_off =fs/4 of the following Hilbert Transf. implementation + // Ex. to TX SSB 3khz BW (3KHZ =fs/4) ,we need to run Hiblert_Trf fs = 12khz . And our anti-aliasing filter is also fcut =fs/4 when we use a half_band_LPF . + switch (n) { case 0: - a = in; + a = in_filtered; b = 0; break; case 1: a = 0; - b = -in; + b = -in_filtered; break; case 2: - a = -in; + a = -in_filtered; b = 0; break; case 3: a = 0; - b = in; + b = in_filtered; break; } diff --git a/firmware/baseband/dsp_hilbert.hpp b/firmware/baseband/dsp_hilbert.hpp index e5e15f625..8aad9ea9c 100644 --- a/firmware/baseband/dsp_hilbert.hpp +++ b/firmware/baseband/dsp_hilbert.hpp @@ -34,6 +34,7 @@ class HilbertTransform { private: uint8_t n = 0; + SOSFilter<5> sos_input = {}; SOSFilter<5> sos_i = {}; SOSFilter<5> sos_q = {}; }; diff --git a/firmware/baseband/dsp_modulate.cpp b/firmware/baseband/dsp_modulate.cpp index e141f3399..5e638613e 100644 --- a/firmware/baseband/dsp_modulate.cpp +++ b/firmware/baseband/dsp_modulate.cpp @@ -81,6 +81,25 @@ SSB::SSB() mode = Mode::LSB; } +void SSB::set_fs_div_factor(float new_bw_ssb) { + switch ((int)new_bw_ssb / 1000) { + case 2: + fs_div_factor = 192; // TXBW_ssb = 2khz = fs/4 ; fs of Hilbert Transform => 8khz fs Hilbert = 1536.000/8000= 192 + break; + case 3: + fs_div_factor = 128; // TXBW_ssb = 3khz = fs/4 ; fs of Hilbert Transform => 12khz fs Hilbert = 1536.000/12000= 128 + break; + /* TODO pending to investigate 4khz, now is making aliasing folding with audio sweep . + case 4: + fs_div_factor = 96; // TXBW_ssb = 4khz = fs/4 ; fs of Hilbert Transform => 16khz fs Hilbert = 1536.000/16000= 96 + break; + */ + default: + fs_div_factor = 128; // TXBW_ssb = 3khz = fs/4 ; fs of Hilbert Transform => 12khz fs Hilbert = 1536.000/12000= 128 + break; + } +} + void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider) { // unused (void)configured_in; @@ -93,9 +112,10 @@ void SSB::execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& co int8_t re = 0, im = 0; for (size_t counter = 0; counter < buffer.count; counter++) { - if (counter % 128 == 0) { + if (counter % fs_div_factor == 0) { // Ex. TX bw_ssb 3khz =fs/4 Hilbert Transform sample rate, 128 = 1.536.000 hz / 12.000 hz (fs H.T.) float i = 0.0, q = 0.0; + // over = 1.536.000/24khz = 64 . (Mic audio has fixed SR in audio_p buffer[] = 24khz), but in tx mode , we are running Transceiver fs @tx = 1.536.000 Hz. sample = audio.p[counter / over] >> audio_shift_bits_s16_AM_DSB_SSB; // originally fixed >> 2, now >>2 for AK, 0,1,2,3 for WM (boost off) sample *= audio_gain; // Apply GAIN Scale factor to the audio TX modulation. diff --git a/firmware/baseband/dsp_modulate.hpp b/firmware/baseband/dsp_modulate.hpp index f90d6b345..7d5c382cb 100644 --- a/firmware/baseband/dsp_modulate.hpp +++ b/firmware/baseband/dsp_modulate.hpp @@ -79,9 +79,12 @@ class SSB : public Modulator { SSB(); virtual void execute(const buffer_s16_t& audio, const buffer_c8_t& buffer, bool& configured_in, uint32_t& new_beep_index, uint32_t& new_beep_timer, TXProgressMessage& new_txprogress_message, AudioLevelReportMessage& new_level_message, uint32_t& new_power_acc_count, uint32_t& new_divider); + void set_fs_div_factor(float new_bw_ssb); private: dsp::HilbertTransform hilbert; + float new_bw_ssb{3.0}; + int fs_div_factor{128}; }; /// diff --git a/firmware/baseband/proc_mictx.cpp b/firmware/baseband/proc_mictx.cpp index b2705d03b..2f37fe9c0 100644 --- a/firmware/baseband/proc_mictx.cpp +++ b/firmware/baseband/proc_mictx.cpp @@ -113,13 +113,27 @@ void MicTXProcessor::on_message(const Message* const msg) { } if (usb_enabled) { - modulator = new dsp::modulate::SSB(); - modulator->set_mode(dsp::modulate::Mode::USB); + dsp::modulate::SSB* ssb = new dsp::modulate::SSB(); + + // Config fs_div_factor private var inside DSP modulate.cpp + ssb->set_fs_div_factor(config_message.deviation_hz); // we use same FM var deviation_hz , to set up also SSB BW + ssb->set_mode(dsp::modulate::Mode::USB); + modulator = ssb; + + // modulator = new dsp::modulate::SSB(); // Keeping previous code as ref., when not passing deviation_hz parameter. + // modulator->set_mode(dsp::modulate::Mode::USB); } if (lsb_enabled) { - modulator = new dsp::modulate::SSB(); - modulator->set_mode(dsp::modulate::Mode::LSB); + dsp::modulate::SSB* ssb = new dsp::modulate::SSB(); + + // Config fs_div_factor private var inside DSP modulate.cpp + ssb->set_fs_div_factor(config_message.deviation_hz); // we use same FM var deviation_hz , to set up also SSB BW + ssb->set_mode(dsp::modulate::Mode::LSB); + modulator = ssb; + + // modulator = new dsp::modulate::SSB(); // Keeping previous code as ref., when not passing deviation_hz parameter. + // modulator->set_mode(dsp::modulate::Mode::LSB); } if (am_enabled) { modulator = new dsp::modulate::AM();