1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-12-17 22:08:05 +00:00

feat: add extra data source

This commit is contained in:
Victor Castillo
2025-05-08 17:05:43 +02:00
committed by Carles Fernandez
parent ba2ca73959
commit 53006b4ea6
14 changed files with 455 additions and 8 deletions

View File

@@ -60,7 +60,15 @@ FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std:
is_complex_(false),
repeat_(configuration->property(role_ + ".repeat"s, false)),
enable_throttle_control_(configuration->property(role_ + ".enable_throttle_control"s, false)),
dump_(configuration->property(role_ + ".dump"s, false))
dump_(configuration->property(role_ + ".dump"s, false)),
// Configuration for attaching extra data to the sample stream
attach_extra_data_(configuration->property(role_ + ".extra_data.enabled"s, false)),
ed_path_(configuration->property(role_ + ".extra_data.filename"s, "../data/extra_data.dat"s)),
ed_offset_in_file_(configuration->property(role_ + ".extra_data.file_offset"s, 0UL)),
ed_item_size_(configuration->property(role_ + ".extra_data.item_size"s, 1UL)),
ed_repeat_(configuration->property(role_ + ".extra_data.repeat"s, false)),
ed_offset_in_samples_(configuration->property(role_ + ".extra_data.sample_offset"s, 0UL)),
ed_sample_period_(configuration->property(role_ + ".extra_data.sample_period"s, 1UL))
{
minimum_tail_s_ = std::max(configuration->property("Acquisition_1C.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
minimum_tail_s_ = std::max(configuration->property("Acquisition_2S.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
@@ -157,6 +165,7 @@ void FileSourceBase::init()
create_throttle();
create_valve();
create_sink();
create_extra_data_source();
}
@@ -205,6 +214,14 @@ void FileSourceBase::connect(gr::top_block_sptr top_block)
DLOG(INFO) << "connected output to file sink";
}
// EXTRA DATA
if (extra_data_source())
{
top_block->connect(std::move(output), 0, extra_data_source(), 0);
DLOG(INFO) << "connected output to extra data source, which now becomes the new output";
output = extra_data_source();
}
post_connect_hook(std::move(top_block));
}
@@ -253,13 +270,21 @@ void FileSourceBase::disconnect(gr::top_block_sptr top_block)
DLOG(INFO) << "disconnected output to file sink";
}
// EXTRA DATA
if (extra_data_source())
{
// TODO - FIXME: This is NOT okay, `output` is the extra data source, not the valve/source/throttle/whatever is left of this
top_block->disconnect(std::move(output), 0, extra_data_source(), 0);
DLOG(INFO) << "disconnected output to extra data source";
output = extra_data_source();
}
post_disconnect_hook(std::move(top_block));
}
gr::basic_block_sptr FileSourceBase::get_left_block()
{
// TODO: is this right? Shouldn't the left block be a nullptr?
LOG(WARNING) << "Left block of a signal source should not be retrieved";
return gr::blocks::file_source::sptr();
}
@@ -270,6 +295,7 @@ gr::basic_block_sptr FileSourceBase::get_right_block()
// clang-tidy wants braces around the if-conditions. clang-format wants to break the braces into
// multiple line blocks. It's much more readable this way
// clang-format off
if (extra_data_source_) { return extra_data_source_; }
if (valve_) { return valve_; }
if (throttle_) { return throttle_; }
return source();
@@ -478,6 +504,7 @@ gnss_shared_ptr<gr::block> FileSourceBase::file_source() const { return file_sou
gnss_shared_ptr<gr::block> FileSourceBase::valve() const { return valve_; }
gnss_shared_ptr<gr::block> FileSourceBase::throttle() const { return throttle_; }
gnss_shared_ptr<gr::block> FileSourceBase::sink() const { return sink_; }
ExtraDataSource::sptr FileSourceBase::extra_data_source() const { return extra_data_source_; }
gr::blocks::file_source::sptr FileSourceBase::create_file_source()
@@ -574,6 +601,24 @@ gr::blocks::file_sink::sptr FileSourceBase::create_sink()
return sink_;
}
ExtraDataSource::sptr FileSourceBase::create_extra_data_source()
{
if (attach_extra_data_)
{
extra_data_source_ = std::make_shared<ExtraDataSource>(
ed_path_,
ed_offset_in_file_,
ed_item_size_,
ed_repeat_,
ed_offset_in_samples_,
ed_sample_period_,
gr::io_signature::make(1, 1, item_size_));
DLOG(INFO) << "extra_data_source(" << extra_data_source_->unique_id() << ")";
}
return extra_data_source_;
}
// Subclass hooks to augment created objects, as required
void FileSourceBase::create_file_source_hook() {}

View File

