Tutorial de desarrollo de aplicaciones de Portapack (tres) pasos de desarrollo

Mi pensamiento es así. Dado que la aplicación que desarrollé es una copia de la reproducción, solo necesito copiar una copia del código que encontré anteriormente, modificarlo (renombrarlo) y luego agregar el archivo de código agregado a las CMakeLists correspondientes Solo adentro.

Di algunos pasos.

El primer paso es agregar un botón a la interfaz principal de portapack, que está temporalmente conectado para reproducir.

El segundo paso es modificar este botón y cambiar el icono (para cambiar el icono, también necesita buscar imágenes en Internet y luego generar datos).

El tercer paso es comenzar a cambiar la interfaz de la aplicación correspondiente al nuevo botón en la interfaz, pero esta aplicación también corresponde al programa de procesamiento en segundo plano original.

El cuarto paso es agregar el programa de procesamiento en segundo plano correspondiente, de modo que la aplicación del nuevo botón en la interfaz tenga un programa de procesamiento en segundo plano completamente independiente.

 

primer paso:

Abra ui_navigation.cpp, busque la siguiente parte y cámbiela de acuerdo con los comentarios.

SystemMenuView::SystemMenuView(NavigationView& nav) {
	add_items({
		{ "Play dead",				ui::Color::red(),		&bitmap_icon_playdead,	[&nav](){ nav.push<PlayDeadView>(); } },
		{ "Receivers", 	ui::Color::dark_cyan(),		&bitmap_icon_receivers,	[&nav](){ nav.push<ReceiversMenuView>(); } },
		{ "Transmit", 	ui::Color::green(),			&bitmap_icon_transmit,	[&nav](){ nav.push<TransmittersMenuView>(); } },
		{ "Capture",				ui::Color::blue(),		&bitmap_icon_capture,	[&nav](){ nav.push<CaptureAppView>(); } },
		{ "Replay",					ui::Color::purple(),	&bitmap_icon_replay,	[&nav](){ nav.push<ReplayAppView>(); } },
                { "GPS Sim",                              ui::Color::white(),     &bitmap_icon_replay,    [&nav]() { nav.push<ReplayAppView>(); } },
 //这一行是我们自己增加的,只改了名字和颜色
		{ "Calls",		ui::Color::yellow(),	    &bitmap_icon_closecall,	[&nav](){ nav.push<SearchView>(); } },
		{ "Scanner",	ui::Color::orange(),		&bitmap_icon_scanner,	[&nav](){ nav.push<ScannerView>(); } },
		{ "Utilities",				ui::Color::light_grey(),	&bitmap_icon_utilities,	[&nav](){ nav.push<UtilitiesMenuView>(); } },
		{ "Settings", 	ui::Color::cyan(),			&bitmap_icon_setup,	  	[&nav](){ nav.push<SettingsMenuView>(); } },
		//{ "Debug",		ui::Color::cyan(),			nullptr,   				[&nav](){ nav.push<DebugMenuView>(); } },
		{ "HackRF", 	ui::Color::cyan(),			&bitmap_icon_hackrf,	[this, &nav](){ hackrf_mode(nav); } },
		{ "About", 		ui::Color::cyan(),			nullptr,				[&nav](){ nav.push<AboutView>(); } }
	});
	
	set_highlighted(1);		// Startup selection is "Receivers"
}

La interfaz principal original: 

Después de la modificación, puede ver la interfaz principal así:

 

El segundo paso:

Aún abra ui_navigation.cpp y busque el cambio de ubicación correspondiente de acuerdo con el comentario.

