copy capture

This commit is contained in:
zxkmm 2025-04-13 15:40:39 +08:00
parent f344a1ca40
commit e8fcb50572
5 changed files with 368 additions and 0 deletions

View File

@ -207,6 +207,10 @@ set(EXTCPPSRC
#gfxEQ
external/gfxeq/main.cpp
external/gfxeq/ui_gfxeq.cpp
#waterfall designer
external/waterfall_designer/main.cpp
external/waterfall_designer/ui_waterfall_designer.cpp
)
set(EXTAPPLIST
@ -260,4 +264,5 @@ set(EXTAPPLIST
scanner
level
gfxeq
waterfall_designer
)

View File

@ -73,6 +73,7 @@ MEMORY
ram_external_app_scanner (rwx) : org = 0xADE00000, len = 32k
ram_external_app_level (rwx) : org = 0xADE10000, len = 32k
ram_external_app_gfxeq (rwx) : org = 0xADE20000, len = 32k
ram_external_app_waterfall_designer (rwx) : org = 0xADE30000, len = 32k
}
SECTIONS
@ -375,4 +376,10 @@ SECTIONS
KEEP(*(.external_app.app_gfxeq.application_information));
*(*ui*external_app*gfxeq*);
} > ram_external_app_gfxeq
.external_app_waterfall_designer : ALIGN(4) SUBALIGN(4)
{
KEEP(*(.external_app.app_waterfall_designer.application_information));
*(*ui*external_app*waterfall_designer*);
} > ram_external_app_waterfall_designer
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2025 Mark Thompson
*
* 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 "ui.hpp"
#include "ui_waterfall_designer.hpp"
#include "ui_navigation.hpp"
#include "external_app.hpp"
namespace ui::external_app::waterfall_designer {
void initialize_app(ui::NavigationView& nav) {
nav.push<WaterfallDesignerView>();
}
} // namespace ui::external_app::waterfall_designer
extern "C" {
__attribute__((section(".external_app.app_waterfall_designer.application_information"), used)) application_information_t _application_information_waterfall_designer = {
/*.memory_location = */ (uint8_t*)0x00000000,
/*.externalAppEntry = */ ui::external_app::waterfall_designer::initialize_app,
/*.header_version = */ CURRENT_HEADER_VERSION,
/*.app_version = */ VERSION_MD5,
/*.app_name = */ "Wtf Design",
/*.bitmap_data = */ {
0x00,
0x00,
0xC0,
0x01,
0x80,
0x00,
0x80,
0x20,
0x60,
0x13,
0x10,
0x0C,
0x88,
0x08,
0x84,
0x10,
0x84,
0x10,
0xC2,
0x21,
0x84,
0x10,
0x04,
0x10,
0x08,
0x08,
0x10,
0x04,
0x60,
0x03,
0x80,
0x00,
},
/*.icon_color = */ ui::Color::cyan().v,
/*.menu_location = */ app_location_t::RX,
/*.desired_menu_position = */ 0,
/*.m4_app_tag = portapack::spi_flash::image_tag_none */ {'P', 'C', 'A', 'P'},
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
};
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2018 Furrtek
*
* 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 "ui_waterfall_designer.hpp"
#include "baseband_api.hpp"
#include "portapack.hpp"
#include "ui_freqman.hpp"
using namespace portapack;
namespace ui::external_app::waterfall_designer {
WaterfallDesignerView::WaterfallDesignerView(NavigationView& nav)
: nav_{nav} {
baseband::run_image(portapack::spi_flash::image_tag_capture);
add_children({
&labels,
&rssi,
&channel,
&field_frequency,
&field_frequency_step,
&field_rf_amp,
&field_lna,
&field_vga,
&option_bandwidth,
&option_format,
&check_trim,
&record_view,
&waterfall,
});
field_frequency_step.set_by_value(receiver_model.frequency_step());
field_frequency_step.on_change = [this](size_t, OptionsField::value_t v) {
receiver_model.set_frequency_step(v);
this->field_frequency.set_step(v);
};
option_format.set_selected_index(file_format);
option_format.on_change = [this](size_t, uint32_t file_type) {
file_format = file_type;
record_view.set_file_type((RecordView::FileType)file_type);
};
check_trim.set_value(trim);
check_trim.on_select = [this](Checkbox&, bool v) {
trim = v;
record_view.set_auto_trim(v);
};
freqman_set_bandwidth_option(SPEC_MODULATION, option_bandwidth);
option_bandwidth.on_change = [this](size_t, uint32_t new_capture_rate) {
/* Nyquist would imply a sample rate of 2x bandwidth, but because the ADC
* provides 2 values (I,Q), the sample_rate is equal to bandwidth here. */
/* capture_rate (bandwidth) is used for FFT calculation and display LCD, and also in recording writing SD Card rate. */
/* ex. sampling_rate values, 4Mhz, when recording 500 kHz (BW) and fs 8 Mhz, when selected 1 Mhz BW ... */
/* ex. recording 500kHz BW to .C16 file, base_rate clock 500kHz x2(I,Q) x 2 bytes (int signed) =2MB/sec rate SD Card. */
waterfall.stop();
// record_view determines the correct oversampling to apply and returns the actual sample rate.
// NB: record_view is what actually updates proc_capture baseband settings.
auto actual_sample_rate = record_view.set_sampling_rate(new_capture_rate);
// Update the radio model with the actual sampling rate.
receiver_model.set_sampling_rate(actual_sample_rate);
// Get suitable anti-aliasing BPF bandwidth for MAX2837 given the actual sample rate.
auto anti_alias_filter_bandwidth = filter_bandwidth_for_sampling_rate(actual_sample_rate);
receiver_model.set_baseband_bandwidth(anti_alias_filter_bandwidth);
// Automatically switch default capture format to C8 when bandwidth setting is increased to >=1.5MHz anb back to C16 for <=1,25Mhz
if ((new_capture_rate >= 1500000) && (capture_rate < 1500000)) {
option_format.set_selected_index(1); // Default C8 format for REC, 1500K ... 5500k
}
if ((new_capture_rate <= 1250000) && (capture_rate > 1250000)) {
option_format.set_selected_index(0); // Default C16 format for REC , 12k5 ... 1250K
}
capture_rate = new_capture_rate;
waterfall.start();
};
receiver_model.enable();
option_bandwidth.set_by_value(capture_rate);
record_view.on_error = [&nav](std::string message) {
nav.display_modal("Error", message);
};
}
WaterfallDesignerView::WaterfallDesignerView(
NavigationView& nav,
ReceiverModel::settings_t override)
: WaterfallDesignerView(nav) {
// Settings to override when launched from another app (versus from AppSettings .ini file)
field_frequency.set_value(override.frequency_app_override);
}
WaterfallDesignerView::~WaterfallDesignerView() {
receiver_model.disable();
baseband::shutdown();
}
void WaterfallDesignerView::set_parent_rect(const Rect new_parent_rect) {
View::set_parent_rect(new_parent_rect);
ui::Rect waterfall_rect{0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height};
waterfall.set_parent_rect(waterfall_rect);
}
void WaterfallDesignerView::focus() {
record_view.focus();
}
void WaterfallDesignerView::on_freqchg(int64_t freq) {
field_frequency.set_value(freq);
}
} /* namespace ui::external_app::waterfall_designer */

View File

@ -0,0 +1,133 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2018 Furrtek
*
* 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 __WATERFALL_DESIGNER_APP_HPP__
#define __WATERFALL_DESIGNER_APP_HPP__
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "ui_freq_field.hpp"
#include "ui_record_view.hpp"
#include "ui_spectrum.hpp"
#include "app_settings.hpp"
#include "radio_state.hpp"
#include "file_path.hpp"
namespace ui::external_app::waterfall_designer {
class WaterfallDesignerView : public View {
public:
WaterfallDesignerView(NavigationView& nav);
WaterfallDesignerView(NavigationView& nav, ReceiverModel::settings_t override);
~WaterfallDesignerView();
void focus() override;
void set_parent_rect(const Rect new_parent_rect) override;
std::string title() const override { return "Capture"; };
private:
static constexpr ui::Dim header_height = 3 * 16;
uint32_t capture_rate{500000};
uint32_t file_format{0};
bool trim{false};
NavigationView& nav_;
RxRadioState radio_state_{ReceiverModel::Mode::Capture};
app_settings::SettingsManager settings_{
"rx_capture",
app_settings::Mode::RX,
{
{"capture_rate"sv, &capture_rate},
{"file_format"sv, &file_format},
{"trim"sv, &trim},
}};
Labels labels{
{{0 * 8, 1 * 16}, "Rate:", Theme::getInstance()->fg_light->foreground},
{{11 * 8, 1 * 16}, "Format:", Theme::getInstance()->fg_light->foreground},
};
RSSI rssi{
{24 * 8, 0, 6 * 8, 4}};
Channel channel{
{24 * 8, 5, 6 * 8, 4}};
RxFrequencyField field_frequency{
{0 * 8, 0 * 16},
nav_};
FrequencyStepView field_frequency_step{
{10 * 8, 0 * 16}};
RFAmpField field_rf_amp{
{16 * 8, 0 * 16}};
LNAGainField field_lna{
{18 * 8, 0 * 16}};
VGAGainField field_vga{
{21 * 8, 0 * 16}};
OptionsField option_bandwidth{
{5 * 8, 1 * 16},
5,
{}};
OptionsField option_format{
{18 * 8, 1 * 16},
3,
{{"C16", RecordView::FileType::RawS16},
{"C8", RecordView::FileType::RawS8}}};
Checkbox check_trim{
{23 * 8, 1 * 16},
4,
"Trim",
/*small*/ true};
RecordView record_view{
{0 * 8, 2 * 16, 30 * 8, 1 * 16},
u"BBD_????.*",
captures_dir,
RecordView::FileType::RawS16,
16384,
3};
spectrum::WaterfallView waterfall{};
MessageHandlerRegistration message_handler_freqchg{
Message::ID::FreqChangeCommand,
[this](Message* const p) {
const auto message = static_cast<const FreqChangeCommandMessage*>(p);
this->on_freqchg(message->freq);
}};
void on_freqchg(int64_t freq);
};
} /* namespace ui::external_app::waterfall_designer */
#endif /*__WATERFALL_DESIGNER_APP_HPP__*/