@@ -28,6 +28,8 @@
#include <string>
#include <tuple>
#include "extra_data_source.h"
/** \addtogroup Signal_Source
* \{ */
/** \addtogroup Signal_Source_adapters
@@ -131,6 +133,7 @@ protected:
gnss_shared_ptr<gr::block> valve() const;
gnss_shared_ptr<gr::block> throttle() const;
gnss_shared_ptr<gr::block> sink() const;
ExtraDataSource::sptr extra_data_source() const;
// The methods create the various blocks, if enabled, and return access to them. The created
// object is also held in this class
@@ -138,6 +141,7 @@ protected:
gr::blocks::throttle::sptr create_throttle();
gnss_shared_ptr<gr::block> create_valve();
gr::blocks::file_sink::sptr create_sink();
ExtraDataSource::sptr create_extra_data_source();
// Subclass hooks to augment created objects, as required
virtual void create_file_source_hook();
@@ -155,6 +159,7 @@ private:
gr::blocks::file_source::sptr file_source_;
gr::blocks::throttle::sptr throttle_;
gr::blocks::file_sink::sptr sink_;
ExtraDataSource::sptr extra_data_source_;
// The valve allows only the configured number of samples through, then it closes.
@@ -179,6 +184,15 @@ private:
bool repeat_;
bool enable_throttle_control_;
bool dump_;
// Configuration for Extra Data source
bool attach_extra_data_;
std::string ed_path_;
std::size_t ed_offset_in_file_;
std::size_t ed_item_size_;
bool ed_repeat_;
std::size_t ed_offset_in_samples_;
std::size_t ed_sample_period_;
};
/** \} */

View File

@@ -31,6 +31,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
unpack_2bit_samples.cc
unpack_spir_gss6450_samples.cc
labsat23_source.cc
extra_data_source.cc
${OPT_DRIVER_SOURCES}
)
@@ -45,6 +46,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_HEADERS
unpack_2bit_samples.h
unpack_spir_gss6450_samples.h
labsat23_source.h
extra_data_source.h
${OPT_DRIVER_HEADERS}
)

View File

@@ -0,0 +1,82 @@
/*!
* \file extra_data_source.cc
* \brief GNURadio block that adds extra data to the sample stream.
* \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "extra_data_source.h"
#include <pmt/pmt.h>
ExtraDataSource::ExtraDataSource(
const std::string& path,
const std::size_t& offset_in_file,
const std::size_t& item_size,
const bool& repeat,
const std::size_t& offset_in_samples,
const std::size_t& sample_period,
const gr::io_signature::sptr& io_signature
)
: gr::sync_block("Extra Data Source",
io_signature, io_signature),
extra_data_file_(
path,
offset_in_file,
item_size,
repeat),
offset_in_samples_(offset_in_samples),
sample_period_(sample_period),
next_tagged_sample_(offset_in_samples_)
{
if (io_signature->min_streams() != 1 and io_signature->max_streams() != 1)
{
std::cout << "ERROR: This block only supports adding data to a single stream." << "\n";
}
}
std::vector<uint8_t> ExtraDataSource::get_next_item()
{
return extra_data_file_.read_item();
}
std::size_t ExtraDataSource::get_offset_in_samples() const
{
return offset_in_samples_;
}
std::size_t ExtraDataSource::get_sample_period() const
{
return sample_period_;
}
int ExtraDataSource::work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
const std::size_t ch = 0;
const int item_size = input_signature()->sizeof_stream_item(ch);
std::memcpy(output_items[ch], input_items[ch], noutput_items * item_size);
const uint64_t total_items_written = nitems_written(ch) + noutput_items;
if (total_items_written >= next_tagged_sample_)
{
for (uint64_t sample = next_tagged_sample_; sample < total_items_written; sample += sample_period_)
{
auto extra_data_item = get_next_item();
add_item_tag(ch, sample, pmt::mp("extra_data"), pmt::init_u8vector(extra_data_item.size(), extra_data_item));
next_tagged_sample_ += sample_period_;
}
}
return noutput_items;
}

View File

@@ -0,0 +1,72 @@
/*!
* \file extra_data_source.h
* \brief GNURadio block that adds extra data to the sample stream.
* \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_EXTRA_DATA_SOURCE_H
#define GNSS_SDR_EXTRA_DATA_SOURCE_H
#include "gnss_block_interface.h"
#include "extra_data_file.h"
#include <gnuradio/sync_block.h> // for sync_block
#include <gnuradio/types.h> // for gr_vector_const_void_star
#include <cstddef> // for size_t
#include <cstdint>
#include <string>
/** \addtogroup Signal_Source
* \{ */
/** \addtogroup Signal_Source_gnuradio_blocks
* \{ */
class ExtraDataSource: public gr::sync_block
{
public:
using sptr = gnss_shared_ptr<ExtraDataSource>;
ExtraDataSource(
const std::string& path,
const std::size_t& offset_in_file,
const std::size_t& item_size,
const bool& repeat,
const std::size_t& offset_in_samples,
const std::size_t& sample_period,
const gr::io_signature::sptr& io_signature);
private:
std::vector<uint8_t> get_next_item();
std::size_t get_offset_in_samples() const;
std::size_t get_sample_period() const;
public:
int work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items) override;
private:
ExtraDataFile extra_data_file_;
std::size_t offset_in_samples_;
std::size_t sample_period_;
std::size_t next_tagged_sample_;
};
/** \} */
/** \} */
#endif // GNSS_SDR_EXTRA_DATA_SOURCE_H