SystemMenuView::SystemMenuView(NavigationView& nav) {
	add_items({
		{ "Play dead",				ui::Color::red(),		&bitmap_icon_playdead,	[&nav](){ nav.push<PlayDeadView>(); } },
		{ "Receivers", 	ui::Color::dark_cyan(),		&bitmap_icon_receivers,	[&nav](){ nav.push<ReceiversMenuView>(); } },
		{ "Transmit", 	ui::Color::green(),			&bitmap_icon_transmit,	[&nav](){ nav.push<TransmittersMenuView>(); } },
		{ "Capture",				ui::Color::blue(),		&bitmap_icon_capture,	[&nav](){ nav.push<CaptureAppView>(); } },
		{ "Replay",					ui::Color::purple(),	&bitmap_icon_replay,	[&nav](){ nav.push<ReplayAppView>(); } },
                { "GPS Sim",                              ui::Color::white(),     &bitmap_gps_sim,    [&nav]()
{ nav.push< ReplayAppView >(); } },
//我们现在把图标从bitmap_icon_replay改为bitmap_gps_sim
		{ "Calls",		ui::Color::yellow(),	    &bitmap_icon_closecall,	[&nav](){ nav.push<SearchView>(); } },
		{ "Scanner",	ui::Color::orange(),		&bitmap_icon_scanner,	[&nav](){ nav.push<ScannerView>(); } },
		{ "Utilities",				ui::Color::light_grey(),	&bitmap_icon_utilities,	[&nav](){ nav.push<UtilitiesMenuView>(); } },
		{ "Settings", 	ui::Color::cyan(),			&bitmap_icon_setup,	  	[&nav](){ nav.push<SettingsMenuView>(); } },
		//{ "Debug",		ui::Color::cyan(),			nullptr,   				[&nav](){ nav.push<DebugMenuView>(); } },
		{ "HackRF", 	ui::Color::cyan(),			&bitmap_icon_hackrf,	[this, &nav](){ hackrf_mode(nav); } },
		{ "About", 		ui::Color::cyan(),			nullptr,				[&nav](){ nav.push<AboutView>(); } }
	});
	
	set_highlighted(1);		// Startup selection is "Receivers"
}

Pero ahora bitmap_gps_sim no está disponible. Si compilamos ahora, se reportará un error. Lo busqué y el bitmap_icon_replay reemplazado por él apareció en bitmap.hpp. El fragmento es el siguiente:

static constexpr uint8_t bitmap_icon_replay_data[] = {
	0x00, 0x00, 
	0xC0, 0x07, 
	0xF0, 0x1F, 
	0x79, 0x3C, 
	0x1D, 0x70, 
	0x0F, 0x60, 
	0x07, 0xE0, 
	0x1F, 0xC0, 
	0x00, 0xC0, 
	0x00, 0xE0, 
	0x00, 0x60, 
	0x00, 0x70, 
	0x30, 0x3C, 
	0xE0, 0x0F, 
	0x80, 0x03, 
	0x00, 0x00, 
};
static constexpr Bitmap bitmap_icon_replay {
	{ 16, 16 }, bitmap_icon_replay_data
};

En otras palabras, tenemos que encontrar una manera de generar dichos datos desde el icono y luego completarlos en este formato.

Encontré firmware / tools / make_bitmap.py. De acuerdo con los requisitos del código, solo necesito encontrar una imagen png cuyo ancho y alto puedan ser divisibles por 8, ponerla en una carpeta y ejecutar:

nombre de la carpeta python make_bitmap.py

Luego, puede generar el archivo bitmap.hpp correspondiente y luego copiar la parte requerida del código en el bitmap.hpp original.

Encontré el siguiente icono

Entonces se generan los datos:

static constexpr uint8_t bitmap_gps_sim_data[] = {
	0x00, 0x00, 
	0x00, 0x00, 
	0x40, 0x06, 
	0x20, 0x00, 
	0x10, 0x10, 
	0x08, 0x10, 
	0x00, 0x20, 
	0x00, 0x00, 
	0x08, 0x00, 
	0x08, 0x00, 
	0x08, 0x10, 
	0x10, 0x00, 
	0x40, 0x0C, 
	0xC0, 0x02, 
	0x00, 0x00, 
	0x00, 0x00, 
};
static constexpr Bitmap bitmap_gps_sim {
	{ 16, 16 }, bitmap_gps_sim_data
};

 Tenga en cuenta que el nombre del archivo del icono corresponde al nombre de la variable del código generado, este nombre también se utilizará posteriormente en el código ui_navigation, y debe ser coherente, de lo contrario no se encontrarán estos datos.

Una vez completado el cambio, la interfaz principal se convertirá en la siguiente:

Pero la interfaz que aparece después de hacer clic en GPS Sim es la misma que la interfaz de hacer clic en reproducir.

tercer paso:

