Move ReceiverView code to AnalogAudioView.

ReceiverView predated the "app" model, was serving as a shell for *all* radio activity, but became outmoded and redundant when non-audio modes were split out into separate apps.

Some stuff is broken in this change, will be fixed imminently.
This commit is contained in:
Jared Boone 2016-01-31 09:13:44 -08:00
parent f134e63f05
commit 4d3294c228
8 changed files with 331 additions and 402 deletions

View File

@ -175,7 +175,6 @@ CPPSRC = main.cpp \
tpms_app.cpp \
ert_app.cpp \
../common/ert_packet.cpp \
spectrum_analysis_app.cpp \
sd_card.cpp \
file.cpp \
log_file.cpp \

View File

@ -30,33 +30,6 @@ using namespace portapack;
#include "utility.hpp"
AnalogAudioModel::AnalogAudioModel(ReceiverModel::Mode mode) {
receiver_model.set_baseband_configuration({
.mode = toUType(mode),
.sampling_rate = 3072000,
.decimation_factor = 1,
});
receiver_model.set_baseband_bandwidth(1750000);
switch(mode) {
case ReceiverModel::Mode::NarrowbandFMAudio:
configure_nbfm(2);
break;
case ReceiverModel::Mode::WidebandFMAudio:
configure_wfm();
break;
case ReceiverModel::Mode::AMAudio:
configure_am(0);
break;
default:
break;
}
}
struct NBFMMode {
const fir_taps_real<24> decim_0;
const fir_taps_real<32> decim_1;
@ -122,3 +95,227 @@ void AnalogAudioModel::configure_am(const size_t index) {
shared_memory.baseband_queue.push(message);
clock_manager.set_base_audio_clock_divider(4);
}
namespace ui {
/* AnalogAudioView *******************************************************/
AnalogAudioView::AnalogAudioView(
NavigationView& nav
) {
add_children({ {
&rssi,
&channel,
&audio,
&field_frequency,
&field_lna,
&field_vga,
&options_modulation,
&field_volume,
&view_frequency_options,
&view_rf_gain_options,
&waterfall,
} });
field_frequency.set_value(receiver_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.on_change = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
};
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
this->field_frequency.set_value(f);
};
};
field_frequency.on_show_options = [this]() {
this->on_show_options_frequency();
};
field_lna.set_value(receiver_model.lna());
field_lna.on_change = [this](int32_t v) {
this->on_lna_changed(v);
};
field_lna.on_show_options = [this]() {
this->on_show_options_rf_gain();
};
field_vga.set_value(receiver_model.vga());
field_vga.on_change = [this](int32_t v_db) {
this->on_vga_changed(v_db);
};
options_modulation.set_by_value(1);
options_modulation.on_change = [this](size_t n, OptionsField::value_t v) {
(void)n;
this->on_modulation_changed(v);
};
field_volume.set_value((receiver_model.headphone_volume() - wolfson::wm8731::headphone_gain_range.max).decibel() + 99);
field_volume.on_change = [this](int32_t v) {
this->on_headphone_volume_changed(v);
};
view_frequency_options.hidden(true);
view_frequency_options.set_step(receiver_model.frequency_step());
view_frequency_options.on_change_step = [this](rf::Frequency f) {
this->on_frequency_step_changed(f);
};
view_frequency_options.set_reference_ppm_correction(receiver_model.reference_ppm_correction());
view_frequency_options.on_change_reference_ppm_correction = [this](int32_t v) {
this->on_reference_ppm_correction_changed(v);
};
view_rf_gain_options.hidden(true);
view_rf_gain_options.set_rf_amp(receiver_model.rf_amp());
view_rf_gain_options.on_change_rf_amp = [this](bool enable) {
this->on_rf_amp_changed(enable);
};
}
AnalogAudioView::~AnalogAudioView() {
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
// both?
audio_codec.headphone_mute();
receiver_model.disable();
}
void AnalogAudioView::on_show() {
View::on_show();
// TODO: Terrible kludge because widget system doesn't notify Waterfall that
// it's being shown or hidden.
}
void AnalogAudioView::on_hide() {
// TODO: Terrible kludge because widget system doesn't notify Waterfall that
// it's being shown or hidden.
waterfall.on_hide();
View::on_hide();
}
void AnalogAudioView::set_parent_rect(const Rect new_parent_rect) {
View::set_parent_rect(new_parent_rect);
const ui::Rect waterfall_rect { 0, header_height, new_parent_rect.width(), static_cast<ui::Dim>(new_parent_rect.height() - header_height) };
waterfall.set_parent_rect(waterfall_rect);
}
void AnalogAudioView::focus() {
field_frequency.focus();
}
void AnalogAudioView::on_tuning_frequency_changed(rf::Frequency f) {
receiver_model.set_tuning_frequency(f);
}
void AnalogAudioView::on_baseband_bandwidth_changed(uint32_t bandwidth_hz) {
receiver_model.set_baseband_bandwidth(bandwidth_hz);
}
void AnalogAudioView::on_rf_amp_changed(bool v) {
receiver_model.set_rf_amp(v);
}
void AnalogAudioView::on_lna_changed(int32_t v_db) {
receiver_model.set_lna(v_db);
}
void AnalogAudioView::on_vga_changed(int32_t v_db) {
receiver_model.set_vga(v_db);
}
void AnalogAudioView::on_modulation_changed(int32_t mode) {
// remove_child(widget_content.get());
// widget_content.reset();
// TODO: Terrible kludge because widget system doesn't notify Waterfall that
// it's being shown or hidden.
waterfall.on_hide();
switch(mode) {
default:
case 1:
receiver_model.set_baseband_configuration({
.mode = toUType(ReceiverModel::Mode::AMAudio),
.sampling_rate = 3072000,
.decimation_factor = 1,
});
receiver_model.set_baseband_bandwidth(1750000);
receiver_model.enable();
model.configure_am(0);
waterfall.on_show();
break;
case 2:
receiver_model.set_baseband_configuration({
.mode = toUType(ReceiverModel::Mode::NarrowbandFMAudio),
.sampling_rate = 3072000,
.decimation_factor = 1,
});
receiver_model.set_baseband_bandwidth(1750000);
receiver_model.enable();
model.configure_nbfm(1);
waterfall.on_show();
break;
case 3:
receiver_model.set_baseband_configuration({
.mode = toUType(ReceiverModel::Mode::WidebandFMAudio),
.sampling_rate = 3072000,
.decimation_factor = 1,
});
receiver_model.set_baseband_bandwidth(1750000);
receiver_model.enable();
model.configure_wfm();
waterfall.on_show();
break;
case 4:
receiver_model.set_baseband_configuration({
.mode = 4,
.sampling_rate = 20000000,
.decimation_factor = 1,
});
receiver_model.set_baseband_bandwidth(12000000);
receiver_model.enable();
waterfall.on_show();
break;
}
}
void AnalogAudioView::on_show_options_frequency() {
view_rf_gain_options.hidden(true);
field_lna.set_style(nullptr);
view_frequency_options.hidden(false);
field_frequency.set_style(&view_frequency_options.style());
}
void AnalogAudioView::on_show_options_rf_gain() {
view_frequency_options.hidden(true);
field_frequency.set_style(nullptr);
view_rf_gain_options.hidden(false);
field_lna.set_style(&view_frequency_options.style());
}
void AnalogAudioView::on_frequency_step_changed(rf::Frequency f) {
receiver_model.set_frequency_step(f);
field_frequency.set_step(f);
}
void AnalogAudioView::on_reference_ppm_correction_changed(int32_t v) {
receiver_model.set_reference_ppm_correction(v);
}
void AnalogAudioView::on_headphone_volume_changed(int32_t v) {
const auto new_volume = volume_t::decibel(v - 99) + wolfson::wm8731::headphone_gain_range.max;
receiver_model.set_headphone_volume(new_volume);
}
} /* namespace ui */