View File

@@ -56,6 +56,7 @@ set(SIGNAL_SOURCE_LIB_SOURCES
rtl_tcp_dongle_info.cc
gnss_sdr_valve.cc
gnss_sdr_timestamp.cc
extra_data_file.cc
${OPT_SIGNAL_SOURCE_LIB_SOURCES}
)
@@ -63,6 +64,7 @@ set(SIGNAL_SOURCE_LIB_HEADERS
rtl_tcp_commands.h
rtl_tcp_dongle_info.h
gnss_sdr_valve.h
extra_data_file.h
${OPT_SIGNAL_SOURCE_LIB_HEADERS}
)

View File

@@ -0,0 +1,93 @@
/*!
* \file extra_data_file.cc
* \brief Provides a simple abstraction for reading contiguous binary data from a file
* \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "extra_data_file.h"
#include <cstring>
ExtraDataFile::ExtraDataFile(
const std::string& path,
const std::size_t& offset_in_file,
const std::size_t& item_size,
const bool& repeat)
: path_(path),
file_(path_),
offset_in_file_(offset_in_file),
item_size_(item_size),
repeat_(repeat),
done_(false),
io_buffer_size_(item_size * IO_BUFFER_CAPACITY),
offset_in_io_buffer_(io_buffer_size_) // Set to end of buffer so that first look up will trigger a read.
{
file_.seekg(offset_in_file_, std::ios_base::beg);
io_buffer_.resize(io_buffer_size_);
}
void ExtraDataFile::reset()
{
file_.seekg(offset_in_file_, std::ios_base::beg);
offset_in_io_buffer_ = io_buffer_size_;
done_ = false;
}
std::vector<uint8_t> ExtraDataFile::read_item()
{
if (offset_in_io_buffer_ >= io_buffer_size_)
{
if (done_)
{
return {};
}
else
{
read_into_io_buffer();
}
}
std::vector<uint8_t> item_buf{};
read_into_item_buffer(item_buf);
return item_buf;
}
void ExtraDataFile::read_into_io_buffer()
{
file_.read(reinterpret_cast<char*>(&io_buffer_[0]), io_buffer_size_);
const std::size_t bytes_read = file_.gcount();
if (bytes_read < io_buffer_size_)
{
if (repeat_)
{
reset();
file_.read(reinterpret_cast<char*>(&io_buffer_[bytes_read]), io_buffer_size_ - bytes_read);
}
else
{
io_buffer_size_ = bytes_read;
done_ = true;
}
}
offset_in_io_buffer_ = 0;
}
void ExtraDataFile::read_into_item_buffer(std::vector<uint8_t>& item_buf)
{
item_buf.resize(item_size_);
std::memcpy(item_buf.data(), &io_buffer_[offset_in_io_buffer_], item_size_);
offset_in_io_buffer_ += item_size_;
}

View File

@@ -0,0 +1,69 @@
/*!
* \file extra_data_file.h
* \brief Provides a simple abstraction for reading contiguous binary data from a file
* \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_EXTRA_DATA_FILE_H
#define GNSS_SDR_EXTRA_DATA_FILE_H
#include <cstddef> // for size_t
#include <cstdint>
#include <fstream>
#include <string>
#include <vector>
/** \addtogroup Signal_Source
* \{ */
/** \addtogroup Signal_Source_libs
* \{ */
class ExtraDataFile
{
static constexpr std::size_t IO_BUFFER_CAPACITY = 1024;
public:
ExtraDataFile(
const std::string& path,
const std::size_t& offset_in_file,
const std::size_t& item_size,
const bool& repeat);
void reset();
std::vector<uint8_t> read_item();
private:
void read_into_io_buffer();
void read_into_item_buffer(std::vector<uint8_t>& item_buf);
private:
std::string path_;
std::ifstream file_;
std::size_t offset_in_file_;
std::size_t item_size_;
bool repeat_;
bool done_;
std::vector<uint8_t> io_buffer_;
std::size_t io_buffer_size_;
std::size_t offset_in_io_buffer_;
};
/** \} */
/** \} */
#endif // GNSS_SDR_EXTRA_DATA_FILE_H