Primero, imite replay_app.cpp y replay_app.hpp para generar gps_sim_app.cpp y gps_sim_app.hpp, y colóquelos en firmware / application / app.

gps_sim_app.cpp

#include "gps_sim_app.hpp"
#include "string_format.hpp"

#include "ui_fileman.hpp"
#include "io_file.hpp"

#include "baseband_api.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"

using namespace portapack;

namespace ui {

void GpsSimAppView::set_ready() {
	ready_signal = true;
}

void GpsSimAppView::on_file_changed(std::filesystem::path new_file_path) {
	File data_file, info_file;
	char file_data[257];
	
	// Get file size
	auto data_open_error = data_file.open("/" + new_file_path.string());
	if (data_open_error.is_valid()) {
		file_error();
		return;
	}
	
	file_path = new_file_path;
	
	// Get original record frequency if available
	std::filesystem::path info_file_path = file_path;
	info_file_path.replace_extension(u".TXT");
	
	sample_rate = 500000;
	
	auto info_open_error = info_file.open("/" + info_file_path.string());
	if (!info_open_error.is_valid()) {
		memset(file_data, 0, 257);
		auto read_size = info_file.read(file_data, 256);
		if (!read_size.is_error()) {
			auto pos1 = strstr(file_data, "center_frequency=");
			if (pos1) {
				pos1 += 17;
				field_frequency.set_value(strtoll(pos1, nullptr, 10));
			}
			
			auto pos2 = strstr(file_data, "sample_rate=");
			if (pos2) {
				pos2 += 12;
				sample_rate = strtoll(pos2, nullptr, 10);
			}
		}
	}
	
	text_sample_rate.set(unit_auto_scale(sample_rate, 3, 1) + "Hz");
	
	auto file_size = data_file.size();
	auto duration = (file_size * 1000) / (1 * 2 * sample_rate);
	
	progressbar.set_max(file_size);
	text_filename.set(file_path.filename().string().substr(0, 12));
	text_duration.set(to_string_time_ms(duration));
	
	button_play.focus();
}

void GpsSimAppView::on_tx_progress(const uint32_t progress) {
	progressbar.set_value(progress);
}

void GpsSimAppView::focus() {
	button_open.focus();
}

void GpsSimAppView::file_error() {
	nav_.display_modal("Error", "File read error.");
}

bool GpsSimAppView::is_active() const {
	return (bool)replay_thread;
}

void GpsSimAppView::toggle() {
	if( is_active() ) {
		stop(false);
	} else {
		start();
	}
}

void GpsSimAppView::start() {
	stop(false);

	std::unique_ptr<stream::Reader> reader;
	
	auto p = std::make_unique<FileReader>();
	auto open_error = p->open(file_path);
	if( open_error.is_valid() ) {
		file_error();
	} else {
		reader = std::move(p);
	}

	if( reader ) {
		button_play.set_bitmap(&bitmap_stop);
		baseband::set_sample_rate(sample_rate * 4);
		
		replay_thread = std::make_unique<ReplayThread>(
			std::move(reader),
			read_size, buffer_count,
			&ready_signal,
			[](uint32_t return_code) {
				ReplayThreadDoneMessage message { return_code };
				EventDispatcher::send_message(message);
			}
		);
	}
	
	radio::enable({
		receiver_model.tuning_frequency(),
		sample_rate * 4,
		baseband_bandwidth,
		rf::Direction::Transmit,
		receiver_model.rf_amp(),
		static_cast<int8_t>(receiver_model.lna()),
		static_cast<int8_t>(receiver_model.vga())
	});
}

void GpsSimAppView::stop(const bool do_loop) {
	if( is_active() )
		replay_thread.reset();
	
	if (do_loop && check_loop.value()) {
		start();
	} else {
		radio::disable();
		button_play.set_bitmap(&bitmap_play);
	}
	
	ready_signal = false;
}

void GpsSimAppView::handle_replay_thread_done(const uint32_t return_code) {
	if (return_code == ReplayThread::END_OF_FILE) {
		stop(true);
	} else if (return_code == ReplayThread::READ_ERROR) {
		stop(false);
		file_error();
	}
	
	progressbar.set_value(0);
}

GpsSimAppView::GpsSimAppView(
	NavigationView& nav
) : nav_ (nav)
{
	baseband::run_image(portapack::spi_flash::image_tag_replay);

	add_children({
		&labels,
		&button_open,
		&text_filename,
		&text_sample_rate,
		&text_duration,
		&progressbar,
		&field_frequency,
		&field_lna,
		&field_rf_amp,
		&check_loop,
		&button_play,
		&waterfall,
	});
	
	field_frequency.set_value(target_frequency());
	field_frequency.set_step(receiver_model.frequency_step());
	field_frequency.on_change = [this](rf::Frequency f) {
		this->on_target_frequency_changed(f);
	};
	field_frequency.on_edit = [this, &nav]() {
		// TODO: Provide separate modal method/scheme?
		auto new_view = nav.push<FrequencyKeypadView>(this->target_frequency());
		new_view->on_changed = [this](rf::Frequency f) {
			this->on_target_frequency_changed(f);
			this->field_frequency.set_value(f);
		};
	};

	field_frequency.set_step(5000);
	
	button_play.on_select = [this](ImageButton&) {
		this->toggle();
	};
	
	button_open.on_select = [this, &nav](Button&) {
		auto open_view = nav.push<FileLoadView>(".C8");
		open_view->on_changed = [this](std::filesystem::path new_file_path) {
			on_file_changed(new_file_path);
		};
	};
}

GpsSimAppView::~GpsSimAppView() {
	radio::disable();
	baseband::shutdown();
}

void GpsSimAppView::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 GpsSimAppView::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(), new_parent_rect.height() - header_height };
	waterfall.set_parent_rect(waterfall_rect);
}

