mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Add capture mode waterfall.
This commit is contained in:
parent
2201a9e95f
commit
ec75c00da2
@ -36,6 +36,7 @@ CaptureAppView::CaptureAppView(NavigationView& nav) {
|
|||||||
&field_frequency,
|
&field_frequency,
|
||||||
&field_lna,
|
&field_lna,
|
||||||
&field_vga,
|
&field_vga,
|
||||||
|
&waterfall,
|
||||||
} });
|
} });
|
||||||
|
|
||||||
field_frequency.set_value(receiver_model.tuning_frequency());
|
field_frequency.set_value(receiver_model.tuning_frequency());
|
||||||
@ -79,6 +80,20 @@ CaptureAppView::~CaptureAppView() {
|
|||||||
receiver_model.disable();
|
receiver_model.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CaptureAppView::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 CaptureAppView::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 CaptureAppView::focus() {
|
void CaptureAppView::focus() {
|
||||||
button_start_stop.focus();
|
button_start_stop.focus();
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "ui_widget.hpp"
|
#include "ui_widget.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "ui_navigation.hpp"
|
||||||
#include "ui_receiver.hpp"
|
#include "ui_receiver.hpp"
|
||||||
|
#include "ui_spectrum.hpp"
|
||||||
|
|
||||||
#include "audio_thread.hpp"
|
#include "audio_thread.hpp"
|
||||||
|
|
||||||
@ -84,11 +85,17 @@ public:
|
|||||||
CaptureAppView(NavigationView& nav);
|
CaptureAppView(NavigationView& nav);
|
||||||
~CaptureAppView();
|
~CaptureAppView();
|
||||||
|
|
||||||
|
void on_hide() override;
|
||||||
|
|
||||||
|
void set_parent_rect(const Rect new_parent_rect) override;
|
||||||
|
|
||||||
void focus() override;
|
void focus() override;
|
||||||
|
|
||||||
std::string title() const override { return "Capture"; };
|
std::string title() const override { return "Capture"; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr ui::Dim header_height = 2 * 16;
|
||||||
|
|
||||||
static constexpr uint32_t sampling_rate = 2457600;
|
static constexpr uint32_t sampling_rate = 2457600;
|
||||||
static constexpr uint32_t baseband_bandwidth = 1750000;
|
static constexpr uint32_t baseband_bandwidth = 1750000;
|
||||||
|
|
||||||
@ -126,6 +133,8 @@ private:
|
|||||||
VGAGainField field_vga {
|
VGAGainField field_vga {
|
||||||
{ 18 * 8, 0 * 16 }
|
{ 18 * 8, 0 * 16 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
spectrum::WaterfallWidget waterfall;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -26,8 +26,29 @@
|
|||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
CaptureProcessor::CaptureProcessor() {
|
CaptureProcessor::CaptureProcessor() {
|
||||||
decim_0.configure(taps_200k_decim_0.taps, 33554432);
|
const auto& decim_0_filter = taps_200k_decim_0;
|
||||||
decim_1.configure(taps_200k_decim_1.taps, 131072);
|
constexpr size_t decim_0_input_fs = baseband_fs;
|
||||||
|
constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor;
|
||||||
|
|
||||||
|
const auto& decim_1_filter = taps_200k_decim_1;
|
||||||
|
constexpr size_t decim_1_input_fs = decim_0_output_fs;
|
||||||
|
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor;
|
||||||
|
|
||||||
|
const auto& channel_filter = decim_1_filter;
|
||||||
|
constexpr size_t channel_filter_input_fs = decim_1_output_fs;
|
||||||
|
constexpr size_t channel_decimation = 1;
|
||||||
|
const size_t channel_filter_output_fs = channel_filter_input_fs / channel_decimation;
|
||||||
|
|
||||||
|
decim_0.configure(decim_0_filter.taps, 33554432);
|
||||||
|
decim_1.configure(decim_1_filter.taps, 131072);
|
||||||
|
|
||||||
|
channel_filter_pass_f = channel_filter.pass_frequency_normalized * channel_filter_input_fs;
|
||||||
|
channel_filter_stop_f = channel_filter.stop_frequency_normalized * channel_filter_input_fs;
|
||||||
|
|
||||||
|
spectrum_interval_samples = channel_filter_output_fs / spectrum_rate_hz;
|
||||||
|
spectrum_samples = 0;
|
||||||
|
|
||||||
|
channel_spectrum.set_decimation_factor(1);
|
||||||
|
|
||||||
stream = std::make_unique<StreamInput>(15);
|
stream = std::make_unique<StreamInput>(15);
|
||||||
}
|
}
|
||||||
@ -36,12 +57,31 @@ void CaptureProcessor::execute(const buffer_c8_t& buffer) {
|
|||||||
/* 2.4576MHz, 2048 samples */
|
/* 2.4576MHz, 2048 samples */
|
||||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||||
const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer);
|
const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer);
|
||||||
const auto decimator_out = decim_1_out;
|
const auto& decimator_out = decim_1_out;
|
||||||
|
const auto& channel = decimator_out;
|
||||||
|
|
||||||
if( stream ) {
|
if( stream ) {
|
||||||
const size_t bytes_to_write = sizeof(*decimator_out.p) * decimator_out.count;
|
const size_t bytes_to_write = sizeof(*decimator_out.p) * decimator_out.count;
|
||||||
const auto result = stream->write(decimator_out.p, bytes_to_write);
|
const auto result = stream->write(decimator_out.p, bytes_to_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
feed_channel_stats(decimator_out);
|
feed_channel_stats(channel);
|
||||||
|
|
||||||
|
spectrum_samples += channel.count;
|
||||||
|
if( spectrum_samples >= spectrum_interval_samples ) {
|
||||||
|
spectrum_samples -= spectrum_interval_samples;
|
||||||
|
channel_spectrum.feed(channel, channel_filter_pass_f, channel_filter_stop_f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaptureProcessor::on_message(const Message* const message) {
|
||||||
|
switch(message->id) {
|
||||||
|
case Message::ID::UpdateSpectrum:
|
||||||
|
case Message::ID::SpectrumStreamingConfig:
|
||||||
|
channel_spectrum.on_message(message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include "baseband_processor.hpp"
|
#include "baseband_processor.hpp"
|
||||||
#include "dsp_decimate.hpp"
|
#include "dsp_decimate.hpp"
|
||||||
|
|
||||||
|
#include "spectrum_collector.hpp"
|
||||||
|
|
||||||
#include "stream_input.hpp"
|
#include "stream_input.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -36,7 +38,12 @@ public:
|
|||||||
|
|
||||||
void execute(const buffer_c8_t& buffer) override;
|
void execute(const buffer_c8_t& buffer) override;
|
||||||
|
|
||||||
|
void on_message(const Message* const message) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr size_t baseband_fs = 2457600;
|
||||||
|
static constexpr auto spectrum_rate_hz = 50.0f;
|
||||||
|
|
||||||
std::array<complex16_t, 512> dst;
|
std::array<complex16_t, 512> dst;
|
||||||
const buffer_c16_t dst_buffer {
|
const buffer_c16_t dst_buffer {
|
||||||
dst.data(),
|
dst.data(),
|
||||||
@ -45,8 +52,14 @@ private:
|
|||||||
|
|
||||||
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0;
|
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0;
|
||||||
dsp::decimate::FIRC16xR16x16Decim2 decim_1;
|
dsp::decimate::FIRC16xR16x16Decim2 decim_1;
|
||||||
|
uint32_t channel_filter_pass_f = 0;
|
||||||
|
uint32_t channel_filter_stop_f = 0;
|
||||||
|
|
||||||
std::unique_ptr<StreamInput> stream;
|
std::unique_ptr<StreamInput> stream;
|
||||||
|
|
||||||
|
SpectrumCollector channel_spectrum;
|
||||||
|
size_t spectrum_interval_samples = 0;
|
||||||
|
size_t spectrum_samples = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif/*__PROC_CAPTURE_HPP__*/
|
#endif/*__PROC_CAPTURE_HPP__*/
|
||||||
|
Loading…
Reference in New Issue
Block a user