View File

@ -23,13 +23,14 @@
#define __ANALOG_AUDIO_APP_H__
#include "receiver_model.hpp"
#include "ui_receiver.hpp"
#include "ui_spectrum.hpp"
#include "ui_font_fixed_8x16.hpp"
class AnalogAudioModel {
public:
AnalogAudioModel(ReceiverModel::Mode mode);
private:
void configure_nbfm(const size_t index);
void configure_wfm();
void configure_am(const size_t index);
@ -37,16 +38,110 @@ private:
namespace ui {
class AnalogAudioView : public spectrum::WaterfallWidget {
constexpr Style style_options_group {
.font = font::fixed_8x16,
.background = Color::blue(),
.foreground = Color::white(),
};
class AnalogAudioView : public View {
public:
AnalogAudioView(
ReceiverModel::Mode mode
) : model { mode }
{
}
AnalogAudioView(NavigationView& nav);
~AnalogAudioView();
void on_show() override;
void on_hide() override;
void set_parent_rect(const Rect new_parent_rect) override;
void focus() override;
private:
AnalogAudioModel model;
static constexpr ui::Dim header_height = 2 * 16;
RSSI rssi {
{ 21 * 8, 0, 6 * 8, 4 },
};
Channel channel {
{ 21 * 8, 5, 6 * 8, 4 },
};
Audio audio {
{ 21 * 8, 10, 6 * 8, 4 },
};
FrequencyField field_frequency {
{ 5 * 8, 0 * 16 },
};
LNAGainField field_lna {
{ 15 * 8, 0 * 16 }
};
NumberField field_vga {
{ 18 * 8, 0 * 16},
2,
{ max2837::vga::gain_db_range.minimum, max2837::vga::gain_db_range.maximum },
max2837::vga::gain_db_step,
' ',
};
OptionsField options_modulation {
{ 0 * 8, 0 * 16 },
4,
{
{ " AM ", 1 },
{ "NFM ", 2 },
{ "WFM ", 3 },
{ "SPEC", 4 },
}
};
NumberField field_volume {
{ 28 * 8, 0 * 16 },
2,
{ 0, 99 },
1,
' ',
};
FrequencyOptionsView view_frequency_options {
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
&style_options_group
};
RadioGainOptionsView view_rf_gain_options {
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
&style_options_group
};
/*
AmplitudeModulationOptionsView view_am_modulation_options {
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
&style_options_group
};
FrequencyModulationOptionsView view_fm_modulation_options {
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
&style_options_group
};
*/
spectrum::WaterfallWidget waterfall;
void on_tuning_frequency_changed(rf::Frequency f);
void on_baseband_bandwidth_changed(uint32_t bandwidth_hz);
void on_rf_amp_changed(bool v);
void on_lna_changed(int32_t v_db);
void on_vga_changed(int32_t v_db);
void on_modulation_changed(int32_t v);
void on_show_options_frequency();
void on_show_options_rf_gain();
void on_frequency_step_changed(rf::Frequency f);
void on_reference_ppm_correction_changed(int32_t v);
void on_headphone_volume_changed(int32_t v);
void on_edit_frequency();
};
} /* namespace ui */

View File

@ -1,34 +0,0 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
*
* 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.
*/
#include "spectrum_analysis_app.hpp"
#include "portapack.hpp"
using namespace portapack;
SpectrumAnalysisModel::SpectrumAnalysisModel() {
receiver_model.set_baseband_configuration({
.mode = 4,
.sampling_rate = 20000000,
.decimation_factor = 1,
});
receiver_model.set_baseband_bandwidth(12000000);
}

View File

@ -1,44 +0,0 @@
/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
*
* 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.
*/
#ifndef __SPECTRUM_ANALYSIS_APP_H__
#define __SPECTRUM_ANALYSIS_APP_H__
#include "receiver_model.hpp"
#include "ui_spectrum.hpp"
class SpectrumAnalysisModel {
public:
SpectrumAnalysisModel();
};
namespace ui {
class SpectrumAnalysisView : public spectrum::WaterfallWidget {
public:
private:
SpectrumAnalysisModel model;
};
} /* namespace ui */
#endif/*__SPECTRUM_ANALYSIS_APP_H__*/

View File

@ -27,8 +27,8 @@
#include "ui_setup.hpp"
#include "ui_debug.hpp"
#include "ui_receiver.hpp"
#include "analog_audio_app.hpp"
#include "ais_app.hpp"
#include "ert_app.hpp"
#include "tpms_app.hpp"
@ -140,7 +140,7 @@ TranspondersMenuView::TranspondersMenuView(NavigationView& nav) {
ReceiverMenuView::ReceiverMenuView(NavigationView& nav) {
add_items<2>({ {
{ "Audio", [&nav](){ nav.push<ReceiverView>(); } },
{ "Audio", [&nav](){ nav.push<AnalogAudioView>(); } },
{ "Transponders", [&nav](){ nav.push<TranspondersMenuView>(); } },
} });
}

View File

@ -26,11 +26,7 @@ using namespace portapack;
#include "string_format.hpp"
#include "analog_audio_app.hpp"
#include "ais_app.hpp"
#include "tpms_app.hpp"
#include "ert_app.hpp"
#include "spectrum_analysis_app.hpp"
#include "max2837.hpp"
namespace ui {
@ -322,184 +318,4 @@ void LNAGainField::on_focus() {
}
}
/* ReceiverView **********************************************************/
ReceiverView::ReceiverView(
NavigationView& nav
) {
add_children({ {
&rssi,
&channel,
&audio,
&field_frequency,
&field_lna,
&field_vga,
&options_modulation,
&field_volume,
&view_frequency_options,
&view_rf_gain_options,
} });
field_frequency.set_value(receiver_model.tuning_frequency());
field_frequency.set_step(receiver_model.frequency_step());
field_frequency.on_change = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
};
field_frequency.on_edit = [this, &nav]() {
// TODO: Provide separate modal method/scheme?
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
new_view->on_changed = [this](rf::Frequency f) {
this->on_tuning_frequency_changed(f);
this->field_frequency.set_value(f);
};
};
field_frequency.on_show_options = [this]() {
this->on_show_options_frequency();
};
field_lna.set_value(receiver_model.lna());
field_lna.on_change = [this](int32_t v) {
this->on_lna_changed(v);
};
field_lna.on_show_options = [this]() {
this->on_show_options_rf_gain();
};
field_vga.set_value(receiver_model.vga());
field_vga.on_change = [this](int32_t v_db) {
this->on_vga_changed(v_db);
};
options_modulation.set_by_value(receiver_model.modulation());
options_modulation.on_change = [this](size_t n, OptionsField::value_t v) {
(void)n;
this->on_modulation_changed(static_cast<ReceiverModel::Mode>(v));
};
field_volume.set_value((receiver_model.headphone_volume() - wolfson::wm8731::headphone_gain_range.max).decibel() + 99);
field_volume.on_change = [this](int32_t v) {
this->on_headphone_volume_changed(v);
};
view_frequency_options.hidden(true);
view_frequency_options.set_step(receiver_model.frequency_step());
view_frequency_options.on_change_step = [this](rf::Frequency f) {
this->on_frequency_step_changed(f);
};
view_frequency_options.set_reference_ppm_correction(receiver_model.reference_ppm_correction());
view_frequency_options.on_change_reference_ppm_correction = [this](int32_t v) {
this->on_reference_ppm_correction_changed(v);
};
view_rf_gain_options.hidden(true);
view_rf_gain_options.set_rf_amp(receiver_model.rf_amp());
view_rf_gain_options.on_change_rf_amp = [this](bool enable) {
this->on_rf_amp_changed(enable);
};
receiver_model.enable();
}
ReceiverView::~ReceiverView() {
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
// both?
audio_codec.headphone_mute();
receiver_model.disable();
}
void ReceiverView::on_show() {
View::on_show();
// TODO: Separate concepts of baseband "modulation" and receiver "mode".
on_modulation_changed(static_cast<ReceiverModel::Mode>(receiver_model.modulation()));
}
void ReceiverView::on_hide() {
on_modulation_changed(static_cast<ReceiverModel::Mode>(-1));
View::on_hide();
}
void ReceiverView::focus() {
field_frequency.focus();
}
void ReceiverView::on_tuning_frequency_changed(rf::Frequency f) {
receiver_model.set_tuning_frequency(f);
}
void ReceiverView::on_baseband_bandwidth_changed(uint32_t bandwidth_hz) {
receiver_model.set_baseband_bandwidth(bandwidth_hz);
}
void ReceiverView::on_rf_amp_changed(bool v) {
receiver_model.set_rf_amp(v);
}
void ReceiverView::on_lna_changed(int32_t v_db) {
receiver_model.set_lna(v_db);
}
void ReceiverView::on_vga_changed(int32_t v_db) {
receiver_model.set_vga(v_db);
}
void ReceiverView::on_modulation_changed(ReceiverModel::Mode mode) {
remove_child(widget_content.get());
widget_content.reset();
switch(mode) {
case ReceiverModel::Mode::AMAudio:
case ReceiverModel::Mode::NarrowbandFMAudio:
case ReceiverModel::Mode::WidebandFMAudio:
widget_content = std::make_unique<AnalogAudioView>(mode);
break;
case ReceiverModel::Mode::SpectrumAnalysis:
widget_content = std::make_unique<SpectrumAnalysisView>();
break;
default:
break;
}
if( widget_content ) {
add_child(widget_content.get());
const ui::Rect rect { 0, header_height, parent_rect.width(), static_cast<ui::Dim>(parent_rect.height() - header_height) };
widget_content->set_parent_rect(rect);
}
}
void ReceiverView::on_show_options_frequency() {
view_rf_gain_options.hidden(true);
field_lna.set_style(nullptr);
view_frequency_options.hidden(false);
field_frequency.set_style(&view_frequency_options.style());
}
void ReceiverView::on_show_options_rf_gain() {
view_frequency_options.hidden(true);
field_frequency.set_style(nullptr);
view_rf_gain_options.hidden(false);
field_lna.set_style(&view_frequency_options.style());
}
void ReceiverView::on_frequency_step_changed(rf::Frequency f) {
receiver_model.set_frequency_step(f);
field_frequency.set_step(f);
}
void ReceiverView::on_reference_ppm_correction_changed(int32_t v) {
receiver_model.set_reference_ppm_correction(v);
}
void ReceiverView::on_headphone_volume_changed(int32_t v) {
const auto new_volume = volume_t::decibel(v - 99) + wolfson::wm8731::headphone_gain_range.max;
receiver_model.set_headphone_volume(new_volume);
}
} /* namespace ui */

View File

@ -23,19 +23,11 @@
#define __UI_RECEIVER_H__
#include "ui.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "ui_navigation.hpp"
#include "ui_painter.hpp"
#include "ui_widget.hpp"
#include "utility.hpp"
#include "max2837.hpp"
#include "rf_path.hpp"
#include "volume.hpp"
#include "wm8731.hpp"
#include "receiver_model.hpp"
#include <cstddef>
#include <cstdint>
@ -323,98 +315,6 @@ public:
void on_focus() override;
};
constexpr Style style_options_group {
.font = font::fixed_8x16,
.background = Color::blue(),
.foreground = Color::white(),
};
class ReceiverView : public View {
public:
ReceiverView(NavigationView& nav);
~ReceiverView();
void on_show() override;
void on_hide() override;
void focus() override;
private:
static constexpr ui::Dim header_height = 2 * 16;
RSSI rssi {
{ 21 * 8, 0, 6 * 8, 4 },
};
Channel channel {
{ 21 * 8, 5, 6 * 8, 4 },
};
Audio audio {
{ 21 * 8, 10, 6 * 8, 4 },
};
FrequencyField field_frequency {
{ 5 * 8, 0 * 16 },
};
LNAGainField field_lna {
{ 15 * 8, 0 * 16 }
};
NumberField field_vga {
{ 18 * 8, 0 * 16},
2,
{ max2837::vga::gain_db_range.minimum, max2837::vga::gain_db_range.maximum },
max2837::vga::gain_db_step,
' ',
};
OptionsField options_modulation {
{ 0 * 8, 0 * 16 },
4,
{
{ " AM ", toUType(ReceiverModel::Mode::AMAudio) },
{ "NFM ", toUType(ReceiverModel::Mode::NarrowbandFMAudio) },
{ "WFM ", toUType(ReceiverModel::Mode::WidebandFMAudio) },
{ "SPEC", toUType(ReceiverModel::Mode::SpectrumAnalysis) },
}
};
NumberField field_volume {
{ 28 * 8, 0 * 16 },
2,
{ 0, 99 },
1,
' ',
};
FrequencyOptionsView view_frequency_options {
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
&style_options_group
};
RadioGainOptionsView view_rf_gain_options {
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
&style_options_group
};
std::unique_ptr<Widget> widget_content;
void on_tuning_frequency_changed(rf::Frequency f);
void on_baseband_bandwidth_changed(uint32_t bandwidth_hz);
void on_rf_amp_changed(bool v);
void on_lna_changed(int32_t v_db);
void on_vga_changed(int32_t v_db);
void on_modulation_changed(ReceiverModel::Mode mode);
void on_show_options_frequency();
void on_show_options_rf_gain();
void on_frequency_step_changed(rf::Frequency f);
void on_reference_ppm_correction_changed(int32_t v);
void on_headphone_volume_changed(int32_t v);
void on_edit_frequency();
};
} /* namespace ui */
#endif/*__UI_RECEIVER_H__*/