void GpsSimAppView::on_target_frequency_changed(rf::Frequency f) {
	set_target_frequency(f);
}

void GpsSimAppView::set_target_frequency(const rf::Frequency new_value) {
	persistent_memory::set_tuned_frequency(new_value);;
}

rf::Frequency GpsSimAppView::target_frequency() const {
	return persistent_memory::tuned_frequency();
}

} /* namespace ui */

gps_sim_app.hpp


#ifndef __GPS_SIM_APP_HPP__
#define __GPS_SIM_APP_HPP__

#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "replay_thread.hpp"
#include "ui_spectrum.hpp"

#include <string>
#include <memory>

namespace ui {

class GpsSimAppView : public View {
public:
	GpsSimAppView(NavigationView& nav);
	~GpsSimAppView();

	void on_hide() override;
	void set_parent_rect(const Rect new_parent_rect) override;
	void focus() override;

	std::string title() const override { return "GPS Simulator"; };
	
private:
	NavigationView& nav_;
	
	static constexpr ui::Dim header_height = 3 * 16;
	
	uint32_t sample_rate = 0;
	static constexpr uint32_t baseband_bandwidth = 2000000;
	const size_t read_size { 16384 };
	const size_t buffer_count { 3 };

	void on_file_changed(std::filesystem::path new_file_path);
	void on_target_frequency_changed(rf::Frequency f);
	void on_tx_progress(const uint32_t progress);
	
	void set_target_frequency(const rf::Frequency new_value);
	rf::Frequency target_frequency() const;

	void toggle();
	void start();
	void stop(const bool do_loop);
	bool is_active() const;
	void set_ready();
	void handle_replay_thread_done(const uint32_t return_code);
	void file_error();

	std::filesystem::path file_path { };
	std::unique_ptr<ReplayThread> replay_thread { };
	bool ready_signal { false };

	Labels labels {
		{ { 10 * 8, 2 * 16 }, "LNA:   A:", Color::light_grey() }
	};
	
	Button button_open {
		{ 0 * 8, 0 * 16, 10 * 8, 2 * 16 },
		"Open file"
	};
	
	Text text_filename {
		{ 11 * 8, 0 * 16, 12 * 8, 16 },
		"-"
	};
	Text text_sample_rate {
		{ 24 * 8, 0 * 16, 6 * 8, 16 },
		"-"
	};
	
	Text text_duration {
		{ 11 * 8, 1 * 16, 6 * 8, 16 },
		"-"
	};
	ProgressBar progressbar {
		{ 18 * 8, 1 * 16, 12 * 8, 16 }
	};
	
