Imrpoved sound quality in analog_audio_app, and added Nyquist protection option to BBW filter for praline. (#3054)

This commit is contained in:
stafur
2026-02-28 17:36:01 -05:00
committed by GitHub
parent b013e68b17
commit 3a54b112ec
7 changed files with 225 additions and 74 deletions
@@ -574,7 +574,11 @@ void AnalogAudioView::update_modulation(ReceiverModel::Mode modulation) {
const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis);
receiver_model.set_modulation(modulation);
#ifdef PRALINE
receiver_model.set_sampling_rate(is_wideband_spectrum_mode ? spec_bw : 3023000);
#else
receiver_model.set_sampling_rate(is_wideband_spectrum_mode ? spec_bw : 3072000);
#endif
receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? spec_bw / 2 : 1750000);
receiver_model.set_hidden_offset(modulation == ReceiverModel::Mode::AMAudioFMApt ? -2200 : 0); // wefax needs to be shifted, see wefax rx app.
+74 -1
View File
@@ -750,7 +750,7 @@ void WFMAudioDebugView::refresh() {
// === Status Summary ===
bool sample_rate_ok = (clk0_khz >= 3000 && clk0_khz <= 3200);
bool lpf_ok = (lpf_coarse >= 0); // 7.5 MHz minimum is technically OK
bool lpf_ok = (lpf_coarse <= 0x0F); // check against the 4-bit max
bool dc_ok = dc_block;
if (sample_rate_ok && lpf_ok && dc_ok) {
@@ -2182,6 +2182,78 @@ void SystemDiagnosticsView::refresh() {
}
#endif
#ifdef PRALINE
PralineClockDebugView::PralineClockDebugView(NavigationView& nav)
: View(),
rows{
{&t0_id, &t0_ma, &t0_mode, &t0_ph, &t0_st},
{&t1_id, &t1_ma, &t1_mode, &t1_ph, &t1_st},
{&t2_id, &t2_ma, &t2_mode, &t2_ph, &t2_st},
{&t3_id, &t3_ma, &t3_mode, &t3_ph, &t3_st},
{&t4_id, &t4_ma, &t4_mode, &t4_ph, &t4_st},
{&t5_id, &t5_ma, &t5_mode, &t5_ph, &t5_st}} {
add_children({&text_title, &text_lbl_pll, &text_pll_status,
&text_lbl_afe, &text_afe_rate, &text_lbl_n, &text_n_val,
&text_header,
&t0_id, &t0_ma, &t0_mode, &t0_ph, &t0_st,
&t1_id, &t1_ma, &t1_mode, &t1_ph, &t1_st,
&t2_id, &t2_ma, &t2_mode, &t2_ph, &t2_st,
&t3_id, &t3_ma, &t3_mode, &t3_ph, &t3_st,
&t4_id, &t4_ma, &t4_mode, &t4_ph, &t4_st,
&t5_id, &t5_ma, &t5_mode, &t5_ph, &t5_st,
&button_refresh, &button_done});
button_refresh.on_select = [this](Button&) { this->refresh(); };
button_done.on_select = [&nav](Button&) { nav.pop(); };
refresh();
}
void PralineClockDebugView::focus() {
button_refresh.focus();
}
void PralineClockDebugView::refresh() {
// 1. System Status
uint8_t status = portapack::clock_manager.si5351_read_status();
bool pll_a = !(status & 0x20);
bool pll_b = !(status & 0x40);
text_pll_status.set(std::string(pll_a ? "A:OK " : "A:ERR ") + (pll_b ? "B:OK" : "B:ERR"));
text_pll_status.set_style((pll_a && pll_b) ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red);
// 2. AFE & Decimation Info
uint32_t base_rate = portapack::clock_manager.get_sampling_frequency();
uint8_t n = portapack::clock_manager.get_resampling_n();
text_afe_rate.set(to_string_dec_uint(base_rate << n) + " Hz");
text_n_val.set(to_string_dec_uint(n));
// 3. Clock Table Decoding
uint8_t output_en = portapack::clock_manager.si5351_read_register(3);
const char* ma_lookup[] = {"2m", "4m", "6m", "8m"};
for (size_t i = 0; i < 6; i++) {
uint8_t ctrl = portapack::clock_manager.si5351_read_register(16 + i);
// mA (Bits 1:0)
rows[i].ma->set(ma_lookup[ctrl & 0x03]);
// Mode (Bit 6: 1=Integer, 0=Fractional)
rows[i].mode->set((ctrl & 0x40) ? "INT" : "FRAC");
rows[i].mode->set_style((ctrl & 0x40) ? Theme::getInstance()->fg_blue : Theme::getInstance()->fg_yellow);
// Phase (Bit 4: 1=Inverted, 0=Normal)
// Use 0x10 (Bit 4)
rows[i].phase->set((ctrl & 0x10) ? "INVRT" : "NORM ");
rows[i].phase->set_style((ctrl & 0x10) ? Theme::getInstance()->fg_orange : Theme::getInstance()->fg_light);
// Status (Powered On and Output Enabled)
bool is_on = !(ctrl & 0x80) && !(output_en & (1 << i));
rows[i].stat->set(is_on ? "ON" : "OFF");
rows[i].stat->set_style(is_on ? Theme::getInstance()->fg_green : Theme::getInstance()->fg_red);
}
}
#endif
#ifdef PRALINE
/* GPIODebugView *************************************************/
GPIODebugView::GPIODebugView(NavigationView& nav) {
@@ -3003,6 +3075,7 @@ void DebugMenuView::on_populate() {
add_items({
#ifdef PRALINE
{"System Diag", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push<SystemDiagnosticsView>(); }},
{"PRO Clocks", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push<ui::PralineClockDebugView>(); }},
{"Radio Diag", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push<RadioDiagnosticsView>(); }},
{"WFM Audio", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push<WFMAudioDebugView>(); }},
{"ProRadio Debug", ui::Theme::getInstance()->fg_yellow->foreground, &bitmap_icon_peripherals, [this]() { nav_.push<PralineRadioDebugView>(); }},
+73
View File
@@ -1125,6 +1125,79 @@ class SystemDiagnosticsView : public View {
};
#endif
#ifdef PRALINE
class PralineClockDebugView : public View {
public:
PralineClockDebugView(NavigationView& nav);
void focus() override;
std::string title() const override { return "Pro Clock Status"; };
private:
void refresh();
Text text_title{{0, 0, 240, 16}, "=== Pro Clock Dashboard ==="};
// System Status
Text text_lbl_pll{{0, 20, 80, 16}, "PLL Lock:"};
Text text_pll_status{{88, 20, 152, 16}, "---"};
Text text_lbl_afe{{0, 36, 80, 16}, "AFE Rate:"};
Text text_afe_rate{{88, 36, 152, 16}, "---"};
Text text_lbl_n{{0, 52, 80, 16}, "Decim (n):"};
Text text_n_val{{88, 52, 152, 16}, "-"};
// Table Header
Text text_header{{0, 72, 240, 16}, "ID mA Mode Phase Stat"};
// Helper structure to group row widgets for CLK0-CLK5
struct ClockRow {
Text* id;
Text* ma;
Text* mode;
Text* phase;
Text* stat;
};
std::vector<ClockRow> rows;
// We define the actual widgets for 6 clocks
// Note: Layout uses 16px vertical spacing per row
Text t0_id{{0, 88, 24, 16}, "C0:"};
Text t0_ma{{32, 88, 24, 16}, "-"};
Text t0_mode{{64, 88, 48, 16}, "-"};
Text t0_ph{{128, 88, 56, 16}, "-"};
Text t0_st{{192, 88, 48, 16}, "-"};
Text t1_id{{0, 104, 24, 16}, "C1:"};
Text t1_ma{{32, 104, 24, 16}, "-"};
Text t1_mode{{64, 104, 48, 16}, "-"};
Text t1_ph{{128, 104, 56, 16}, "-"};
Text t1_st{{192, 104, 48, 16}, "-"};
Text t2_id{{0, 120, 24, 16}, "C2:"};
Text t2_ma{{32, 120, 24, 16}, "-"};
Text t2_mode{{64, 120, 48, 16}, "-"};
Text t2_ph{{128, 120, 56, 16}, "-"};
Text t2_st{{192, 120, 48, 16}, "-"};
Text t3_id{{0, 136, 24, 16}, "C3:"};
Text t3_ma{{32, 136, 24, 16}, "-"};
Text t3_mode{{64, 136, 48, 16}, "-"};
Text t3_ph{{128, 136, 56, 16}, "-"};
Text t3_st{{192, 136, 48, 16}, "-"};
Text t4_id{{0, 152, 24, 16}, "C4:"};
Text t4_ma{{32, 152, 24, 16}, "-"};
Text t4_mode{{64, 152, 48, 16}, "-"};
Text t4_ph{{128, 152, 56, 16}, "-"};
Text t4_st{{192, 152, 48, 16}, "-"};
Text t5_id{{0, 168, 24, 16}, "C5:"};
Text t5_ma{{32, 168, 24, 16}, "-"};
Text t5_mode{{64, 168, 48, 16}, "-"};
Text t5_ph{{128, 168, 56, 16}, "-"};
Text t5_st{{192, 168, 48, 16}, "-"};
Button button_refresh{{8, 260, 100, 24}, "Refresh"};
Button button_done{{132, 260, 100, 24}, "Done"};
};
#endif
#endif
class DebugPeripheralsMenuView : public BtnGridView {