mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-11-10 20:10:05 +00:00
Added valves to properly handle end of samples
This commit is contained in:
parent
92dcec67e0
commit
89d73174a8
2
AUTHORS
2
AUTHORS
@ -64,7 +64,7 @@ Marc Sales marcsales92@gmail.com Contributor
|
||||
Piyush Gupta piyush04111999@gmail.com Contributor
|
||||
Rodrigo Muñoz rodrigo.munoz@proteinlab.cl Contributor
|
||||
Stefan van der Linden spvdlinden@gmail.com Contributor
|
||||
Victor Castillo-Agüero victorcastilloaguero@gmail.com Contributor
|
||||
Víctor Castillo-Agüero victorcastilloaguero@gmail.com Contributor
|
||||
Will Silberman wsilberm@google.com Contributor
|
||||
Carlos Paniego carpanie@hotmail.com Artwork
|
||||
|
||||
|
@ -38,7 +38,7 @@ authors:
|
||||
affiliation: "Instituto Nacional de Técnica Aeroespacial"
|
||||
email: victorcastilloaguero@gmail.com
|
||||
family-names: "Castillo-Agüero"
|
||||
given-names: Victor
|
||||
given-names: Víctor
|
||||
- alias: acebrianjuan
|
||||
email: acebrianjuan@gmail.com
|
||||
family-names: "Cebrián-Juan"
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "ion_gsms_signal_source.h"
|
||||
#include "gnss_sdr_flags.h"
|
||||
#include "gnss_sdr_string_literals.h"
|
||||
#include "gnss_sdr_valve.h"
|
||||
#include <gnuradio/blocks/copy.h>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
@ -54,7 +55,7 @@ IONGSMSSignalSource::IONGSMSSignalSource(const ConfigurationInterface* configura
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams,
|
||||
Concurrent_Queue<pmt::pmt_t>* queue __attribute__((unused)))
|
||||
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||
: SignalSourceBase(configuration, role, "ION_GSMS_Signal_Source"s),
|
||||
stream_ids_(parse_comma_list(configuration->property(role + ".streams"s, ""s))),
|
||||
metadata_filepath_(configuration->property(role + ".metadata_filename"s, "../data/example_capture_metadata.sdrx"s)),
|
||||
@ -82,6 +83,7 @@ IONGSMSSignalSource::IONGSMSSignalSource(const ConfigurationInterface* configura
|
||||
for (std::size_t i = 0; i < source->output_stream_count(); ++i)
|
||||
{
|
||||
copy_blocks_.push_back(gr::blocks::copy::make(source->output_stream_item_size(i)));
|
||||
valves_.push_back(gnss_sdr_make_valve(source->output_stream_item_size(i), source->output_stream_total_sample_count(i), queue));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -186,6 +188,7 @@ void IONGSMSSignalSource::connect(gr::top_block_sptr top_block)
|
||||
for (std::size_t i = 0; i < source->output_stream_count(); ++i, ++cumulative_index)
|
||||
{
|
||||
top_block->connect(source, i, copy_blocks_[cumulative_index], 0);
|
||||
top_block->connect(copy_blocks_[cumulative_index], 0, valves_[cumulative_index], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -193,9 +196,14 @@ void IONGSMSSignalSource::connect(gr::top_block_sptr top_block)
|
||||
|
||||
void IONGSMSSignalSource::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
std::size_t cumulative_index = 0;
|
||||
for (const auto& source : sources_)
|
||||
{
|
||||
top_block->disconnect(source);
|
||||
for (std::size_t i = 0; i < source->output_stream_count(); ++i, ++cumulative_index)
|
||||
{
|
||||
top_block->disconnect(source, i, copy_blocks_[cumulative_index], 0);
|
||||
top_block->disconnect(copy_blocks_[cumulative_index], 0, valves_[cumulative_index], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,7 +227,7 @@ gr::basic_block_sptr IONGSMSSignalSource::get_right_block(int RF_channel)
|
||||
if (RF_channel < 0 || RF_channel >= static_cast<int>(copy_blocks_.size()))
|
||||
{
|
||||
LOG(WARNING) << "'RF_channel' out of bounds while trying to get signal source right block.";
|
||||
return copy_blocks_[0];
|
||||
return valves_[0];
|
||||
}
|
||||
return copy_blocks_[RF_channel];
|
||||
return valves_[RF_channel];
|
||||
}
|
||||
|
@ -19,6 +19,12 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
IONGSMSFileSource::IONGSMSFileSource(
|
||||
@ -30,13 +36,20 @@ IONGSMSFileSource::IONGSMSFileSource(
|
||||
"ion_gsms_file_source",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
make_output_signature(block, stream_ids)),
|
||||
file_stream_(metadata_filepath.parent_path() / file.Url().Value()),
|
||||
file_stream_(metadata_filepath.parent_path() / file.Url().Value(), std::ios::in | std::ios::binary),
|
||||
io_buffer_offset_(0),
|
||||
maximum_item_rate_(0),
|
||||
chunk_cycle_length_(0)
|
||||
{
|
||||
fs::path data_filepath = metadata_filepath.parent_path() / file.Url().Value();
|
||||
std::size_t block_offset = file.Offset();
|
||||
|
||||
if (!file_stream_.is_open())
|
||||
{
|
||||
LOG(ERROR) << "ion_gsms_file_source: Unable to open the samples file: " << (data_filepath).c_str();
|
||||
}
|
||||
|
||||
// Skip offset and block header
|
||||
file_stream_.seekg(file.Offset() + block_offset + block.SizeHeader());
|
||||
|
||||
std::size_t output_stream_offset = 0;
|
||||
@ -49,42 +62,26 @@ IONGSMSFileSource::IONGSMSFileSource(
|
||||
for (std::size_t i = 0; i < out_count; ++i)
|
||||
{
|
||||
output_stream_item_sizes_.push_back(chunk_data_.back()->output_stream_item_size(i));
|
||||
output_stream_item_rates_.push_back(chunk_data_.back()->output_stream_item_rate(i));
|
||||
maximum_item_rate_ = std::max(chunk_data_.back()->output_stream_item_rate(i), maximum_item_rate_);
|
||||
}
|
||||
}
|
||||
output_stream_count_ = output_stream_offset;
|
||||
}
|
||||
|
||||
output_stream_total_sample_counts_.resize(output_stream_count_);
|
||||
|
||||
int IONGSMSFileSource::work(
|
||||
int noutput_items,
|
||||
gr_vector_const_void_star& input_items __attribute__((unused)),
|
||||
gr_vector_void_star& output_items)
|
||||
{
|
||||
const std::size_t max_sample_output = std::floor((noutput_items - 1.0) / maximum_item_rate_);
|
||||
io_buffer_.resize(max_sample_output * chunk_cycle_length_);
|
||||
io_buffer_offset_ = 0;
|
||||
file_stream_.read(io_buffer_.data(), sizeof(decltype(io_buffer_)::value_type) * io_buffer_.size());
|
||||
|
||||
items_produced_.clear();
|
||||
items_produced_.resize(output_items.size());
|
||||
|
||||
while (io_buffer_offset_ < io_buffer_.size())
|
||||
std::size_t cycle_count = block.Cycles();
|
||||
if (cycle_count == 0)
|
||||
{
|
||||
for (auto& c : chunk_data_)
|
||||
{
|
||||
auto* chunk = c.get();
|
||||
io_buffer_offset_ += chunk->read_from_buffer(reinterpret_cast<uint8_t*>(io_buffer_.data()), io_buffer_offset_);
|
||||
chunk->write_to_output(output_items, items_produced_);
|
||||
}
|
||||
// Read the whole file
|
||||
const std::size_t file_size = fs::file_size(data_filepath);
|
||||
cycle_count = std::floor((file_size - block_offset - block.SizeHeader()) / chunk_cycle_length_);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < items_produced_.size(); ++i)
|
||||
for (std::size_t i = 0; i < output_stream_count_; ++i)
|
||||
{
|
||||
produce(i, items_produced_[i]);
|
||||
output_stream_total_sample_counts_[i] = cycle_count * output_stream_item_rates_[i];
|
||||
}
|
||||
|
||||
return WORK_CALLED_PRODUCE;
|
||||
}
|
||||
|
||||
|
||||
@ -99,6 +96,10 @@ std::size_t IONGSMSFileSource::output_stream_item_size(std::size_t stream_index)
|
||||
return output_stream_item_sizes_[stream_index];
|
||||
}
|
||||
|
||||
std::size_t IONGSMSFileSource::output_stream_total_sample_count(std::size_t stream_index) const
|
||||
{
|
||||
return output_stream_total_sample_counts_[stream_index];
|
||||
}
|
||||
|
||||
gr::io_signature::sptr IONGSMSFileSource::make_output_signature(const GnssMetadata::Block& block, const std::vector<std::string>& stream_ids)
|
||||
{
|
||||
@ -140,3 +141,58 @@ gr::io_signature::sptr IONGSMSFileSource::make_output_signature(const GnssMetada
|
||||
nstreams,
|
||||
item_sizes);
|
||||
}
|
||||
|
||||
int IONGSMSFileSource::work(
|
||||
int noutput_items,
|
||||
gr_vector_const_void_star& input_items __attribute__((unused)),
|
||||
gr_vector_void_star& output_items)
|
||||
{
|
||||
// Compute the maximum number of samples that will be copied across all output buffer.
|
||||
// If there are more than one output buffer (multichannel set up), the one with the most samples will be used as the maximum.
|
||||
//
|
||||
// Complex samples produce 2 items each (I and Q). In order to account for them, we subtract 1 from `noutput_items` and
|
||||
// then floor the division. During testing, not doing this caused `max_sample_output` to oscillate between two values, thus
|
||||
// resizing the `io_buffer_` on each call to `work()`.
|
||||
const std::size_t max_sample_output = std::floor((noutput_items - 1.0) / maximum_item_rate_);
|
||||
|
||||
// Resize the IO buffer to fit exactly the maximum amount of samples that will be outputted.
|
||||
io_buffer_.resize(max_sample_output * chunk_cycle_length_);
|
||||
|
||||
// We will be walking the IO buffer with this variable.
|
||||
io_buffer_offset_ = 0;
|
||||
|
||||
// Read samples from file into IO buffer
|
||||
const std::size_t bytes_to_read = io_buffer_.size();
|
||||
file_stream_.read(io_buffer_.data(), bytes_to_read);
|
||||
|
||||
// Reset `items_produced_` vector. This vector will accumulate the amount of items produced for each output stream.
|
||||
items_produced_.clear();
|
||||
items_produced_.resize(output_items.size());
|
||||
|
||||
// Walk the IO buffer one chunk cycle at a time. See ION documentation for a definition of chunk and chunk cycle.
|
||||
while (io_buffer_offset_ < bytes_to_read)
|
||||
{
|
||||
// Iterate chunks within a chunk cycle
|
||||
for (auto& c : chunk_data_)
|
||||
{
|
||||
auto* chunk = c.get();
|
||||
|
||||
// Copy chunk into a separate buffer where the samples will be shifted from.
|
||||
const std::size_t bytes_copied = chunk->read_from_buffer(reinterpret_cast<uint8_t*>(io_buffer_.data()), io_buffer_offset_);
|
||||
|
||||
// Advance IO buffer offset
|
||||
io_buffer_offset_ += bytes_copied;
|
||||
|
||||
// Shift samples into output buffers following the appropriate unpacking strategy for this chunk.
|
||||
chunk->write_to_output(output_items, items_produced_);
|
||||
}
|
||||
}
|
||||
|
||||
// Call `produce(int, int)` with the appropriate item count for each output stream.
|
||||
for (std::size_t i = 0; i < items_produced_.size(); ++i)
|
||||
{
|
||||
produce(i, items_produced_[i]);
|
||||
}
|
||||
|
||||
return WORK_CALLED_PRODUCE;
|
||||
}
|
||||
|
@ -24,10 +24,10 @@
|
||||
#include <gnuradio/sync_block.h>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
/** \addtogroup Signal_Source
|
||||
* \{ */
|
||||
@ -52,6 +52,7 @@ public:
|
||||
|
||||
std::size_t output_stream_count() const;
|
||||
std::size_t output_stream_item_size(std::size_t stream_index) const;
|
||||
std::size_t output_stream_total_sample_count(std::size_t stream_index) const;
|
||||
|
||||
private:
|
||||
static gr::io_signature::sptr make_output_signature(const GnssMetadata::Block& block, const std::vector<std::string>& stream_ids);
|
||||
@ -62,6 +63,8 @@ private:
|
||||
std::vector<int> items_produced_;
|
||||
std::size_t output_stream_count_;
|
||||
std::vector<std::size_t> output_stream_item_sizes_;
|
||||
std::vector<std::size_t> output_stream_item_rates_;
|
||||
std::vector<std::size_t> output_stream_total_sample_counts_;
|
||||
std::size_t maximum_item_rate_;
|
||||
std::vector<std::shared_ptr<IONGSMSChunkData>> chunk_data_;
|
||||
std::size_t chunk_cycle_length_;
|
||||
|
Loading…
Reference in New Issue
Block a user