	FrequencyField field_frequency {
		{ 0 * 8, 2 * 16 },
	};
	LNAGainField field_lna {
		{ 14 * 8, 2 * 16 }
	};
	RFAmpField field_rf_amp {
		{ 19 * 8, 2 * 16 }
	};
	Checkbox check_loop {
		{ 21 * 8, 2 * 16 },
		4,
		"Loop",
		true
	};
	ImageButton button_play {
		{ 28 * 8, 2 * 16, 2 * 8, 1 * 16 },
		&bitmap_play,
		Color::green(),
		Color::black()
	};

	spectrum::WaterfallWidget waterfall { };

	MessageHandlerRegistration message_handler_replay_thread_error {
		Message::ID::ReplayThreadDone,
		[this](const Message* const p) {
			const auto message = *reinterpret_cast<const ReplayThreadDoneMessage*>(p);
			this->handle_replay_thread_done(message.return_code);
		}
	};
	
	MessageHandlerRegistration message_handler_fifo_signal {
		Message::ID::RequestSignal,
		[this](const Message* const p) {
			const auto message = static_cast<const RequestSignalMessage*>(p);
			if (message->signal == RequestSignalMessage::Signal::FillRequest) {
				this->set_ready();
			}
		}
	};
	
	MessageHandlerRegistration message_handler_tx_progress {
		Message::ID::TXProgress,
		[this](const Message* const p) {
			const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
			this->on_tx_progress(message.progress);
		}
	};
};

} /* namespace ui */

#endif/*__GPS_SIM_APP_HPP__*/

Luego, busque apps / replay_app.cpp en firmware / application / CMakeLists.txt e inserte apps / gps_sim_app.cpp debajo. como sigue:

	apps/replay_app.cpp
        apps/gps_sim_app.cpp

Luego abra ui_navigation.cpp y agregue #include "gps_sim_app.hpp" al principio

Entonces también es la ventana en ui_navigation.cpp para cambiar la llamada nav.push de GPS Sim

SystemMenuView::SystemMenuView(NavigationView& nav) {
	add_items({
		{ "Play dead",				ui::Color::red(),		&bitmap_icon_playdead,	[&nav](){ nav.push<PlayDeadView>(); } },
		{ "Receivers", 	ui::Color::dark_cyan(),		&bitmap_icon_receivers,	[&nav](){ nav.push<ReceiversMenuView>(); } },
		{ "Transmit", 	ui::Color::green(),			&bitmap_icon_transmit,	[&nav](){ nav.push<TransmittersMenuView>(); } },
		{ "Capture",				ui::Color::blue(),		&bitmap_icon_capture,	[&nav](){ nav.push<CaptureAppView>(); } },
		{ "Replay",					ui::Color::purple(),	&bitmap_icon_replay,	[&nav](){ nav.push<ReplayAppView>(); } },
                { "GPS Sim",                              ui::Color::white(),     &bitmap_gps_sim,    [&nav]()
{ nav.push<GpsSimAppView>(); } }, //注意nav.push这改为另一个界面了
		{ "Calls",		ui::Color::yellow(),	    &bitmap_icon_closecall,	[&nav](){ nav.push<SearchView>(); } },
		{ "Scanner",	ui::Color::orange(),		&bitmap_icon_scanner,	[&nav](){ nav.push<ScannerView>(); } },
		{ "Utilities",				ui::Color::light_grey(),	&bitmap_icon_utilities,	[&nav](){ nav.push<UtilitiesMenuView>(); } },
		{ "Settings", 	ui::Color::cyan(),			&bitmap_icon_setup,	  	[&nav](){ nav.push<SettingsMenuView>(); } },
		//{ "Debug",		ui::Color::cyan(),			nullptr,   				[&nav](){ nav.push<DebugMenuView>(); } },
		{ "HackRF", 	ui::Color::cyan(),			&bitmap_icon_hackrf,	[this, &nav](){ hackrf_mode(nav); } },
		{ "About", 		ui::Color::cyan(),			nullptr,				[&nav](){ nav.push<AboutView>(); } }
	});
	
	set_highlighted(1);		// Startup selection is "Receivers"
}

Después de completar el tercer paso, haga clic en GPS Sim y verá una interfaz similar a la siguiente. Puede ver que el título ha cambiado. También abrí un archivo de datos GPS que preparé antes. La diferencia será más obvia.

