diff --git a/src/algorithms/signal_source/adapters/file_source_base.cc b/src/algorithms/signal_source/adapters/file_source_base.cc index 4e172e76b..0beb95b7f 100644 --- a/src/algorithms/signal_source/adapters/file_source_base.cc +++ b/src/algorithms/signal_source/adapters/file_source_base.cc @@ -28,9 +28,82 @@ using namespace std::string_literals; +FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std::string const& role, std::string impl, + Concurrent_Queue* queue, + std::string default_item_type) + : SignalSourceBase(configuration, role, std::move(impl)), filename_(configuration->property(role + ".filename"s, "../data/example_capture.dat"s)), + + file_source_(), // NOLINT + + item_type_(configuration->property(role + ".item_type"s, default_item_type)), // NOLINT + item_size_(0), + is_complex_(false), + + // apparently, MacOS (LLVM) finds 0UL ambiguous with bool, int64_t, uint64_t, int32_t, int16_t, uint16_t,... float, double + header_size_(configuration->property(role + ".header_size"s, uint64_t(0))), + seconds_to_skip_(configuration->property(role + ".seconds_to_skip"s, 0.0)), + repeat_(configuration->property(role + ".repeat"s, false)), + + samples_(configuration->property(role + ".samples"s, uint64_t(0))), + sampling_frequency_(configuration->property(role + ".sampling_frequency"s, int64_t(0))), + valve_(), // NOLINT + queue_(queue), + + enable_throttle_control_(configuration->property(role + ".enable_throttle_control"s, false)), + throttle_(), // NOLINT + + dump_(configuration->property(role + ".dump"s, false)), + dump_filename_(configuration->property(role + ".dump_filename"s, "../data/my_capture.dat"s)), + sink_() // NOLINT +{ + // override value with commandline flag, if present + if (FLAGS_signal_source != "-") + { + filename_ = FLAGS_signal_source; + } + if (FLAGS_s != "-") + { + filename_ = FLAGS_s; + } + + init(); +} + + +void FileSourceBase::init() +{ + create_file_source(); + + // At this point, we know that the file exists + samples_ = computeSamplesInFile(); + auto signal_duration_s = 1.0 * samples_ / sampling_frequency_; + + if (is_complex()) + { + signal_duration_s /= 2.0; + } + + DLOG(INFO) << "Total number samples to be processed= " << samples_ << " GNSS signal duration= " << signal_duration_s << " [s]"; + std::cout << "GNSS signal recorded time to be processed: " << signal_duration_s << " [s]\n"; + + DLOG(INFO) << "File source filename " << filename_; + DLOG(INFO) << "Samples " << samples_; + DLOG(INFO) << "Sampling frequency " << sampling_frequency_; + DLOG(INFO) << "Item type " << item_type_; + DLOG(INFO) << "Item size " << item_size_; + DLOG(INFO) << "Repeat " << repeat_; + + DLOG(INFO) << "Dump " << dump_; + DLOG(INFO) << "Dump filename " << dump_filename_; + + create_throttle(); + create_valve(); + create_sink(); +} + + void FileSourceBase::connect(gr::top_block_sptr top_block) { - init(); pre_connect_hook(top_block); auto input = gr::basic_block_sptr(); @@ -150,109 +223,43 @@ std::string FileSourceBase::filename() const return filename_; } + std::string FileSourceBase::item_type() const { return item_type_; } + size_t FileSourceBase::item_size() { return item_size_; } + + size_t FileSourceBase::item_size() const { return item_size_; } + bool FileSourceBase::repeat() const { return repeat_; } + int64_t FileSourceBase::sampling_frequency() const { return sampling_frequency_; } + uint64_t FileSourceBase::samples() const { return samples_; } -FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std::string const& role, std::string impl, - Concurrent_Queue* queue, - std::string default_item_type) - : SignalSourceBase(configuration, role, std::move(impl)), filename_(configuration->property(role + ".filename"s, "../data/example_capture.dat"s)), - - file_source_(), // NOLINT - - item_type_(configuration->property(role + ".item_type"s, default_item_type)), // NOLINT - item_size_(0), - is_complex_(false), - - // apparently, MacOS (LLVM) finds 0UL ambiguous with bool, int64_t, uint64_t, int32_t, int16_t, uint16_t,... float, double - header_size_(configuration->property(role + ".header_size"s, uint64_t(0))), - seconds_to_skip_(configuration->property(role + ".seconds_to_skip", 0.0)), - repeat_(configuration->property(role + ".repeat"s, false)), - - - samples_(configuration->property(role + ".samples"s, uint64_t(0))), - sampling_frequency_(configuration->property(role + ".sampling_frequency"s, int64_t(0))), - valve_(), // NOLINT - queue_(queue), - - enable_throttle_control_(configuration->property(role + ".enable_throttle_control"s, false)), - throttle_(), // NOLINT - - dump_(configuration->property(role + ".dump"s, false)), - dump_filename_(configuration->property(role + ".dump_filename"s, "../data/my_capture.dat"s)), - sink_() // NOLINT -{ - // override value with commandline flag, if present - if (FLAGS_signal_source != "-") - { - filename_ = FLAGS_signal_source; - } - if (FLAGS_s != "-") - { - filename_ = FLAGS_s; - } -} - -void FileSourceBase::init() -{ - create_file_source(); - - // At this point, we know that the file exists - samples_ = computeSamplesInFile(); - auto signal_duration_s = 1.0 * samples_ / sampling_frequency_; - - if (is_complex()) - { - signal_duration_s /= 2.0; - } - - DLOG(INFO) << "Total number samples to be processed= " << samples_ << " GNSS signal duration= " << signal_duration_s << " [s]"; - std::cout << "GNSS signal recorded time to be processed: " << signal_duration_s << " [s]\n"; - - - DLOG(INFO) << "File source filename " << filename_; - DLOG(INFO) << "Samples " << samples_; - DLOG(INFO) << "Sampling frequency " << sampling_frequency_; - DLOG(INFO) << "Item type " << item_type_; - DLOG(INFO) << "Item size " << item_size_; - DLOG(INFO) << "Repeat " << repeat_; - - DLOG(INFO) << "Dump " << dump_; - DLOG(INFO) << "Dump filename " << dump_filename_; - - create_throttle(); - create_valve(); - create_sink(); -} - - std::tuple FileSourceBase::itemTypeToSize() { auto is_complex_t = false; @@ -294,9 +301,11 @@ std::tuple FileSourceBase::itemTypeToSize() return std::make_tuple(item_size, is_complex_t); } + // Default case is one decoded packet per one read sample double FileSourceBase::packetsPerSample() const { return 1.0; } + size_t FileSourceBase::samplesToSkip() const { auto samples_to_skip = size_t(0); @@ -327,11 +336,11 @@ size_t FileSourceBase::samplesToSkip() const return samples_to_skip; } + size_t FileSourceBase::computeSamplesInFile() const { auto n_samples = size_t(samples()); - // if configured with 0 samples (read the whole file), figure out how many samples are in the file, and go from there if (n_samples == 0) { @@ -369,21 +378,26 @@ size_t FileSourceBase::computeSamplesInFile() const return n_samples; } -gnss_shared_ptr FileSourceBase::source() const { return file_source(); } + size_t FileSourceBase::source_item_size() const { // delegate the size of the source to the source() object, so sub-classes have less work to do DLOG(INFO) << "source_item_size is " << source()->output_signature()->sizeof_stream_item(0); return source()->output_signature()->sizeof_stream_item(0); } + + bool FileSourceBase::is_complex() const { return is_complex_; } + // Simple accessors +gnss_shared_ptr FileSourceBase::source() const { return file_source(); } gnss_shared_ptr FileSourceBase::file_source() const { return file_source_; } gnss_shared_ptr FileSourceBase::valve() const { return valve_; } gnss_shared_ptr FileSourceBase::throttle() const { return throttle_; } gnss_shared_ptr FileSourceBase::sink() const { return sink_; } + gr::blocks::file_source::sptr FileSourceBase::create_file_source() { auto item_tuple = itemTypeToSize(); @@ -430,10 +444,10 @@ gr::blocks::file_source::sptr FileSourceBase::create_file_source() // enable subclass hooks create_file_source_hook(); - return file_source_; } + gr::blocks::throttle::sptr FileSourceBase::create_throttle() { if (enable_throttle_control_) @@ -448,6 +462,7 @@ gr::blocks::throttle::sptr FileSourceBase::create_throttle() return throttle_; } + gnss_shared_ptr FileSourceBase::create_valve() { if (samples() > 0) @@ -463,6 +478,7 @@ gnss_shared_ptr FileSourceBase::create_valve() return valve_; } + gr::blocks::file_sink::sptr FileSourceBase::create_sink() { if (dump_) @@ -476,12 +492,14 @@ gr::blocks::file_sink::sptr FileSourceBase::create_sink() return sink_; } + // Subclass hooks to augment created objects, as required void FileSourceBase::create_file_source_hook() {} void FileSourceBase::create_throttle_hook() {} void FileSourceBase::create_valve_hook() {} void FileSourceBase::create_sink_hook() {} + // Subclass hooks for connection/disconnectino void FileSourceBase::pre_connect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {} void FileSourceBase::post_connect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {} diff --git a/src/algorithms/signal_source/adapters/file_source_base.h b/src/algorithms/signal_source/adapters/file_source_base.h index 88802c067..2b0eb903e 100644 --- a/src/algorithms/signal_source/adapters/file_source_base.h +++ b/src/algorithms/signal_source/adapters/file_source_base.h @@ -23,6 +23,7 @@ #include #include #include +#include // for dump #include @@ -32,88 +33,100 @@ class ConfigurationInterface; -// This class supports the following properties: -// -// .filename - the path to the input file -// - may be overridden by the -signal_source or -s command-line arguments -// .samples - number of samples to process (default 0) -// - if not specified or 0, read the entire file; otherwise stop after that many samples -// .sampling_frequency - the frequency of the sampled data (samples/second) -// .item_type - data type of the samples (default "short") -// .header_size - the size of a prefixed header to skip in "samples" (default 0) -// .seconds_to_skip - number of seconds of lead-in data to skip over (default 0) -// .enable_throttle_control - whether to stop reading if the upstream buffer is full (default false) -// .repeat - whether to rewind and continue at end of file (default false) -// -// (probably abstracted to the base class) -// .dump - whether to archive input data -// .dump_filename - if dumping, path to file for output + +//! \brief Base class to file-oriented SignalSourceBase GNSS blocks. +//! +//! This class supports the following properties: +//! +//! .filename - the path to the input file +//! - may be overridden by the -signal_source or -s command-line arguments +//! +//! .samples - number of samples to process (default 0) +//! - if not specified or 0, read the entire file; otherwise stop after that many samples +//! +//! .sampling_frequency - the frequency of the sampled data (samples/second) +//! +//! .item_type - data type of the samples (default "short") +//! +//! .header_size - the size of a prefixed header to skip in "samples" (default 0) +//! +//! .seconds_to_skip - number of seconds of lead-in data to skip over (default 0) +//! +//! .enable_throttle_control - whether to stop reading if the upstream buffer is full (default false) +//! +//! .repeat - whether to rewind and continue at end of file (default false) +//! +//! (probably abstracted to the base class) +//! +//! .dump - whether to archive input data +//! +//! .dump_filename - if dumping, path to file for output class FileSourceBase : public SignalSourceBase { public: - //! virtual overrides + // Virtual overrides void connect(gr::top_block_sptr top_block) override; void disconnect(gr::top_block_sptr top_block) override; gr::basic_block_sptr get_left_block() override; gr::basic_block_sptr get_right_block() override; - - //! the file to read + //! The file to read std::string filename() const; - //! the item type + //! The item type std::string item_type() const; - //! the configured size of each item + //! The configured size of each item size_t item_size() override; virtual size_t item_size() const; // what the interface **should** have declared //! Whether to repeat reading after end-of-file bool repeat() const; - //! the sampling frequency of the source file + //! The sampling frequency of the source file int64_t sampling_frequency() const; - //! the number of samples in the file + //! The number of samples in the file uint64_t samples() const; protected: - //! Constructor - // Subclasses may want to assert default item types that are appropriate to the specific file - // type supported. Rather than require the item type to be specified in the config file, allow - // sub-classes to impose their will + //! \brief Constructor + //! + //! Subclasses may want to assert default item types that are appropriate to the specific file + //! type supported. Rather than require the item type to be specified in the config file, allow + //! sub-classes to impose their will FileSourceBase(ConfigurationInterface const* configuration, std::string const& role, std::string impl, Concurrent_Queue* queue, std::string default_item_type = "short"); - //! perform post-construction initialization + //! Perform post-construction initialization void init(); - //! compute the item size, from the item_type(). Subclasses may constrain types that don't make + //! Compute the item size, from the item_type(). Subclasses may constrain types that don't make // sense. The return of this method is a tuple of item_size and is_complex virtual std::tuple itemTypeToSize(); - //! the number of (possibly unpacked) samples in a (raw) file sample (default=1) + //! The number of (possibly unpacked) samples in a (raw) file sample (default=1) virtual double packetsPerSample() const; - //! compute the number of samples to skip + //! Compute the number of samples to skip virtual size_t samplesToSkip() const; - //! compute the number of samples in the file + //! Compute the number of samples in the file size_t computeSamplesInFile() const; - //! abstracted front-end source. Sub-classes may override if they create specialized chains to + //! Abstracted front-end source. Sub-classes may override if they create specialized chains to //! decode source files into a usable format virtual gnss_shared_ptr source() const; - //! for complex source chains, the size of the file item may not be the same as the size of the + //! For complex source chains, the size of the file item may not be the same as the size of the // "source" (decoded) item. This method allows subclasses to handle these differences virtual size_t source_item_size() const; bool is_complex() const; - //! generic access to created objects + // Generic access to created objects gnss_shared_ptr file_source() const; gnss_shared_ptr valve() const; gnss_shared_ptr throttle() const;