mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2026-10-19 05:52:36 +00:00
Fix unused private member, rename file_offset by seconds_to_skip, update comments
This commit is contained in:
@@ -63,7 +63,7 @@ SignalSource0.sampling_frequency = 177500000
|
||||
SignalSource0.RF_channels = 2 ; one IF conditioner per band below
|
||||
; Jump straight to a time of interest (seconds) in a long capture instead
|
||||
; of always reprocessing from the start (see #1114):
|
||||
;SignalSource0.file_offset = 3600
|
||||
;SignalSource0.seconds_to_skip = 3600
|
||||
;SignalSource0.dump = true
|
||||
;SignalSource0.dump_filename = ./evk1029_signal_source.dat
|
||||
|
||||
|
||||
@@ -42,42 +42,35 @@ Evk1029SignalSource::Evk1029SignalSource(
|
||||
const std::string filename = configuration->property(role + ".filename"s, "data.bin"s);
|
||||
// NOTE: this must be the RAW (pre-decimation) ADC sample rate of the capture
|
||||
// file (e.g. the .sdrx metadata's <freqbase>), NOT GNSS-SDR.internal_fs_sps
|
||||
// (which is the decimated working rate downstream of InputFilter). It is
|
||||
// only used to pace the throttle, when enabled.
|
||||
// (which is the decimated working rate downstream of InputFilter). It paces
|
||||
// the throttle (when enabled), sizes the block's scheduling quantum, and
|
||||
// converts .seconds_to_skip into a position in the file.
|
||||
const int64_t default_fs = configuration->property("GNSS-SDR.internal_fs_sps"s, int64_t(0));
|
||||
const int64_t fs = configuration->property(role + ".sampling_frequency"s, default_fs);
|
||||
|
||||
// Lets a long capture be jumped straight to a "time of interest" (e.g.
|
||||
// to check effective signal strength at a specific point) instead of
|
||||
// always reprocessed from the start. Expressed in seconds, not bytes --
|
||||
// fs (the raw capture's own sample rate) is already known right here,
|
||||
// so converting is trivial and saves the caller from hand-computing a
|
||||
// byte count themselves. Two OBA samples are packed per byte, hence the
|
||||
// /2; Evk1029Source rounds the resulting byte count up to the next
|
||||
// 64-bit word boundary itself (see its header) before seeking.
|
||||
const double file_offset_s = configuration->property(role + ".file_offset"s, 0.0);
|
||||
const auto file_offset_bytes = (file_offset_s > 0.0 && fs > 0)
|
||||
? static_cast<uint64_t>(std::llround(file_offset_s * static_cast<double>(fs) / 2.0))
|
||||
: uint64_t(0);
|
||||
const double seconds_to_skip = configuration->property(role + ".seconds_to_skip"s, 0.0);
|
||||
uint64_t bytes_to_skip = 0;
|
||||
if (seconds_to_skip > 0.0 && fs > 0)
|
||||
{
|
||||
bytes_to_skip = static_cast<uint64_t>(std::llround(seconds_to_skip * static_cast<double>(fs) / 2.0));
|
||||
if (!configuration->is_present(role + ".sampling_frequency"s))
|
||||
{
|
||||
LOG(WARNING) << role << ".seconds_to_skip is set but " << role << ".sampling_frequency is not: "
|
||||
<< "converting seconds into a file position with GNSS-SDR.internal_fs_sps=" << fs
|
||||
<< " Sps, which is wrong if the Input Filter decimates. Set " << role
|
||||
<< ".sampling_frequency to the raw ADC rate of the capture.";
|
||||
}
|
||||
}
|
||||
|
||||
if (rf_channels_ == 0)
|
||||
{
|
||||
rf_channels_ = 1;
|
||||
}
|
||||
|
||||
if (enable_throttle_control_ && rf_channels_ > 1)
|
||||
{
|
||||
LOG(WARNING) << role << ".enable_throttle_control is not supported with RF_channels > 1 "
|
||||
<< "(would need its own N-independent-readers wiring, same as Evk1029Source itself; "
|
||||
<< "not yet implemented); ignoring it.";
|
||||
std::cout << role << ": enable_throttle_control ignored with RF_channels=" << rf_channels_ << "\n";
|
||||
enable_throttle_control_ = false;
|
||||
}
|
||||
|
||||
DLOG(INFO) << "EVK1029 Signal Source: filename=" << filename << ", fs=" << fs << ", item_size=" << item_size_
|
||||
<< ", RF_channels=" << rf_channels_ << ", file_offset_s=" << file_offset_s;
|
||||
<< ", RF_channels=" << rf_channels_ << ", seconds_to_skip=" << seconds_to_skip;
|
||||
|
||||
evk1029_source_ = evk1029_make_source(filename, static_cast<int>(rf_channels_), queue, static_cast<double>(fs), file_offset_bytes);
|
||||
evk1029_source_ = evk1029_make_source(filename, queue, static_cast<double>(fs), bytes_to_skip);
|
||||
|
||||
if (enable_throttle_control_)
|
||||
{
|
||||
|
||||
@@ -9,21 +9,18 @@
|
||||
* for the current EVK1029 capture format (see evk1029_source.h).
|
||||
*
|
||||
* Set role + ".RF_channels" to N > 1 (e.g. for a multi-band setup sharing a
|
||||
* single IF capture) to get N independent readers of ONE underlying
|
||||
* single IF capture) to feed N Signal Conditioners from ONE underlying
|
||||
* Evk1029Source instance/read, instead of instantiating N separate
|
||||
* SignalSourceN blocks each reading the file independently -- the latter
|
||||
* has no shared read position, so a long, slow file open/seek on one of
|
||||
* them can leave it at a different point in the capture than the others.
|
||||
* Evk1029Source itself only ever declares a single real output port (see
|
||||
* its own header); gnss_flowgraph.cc's generic signal-source-to-conditioner
|
||||
* wiring detects this (output_signature()->max_streams() == 1) and connects
|
||||
* each of the N signal conditioners to that same port independently, using
|
||||
* GNU Radio's native support for multiple readers on one producer port.
|
||||
* Each reader then advances at its own pace -- one RF band's downstream
|
||||
* chain running behind never blocks the others.
|
||||
* In RF_channels > 1 mode, .enable_throttle_control is not supported (a
|
||||
* single throttle block would itself need N independent readers wired the
|
||||
* same way, not yet implemented); it is ignored with a warning.
|
||||
* SignalSourceN blocks each reading the file independently. Evk1029Source
|
||||
* has a single output port (see its own header); gnss_flowgraph.cc's
|
||||
* generic signal-source-to-conditioner wiring detects this
|
||||
* (output_signature()->max_streams() == 1) and connects each of the N
|
||||
* Signal Conditioners to that same port, so all of them read the same
|
||||
* sample stream and GNU Radio keeps them within one output buffer of each
|
||||
* other. The optional throttle sits between the source and that shared
|
||||
* port, so .enable_throttle_control works for any RF_channels value.
|
||||
* Set role + ".seconds_to_skip" to start reading at a given time into the
|
||||
* capture (converted to a byte position using the raw sampling frequency).
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
|
||||
@@ -61,25 +61,21 @@ int output_multiple_from_sampling_frequency(double sampling_frequency)
|
||||
} // namespace
|
||||
|
||||
|
||||
Evk1029Source_sptr evk1029_make_source(const std::string& filename, int n_streams, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t file_offset_bytes)
|
||||
Evk1029Source_sptr evk1029_make_source(const std::string& filename, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t bytes_to_skip)
|
||||
{
|
||||
return Evk1029Source_sptr(new Evk1029Source(filename, n_streams, queue, sampling_frequency, file_offset_bytes));
|
||||
return Evk1029Source_sptr(new Evk1029Source(filename, queue, sampling_frequency, bytes_to_skip));
|
||||
}
|
||||
|
||||
|
||||
Evk1029Source::Evk1029Source(const std::string& filename, int n_streams, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t file_offset_bytes)
|
||||
Evk1029Source::Evk1029Source(const std::string& filename, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t bytes_to_skip)
|
||||
: gr::sync_block("evk1029_source",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 1, sizeof(int8_t))),
|
||||
queue_(queue),
|
||||
buffer_(kReadChunkBytes),
|
||||
buffer_valid_(0),
|
||||
buffer_pos_(0),
|
||||
n_streams_(n_streams)
|
||||
buffer_pos_(0)
|
||||
{
|
||||
// Exactly one real output port, always -- see this class's header for
|
||||
// why. n_streams_ (the RF_channels count) is kept only for logging;
|
||||
// it no longer sizes the io_signature.
|
||||
// Keep the scheduler from calling work() with a tiny noutput_items; each
|
||||
// unit of work produces a pair of samples (one input byte -> 2 samples).
|
||||
// This block runs at the raw, pre-decimation sample rate (up to ~180 Msps),
|
||||
@@ -100,26 +96,26 @@ Evk1029Source::Evk1029Source(const std::string& filename, int n_streams, Concurr
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (file_offset_bytes > 0)
|
||||
if (bytes_to_skip > 0)
|
||||
{
|
||||
// Round up to the next 64-bit (8-byte) word boundary -- see this
|
||||
// parameter's doc comment in the header for why.
|
||||
constexpr uint64_t kWordBytes = 8;
|
||||
const uint64_t aligned_offset = ((file_offset_bytes + kWordBytes - 1) / kWordBytes) * kWordBytes;
|
||||
const uint64_t aligned_offset = ((bytes_to_skip + kWordBytes - 1) / kWordBytes) * kWordBytes;
|
||||
|
||||
binary_input_file_.seekg(0, std::ios::end);
|
||||
const auto file_size = static_cast<uint64_t>(binary_input_file_.tellg());
|
||||
if (aligned_offset >= file_size)
|
||||
{
|
||||
std::cerr << "EVK1029_Source: file_offset (" << aligned_offset
|
||||
<< " bytes, aligned) is at or beyond the end of '" << filename
|
||||
std::cerr << "EVK1029_Source: seconds_to_skip lands at byte " << aligned_offset
|
||||
<< " (rounded up to a 64-bit word), at or beyond the end of '" << filename
|
||||
<< "' (" << file_size << " bytes) -- nothing to read.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
binary_input_file_.seekg(static_cast<std::streamoff>(aligned_offset), std::ios::beg);
|
||||
std::cout << "EVK1029_Source: skipping to file offset " << aligned_offset
|
||||
<< " bytes (requested " << file_offset_bytes << ", rounded up to a 64-bit word boundary).\n";
|
||||
std::cout << "EVK1029_Source: skipping the first " << aligned_offset << " bytes of the capture (requested "
|
||||
<< bytes_to_skip << ", rounded up to a 64-bit word boundary)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,23 +11,20 @@
|
||||
* 4-bit OBA samples per byte (16 samples per 64-bit word, per the
|
||||
* capture's .sdrx metadata: quantization=4, packedbits=64, encoding=OBA).
|
||||
*
|
||||
* Exactly ONE real output port, always (n_streams_ is kept only for
|
||||
* logging -- it no longer sizes the io_signature). Multiple RF bands
|
||||
* sharing this same raw capture (e.g. several Freq_Xlating_Fir_Filter
|
||||
* instances tuned to different IFs) each get their OWN connect() to this
|
||||
* one port instead (see gnss_flowgraph.cc's signal-source-to-conditioner
|
||||
* wiring, which already takes this path whenever output_signature()'s
|
||||
* max_streams() == 1): GNU Radio's buffer model natively supports several
|
||||
* independent readers on one producer port, each with its own read
|
||||
* pointer, so a downstream chain that temporarily falls behind only
|
||||
* delays *itself* -- it can't force every port's own production to stall
|
||||
* together the way N separate, GNU-Radio-scheduler-coupled sync_block
|
||||
* output ports would (a single slow port failing GNU Radio's "space
|
||||
* available on every port" check before work() is even called stalls
|
||||
* production on every port at once). An earlier version of this block
|
||||
* used N separate ports and copied the same decoded output into each of
|
||||
* them; besides the tighter coupling above, that meant N-1 extra full-
|
||||
* buffer memcpy calls per work() call at up to the raw capture rate.
|
||||
* The block has a single output port. Multiple RF bands sharing the same
|
||||
* raw capture (e.g. several Freq_Xlating_Fir_Filter instances tuned to
|
||||
* different IFs) are each connected to that one port (see the
|
||||
* signal-source-to-conditioner wiring in gnss_flowgraph.cc, which takes
|
||||
* this path whenever output_signature()->max_streams() == 1): GNU Radio
|
||||
* supports several readers on one producer port, each with its own read
|
||||
* pointer over the same buffer. The scheduler still throttles this block
|
||||
* to the slowest of those readers (buffer::space_available() is bounded by
|
||||
* the reader with the most unconsumed items), exactly as it would with one
|
||||
* buffer per port, so the bands cannot drift apart by more than one output
|
||||
* buffer. What the single port saves is the N-1 extra output buffers and
|
||||
* the N-1 full-buffer memcpy calls per work() call, at up to the raw
|
||||
* capture rate, that a port-per-band design needs in order to duplicate
|
||||
* the same decoded samples.
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
@@ -62,19 +59,18 @@ class Evk1029Source;
|
||||
|
||||
using Evk1029Source_sptr = gnss_shared_ptr<Evk1029Source>;
|
||||
|
||||
// file_offset_bytes: byte position in the raw capture to seek to before the
|
||||
// first read, letting a long capture be jumped straight to a "time of
|
||||
// interest" instead of always reprocessed from the start (see
|
||||
// Evk1029SignalSource.file_offset in the adapter, which converts a
|
||||
// requested offset in seconds -- since the sampling frequency is already
|
||||
// known there -- into this byte count). Rounded up to the next multiple of
|
||||
// 8 bytes (64 bits) here, matching the capture's native packing (16 OBA
|
||||
// samples per little-endian 64-bit word): this block itself only ever reads
|
||||
// byte-by-byte and would decode correctly from any byte offset, but seeking
|
||||
// to a non-word-aligned byte splits a 64-bit DMA word the real hardware
|
||||
// always transferred as one unit, which needlessly complicates comparing a
|
||||
// jumped-to run against a from-the-start one at the file/word level.
|
||||
Evk1029Source_sptr evk1029_make_source(const std::string& filename, int n_streams, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t file_offset_bytes = 0);
|
||||
// bytes_to_skip: byte position in the raw capture at which reading starts,
|
||||
// so that a long capture can be jumped straight to a time of interest
|
||||
// instead of being processed from the beginning (the adapter derives it
|
||||
// from its .seconds_to_skip parameter and the raw sampling frequency).
|
||||
// Rounded up to the next multiple of 8 bytes (64 bits) here, matching the
|
||||
// capture's native packing (16 OBA samples per little-endian 64-bit word):
|
||||
// this block itself only ever reads byte-by-byte and would decode correctly
|
||||
// from any byte offset, but seeking to a non-word-aligned byte splits a
|
||||
// 64-bit DMA word the real hardware always transferred as one unit, which
|
||||
// needlessly complicates comparing a jumped-to run against a from-the-start
|
||||
// one at the file/word level.
|
||||
Evk1029Source_sptr evk1029_make_source(const std::string& filename, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t bytes_to_skip = 0);
|
||||
|
||||
/*!
|
||||
* \brief Reads a continuous, header-less EVK1029 raw capture file and
|
||||
@@ -86,8 +82,8 @@ public:
|
||||
~Evk1029Source() override;
|
||||
|
||||
private:
|
||||
friend Evk1029Source_sptr evk1029_make_source(const std::string& filename, int n_streams, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t file_offset_bytes);
|
||||
Evk1029Source(const std::string& filename, int n_streams, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t file_offset_bytes = 0);
|
||||
friend Evk1029Source_sptr evk1029_make_source(const std::string& filename, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t bytes_to_skip);
|
||||
Evk1029Source(const std::string& filename, Concurrent_Queue<pmt::pmt_t>* queue, double sampling_frequency, uint64_t bytes_to_skip = 0);
|
||||
|
||||
int work(int noutput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
@@ -98,7 +94,6 @@ private:
|
||||
std::vector<uint8_t> buffer_;
|
||||
std::size_t buffer_valid_; // number of valid bytes currently in buffer_
|
||||
std::size_t buffer_pos_; // next unread byte offset within buffer_
|
||||
int n_streams_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user