el cuarto paso:

En la línea 183 de gps_sim_app.cpp en el tercer paso, image_tag_replay se cambia a image_tag_gps.

	baseband::run_image(portapack::spi_flash::image_tag_gps);

De esta manera, este programa de interfaz buscará otro programa de procesamiento en segundo plano cuando se ejecute, pero no se puede encontrar temporalmente. Necesitamos agregar dos archivos, proc_gps_sim.cpp y proc_gps_sim.hpp, en firmware / baseband, imitando proc_replay.app y proc_replay.hpp. Luego busque spi_image.hpp en firmware / common / y búsquelo. image_tag_replay, imítelo para aumentar image_tag_gps.

constexpr image_tag_t image_tag_replay				{ 'P', 'R', 'E', 'P' };
constexpr image_tag_t image_tag_gps                             { 'P', 'G', 'P', 'S' };

Entonces, cada vez que el programa de interfaz busque image_tag_gps, buscará PGPS ¿Cómo se corresponde este PGPS con proc_gps_sim.cpp? Esto es lo que haremos a continuación.

Abra firmware / baseband / CMakeLists.txt y busque ### Replay

### Replay

set(MODE_CPPSRC
	proc_replay.cpp
)
DeclareTargets(PREP replay)

### GPS Simulator

set(MODE_CPPSRC
	proc_gps_sim.cpp
)
DeclareTargets(PGPS gps_sim)

Luego imítelo y escriba el contenido detrás del ### GPS Simulator y vea que hay PGPS en DeclareTargets en la parte inferior, lo que significa que cada vez que se llama a PGPS, irá al programa compilado por proc_gps_sim.cpp.

Finalmente, adjunte mi proc_gps_sim.cpp actual y proc_gps_sim.hpp

proc_gps_sim.cpp

#include "proc_gps_sim.hpp"
#include "sine_table_int8.hpp"
#include "portapack_shared_memory.hpp"

#include "event_m4.hpp"

#include "utility.hpp"

ReplayProcessor::ReplayProcessor() {
	channel_filter_pass_f = taps_200k_decim_1.pass_frequency_normalized * 1000000;	// 162760.416666667
	channel_filter_stop_f = taps_200k_decim_1.stop_frequency_normalized * 1000000;	// 337239.583333333
	
	spectrum_samples = 0;

	channel_spectrum.set_decimation_factor(1);
	
	configured = false;
}

void ReplayProcessor::execute(const buffer_c8_t& buffer) {
	/* 4MHz, 2048 samples */
	
	if (!configured) return;
	
	// File data is in C16 format, we need C8
	// File samplerate is 500kHz, we're at 4MHz
	// iq_buffer can only be 512 C16 samples (RAM limitation)
	// To fill up the 2048-sample C8 buffer, we need:
	// 2048 samples * 2 bytes per sample = 4096 bytes
	// Since we're oversampling by 4M/500k = 8, we only need 2048/8 = 256 samples from the file and duplicate them 8 times each
	// So 256 * 4 bytes per sample (C16) = 1024 bytes from the file
	if( stream ) {                             //sizeof(*buffer.p) = sizeof(C8) = 2*int8 = 2 bytes //buffer.count = 2048
		const size_t bytes_to_read = sizeof(*buffer.p) * 1 * (buffer.count / 8);	// *2 (C16), /8 (oversampling) should be == 1024
		bytes_read += stream->read(iq_buffer.p, bytes_to_read);
	}
	
	// Fill and "stretch"
	for (size_t i = 0; i < buffer.count; i++) {
		/*if (i & 3) {
			buffer.p[i] = buffer.p[i - 1];
		} else {
			auto re_out = iq_buffer.p[i >> 3].real() ;
			auto im_out = iq_buffer.p[i >> 3].imag() ;
			buffer.p[i] = { (int8_t)re_out, (int8_t)im_out };
		}*/
                if (i % 8 != 0) {
			buffer.p[i] = buffer.p[i - 1];
		} else {
			auto re_out = iq_buffer.p[i/8].real() ;
			auto im_out = iq_buffer.p[i/8].imag() ;
			buffer.p[i] = { (int8_t)re_out, (int8_t)im_out };
		}
                /*
                auto re_out = iq_buffer.p[i].real() ;
	        auto im_out = iq_buffer.p[i].imag() ;
		buffer.p[i] = { (int8_t)re_out, (int8_t)im_out };*/
	}
	
	spectrum_samples += buffer.count;
	if( spectrum_samples >= spectrum_interval_samples ) {
		spectrum_samples -= spectrum_interval_samples;
		//channel_spectrum.feed(iq_buffer, channel_filter_pass_f, channel_filter_stop_f);
		
		txprogress_message.progress = bytes_read;	// Inform UI about progress
		txprogress_message.done = false;
		shared_memory.application_queue.push(txprogress_message);
	}
}

void ReplayProcessor::on_message(const Message* const message) {
	switch(message->id) {
	case Message::ID::UpdateSpectrum:
	case Message::ID::SpectrumStreamingConfig:
		channel_spectrum.on_message(message);
		break;

	case Message::ID::SamplerateConfig:
		samplerate_config(*reinterpret_cast<const SamplerateConfigMessage*>(message));
		break;
	
	case Message::ID::ReplayConfig:
		configured = false;
		bytes_read = 0;
		replay_config(*reinterpret_cast<const ReplayConfigMessage*>(message));
		break;
		
	// App has prefilled the buffers, we're ready to go now
	case Message::ID::FIFOData:
		configured = true;
		break;

	default:
		break;
	}
}

void ReplayProcessor::samplerate_config(const SamplerateConfigMessage& message) {
	baseband_fs = message.sample_rate;
	baseband_thread.set_sampling_rate(baseband_fs);
	spectrum_interval_samples = baseband_fs / spectrum_rate_hz;
}

void ReplayProcessor::replay_config(const ReplayConfigMessage& message) {
	if( message.config ) {
		
		stream = std::make_unique<StreamOutput>(message.config);
		
		// Tell application that the buffers and FIFO pointers are ready, prefill
		shared_memory.application_queue.push(sig_message);
	} else {
		stream.reset();
	}
}

int main() {
	EventDispatcher event_dispatcher { std::make_unique<ReplayProcessor>() };
	event_dispatcher.run();
	return 0;
}

proc_gps_sim.hpp

#ifndef __PROC_GPS_SIM_HPP__
#define __PROC_GPS_SIM_HPP__

#include "baseband_processor.hpp"
#include "baseband_thread.hpp"

#include "spectrum_collector.hpp"

#include "stream_output.hpp"

#include <array>
#include <memory>

class ReplayProcessor : public BasebandProcessor {
public:
	ReplayProcessor();

	void execute(const buffer_c8_t& buffer) override;

	void on_message(const Message* const message) override;

private:
	size_t baseband_fs = 0;
	static constexpr auto spectrum_rate_hz = 50.0f;

	BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Transmit };

	std::array<complex8_t, 256> iq { };
	const buffer_c8_t iq_buffer {
		iq.data(),
		iq.size(),
		baseband_fs /4
	};
	
	uint32_t channel_filter_pass_f = 0;
	uint32_t channel_filter_stop_f = 0;

	std::unique_ptr<StreamOutput> stream { };

	SpectrumCollector channel_spectrum { };
	size_t spectrum_interval_samples = 0;
	size_t spectrum_samples = 0;
	
	bool configured { false };
	uint32_t bytes_read { 0 };

	void samplerate_config(const SamplerateConfigMessage& message);
	void replay_config(const ReplayConfigMessage& message);
	
	TXProgressMessage txprogress_message { };
	RequestSignalMessage sig_message { RequestSignalMessage::Signal::FillRequest };
};

#endif/*__PROC_GPS_SIM_HPP__*/

El siguiente artículo analizará cuidadosamente los 4 archivos que escribí gps_sim_app.cpp, gps_sim_app.hpp, proc_gps_sim.cpp, proc_gps_sim.hpp y los problemas que encontré.

Estos problemas están relacionados con la señal GPS y el procesamiento de datos iq.

Pero los pasos anteriores pueden considerarse como el proceso de redacción de una nueva aplicación.

Supongo que te gusta

Origin blog.csdn.net/shukebeta008/article/details/104308453
Recomendado
Clasificación