mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-14 04:00:34 +00:00
Merge branch 'jwmelto-feature/signal_source_interface' into next
This commit is contained in:
commit
7fc6074f70
@ -36,6 +36,9 @@ SPDX-FileCopyrightText: 2011-2021 Carles Fernandez-Prades <carles.fernandez@cttc
|
|||||||
asking them to sign the CLA document).
|
asking them to sign the CLA document).
|
||||||
- Improved handling of change in GNU Radio 3.9 FFT API.
|
- Improved handling of change in GNU Radio 3.9 FFT API.
|
||||||
- Improved handling of the filesystem library.
|
- Improved handling of the filesystem library.
|
||||||
|
- Added an abstract class `SignalSourceInterface` and a common base class
|
||||||
|
`SignalSourceBase`, which allow to remove a lot of duplicated code in Signal
|
||||||
|
Source blocks, and further abstract file-based interfaces behind them.
|
||||||
- Do not apply clang-tidy fixes to protobuf-generated headers.
|
- Do not apply clang-tidy fixes to protobuf-generated headers.
|
||||||
- Refactored private implementation of flow graph connection and disconnection
|
- Refactored private implementation of flow graph connection and disconnection
|
||||||
for improved source code readability.
|
for improved source code readability.
|
||||||
|
@ -31,6 +31,7 @@ set(GNSS_SPLIBS_SOURCES
|
|||||||
item_type_helpers.cc
|
item_type_helpers.cc
|
||||||
pass_through.cc
|
pass_through.cc
|
||||||
short_x2_to_cshort.cc
|
short_x2_to_cshort.cc
|
||||||
|
gnss_sdr_string_literals.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(GNSS_SPLIBS_HEADERS
|
set(GNSS_SPLIBS_HEADERS
|
||||||
@ -61,6 +62,7 @@ set(GNSS_SPLIBS_HEADERS
|
|||||||
item_type_helpers.h
|
item_type_helpers.h
|
||||||
pass_through.h
|
pass_through.h
|
||||||
short_x2_to_cshort.h
|
short_x2_to_cshort.h
|
||||||
|
gnss_sdr_string_literals.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if(ENABLE_OPENCL)
|
if(ENABLE_OPENCL)
|
||||||
|
37
src/algorithms/libs/gnss_sdr_string_literals.cc
Normal file
37
src/algorithms/libs/gnss_sdr_string_literals.cc
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*!
|
||||||
|
* \file gnss_sdr_string_literals.cc
|
||||||
|
* \brief This file implements the ""s operator for std::string in C++11, and
|
||||||
|
* puts it into the std::string_literals namespace. This is already implemented
|
||||||
|
* in C++14, so this is only compiled when using C++11. The .cc file is required
|
||||||
|
* for avoiding the duplication of symbols.
|
||||||
|
*
|
||||||
|
* \author Carles Fernandez-Prades, 2021. cfernandez(at)cttc.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 "gnss_sdr_string_literals.h"
|
||||||
|
|
||||||
|
#if __cplusplus == 201103L
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
namespace string_literals
|
||||||
|
{
|
||||||
|
std::string operator"" s(const char* str, std::size_t len)
|
||||||
|
{
|
||||||
|
return std::string(str, len);
|
||||||
|
};
|
||||||
|
} // namespace string_literals
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
#endif // __cplusplus == 201103L
|
48
src/algorithms/libs/gnss_sdr_string_literals.h
Normal file
48
src/algorithms/libs/gnss_sdr_string_literals.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*!
|
||||||
|
* \file gnss_sdr_string_literals.h
|
||||||
|
* \brief This file implements the ""s operator for std::string in C++11, and
|
||||||
|
* puts it into the std::string_literals namespace. This is already implemented
|
||||||
|
* in C++14, so this is only compiled when using C++11. The .cc file is required
|
||||||
|
* for avoiding the duplication of symbols.
|
||||||
|
*
|
||||||
|
* \author Carles Fernandez-Prades, 2021. cfernandez(at)cttc.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_STRING_LITERALS_H
|
||||||
|
#define GNSS_SDR_STRING_LITERALS_H
|
||||||
|
|
||||||
|
/** \addtogroup Algorithms_Library
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Algorithm_libs algorithms_libs
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
#if __cplusplus == 201103L
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
namespace string_literals
|
||||||
|
{
|
||||||
|
std::string operator"" s(const char* str, std::size_t len);
|
||||||
|
} // namespace string_literals
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
#endif // __cplusplus == 201103L
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
#endif // GNSS_SDR_STRING_LITERALS_H
|
@ -92,6 +92,8 @@ endif()
|
|||||||
|
|
||||||
|
|
||||||
set(SIGNAL_SOURCE_ADAPTER_SOURCES
|
set(SIGNAL_SOURCE_ADAPTER_SOURCES
|
||||||
|
signal_source_base.cc
|
||||||
|
file_source_base.cc
|
||||||
file_signal_source.cc
|
file_signal_source.cc
|
||||||
multichannel_file_signal_source.cc
|
multichannel_file_signal_source.cc
|
||||||
gen_signal_source.cc
|
gen_signal_source.cc
|
||||||
@ -106,6 +108,8 @@ set(SIGNAL_SOURCE_ADAPTER_SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(SIGNAL_SOURCE_ADAPTER_HEADERS
|
set(SIGNAL_SOURCE_ADAPTER_HEADERS
|
||||||
|
signal_source_base.h
|
||||||
|
file_source_base.h
|
||||||
file_signal_source.h
|
file_signal_source.h
|
||||||
multichannel_file_signal_source.h
|
multichannel_file_signal_source.h
|
||||||
gen_signal_source.h
|
gen_signal_source.h
|
||||||
@ -156,6 +160,7 @@ target_link_libraries(signal_source_adapters
|
|||||||
Gnuradio::blocks
|
Gnuradio::blocks
|
||||||
signal_source_gr_blocks
|
signal_source_gr_blocks
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
algorithms_libs
|
||||||
gnss_sdr_flags
|
gnss_sdr_flags
|
||||||
core_system_parameters
|
core_system_parameters
|
||||||
Glog::glog
|
Glog::glog
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "ad9361_manager.h"
|
#include "ad9361_manager.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
#include "gnss_sdr_flags.h"
|
#include "gnss_sdr_flags.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "uio_fpga.h"
|
#include "uio_fpga.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <iio.h>
|
#include <iio.h>
|
||||||
@ -42,9 +43,12 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *configuration,
|
Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *configuration,
|
||||||
const std::string &role, unsigned int in_stream, unsigned int out_stream,
|
const std::string &role, unsigned int in_stream, unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t> *queue __attribute__((unused))) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
Concurrent_Queue<pmt::pmt_t> *queue __attribute__((unused)))
|
||||||
|
: SignalSourceBase(configuration, role, "Ad9361_Fpga_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
const std::string default_gain_mode("slow_attack");
|
const std::string default_gain_mode("slow_attack");
|
||||||
const double default_tx_attenuation_db = -10.0;
|
const double default_tx_attenuation_db = -10.0;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "fpga_dynamic_bit_selection.h"
|
#include "fpga_dynamic_bit_selection.h"
|
||||||
#include "fpga_switch.h"
|
#include "fpga_switch.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "gnss_block_interface.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
#include <pmt/pmt.h>
|
#include <pmt/pmt.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -39,7 +40,7 @@
|
|||||||
|
|
||||||
class ConfigurationInterface;
|
class ConfigurationInterface;
|
||||||
|
|
||||||
class Ad9361FpgaSignalSource : public GNSSBlockInterface
|
class Ad9361FpgaSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Ad9361FpgaSignalSource(const ConfigurationInterface *configuration,
|
Ad9361FpgaSignalSource(const ConfigurationInterface *configuration,
|
||||||
@ -50,19 +51,6 @@ public:
|
|||||||
|
|
||||||
void start() override;
|
void start() override;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Ad9361_Fpga_Signal_Source"
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Ad9361_Fpga_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -100,8 +88,6 @@ private:
|
|||||||
std::shared_ptr<Fpga_dynamic_bit_selection> dynamic_bit_selection_fpga;
|
std::shared_ptr<Fpga_dynamic_bit_selection> dynamic_bit_selection_fpga;
|
||||||
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_fpga;
|
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_fpga;
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
|
|
||||||
// Front-end settings
|
// Front-end settings
|
||||||
std::string gain_mode_rx1_;
|
std::string gain_mode_rx1_;
|
||||||
std::string gain_mode_rx2_;
|
std::string gain_mode_rx2_;
|
||||||
|
@ -17,13 +17,17 @@
|
|||||||
|
|
||||||
#include "custom_udp_signal_source.h"
|
#include "custom_udp_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
CustomUDPSignalSource::CustomUDPSignalSource(const ConfigurationInterface* configuration,
|
CustomUDPSignalSource::CustomUDPSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, unsigned int in_stream, unsigned int out_stream,
|
const std::string& role, unsigned int in_stream, unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue __attribute__((unused))) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
Concurrent_Queue<pmt::pmt_t>* queue __attribute__((unused)))
|
||||||
|
: SignalSourceBase(configuration, role, "Custom_UDP_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
// DUMP PARAMETERS
|
// DUMP PARAMETERS
|
||||||
const std::string default_dump_file("./data/signal_source.dat");
|
const std::string default_dump_file("./data/signal_source.dat");
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
#define GNSS_SDR_CUSTOM_UDP_SIGNAL_SOURCE_H
|
#define GNSS_SDR_CUSTOM_UDP_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
|
||||||
#include "gr_complex_ip_packet_source.h"
|
#include "gr_complex_ip_packet_source.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gnuradio/blocks/null_sink.h>
|
#include <gnuradio/blocks/null_sink.h>
|
||||||
#include <pmt/pmt.h>
|
#include <pmt/pmt.h>
|
||||||
@ -40,7 +40,7 @@ class ConfigurationInterface;
|
|||||||
* \brief This class reads from UDP packets, which streams interleaved
|
* \brief This class reads from UDP packets, which streams interleaved
|
||||||
* I/Q samples over a network.
|
* I/Q samples over a network.
|
||||||
*/
|
*/
|
||||||
class CustomUDPSignalSource : public GNSSBlockInterface
|
class CustomUDPSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CustomUDPSignalSource(const ConfigurationInterface* configuration,
|
CustomUDPSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -49,19 +49,6 @@ public:
|
|||||||
|
|
||||||
~CustomUDPSignalSource() = default;
|
~CustomUDPSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Custom_UDP_Signal_Source"
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Custom_UDP_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -78,7 +65,6 @@ private:
|
|||||||
std::vector<gnss_shared_ptr<gr::block>> null_sinks_;
|
std::vector<gnss_shared_ptr<gr::block>> null_sinks_;
|
||||||
std::vector<gnss_shared_ptr<gr::block>> file_sink_;
|
std::vector<gnss_shared_ptr<gr::block>> file_sink_;
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
|
|
||||||
|
@ -10,343 +10,29 @@
|
|||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is part of GNSS-SDR.
|
* This file is part of GNSS-SDR.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "file_signal_source.h"
|
#include "file_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_flags.h"
|
|
||||||
#include "gnss_sdr_valve.h"
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <exception>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream> // for std::cerr
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
FileSignalSource::FileSignalSource(const ConfigurationInterface* configuration,
|
FileSignalSource::FileSignalSource(ConfigurationInterface const* configuration,
|
||||||
const std::string& role, unsigned int in_streams, unsigned int out_streams,
|
std::string const& role, unsigned int in_streams, unsigned int out_streams,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: FileSourceBase(configuration, role, "File_Signal_Source"s, queue, "short"s)
|
||||||
{
|
{
|
||||||
const std::string default_filename("./example_capture.dat");
|
if (in_streams > 0)
|
||||||
const std::string default_item_type("short");
|
|
||||||
const std::string default_dump_filename("./my_capture.dat");
|
|
||||||
|
|
||||||
const double default_seconds_to_skip = 0.0;
|
|
||||||
|
|
||||||
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
|
|
||||||
sampling_frequency_ = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(0));
|
|
||||||
filename_ = configuration->property(role + ".filename", default_filename);
|
|
||||||
|
|
||||||
// override value with commandline flag, if present
|
|
||||||
if (FLAGS_signal_source != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_signal_source;
|
|
||||||
}
|
|
||||||
if (FLAGS_s != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_s;
|
|
||||||
}
|
|
||||||
|
|
||||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
|
||||||
repeat_ = configuration->property(role + ".repeat", false);
|
|
||||||
dump_ = configuration->property(role + ".dump", false);
|
|
||||||
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
|
|
||||||
enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false);
|
|
||||||
|
|
||||||
const double seconds_to_skip = configuration->property(role + ".seconds_to_skip", default_seconds_to_skip);
|
|
||||||
const size_t header_size = configuration->property(role + ".header_size", 0);
|
|
||||||
int64_t samples_to_skip = 0;
|
|
||||||
|
|
||||||
bool is_complex = false;
|
|
||||||
|
|
||||||
if (item_type_ == "gr_complex")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(gr_complex);
|
|
||||||
}
|
|
||||||
else if (item_type_ == "float")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(float);
|
|
||||||
}
|
|
||||||
else if (item_type_ == "short")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(int16_t);
|
|
||||||
}
|
|
||||||
else if (item_type_ == "ishort")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(int16_t);
|
|
||||||
is_complex = true;
|
|
||||||
}
|
|
||||||
else if (item_type_ == "byte")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(int8_t);
|
|
||||||
}
|
|
||||||
else if (item_type_ == "ibyte")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(int8_t);
|
|
||||||
is_complex = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(WARNING) << item_type_
|
|
||||||
<< " unrecognized item type. Using gr_complex.";
|
|
||||||
item_size_ = sizeof(gr_complex);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
file_source_ = gr::blocks::file_source::make(item_size_, filename_.c_str(), repeat_);
|
|
||||||
|
|
||||||
if (seconds_to_skip > 0)
|
|
||||||
{
|
|
||||||
samples_to_skip = static_cast<int64_t>(seconds_to_skip * sampling_frequency_);
|
|
||||||
|
|
||||||
if (is_complex)
|
|
||||||
{
|
|
||||||
samples_to_skip *= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (header_size > 0)
|
|
||||||
{
|
|
||||||
samples_to_skip += header_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samples_to_skip > 0)
|
|
||||||
{
|
|
||||||
LOG(INFO) << "Skipping " << samples_to_skip << " samples of the input file";
|
|
||||||
if (not file_source_->seek(samples_to_skip, SEEK_SET))
|
|
||||||
{
|
|
||||||
LOG(INFO) << "Error skipping bytes!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
if (filename_ == default_filename)
|
|
||||||
{
|
|
||||||
std::cerr
|
|
||||||
<< "The configuration file has not been found.\n"
|
|
||||||
<< "Please create a configuration file based on the examples at the 'conf/' folder\n"
|
|
||||||
<< "and then generate your own GNSS Software Defined Receiver by doing:\n"
|
|
||||||
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr
|
|
||||||
<< "The receiver was configured to work with a file signal source\n"
|
|
||||||
<< "but the specified file is unreachable by GNSS-SDR.\n"
|
|
||||||
<< "Please modify your configuration file\n"
|
|
||||||
<< "and point SignalSource.filename to a valid raw data file. Then:\n"
|
|
||||||
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n"
|
|
||||||
<< "Examples of configuration files available at:\n"
|
|
||||||
<< GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "file_signal_source: Unable to open the samples file "
|
|
||||||
<< filename_.c_str() << ", exiting the program.";
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
DLOG(INFO) << "file_source(" << file_source_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (samples_ == 0) // read all file
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
* BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File.
|
|
||||||
* A possible solution is to compute the file length in samples using file size, excluding the last 100 milliseconds, and enable always the
|
|
||||||
* valve block
|
|
||||||
*/
|
|
||||||
std::ifstream file(filename_.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
|
|
||||||
std::ifstream::pos_type size;
|
|
||||||
|
|
||||||
if (file.is_open())
|
|
||||||
{
|
|
||||||
size = file.tellg();
|
|
||||||
DLOG(INFO) << "Total samples in the file= " << floor(static_cast<double>(size) / static_cast<double>(item_size_));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "file_signal_source: Unable to open the samples file " << filename_.c_str() << '\n';
|
|
||||||
LOG(ERROR) << "file_signal_source: Unable to open the samples file " << filename_.c_str();
|
|
||||||
}
|
|
||||||
std::streamsize ss = std::cout.precision();
|
|
||||||
std::cout << std::setprecision(16);
|
|
||||||
std::cout << "Processing file " << filename_ << ", which contains " << static_cast<double>(size) << " [bytes]\n";
|
|
||||||
std::cout.precision(ss);
|
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
const int64_t bytes_to_skip = samples_to_skip * item_size_;
|
|
||||||
const int64_t bytes_to_process = static_cast<int64_t>(size) - bytes_to_skip;
|
|
||||||
samples_ = floor(static_cast<double>(bytes_to_process) / static_cast<double>(item_size_) - ceil(0.002 * static_cast<double>(sampling_frequency_))); // process all the samples available in the file excluding at least the last 1 ms
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(samples_ > 0) << "File does not contain enough samples to process.";
|
|
||||||
double signal_duration_s = static_cast<double>(samples_) * (1 / static_cast<double>(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";
|
|
||||||
|
|
||||||
valve_ = gnss_sdr_make_valve(item_size_, samples_, queue);
|
|
||||||
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str());
|
|
||||||
DLOG(INFO) << "file_sink(" << sink_->unique_id() << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable_throttle_control_)
|
|
||||||
{
|
|
||||||
throttle_ = gr::blocks::throttle::make(item_size_, sampling_frequency_);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_;
|
|
||||||
if (in_streams_ > 0)
|
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "A signal source does not have an input stream";
|
LOG(ERROR) << "A signal source does not have an input stream";
|
||||||
}
|
}
|
||||||
if (out_streams_ > 1)
|
if (out_streams > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one output stream";
|
LOG(ERROR) << "This implementation only supports one output stream";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FileSignalSource::connect(gr::top_block_sptr top_block)
|
|
||||||
{
|
|
||||||
if (samples_ > 0)
|
|
||||||
{
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to throttle";
|
|
||||||
top_block->connect(throttle_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected throttle to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to throttle";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FileSignalSource::disconnect(gr::top_block_sptr top_block)
|
|
||||||
{
|
|
||||||
if (samples_ > 0)
|
|
||||||
{
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to throttle";
|
|
||||||
top_block->disconnect(throttle_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected throttle to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to throttle";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gr::basic_block_sptr FileSignalSource::get_left_block()
|
|
||||||
{
|
|
||||||
LOG(WARNING) << "Left block of a signal source should not be retrieved";
|
|
||||||
return gr::blocks::file_source::sptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gr::basic_block_sptr FileSignalSource::get_right_block()
|
|
||||||
{
|
|
||||||
if (samples_ > 0)
|
|
||||||
{
|
|
||||||
return valve_;
|
|
||||||
}
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
return throttle_;
|
|
||||||
}
|
|
||||||
return file_source_;
|
|
||||||
}
|
|
||||||
|
@ -21,15 +21,7 @@
|
|||||||
#ifndef GNSS_SDR_FILE_SIGNAL_SOURCE_H
|
#ifndef GNSS_SDR_FILE_SIGNAL_SOURCE_H
|
||||||
#define GNSS_SDR_FILE_SIGNAL_SOURCE_H
|
#define GNSS_SDR_FILE_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "file_source_base.h"
|
||||||
#include "gnss_block_interface.h"
|
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
|
||||||
#include <gnuradio/blocks/file_source.h>
|
|
||||||
#include <gnuradio/blocks/throttle.h>
|
|
||||||
#include <gnuradio/hier_block2.h>
|
|
||||||
#include <pmt/pmt.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/** \addtogroup Signal_Source Signal Source
|
/** \addtogroup Signal_Source Signal Source
|
||||||
* Classes for Signal Source management.
|
* Classes for Signal Source management.
|
||||||
@ -45,84 +37,16 @@ class ConfigurationInterface;
|
|||||||
* \brief Class that reads signals samples from a file
|
* \brief Class that reads signals samples from a file
|
||||||
* and adapts it to a SignalSourceInterface
|
* and adapts it to a SignalSourceInterface
|
||||||
*/
|
*/
|
||||||
class FileSignalSource : public GNSSBlockInterface
|
class FileSignalSource : public FileSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
FileSignalSource(ConfigurationInterface const* configuration, std::string const& role,
|
||||||
unsigned int in_streams, unsigned int out_streams,
|
unsigned int in_streams, unsigned int out_streams,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue);
|
Concurrent_Queue<pmt::pmt_t>* queue);
|
||||||
|
|
||||||
~FileSignalSource() = default;
|
~FileSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "File_Signal_Source".
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "File_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
|
||||||
{
|
|
||||||
return item_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
inline std::string filename() const
|
|
||||||
{
|
|
||||||
return filename_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string item_type() const
|
|
||||||
{
|
|
||||||
return item_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool repeat() const
|
|
||||||
{
|
|
||||||
return repeat_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t sampling_frequency() const
|
|
||||||
{
|
|
||||||
return sampling_frequency_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t samples() const
|
|
||||||
{
|
|
||||||
return samples_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gr::blocks::file_source::sptr file_source_;
|
|
||||||
gnss_shared_ptr<gr::block> valve_;
|
|
||||||
gr::blocks::file_sink::sptr sink_;
|
|
||||||
gr::blocks::throttle::sptr throttle_;
|
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
|
||||||
std::string filename_;
|
|
||||||
std::string dump_filename_;
|
|
||||||
|
|
||||||
uint64_t samples_;
|
|
||||||
int64_t sampling_frequency_;
|
|
||||||
size_t item_size_;
|
|
||||||
|
|
||||||
uint32_t in_streams_;
|
|
||||||
uint32_t out_streams_;
|
|
||||||
|
|
||||||
bool enable_throttle_control_;
|
|
||||||
bool repeat_;
|
|
||||||
bool dump_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
506
src/algorithms/signal_source/adapters/file_source_base.cc
Normal file
506
src/algorithms/signal_source/adapters/file_source_base.cc
Normal file
@ -0,0 +1,506 @@
|
|||||||
|
/*!
|
||||||
|
* \file file_source_base.cc
|
||||||
|
* \brief Implementation of the base class for file-oriented signal_source GNSS blocks
|
||||||
|
* \author Jim Melton, 2021. jim.melton(at)sncorp.com
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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 "file_source_base.h"
|
||||||
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_filesystem.h"
|
||||||
|
#include "gnss_sdr_flags.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
|
#include "gnss_sdr_valve.h"
|
||||||
|
#include <glog/logging.h>
|
||||||
|
#include <cmath> // ceil, floor
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility> // move
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std::string const& role, std::string impl,
|
||||||
|
Concurrent_Queue<pmt::pmt_t>* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
auto output = gr::basic_block_sptr();
|
||||||
|
|
||||||
|
// THROTTLE
|
||||||
|
if (throttle())
|
||||||
|
{
|
||||||
|
// if we are throttling...
|
||||||
|
top_block->connect(source(), 0, throttle(), 0);
|
||||||
|
DLOG(INFO) << "connected file source to throttle";
|
||||||
|
|
||||||
|
input = throttle();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no throttle; let 'er rip
|
||||||
|
input = source();
|
||||||
|
}
|
||||||
|
|
||||||
|
// VALVE
|
||||||
|
if (valve())
|
||||||
|
{
|
||||||
|
top_block->connect(input, 0, valve(), 0);
|
||||||
|
DLOG(INFO) << "connected source to valve";
|
||||||
|
|
||||||
|
output = valve();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: dumping a file source is unlikely, but should this be the raw file source or the
|
||||||
|
// throttle if there is one? I'm leaning towards "output=input"
|
||||||
|
output = source(); // output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DUMP
|
||||||
|
if (sink())
|
||||||
|
{
|
||||||
|
top_block->connect(output, 0, sink(), 0);
|
||||||
|
DLOG(INFO) << "connected output to file sink";
|
||||||
|
}
|
||||||
|
|
||||||
|
post_connect_hook(top_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FileSourceBase::disconnect(gr::top_block_sptr top_block)
|
||||||
|
{
|
||||||
|
auto input = gr::basic_block_sptr();
|
||||||
|
auto output = gr::basic_block_sptr();
|
||||||
|
|
||||||
|
pre_disconnect_hook(top_block);
|
||||||
|
|
||||||
|
// THROTTLE
|
||||||
|
if (throttle())
|
||||||
|
{
|
||||||
|
// if we are throttling...
|
||||||
|
top_block->disconnect(source(), 0, throttle(), 0);
|
||||||
|
DLOG(INFO) << "disconnected file source from throttle";
|
||||||
|
|
||||||
|
input = throttle();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no throttle; let 'er rip
|
||||||
|
input = source();
|
||||||
|
}
|
||||||
|
|
||||||
|
// VALVE
|
||||||
|
if (valve())
|
||||||
|
{
|
||||||
|
top_block->disconnect(input, 0, valve(), 0);
|
||||||
|
DLOG(INFO) << "disconnected source to valve";
|
||||||
|
|
||||||
|
output = valve();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: dumping a file source is unlikely, but should this be the raw file source or the
|
||||||
|
// throttle if there is one? I'm leaning towards "output=input"
|
||||||
|
output = source(); // output = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DUMP
|
||||||
|
if (sink())
|
||||||
|
{
|
||||||
|
top_block->disconnect(output, 0, sink(), 0);
|
||||||
|
DLOG(INFO) << "disconnected output to file sink";
|
||||||
|
}
|
||||||
|
|
||||||
|
post_disconnect_hook(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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 (valve_) { return valve_; }
|
||||||
|
if (throttle_) { return throttle_; }
|
||||||
|
return source();
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::tuple<size_t, bool> FileSourceBase::itemTypeToSize()
|
||||||
|
{
|
||||||
|
auto is_complex_t = false;
|
||||||
|
auto item_size = size_t(0);
|
||||||
|
|
||||||
|
if (item_type_ == "gr_complex")
|
||||||
|
{
|
||||||
|
item_size = sizeof(gr_complex);
|
||||||
|
}
|
||||||
|
else if (item_type_ == "float")
|
||||||
|
{
|
||||||
|
item_size = sizeof(float);
|
||||||
|
}
|
||||||
|
else if (item_type_ == "short")
|
||||||
|
{
|
||||||
|
item_size = sizeof(int16_t);
|
||||||
|
}
|
||||||
|
else if (item_type_ == "ishort")
|
||||||
|
{
|
||||||
|
item_size = sizeof(int16_t);
|
||||||
|
is_complex_t = true;
|
||||||
|
}
|
||||||
|
else if (item_type_ == "byte")
|
||||||
|
{
|
||||||
|
item_size = sizeof(int8_t);
|
||||||
|
}
|
||||||
|
else if (item_type_ == "ibyte")
|
||||||
|
{
|
||||||
|
item_size = sizeof(int8_t);
|
||||||
|
is_complex_t = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(WARNING) << item_type_
|
||||||
|
<< " unrecognized item type. Using gr_complex.";
|
||||||
|
item_size = sizeof(gr_complex);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (seconds_to_skip_ > 0)
|
||||||
|
{
|
||||||
|
// sampling_frequency is in terms of actual samples (output packets). If this source is
|
||||||
|
// compressed, there may be multiple packets per file (read) sample. First compute the
|
||||||
|
// actual number of samples to skip (function of time and sample rate)
|
||||||
|
samples_to_skip = static_cast<size_t>(seconds_to_skip_ * sampling_frequency_);
|
||||||
|
|
||||||
|
// convert from sample to input items, scaling this value to input item space
|
||||||
|
// (rounding up)
|
||||||
|
samples_to_skip = std::ceil(samples_to_skip / packetsPerSample());
|
||||||
|
|
||||||
|
// complex inputs require two input items for one sample (arguably, packetsPerSample could be scaled by 0.5)
|
||||||
|
if (is_complex())
|
||||||
|
{
|
||||||
|
samples_to_skip *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header_size_ > 0)
|
||||||
|
{
|
||||||
|
samples_to_skip += header_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// this could throw, but the existence of the file has been proven before we get here.
|
||||||
|
auto size = fs::file_size(filename());
|
||||||
|
|
||||||
|
// if there is some kind of compression/encoding, figure out the uncompressed number of samples
|
||||||
|
n_samples = std::floor(packetsPerSample() * size / item_size());
|
||||||
|
|
||||||
|
auto to_skip = samplesToSkip();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File.
|
||||||
|
* A possible solution is to compute the file length in samples using file size, excluding at least
|
||||||
|
* the last 2 milliseconds, and enable always the valve block
|
||||||
|
*/
|
||||||
|
auto tail = static_cast<size_t>(std::ceil(0.002 * sampling_frequency()));
|
||||||
|
|
||||||
|
DLOG(INFO) << "Total samples in the file= " << n_samples;
|
||||||
|
std::cout << "Processing file " << filename() << ", which contains " << n_samples << " samples (" << size << " bytes)\n";
|
||||||
|
|
||||||
|
if (n_samples > (to_skip + tail))
|
||||||
|
{
|
||||||
|
// process all the samples available in the file excluding up to the last 2 ms
|
||||||
|
n_samples -= to_skip + tail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this will terminate the program
|
||||||
|
LOG(FATAL) << "Skipping " << to_skip << " samples from the front and truncating 2ms (" << tail << " samples)\n"
|
||||||
|
<< "is greater than the number of samples in the file (" << n_samples << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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<gr::block> FileSourceBase::source() const { return file_source(); }
|
||||||
|
gnss_shared_ptr<gr::block> FileSourceBase::file_source() const { return file_source_; }
|
||||||
|
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_; }
|
||||||
|
|
||||||
|
|
||||||
|
gr::blocks::file_source::sptr FileSourceBase::create_file_source()
|
||||||
|
{
|
||||||
|
auto item_tuple = itemTypeToSize();
|
||||||
|
item_size_ = std::get<0>(item_tuple);
|
||||||
|
is_complex_ = std::get<1>(item_tuple);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO: why are we manually seeking, instead of passing the samples_to_skip to the file_source factory?
|
||||||
|
auto samples_to_skip = samplesToSkip();
|
||||||
|
|
||||||
|
file_source_ = gr::blocks::file_source::make(item_size(), filename().data(), repeat());
|
||||||
|
|
||||||
|
if (samples_to_skip > 0)
|
||||||
|
{
|
||||||
|
LOG(INFO) << "Skipping " << samples_to_skip << " samples of the input file";
|
||||||
|
if (not file_source_->seek(samples_to_skip, SEEK_SET))
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "Error skipping bytes!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr
|
||||||
|
<< "The receiver was configured to work with a file-based signal source\n"
|
||||||
|
<< "but the specified file is unreachable by GNSS-SDR.\n"
|
||||||
|
<< "[" << filename() << "]\n"
|
||||||
|
<< "\n"
|
||||||
|
<< "Please modify your configuration file\n"
|
||||||
|
<< "and point SignalSource.filename to a valid raw data file. Then:\n"
|
||||||
|
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n"
|
||||||
|
<< "Examples of configuration files available at:\n"
|
||||||
|
<< GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/\n"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
LOG(ERROR) << "file_signal_source: Unable to open the samples file "
|
||||||
|
<< filename() << ", exiting the program.";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
DLOG(INFO) << implementation() << "(" << file_source_->unique_id() << ")";
|
||||||
|
|
||||||
|
// enable subclass hooks
|
||||||
|
create_file_source_hook();
|
||||||
|
|
||||||
|
return file_source_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gr::blocks::throttle::sptr FileSourceBase::create_throttle()
|
||||||
|
{
|
||||||
|
if (enable_throttle_control_)
|
||||||
|
{
|
||||||
|
// if we are throttling...
|
||||||
|
throttle_ = gr::blocks::throttle::make(source_item_size(), sampling_frequency());
|
||||||
|
DLOG(INFO) << "throttle(" << throttle_->unique_id() << ")";
|
||||||
|
|
||||||
|
// enable subclass hooks
|
||||||
|
create_throttle_hook();
|
||||||
|
}
|
||||||
|
return throttle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gnss_shared_ptr<gr::block> FileSourceBase::create_valve()
|
||||||
|
{
|
||||||
|
if (samples() > 0)
|
||||||
|
{
|
||||||
|
// if a number of samples is specified, honor it by creating a valve
|
||||||
|
// In practice, this is always true
|
||||||
|
valve_ = gnss_sdr_make_valve(source_item_size(), samples(), queue_);
|
||||||
|
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
|
||||||
|
|
||||||
|
// enable subclass hooks
|
||||||
|
create_valve_hook();
|
||||||
|
}
|
||||||
|
return valve_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gr::blocks::file_sink::sptr FileSourceBase::create_sink()
|
||||||
|
{
|
||||||
|
if (dump_)
|
||||||
|
{
|
||||||
|
sink_ = gr::blocks::file_sink::make(source_item_size(), dump_filename_.c_str());
|
||||||
|
DLOG(INFO) << "file_sink(" << sink_->unique_id() << ")";
|
||||||
|
|
||||||
|
// enable subclass hooks
|
||||||
|
create_sink_hook();
|
||||||
|
}
|
||||||
|
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]]) {}
|
||||||
|
void FileSourceBase::pre_disconnect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {}
|
||||||
|
void FileSourceBase::post_disconnect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {}
|
186
src/algorithms/signal_source/adapters/file_source_base.h
Normal file
186
src/algorithms/signal_source/adapters/file_source_base.h
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*!
|
||||||
|
* \file file_source_base.h
|
||||||
|
* \brief Header file of the base class to file-oriented signal_source GNSS blocks.
|
||||||
|
* \author Jim Melton, 2021. jim.melton(at)sncorp.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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_FILE_SOURCE_BASE_H
|
||||||
|
#define GNSS_SDR_FILE_SOURCE_BASE_H
|
||||||
|
|
||||||
|
#include "concurrent_queue.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
|
#include <gnuradio/blocks/file_source.h>
|
||||||
|
#include <gnuradio/blocks/throttle.h>
|
||||||
|
#include <pmt/pmt.h>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
// for dump
|
||||||
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigurationInterface;
|
||||||
|
|
||||||
|
|
||||||
|
//! \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
|
||||||
|
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
|
||||||
|
std::string filename() const;
|
||||||
|
|
||||||
|
//! The item type
|
||||||
|
std::string item_type() const;
|
||||||
|
|
||||||
|
//! 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
|
||||||
|
int64_t sampling_frequency() const;
|
||||||
|
|
||||||
|
//! The number of samples in the file
|
||||||
|
uint64_t samples() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! \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<pmt::pmt_t>* queue,
|
||||||
|
std::string default_item_type = "short");
|
||||||
|
|
||||||
|
//! Perform post-construction initialization
|
||||||
|
void init();
|
||||||
|
|
||||||
|
//! 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<size_t, bool> itemTypeToSize();
|
||||||
|
|
||||||
|
//! The number of (possibly unpacked) samples in a (raw) file sample (default=1)
|
||||||
|
virtual double packetsPerSample() const;
|
||||||
|
|
||||||
|
//! Compute the number of samples to skip
|
||||||
|
virtual size_t samplesToSkip() const;
|
||||||
|
|
||||||
|
//! 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
|
||||||
|
//! decode source files into a usable format
|
||||||
|
virtual gnss_shared_ptr<gr::block> source() const;
|
||||||
|
|
||||||
|
//! 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
|
||||||
|
gnss_shared_ptr<gr::block> file_source() const;
|
||||||
|
gnss_shared_ptr<gr::block> valve() const;
|
||||||
|
gnss_shared_ptr<gr::block> throttle() const;
|
||||||
|
gnss_shared_ptr<gr::block> sink() const;
|
||||||
|
|
||||||
|
// The methods create the various blocks, if enabled, and return access to them. The created
|
||||||
|
// object is also held in this class
|
||||||
|
gr::blocks::file_source::sptr create_file_source();
|
||||||
|
gr::blocks::throttle::sptr create_throttle();
|
||||||
|
gnss_shared_ptr<gr::block> create_valve();
|
||||||
|
gr::blocks::file_sink::sptr create_sink();
|
||||||
|
|
||||||
|
// Subclass hooks to augment created objects, as required
|
||||||
|
virtual void create_file_source_hook();
|
||||||
|
virtual void create_throttle_hook();
|
||||||
|
virtual void create_valve_hook();
|
||||||
|
virtual void create_sink_hook();
|
||||||
|
|
||||||
|
// Subclass hooks for connection/disconnection
|
||||||
|
virtual void pre_connect_hook(gr::top_block_sptr top_block);
|
||||||
|
virtual void post_connect_hook(gr::top_block_sptr top_block);
|
||||||
|
virtual void pre_disconnect_hook(gr::top_block_sptr top_block);
|
||||||
|
virtual void post_disconnect_hook(gr::top_block_sptr top_block);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string filename_;
|
||||||
|
gr::blocks::file_source::sptr file_source_;
|
||||||
|
|
||||||
|
std::string item_type_;
|
||||||
|
size_t item_size_;
|
||||||
|
bool is_complex_; // a misnomer; if I/Q are interleaved as integer values
|
||||||
|
|
||||||
|
size_t header_size_; // length (in samples) of the header (if any)
|
||||||
|
double seconds_to_skip_;
|
||||||
|
bool repeat_;
|
||||||
|
|
||||||
|
// The valve allows only the configured number of samples through, then it closes.
|
||||||
|
|
||||||
|
// The framework passes the queue as a naked pointer, rather than a shared pointer, so this
|
||||||
|
// class has two choices: construct the valve in the ctor, or hold onto the pointer, possibly
|
||||||
|
// beyond its lifetime. Fortunately, the queue is only used to create the valve, so the
|
||||||
|
// likelihood of holding a stale pointer is mitigated
|
||||||
|
uint64_t samples_;
|
||||||
|
int64_t sampling_frequency_; // why is this signed
|
||||||
|
gnss_shared_ptr<gr::block> valve_;
|
||||||
|
Concurrent_Queue<pmt::pmt_t>* queue_;
|
||||||
|
|
||||||
|
bool enable_throttle_control_;
|
||||||
|
gr::blocks::throttle::sptr throttle_;
|
||||||
|
|
||||||
|
bool dump_;
|
||||||
|
std::string dump_filename_;
|
||||||
|
gr::blocks::file_sink::sptr sink_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -18,17 +18,21 @@
|
|||||||
|
|
||||||
#include "flexiband_signal_source.h"
|
#include "flexiband_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <teleorbit/frontend.h>
|
#include <teleorbit/frontend.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
|
||||||
FlexibandSignalSource::FlexibandSignalSource(const ConfigurationInterface* configuration,
|
FlexibandSignalSource::FlexibandSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role,
|
const std::string& role,
|
||||||
unsigned int in_stream,
|
unsigned int in_stream,
|
||||||
unsigned int out_stream,
|
unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue __attribute__((unused))) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
Concurrent_Queue<pmt::pmt_t>* queue __attribute__((unused)))
|
||||||
|
: SignalSourceBase(configuration, role, "Flexiband_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
const std::string default_item_type("byte");
|
const std::string default_item_type("byte");
|
||||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#define GNSS_SDR_FLEXIBAND_SIGNAL_SOURCE_H
|
#define GNSS_SDR_FLEXIBAND_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/char_to_float.h>
|
#include <gnuradio/blocks/char_to_float.h>
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gnuradio/blocks/float_to_complex.h>
|
#include <gnuradio/blocks/float_to_complex.h>
|
||||||
@ -45,7 +45,7 @@ class ConfigurationInterface;
|
|||||||
* \brief This class configures and reads samples from Teleorbit Flexiband front-end.
|
* \brief This class configures and reads samples from Teleorbit Flexiband front-end.
|
||||||
* This software requires a Flexiband GNU Radio driver installed (not included with GNSS-SDR).
|
* This software requires a Flexiband GNU Radio driver installed (not included with GNSS-SDR).
|
||||||
*/
|
*/
|
||||||
class FlexibandSignalSource : public GNSSBlockInterface
|
class FlexibandSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FlexibandSignalSource(const ConfigurationInterface* configuration,
|
FlexibandSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -54,19 +54,6 @@ public:
|
|||||||
|
|
||||||
~FlexibandSignalSource() = default;
|
~FlexibandSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Flexiband_Signal_Source".
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Flexiband_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -85,7 +72,6 @@ private:
|
|||||||
std::vector<boost::shared_ptr<gr::block>> float_to_complex_;
|
std::vector<boost::shared_ptr<gr::block>> float_to_complex_;
|
||||||
std::vector<gr::blocks::null_sink::sptr> null_sinks_;
|
std::vector<gr::blocks::null_sink::sptr> null_sinks_;
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string firmware_filename_;
|
std::string firmware_filename_;
|
||||||
std::string signal_file;
|
std::string signal_file;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "ad9361_manager.h"
|
#include "ad9361_manager.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
#include "gnss_sdr_flags.h"
|
#include "gnss_sdr_flags.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_valve.h"
|
#include "gnss_sdr_valve.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <algorithm> // for max
|
#include <algorithm> // for max
|
||||||
@ -29,10 +30,12 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
Fmcomms2SignalSource::Fmcomms2SignalSource(const ConfigurationInterface *configuration,
|
Fmcomms2SignalSource::Fmcomms2SignalSource(const ConfigurationInterface *configuration,
|
||||||
const std::string &role, unsigned int in_stream, unsigned int out_stream,
|
const std::string &role, unsigned int in_stream, unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t> *queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
Concurrent_Queue<pmt::pmt_t> *queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Fmcomms2_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
const std::string default_item_type("gr_complex");
|
const std::string default_item_type("gr_complex");
|
||||||
const std::string default_dump_file("./data/signal_source.dat");
|
const std::string default_dump_file("./data/signal_source.dat");
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#ifndef GNSS_SDR_FMCOMMS2_SIGNAL_SOURCE_H
|
#ifndef GNSS_SDR_FMCOMMS2_SIGNAL_SOURCE_H
|
||||||
#define GNSS_SDR_FMCOMMS2_SIGNAL_SOURCE_H
|
#define GNSS_SDR_FMCOMMS2_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "gnss_block_interface.h"
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#if GRIIO_INCLUDE_HAS_GNURADIO
|
#if GRIIO_INCLUDE_HAS_GNURADIO
|
||||||
#include <gnuradio/iio/fmcomms2_source.h>
|
#include <gnuradio/iio/fmcomms2_source.h>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
class ConfigurationInterface;
|
class ConfigurationInterface;
|
||||||
|
|
||||||
class Fmcomms2SignalSource : public GNSSBlockInterface
|
class Fmcomms2SignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Fmcomms2SignalSource(const ConfigurationInterface* configuration,
|
Fmcomms2SignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -50,19 +50,6 @@ public:
|
|||||||
|
|
||||||
~Fmcomms2SignalSource();
|
~Fmcomms2SignalSource();
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Fmcomms2_Signal_Source"
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Fmcomms2_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -78,7 +65,6 @@ private:
|
|||||||
gnss_shared_ptr<gr::block> valve_;
|
gnss_shared_ptr<gr::block> valve_;
|
||||||
gr::blocks::file_sink::sptr file_sink_;
|
gr::blocks::file_sink::sptr file_sink_;
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "gnss_block_interface.h"
|
||||||
|
#include "signal_source_interface.h"
|
||||||
#include <pmt/pmt.h>
|
#include <pmt/pmt.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -37,16 +38,13 @@
|
|||||||
* \brief This class wraps blocks that generates synthesized GNSS signal and
|
* \brief This class wraps blocks that generates synthesized GNSS signal and
|
||||||
* filters the signal.
|
* filters the signal.
|
||||||
*/
|
*/
|
||||||
class GenSignalSource : public GNSSBlockInterface
|
class GenSignalSource : public SignalSourceInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! Constructor
|
//! Constructor
|
||||||
GenSignalSource(std::shared_ptr<GNSSBlockInterface> signal_generator, std::shared_ptr<GNSSBlockInterface> filter,
|
GenSignalSource(std::shared_ptr<GNSSBlockInterface> signal_generator, std::shared_ptr<GNSSBlockInterface> filter,
|
||||||
std::string role, Concurrent_Queue<pmt::pmt_t> *queue);
|
std::string role, Concurrent_Queue<pmt::pmt_t> *queue);
|
||||||
|
|
||||||
//! Virtual destructor
|
|
||||||
virtual ~GenSignalSource() = default;
|
|
||||||
|
|
||||||
void connect(gr::top_block_sptr top_block) override;
|
void connect(gr::top_block_sptr top_block) override;
|
||||||
void disconnect(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_left_block() override;
|
||||||
@ -56,6 +54,8 @@ public:
|
|||||||
//! Returns "Signal Source"
|
//! Returns "Signal Source"
|
||||||
inline std::string implementation() override { return "Signal Source"; }
|
inline std::string implementation() override { return "Signal Source"; }
|
||||||
inline size_t item_size() override { return 0; }
|
inline size_t item_size() override { return 0; }
|
||||||
|
inline size_t getRfChannels() const final { return 0; }
|
||||||
|
|
||||||
inline std::shared_ptr<GNSSBlockInterface> signal_generator() const { return signal_generator_; }
|
inline std::shared_ptr<GNSSBlockInterface> signal_generator() const { return signal_generator_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -16,16 +16,20 @@
|
|||||||
|
|
||||||
#include "gn3s_signal_source.h"
|
#include "gn3s_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gn3s/gn3s_source_cc.h>
|
#include <gn3s/gn3s_source_cc.h>
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
|
||||||
Gn3sSignalSource::Gn3sSignalSource(const ConfigurationInterface* configuration,
|
Gn3sSignalSource::Gn3sSignalSource(const ConfigurationInterface* configuration,
|
||||||
std::string role,
|
std::string role,
|
||||||
unsigned int in_stream,
|
unsigned int in_stream,
|
||||||
unsigned int out_stream,
|
unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Gn3s_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
const std::string default_item_type("short");
|
const std::string default_item_type("short");
|
||||||
const std::string default_dump_file("./data/gn3s_source.dat");
|
const std::string default_dump_file("./data/gn3s_source.dat");
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#define GNSS_SDR_GN3S_SIGNAL_SOURCE_H
|
#define GNSS_SDR_GN3S_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gnuradio/hier_block2.h>
|
#include <gnuradio/hier_block2.h>
|
||||||
#include <pmt/pmt.h>
|
#include <pmt/pmt.h>
|
||||||
@ -38,7 +38,7 @@ class ConfigurationInterface;
|
|||||||
/*!
|
/*!
|
||||||
* \brief This class reads samples from a GN3S USB dongle, a RF front-end signal sampler
|
* \brief This class reads samples from a GN3S USB dongle, a RF front-end signal sampler
|
||||||
*/
|
*/
|
||||||
class Gn3sSignalSource : public GNSSBlockInterface
|
class Gn3sSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Gn3sSignalSource(const ConfigurationInterface* configuration,
|
Gn3sSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -47,19 +47,6 @@ public:
|
|||||||
|
|
||||||
~Gn3sSignalSource() = default;
|
~Gn3sSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Gn3s_Signal_Source".
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Gn3s_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -73,11 +60,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
gr::block_sptr gn3s_source_;
|
gr::block_sptr gn3s_source_;
|
||||||
gr::blocks::file_sink::sptr file_sink_;
|
gr::blocks::file_sink::sptr file_sink_;
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
int64_t samples_;
|
[[maybe_unused]] int64_t samples_;
|
||||||
unsigned int in_stream_;
|
unsigned int in_stream_;
|
||||||
unsigned int out_stream_;
|
unsigned int out_stream_;
|
||||||
bool dump_;
|
bool dump_;
|
||||||
|
@ -16,14 +16,15 @@
|
|||||||
|
|
||||||
#include "labsat_signal_source.h"
|
#include "labsat_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "labsat23_source.h"
|
#include "labsat23_source.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <cstdint>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
LabsatSignalSource::LabsatSignalSource(const ConfigurationInterface* configuration,
|
LabsatSignalSource::LabsatSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, unsigned int in_stream, unsigned int out_stream, Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
const std::string& role, unsigned int in_stream, unsigned int out_stream, Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Labsat_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
const std::string default_item_type("gr_complex");
|
const std::string default_item_type("gr_complex");
|
||||||
const std::string default_dump_file("./labsat_output.dat");
|
const std::string default_dump_file("./labsat_output.dat");
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "gnss_block_interface.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gnuradio/blocks/throttle.h>
|
#include <gnuradio/blocks/throttle.h>
|
||||||
#include <gnuradio/hier_block2.h>
|
#include <gnuradio/hier_block2.h>
|
||||||
@ -38,7 +39,7 @@ class ConfigurationInterface;
|
|||||||
/*!
|
/*!
|
||||||
* \brief This class reads samples stored by a LabSat 2 or LabSat 3 device
|
* \brief This class reads samples stored by a LabSat 2 or LabSat 3 device
|
||||||
*/
|
*/
|
||||||
class LabsatSignalSource : public GNSSBlockInterface
|
class LabsatSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LabsatSignalSource(const ConfigurationInterface* configuration,
|
LabsatSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -47,19 +48,6 @@ public:
|
|||||||
|
|
||||||
~LabsatSignalSource() = default;
|
~LabsatSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Labsat_Signal_Source".
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Labsat_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -75,7 +63,6 @@ private:
|
|||||||
gr::blocks::file_sink::sptr file_sink_;
|
gr::blocks::file_sink::sptr file_sink_;
|
||||||
gr::blocks::throttle::sptr throttle_;
|
gr::blocks::throttle::sptr throttle_;
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string filename_;
|
std::string filename_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "multichannel_file_signal_source.h"
|
#include "multichannel_file_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
#include "gnss_sdr_flags.h"
|
#include "gnss_sdr_flags.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_valve.h"
|
#include "gnss_sdr_valve.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@ -27,18 +28,21 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
MultichannelFileSignalSource::MultichannelFileSignalSource(const ConfigurationInterface* configuration,
|
MultichannelFileSignalSource::MultichannelFileSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, unsigned int in_streams, unsigned int out_streams,
|
const std::string& role, unsigned int in_streams, unsigned int out_streams,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Multichannel_File_Signal_Source"s), in_streams_(in_streams), out_streams_(out_streams)
|
||||||
{
|
{
|
||||||
const std::string default_filename("./example_capture.dat");
|
const std::string default_filename("./example_capture.dat"s);
|
||||||
const std::string default_item_type("short");
|
const std::string default_item_type("short"s);
|
||||||
const std::string default_dump_filename("./my_capture.dat");
|
const std::string default_dump_filename("./my_capture.dat"s);
|
||||||
|
|
||||||
const double default_seconds_to_skip = 0.0;
|
const double default_seconds_to_skip = 0.0;
|
||||||
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
|
samples_ = configuration->property(role + ".samples"s, static_cast<uint64_t>(0));
|
||||||
sampling_frequency_ = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(0));
|
sampling_frequency_ = configuration->property(role + ".sampling_frequency"s, static_cast<int64_t>(0));
|
||||||
n_channels_ = configuration->property(role + ".total_channels", 1);
|
n_channels_ = configuration->property(role + ".total_channels"s, 1);
|
||||||
|
|
||||||
for (int32_t n = 0; n < n_channels_; n++)
|
for (int32_t n = 0; n < n_channels_; n++)
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "gnss_block_interface.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gnuradio/blocks/file_source.h>
|
#include <gnuradio/blocks/file_source.h>
|
||||||
#include <gnuradio/blocks/throttle.h>
|
#include <gnuradio/blocks/throttle.h>
|
||||||
@ -45,7 +46,7 @@ class ConfigurationInterface;
|
|||||||
* \brief Class that reads signals samples from files at different frequency bands
|
* \brief Class that reads signals samples from files at different frequency bands
|
||||||
* and adapts it to a SignalSourceInterface
|
* and adapts it to a SignalSourceInterface
|
||||||
*/
|
*/
|
||||||
class MultichannelFileSignalSource : public GNSSBlockInterface
|
class MultichannelFileSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MultichannelFileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
MultichannelFileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
||||||
@ -54,19 +55,6 @@ public:
|
|||||||
|
|
||||||
~MultichannelFileSignalSource() = default;
|
~MultichannelFileSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Multichannel_File_Signal_Source".
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Multichannel_File_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -109,7 +97,6 @@ private:
|
|||||||
std::vector<gr::blocks::throttle::sptr> throttle_vec_;
|
std::vector<gr::blocks::throttle::sptr> throttle_vec_;
|
||||||
std::vector<std::string> filename_vec_;
|
std::vector<std::string> filename_vec_;
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string role_;
|
|
||||||
uint64_t samples_;
|
uint64_t samples_;
|
||||||
int64_t sampling_frequency_;
|
int64_t sampling_frequency_;
|
||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
|
@ -10,286 +10,69 @@
|
|||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is part of GNSS-SDR.
|
* This file is part of GNSS-SDR.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsr_file_signal_source.h"
|
#include "nsr_file_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_flags.h"
|
|
||||||
#include "gnss_sdr_valve.h"
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <exception>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
NsrFileSignalSource::NsrFileSignalSource(const ConfigurationInterface* configuration,
|
NsrFileSignalSource::NsrFileSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, unsigned int in_streams, unsigned int out_streams,
|
const std::string& role, unsigned int in_streams, unsigned int out_streams,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: FileSourceBase(configuration, role, "Nsr_File_Signal_Source"s, queue, "byte"s)
|
||||||
{
|
{
|
||||||
const std::string default_filename("../data/my_capture.dat");
|
if (in_streams > 0)
|
||||||
const std::string default_item_type("byte");
|
|
||||||
const std::string default_dump_filename("../data/my_capture_dump.dat");
|
|
||||||
|
|
||||||
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
|
|
||||||
sampling_frequency_ = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(0));
|
|
||||||
filename_ = configuration->property(role + ".filename", default_filename);
|
|
||||||
|
|
||||||
// override value with commandline flag, if present
|
|
||||||
if (FLAGS_signal_source != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_signal_source;
|
|
||||||
}
|
|
||||||
if (FLAGS_s != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_s;
|
|
||||||
}
|
|
||||||
|
|
||||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
|
||||||
repeat_ = configuration->property(role + ".repeat", false);
|
|
||||||
dump_ = configuration->property(role + ".dump", false);
|
|
||||||
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
|
|
||||||
enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false);
|
|
||||||
|
|
||||||
if (item_type_ == "byte")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(char);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(WARNING) << item_type_ << " unrecognized item type. Using byte.";
|
|
||||||
item_size_ = sizeof(char);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
file_source_ = gr::blocks::file_source::make(item_size_, filename_.c_str(), repeat_);
|
|
||||||
unpack_byte_ = make_unpack_byte_2bit_samples();
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr
|
|
||||||
<< "The receiver was configured to work with a file signal source\n"
|
|
||||||
<< "but the specified file is unreachable by GNSS-SDR.\n"
|
|
||||||
<< "Please modify your configuration file\n"
|
|
||||||
<< "and point SignalSource.filename to a valid raw data file. Then:\n"
|
|
||||||
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n"
|
|
||||||
<< "Examples of configuration files available at:\n"
|
|
||||||
<< GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/\n";
|
|
||||||
|
|
||||||
LOG(WARNING) << "file_signal_source: Unable to open the samples file "
|
|
||||||
<< filename_.c_str() << ", exiting the program.";
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
DLOG(INFO) << "file_source(" << file_source_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (samples_ == 0) // read all file
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
* BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File.
|
|
||||||
* A possible solution is to compute the file length in samples using file size, excluding the last 2 milliseconds, and enable always the
|
|
||||||
* valve block
|
|
||||||
*/
|
|
||||||
std::ifstream file(filename_.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
|
|
||||||
std::ifstream::pos_type size;
|
|
||||||
|
|
||||||
if (file.is_open())
|
|
||||||
{
|
|
||||||
size = file.tellg();
|
|
||||||
LOG(INFO) << "Total samples in the file= " << floor(static_cast<double>(size) / static_cast<double>(item_size()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "file_signal_source: Unable to open the samples file " << filename_.c_str() << '\n';
|
|
||||||
LOG(ERROR) << "file_signal_source: Unable to open the samples file " << filename_.c_str();
|
|
||||||
}
|
|
||||||
std::streamsize ss = std::cout.precision();
|
|
||||||
std::cout << std::setprecision(16);
|
|
||||||
std::cout << "Processing file " << filename_ << ", which contains " << size << " [bytes]\n";
|
|
||||||
std::cout.precision(ss);
|
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
int sample_packet_factor = 4; // 1 byte -> 4 samples
|
|
||||||
samples_ = floor(static_cast<double>(size) / static_cast<double>(item_size())) * sample_packet_factor;
|
|
||||||
samples_ = samples_ - ceil(0.002 * static_cast<double>(sampling_frequency_)); // process all the samples available in the file excluding the last 2 ms
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(samples_ > 0) << "File does not contain enough samples to process.";
|
|
||||||
const double signal_duration_s = static_cast<double>(samples_) * (1 / static_cast<double>(sampling_frequency_));
|
|
||||||
LOG(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";
|
|
||||||
|
|
||||||
valve_ = gnss_sdr_make_valve(sizeof(float), samples_, queue);
|
|
||||||
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
// sink_ = gr_make_file_sink(item_size_, dump_filename_.c_str());
|
|
||||||
sink_ = gr::blocks::file_sink::make(sizeof(float), dump_filename_.c_str());
|
|
||||||
DLOG(INFO) << "file_sink(" << sink_->unique_id() << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable_throttle_control_)
|
|
||||||
{
|
|
||||||
throttle_ = gr::blocks::throttle::make(sizeof(float), sampling_frequency_);
|
|
||||||
}
|
|
||||||
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_;
|
|
||||||
if (in_streams_ > 0)
|
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "A signal source does not have an input stream";
|
LOG(ERROR) << "A signal source does not have an input stream";
|
||||||
}
|
}
|
||||||
if (out_streams_ > 1)
|
if (out_streams > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one output stream";
|
LOG(ERROR) << "This implementation only supports one output stream";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::tuple<size_t, bool> NsrFileSignalSource::itemTypeToSize()
|
||||||
void NsrFileSignalSource::connect(gr::top_block_sptr top_block)
|
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
auto is_complex = false;
|
||||||
|
auto item_size = size_t(sizeof(char)); // default
|
||||||
|
|
||||||
|
if (item_type() == "byte")
|
||||||
{
|
{
|
||||||
if (enable_throttle_control_ == true)
|
item_size = sizeof(char);
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
top_block->connect(unpack_byte_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to throttle";
|
|
||||||
top_block->connect(throttle_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected throttle to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
top_block->connect(unpack_byte_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (enable_throttle_control_ == true)
|
LOG(WARNING) << item_type() << " unrecognized item type. Using byte.";
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
top_block->connect(unpack_byte_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to throttle";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(throttle_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
top_block->connect(unpack_byte_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return std::make_tuple(item_size, is_complex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1 byte -> 4 samples
|
||||||
|
double NsrFileSignalSource::packetsPerSample() const { return 4.0; }
|
||||||
|
gnss_shared_ptr<gr::block> NsrFileSignalSource::source() const { return unpack_byte_; }
|
||||||
|
|
||||||
void NsrFileSignalSource::disconnect(gr::top_block_sptr top_block)
|
|
||||||
|
void NsrFileSignalSource::create_file_source_hook()
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
unpack_byte_ = make_unpack_byte_2bit_samples();
|
||||||
{
|
DLOG(INFO) << "unpack_byte_2bit_samples(" << unpack_byte_->unique_id() << ")";
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_byte_";
|
|
||||||
top_block->connect(unpack_byte_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_byte_ to throttle_";
|
|
||||||
top_block->disconnect(throttle_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected throttle to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_byte_";
|
|
||||||
top_block->disconnect(unpack_byte_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_byte_ to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_byte_";
|
|
||||||
top_block->disconnect(unpack_byte_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_byte_ to throttle";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(unpack_byte_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected funpack_byte_ to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_byte_";
|
|
||||||
top_block->disconnect(unpack_byte_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_byte_ to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NsrFileSignalSource::pre_connect_hook(gr::top_block_sptr top_block)
|
||||||
gr::basic_block_sptr NsrFileSignalSource::get_left_block()
|
|
||||||
{
|
{
|
||||||
LOG(WARNING) << "Left block of a signal source should not be retrieved";
|
top_block->connect(file_source(), 0, unpack_byte_, 0);
|
||||||
// return gr_block_sptr();
|
DLOG(INFO) << "connected file_source to unpacker";
|
||||||
return gr::blocks::file_source::sptr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NsrFileSignalSource::pre_disconnect_hook(gr::top_block_sptr top_block)
|
||||||
gr::basic_block_sptr NsrFileSignalSource::get_right_block()
|
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
top_block->disconnect(file_source(), 0, unpack_byte_, 0);
|
||||||
{
|
DLOG(INFO) << "disconnected file_source from unpacker";
|
||||||
return valve_;
|
|
||||||
}
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
return throttle_;
|
|
||||||
}
|
|
||||||
return unpack_byte_;
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is part of GNSS-SDR.
|
* This file is part of GNSS-SDR.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
@ -21,15 +21,8 @@
|
|||||||
#ifndef GNSS_SDR_NSR_FILE_SIGNAL_SOURCE_H
|
#ifndef GNSS_SDR_NSR_FILE_SIGNAL_SOURCE_H
|
||||||
#define GNSS_SDR_NSR_FILE_SIGNAL_SOURCE_H
|
#define GNSS_SDR_NSR_FILE_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "file_source_base.h"
|
||||||
#include "gnss_block_interface.h"
|
|
||||||
#include "unpack_byte_2bit_samples.h"
|
#include "unpack_byte_2bit_samples.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
|
||||||
#include <gnuradio/blocks/file_source.h>
|
|
||||||
#include <gnuradio/blocks/throttle.h>
|
|
||||||
#include <gnuradio/hier_block2.h>
|
|
||||||
#include <pmt/pmt.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/** \addtogroup Signal_Source
|
/** \addtogroup Signal_Source
|
||||||
* \{ */
|
* \{ */
|
||||||
@ -42,7 +35,7 @@ class ConfigurationInterface;
|
|||||||
* \brief Class that reads signals samples from a file
|
* \brief Class that reads signals samples from a file
|
||||||
* and adapts it to a SignalSourceInterface
|
* and adapts it to a SignalSourceInterface
|
||||||
*/
|
*/
|
||||||
class NsrFileSignalSource : public GNSSBlockInterface
|
class NsrFileSignalSource : public FileSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NsrFileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
NsrFileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
||||||
@ -50,73 +43,17 @@ public:
|
|||||||
Concurrent_Queue<pmt::pmt_t>* queue);
|
Concurrent_Queue<pmt::pmt_t>* queue);
|
||||||
|
|
||||||
~NsrFileSignalSource() = default;
|
~NsrFileSignalSource() = default;
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
protected:
|
||||||
* \brief Returns "Nsr_File_Signal_Source".
|
std::tuple<size_t, bool> itemTypeToSize() override;
|
||||||
*/
|
double packetsPerSample() const override;
|
||||||
inline std::string implementation() override
|
gnss_shared_ptr<gr::block> source() const override;
|
||||||
{
|
void create_file_source_hook() override;
|
||||||
return "Nsr_File_Signal_Source";
|
void pre_connect_hook(gr::top_block_sptr top_block) override;
|
||||||
}
|
void pre_disconnect_hook(gr::top_block_sptr top_block) override;
|
||||||
|
|
||||||
inline size_t item_size() override
|
|
||||||
{
|
|
||||||
return item_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
inline std::string filename() const
|
|
||||||
{
|
|
||||||
return filename_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string item_type() const
|
|
||||||
{
|
|
||||||
return item_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool repeat() const
|
|
||||||
{
|
|
||||||
return repeat_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t sampling_frequency() const
|
|
||||||
{
|
|
||||||
return sampling_frequency_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t samples() const
|
|
||||||
{
|
|
||||||
return samples_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gr::blocks::file_source::sptr file_source_;
|
|
||||||
unpack_byte_2bit_samples_sptr unpack_byte_;
|
unpack_byte_2bit_samples_sptr unpack_byte_;
|
||||||
gnss_shared_ptr<gr::block> valve_;
|
|
||||||
gr::blocks::file_sink::sptr sink_;
|
|
||||||
gr::blocks::throttle::sptr throttle_;
|
|
||||||
uint64_t samples_;
|
|
||||||
int64_t sampling_frequency_;
|
|
||||||
size_t item_size_;
|
|
||||||
std::string filename_;
|
|
||||||
std::string item_type_;
|
|
||||||
std::string dump_filename_;
|
|
||||||
std::string role_;
|
|
||||||
uint32_t in_streams_;
|
|
||||||
uint32_t out_streams_;
|
|
||||||
bool repeat_;
|
|
||||||
bool dump_;
|
|
||||||
// Throttle control
|
|
||||||
bool enable_throttle_control_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "osmosdr_signal_source.h"
|
#include "osmosdr_signal_source.h"
|
||||||
#include "GPS_L1_CA.h"
|
#include "GPS_L1_CA.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_valve.h"
|
#include "gnss_sdr_valve.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
@ -25,9 +26,13 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
|
||||||
OsmosdrSignalSource::OsmosdrSignalSource(const ConfigurationInterface* configuration,
|
OsmosdrSignalSource::OsmosdrSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, unsigned int in_stream, unsigned int out_stream,
|
const std::string& role, unsigned int in_stream, unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Osmosdr_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
// DUMP PARAMETERS
|
// DUMP PARAMETERS
|
||||||
const std::string empty;
|
const std::string empty;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#define GNSS_SDR_OSMOSDR_SIGNAL_SOURCE_H
|
#define GNSS_SDR_OSMOSDR_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <pmt/pmt.h>
|
#include <pmt/pmt.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -42,7 +42,7 @@ class ConfigurationInterface;
|
|||||||
* HackRF or Realtek's RTL2832U-based USB dongle DVB-T receivers
|
* HackRF or Realtek's RTL2832U-based USB dongle DVB-T receivers
|
||||||
* (see https://osmocom.org/projects/rtl-sdr/wiki)
|
* (see https://osmocom.org/projects/rtl-sdr/wiki)
|
||||||
*/
|
*/
|
||||||
class OsmosdrSignalSource : public GNSSBlockInterface
|
class OsmosdrSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OsmosdrSignalSource(const ConfigurationInterface* configuration,
|
OsmosdrSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -51,19 +51,6 @@ public:
|
|||||||
|
|
||||||
~OsmosdrSignalSource() = default;
|
~OsmosdrSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Osmosdr_Signal_Source"
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Osmosdr_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -81,7 +68,6 @@ private:
|
|||||||
gnss_shared_ptr<gr::block> valve_;
|
gnss_shared_ptr<gr::block> valve_;
|
||||||
gr::blocks::file_sink::sptr file_sink_;
|
gr::blocks::file_sink::sptr file_sink_;
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
std::string osmosdr_args_;
|
std::string osmosdr_args_;
|
||||||
|
@ -18,15 +18,20 @@
|
|||||||
#include "plutosdr_signal_source.h"
|
#include "plutosdr_signal_source.h"
|
||||||
#include "GPS_L1_CA.h"
|
#include "GPS_L1_CA.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_valve.h"
|
#include "gnss_sdr_valve.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
|
||||||
PlutosdrSignalSource::PlutosdrSignalSource(const ConfigurationInterface* configuration,
|
PlutosdrSignalSource::PlutosdrSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, unsigned int in_stream, unsigned int out_stream,
|
const std::string& role, unsigned int in_stream, unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Plutosdr_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
const std::string default_item_type("gr_complex");
|
const std::string default_item_type("gr_complex");
|
||||||
const std::string default_dump_file("./data/signal_source.dat");
|
const std::string default_dump_file("./data/signal_source.dat");
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#ifndef GNSS_SDR_PLUTOSDR_SIGNAL_SOURCE_H
|
#ifndef GNSS_SDR_PLUTOSDR_SIGNAL_SOURCE_H
|
||||||
#define GNSS_SDR_PLUTOSDR_SIGNAL_SOURCE_H
|
#define GNSS_SDR_PLUTOSDR_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "gnss_block_interface.h"
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#if GRIIO_INCLUDE_HAS_GNURADIO
|
#if GRIIO_INCLUDE_HAS_GNURADIO
|
||||||
#include <gnuradio/iio/pluto_source.h>
|
#include <gnuradio/iio/pluto_source.h>
|
||||||
@ -42,7 +42,7 @@ class ConfigurationInterface;
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
*/
|
*/
|
||||||
class PlutosdrSignalSource : public GNSSBlockInterface
|
class PlutosdrSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PlutosdrSignalSource(const ConfigurationInterface* configuration,
|
PlutosdrSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -51,18 +51,6 @@ public:
|
|||||||
|
|
||||||
~PlutosdrSignalSource() = default;
|
~PlutosdrSignalSource() = default;
|
||||||
|
|
||||||
std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Plutosdr_Signal_Source"
|
|
||||||
*/
|
|
||||||
std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Plutosdr_Signal_Source";
|
|
||||||
}
|
|
||||||
size_t item_size() override
|
size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -79,7 +67,6 @@ private:
|
|||||||
gnss_shared_ptr<gr::block> valve_;
|
gnss_shared_ptr<gr::block> valve_;
|
||||||
gr::blocks::file_sink::sptr file_sink_;
|
gr::blocks::file_sink::sptr file_sink_;
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
|
|
||||||
// Front-end settings
|
// Front-end settings
|
||||||
|
@ -17,14 +17,18 @@
|
|||||||
#include "raw_array_signal_source.h"
|
#include "raw_array_signal_source.h"
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <pmt/pmt.h>
|
#include <pmt/pmt.h>
|
||||||
#include <dbfcttc/raw_array.h>
|
#include <dbfcttc/raw_array.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
RawArraySignalSource::RawArraySignalSource(const ConfigurationInterface* configuration,
|
RawArraySignalSource::RawArraySignalSource(const ConfigurationInterface* configuration,
|
||||||
std::string role, unsigned int in_stream, unsigned int out_stream, Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
std::string role, unsigned int in_stream, unsigned int out_stream, Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Raw_Array_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
const std::string default_item_type("gr_complex");
|
const std::string default_item_type("gr_complex");
|
||||||
const std::string default_dump_file("./data/raw_array_source.dat");
|
const std::string default_dump_file("./data/raw_array_source.dat");
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#define GNSS_SDR_RAW_ARRAY_SIGNAL_SOURCE_H
|
#define GNSS_SDR_RAW_ARRAY_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gnuradio/hier_block2.h>
|
#include <gnuradio/hier_block2.h>
|
||||||
#include <pmt/pmt.h>
|
#include <pmt/pmt.h>
|
||||||
@ -39,7 +39,7 @@ class ConfigurationInterface;
|
|||||||
/*!
|
/*!
|
||||||
* \brief This class reads samples from a GN3S USB dongle, a RF front-end signal sampler
|
* \brief This class reads samples from a GN3S USB dongle, a RF front-end signal sampler
|
||||||
*/
|
*/
|
||||||
class RawArraySignalSource : public GNSSBlockInterface
|
class RawArraySignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RawArraySignalSource(const ConfigurationInterface* configuration,
|
RawArraySignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -48,19 +48,6 @@ public:
|
|||||||
|
|
||||||
~RawArraySignalSource() = default;
|
~RawArraySignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "RawArraySignalSource".
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Raw_Array_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -74,12 +61,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
gr::block_sptr raw_array_source_;
|
gr::block_sptr raw_array_source_;
|
||||||
gr::blocks::file_sink::sptr file_sink_;
|
gr::blocks::file_sink::sptr file_sink_;
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
std::string eth_device_;
|
std::string eth_device_;
|
||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
int64_t samples_;
|
[[maybe_unused]] int64_t samples_;
|
||||||
unsigned int in_stream_;
|
unsigned int in_stream_;
|
||||||
unsigned int out_stream_;
|
unsigned int out_stream_;
|
||||||
bool dump_;
|
bool dump_;
|
||||||
|
@ -19,20 +19,21 @@
|
|||||||
#include "rtl_tcp_signal_source.h"
|
#include "rtl_tcp_signal_source.h"
|
||||||
#include "GPS_L1_CA.h"
|
#include "GPS_L1_CA.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_valve.h"
|
#include "gnss_sdr_valve.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
RtlTcpSignalSource::RtlTcpSignalSource(const ConfigurationInterface* configuration,
|
RtlTcpSignalSource::RtlTcpSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role,
|
const std::string& role,
|
||||||
unsigned int in_stream,
|
unsigned int in_stream,
|
||||||
unsigned int out_stream,
|
unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role),
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
in_stream_(in_stream),
|
: SignalSourceBase(configuration, role, "RtlTcp_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
out_stream_(out_stream)
|
|
||||||
{
|
{
|
||||||
// DUMP PARAMETERS
|
// DUMP PARAMETERS
|
||||||
const std::string default_dump_file("./data/signal_source.dat");
|
const std::string default_dump_file("./data/signal_source.dat");
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
#define GNSS_SDR_RTL_TCP_SIGNAL_SOURCE_H
|
#define GNSS_SDR_RTL_TCP_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
|
||||||
#include "rtl_tcp_signal_source_c.h"
|
#include "rtl_tcp_signal_source_c.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/deinterleave.h>
|
#include <gnuradio/blocks/deinterleave.h>
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gnuradio/blocks/float_to_complex.h>
|
#include <gnuradio/blocks/float_to_complex.h>
|
||||||
@ -42,7 +42,7 @@ class ConfigurationInterface;
|
|||||||
* I/Q samples over TCP.
|
* I/Q samples over TCP.
|
||||||
* (see https://osmocom.org/projects/rtl-sdr/wiki)
|
* (see https://osmocom.org/projects/rtl-sdr/wiki)
|
||||||
*/
|
*/
|
||||||
class RtlTcpSignalSource : public GNSSBlockInterface
|
class RtlTcpSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RtlTcpSignalSource(const ConfigurationInterface* configuration,
|
RtlTcpSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -53,19 +53,6 @@ public:
|
|||||||
|
|
||||||
~RtlTcpSignalSource() = default;
|
~RtlTcpSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "RtlTcp_Signal_Source"
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "RtlTcp_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -84,7 +71,6 @@ private:
|
|||||||
gnss_shared_ptr<gr::block> valve_;
|
gnss_shared_ptr<gr::block> valve_;
|
||||||
gr::blocks::file_sink::sptr file_sink_;
|
gr::blocks::file_sink::sptr file_sink_;
|
||||||
|
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
|
|
||||||
|
46
src/algorithms/signal_source/adapters/signal_source_base.cc
Normal file
46
src/algorithms/signal_source/adapters/signal_source_base.cc
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*!
|
||||||
|
* \file signal_source_base.cc
|
||||||
|
* \brief Base class for signal sources
|
||||||
|
* \author Jim Melton, 2020. jim.melton(at)sncorp.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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 "signal_source_base.h"
|
||||||
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
|
#include <utility> // move
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
std::string SignalSourceBase::role()
|
||||||
|
{
|
||||||
|
return role_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SignalSourceBase::implementation()
|
||||||
|
{
|
||||||
|
return implementation_;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SignalSourceBase::getRfChannels() const
|
||||||
|
{
|
||||||
|
return rfChannels_;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalSourceBase::SignalSourceBase(ConfigurationInterface const* configuration, std::string role, std::string impl)
|
||||||
|
: role_(std::move(role)), implementation_(std::move(impl))
|
||||||
|
{
|
||||||
|
// because clang-tidy insists on using std::move for the string arguments, and to avoid
|
||||||
|
// depending on the order of initialization, assign rfChannels_ in the body
|
||||||
|
rfChannels_ = configuration->property(role_ + ".RF_channels"s, uint64_t(1U));
|
||||||
|
}
|
47
src/algorithms/signal_source/adapters/signal_source_base.h
Normal file
47
src/algorithms/signal_source/adapters/signal_source_base.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*!
|
||||||
|
* \file signal_source_base.h
|
||||||
|
* \brief Header file of the base class to signal_source GNSS blocks.
|
||||||
|
* \author Jim Melton, 2020. jim.melton(at)sncorp.com
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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_SIGNAL_SOURCE_BASE_H
|
||||||
|
#define GNSS_SDR_SIGNAL_SOURCE_BASE_H
|
||||||
|
|
||||||
|
#include "signal_source_interface.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigurationInterface;
|
||||||
|
|
||||||
|
class SignalSourceBase : public SignalSourceInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string role() final;
|
||||||
|
std::string implementation() final;
|
||||||
|
|
||||||
|
size_t getRfChannels() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! Constructor
|
||||||
|
SignalSourceBase(ConfigurationInterface const* configuration, std::string role, std::string impl);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string const role_;
|
||||||
|
std::string const implementation_;
|
||||||
|
size_t rfChannels_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -6,290 +6,74 @@
|
|||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
|
||||||
*
|
|
||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is not part of GNSS-SDR.
|
* 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
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "spir_file_signal_source.h"
|
#include "spir_file_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_flags.h"
|
|
||||||
#include "gnss_sdr_valve.h"
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <exception>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
SpirFileSignalSource::SpirFileSignalSource(const ConfigurationInterface* configuration,
|
SpirFileSignalSource::SpirFileSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, unsigned int in_streams, unsigned int out_streams,
|
const std::string& role, unsigned int in_streams, unsigned int out_streams,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: FileSourceBase(configuration, role, "Spir_File_Signal_Source"s, queue, "int"s)
|
||||||
{
|
{
|
||||||
const std::string default_filename("../data/my_capture.dat");
|
if (in_streams > 0)
|
||||||
const std::string default_item_type("int");
|
|
||||||
const std::string default_dump_filename("../data/my_capture_dump.dat");
|
|
||||||
|
|
||||||
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
|
|
||||||
sampling_frequency_ = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(0));
|
|
||||||
filename_ = configuration->property(role + ".filename", default_filename);
|
|
||||||
|
|
||||||
// override value with commandline flag, if present
|
|
||||||
if (FLAGS_signal_source != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_signal_source;
|
|
||||||
}
|
|
||||||
if (FLAGS_s != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_s;
|
|
||||||
}
|
|
||||||
|
|
||||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
|
||||||
repeat_ = configuration->property(role + ".repeat", false);
|
|
||||||
dump_ = configuration->property(role + ".dump", false);
|
|
||||||
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
|
|
||||||
enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false);
|
|
||||||
|
|
||||||
if (item_type_ == "int")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(int);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(WARNING) << item_type_ << " unrecognized item type. Using int.";
|
|
||||||
item_size_ = sizeof(int);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
file_source_ = gr::blocks::file_source::make(item_size_, filename_.c_str(), repeat_);
|
|
||||||
unpack_intspir_ = make_unpack_intspir_1bit_samples();
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr
|
|
||||||
<< "The receiver was configured to work with a file signal source\n"
|
|
||||||
<< "but the specified file is unreachable by GNSS-SDR.\n"
|
|
||||||
<< "Please modify your configuration file\n"
|
|
||||||
<< "and point SignalSource.filename to a valid raw data file. Then:\n"
|
|
||||||
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n"
|
|
||||||
<< "Examples of configuration files available at:\n"
|
|
||||||
<< GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/\n";
|
|
||||||
|
|
||||||
LOG(WARNING) << "file_signal_source: Unable to open the samples file "
|
|
||||||
<< filename_.c_str() << ", exiting the program.";
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
DLOG(INFO) << "file_source(" << file_source_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (samples_ == 0) // read all file
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
* BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File.
|
|
||||||
* A possible solution is to compute the file length in samples using file size, excluding the last 100 milliseconds, and enable always the
|
|
||||||
* valve block
|
|
||||||
*/
|
|
||||||
std::ifstream file(filename_.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
|
|
||||||
std::ifstream::pos_type size;
|
|
||||||
|
|
||||||
if (file.is_open())
|
|
||||||
{
|
|
||||||
size = file.tellg();
|
|
||||||
LOG(INFO) << "Total samples in the file= " << floor(static_cast<double>(size) / static_cast<double>(item_size()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "file_signal_source: Unable to open the samples file " << filename_.c_str() << '\n';
|
|
||||||
LOG(ERROR) << "file_signal_source: Unable to open the samples file " << filename_.c_str();
|
|
||||||
}
|
|
||||||
std::streamsize ss = std::cout.precision();
|
|
||||||
std::cout << std::setprecision(16);
|
|
||||||
std::cout << "Processing file " << filename_ << ", which contains " << size << " [bytes]\n";
|
|
||||||
std::cout.precision(ss);
|
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
int sample_packet_factor = 1; // 1 int -> 1 complex sample (I&Q from 1 channel)
|
|
||||||
samples_ = floor(static_cast<double>(size) / static_cast<double>(item_size())) * sample_packet_factor;
|
|
||||||
samples_ = samples_ - ceil(0.002 * static_cast<double>(sampling_frequency_)); // process all the samples available in the file excluding the last 2 ms
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(samples_ > 0) << "File does not contain enough samples to process.";
|
|
||||||
double signal_duration_s = static_cast<double>(samples_) * (1 / static_cast<double>(sampling_frequency_));
|
|
||||||
LOG(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";
|
|
||||||
|
|
||||||
valve_ = gnss_sdr_make_valve(sizeof(float), samples_, queue);
|
|
||||||
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
// sink_ = gr_make_file_sink(item_size_, dump_filename_.c_str());
|
|
||||||
sink_ = gr::blocks::file_sink::make(sizeof(float), dump_filename_.c_str());
|
|
||||||
DLOG(INFO) << "file_sink(" << sink_->unique_id() << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable_throttle_control_)
|
|
||||||
{
|
|
||||||
throttle_ = gr::blocks::throttle::make(sizeof(float), sampling_frequency_);
|
|
||||||
}
|
|
||||||
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_;
|
|
||||||
if (in_streams_ > 0)
|
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "A signal source does not have an input stream";
|
LOG(ERROR) << "A signal source does not have an input stream";
|
||||||
}
|
}
|
||||||
if (out_streams_ > 1)
|
if (out_streams > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one output stream";
|
LOG(ERROR) << "This implementation only supports one output stream";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::tuple<size_t, bool> SpirFileSignalSource::itemTypeToSize()
|
||||||
void SpirFileSignalSource::connect(gr::top_block_sptr top_block)
|
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
auto is_complex = false;
|
||||||
|
auto item_size = size_t(0);
|
||||||
|
|
||||||
|
if (item_type() == "int")
|
||||||
{
|
{
|
||||||
if (enable_throttle_control_ == true)
|
item_size = sizeof(int);
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_intspir_, 0);
|
|
||||||
top_block->connect(unpack_intspir_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to throttle";
|
|
||||||
top_block->connect(throttle_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected throttle to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_intspir_, 0);
|
|
||||||
top_block->connect(unpack_intspir_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (enable_throttle_control_ == true)
|
LOG(WARNING) << item_type() << " unsupported item type. Using int.";
|
||||||
{
|
item_size = sizeof(int);
|
||||||
top_block->connect(file_source_, 0, unpack_intspir_, 0);
|
|
||||||
top_block->connect(unpack_intspir_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to throttle";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(throttle_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_intspir_, 0);
|
|
||||||
top_block->connect(unpack_intspir_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return std::make_tuple(item_size, is_complex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This class feeds the file data through a decoder to produce samples; for all intents this is the "source"
|
||||||
|
gnss_shared_ptr<gr::block> SpirFileSignalSource::source() const { return unpack_intspir_; }
|
||||||
|
|
||||||
void SpirFileSignalSource::disconnect(gr::top_block_sptr top_block)
|
|
||||||
|
void SpirFileSignalSource::create_file_source_hook()
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
// connect the file to the decoder
|
||||||
{
|
unpack_intspir_ = make_unpack_intspir_1bit_samples();
|
||||||
if (enable_throttle_control_ == true)
|
DLOG(INFO) << "unpack_intspir_1bit_samples(" << unpack_intspir_->unique_id() << ")";
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_intspir_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_intspir_";
|
|
||||||
top_block->connect(unpack_intspir_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_intspir_ to throttle_";
|
|
||||||
top_block->disconnect(throttle_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected throttle to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_intspir_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_intspir_";
|
|
||||||
top_block->disconnect(unpack_intspir_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_intspir_ to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_intspir_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_intspir_";
|
|
||||||
top_block->disconnect(unpack_intspir_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_intspir_ to throttle";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(unpack_intspir_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected funpack_intspir_ to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_intspir_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_intspir_";
|
|
||||||
top_block->disconnect(unpack_intspir_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_intspir_ to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpirFileSignalSource::pre_connect_hook(gr::top_block_sptr top_block)
|
||||||
gr::basic_block_sptr SpirFileSignalSource::get_left_block()
|
|
||||||
{
|
{
|
||||||
LOG(WARNING) << "Left block of a signal source should not be retrieved";
|
top_block->connect(file_source(), 0, unpack_intspir_, 0);
|
||||||
// return gr_block_sptr();
|
DLOG(INFO) << "connected file_source to unpacker";
|
||||||
return gr::blocks::file_source::sptr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpirFileSignalSource::post_disconnect_hook(gr::top_block_sptr top_block)
|
||||||
gr::basic_block_sptr SpirFileSignalSource::get_right_block()
|
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
top_block->disconnect(file_source(), 0, unpack_intspir_, 0);
|
||||||
{
|
DLOG(INFO) << "disconnected file_source from unpacker";
|
||||||
return valve_;
|
|
||||||
}
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
return throttle_;
|
|
||||||
}
|
|
||||||
return unpack_intspir_;
|
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,10 @@
|
|||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
*
|
* This file is part of GNSS-SDR.
|
||||||
* GNSS-SDR is a software defined Global Navigation
|
|
||||||
* Satellite Systems receiver
|
|
||||||
*
|
|
||||||
* This file is not part of GNSS-SDR.
|
|
||||||
*
|
*
|
||||||
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
@ -21,16 +18,8 @@
|
|||||||
#ifndef GNSS_SDR_SPIR_FILE_SIGNAL_SOURCE_H
|
#ifndef GNSS_SDR_SPIR_FILE_SIGNAL_SOURCE_H
|
||||||
#define GNSS_SDR_SPIR_FILE_SIGNAL_SOURCE_H
|
#define GNSS_SDR_SPIR_FILE_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "file_source_base.h"
|
||||||
#include "gnss_block_interface.h"
|
|
||||||
#include "unpack_intspir_1bit_samples.h"
|
#include "unpack_intspir_1bit_samples.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
|
||||||
#include <gnuradio/blocks/file_source.h>
|
|
||||||
#include <gnuradio/blocks/throttle.h>
|
|
||||||
#include <gnuradio/hier_block2.h>
|
|
||||||
#include <pmt/pmt.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
/** \addtogroup Signal_Source
|
/** \addtogroup Signal_Source
|
||||||
@ -45,7 +34,7 @@ class ConfigurationInterface;
|
|||||||
* \brief Class that reads signals samples from a file
|
* \brief Class that reads signals samples from a file
|
||||||
* and adapts it to a SignalSourceInterface
|
* and adapts it to a SignalSourceInterface
|
||||||
*/
|
*/
|
||||||
class SpirFileSignalSource : public GNSSBlockInterface
|
class SpirFileSignalSource : public FileSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpirFileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
SpirFileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
||||||
@ -54,77 +43,16 @@ public:
|
|||||||
|
|
||||||
~SpirFileSignalSource() = default;
|
~SpirFileSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
protected:
|
||||||
{
|
std::tuple<size_t, bool> itemTypeToSize() override;
|
||||||
return role_;
|
gnss_shared_ptr<gr::block> source() const override;
|
||||||
}
|
void create_file_source_hook() override;
|
||||||
|
void pre_connect_hook(gr::top_block_sptr top_block) override;
|
||||||
|
void post_disconnect_hook(gr::top_block_sptr top_block) override;
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Spir_File_Signal_Source".
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Spir_File_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
|
||||||
{
|
|
||||||
return item_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
inline std::string filename() const
|
|
||||||
{
|
|
||||||
return filename_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string item_type() const
|
|
||||||
{
|
|
||||||
return item_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool repeat() const
|
|
||||||
{
|
|
||||||
return repeat_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t sampling_frequency() const
|
|
||||||
{
|
|
||||||
return sampling_frequency_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t samples() const
|
|
||||||
{
|
|
||||||
return samples_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gr::blocks::file_source::sptr file_source_;
|
|
||||||
unpack_intspir_1bit_samples_sptr unpack_intspir_;
|
unpack_intspir_1bit_samples_sptr unpack_intspir_;
|
||||||
gnss_shared_ptr<gr::block> valve_;
|
|
||||||
gr::blocks::file_sink::sptr sink_;
|
|
||||||
gr::blocks::throttle::sptr throttle_;
|
|
||||||
std::string filename_;
|
|
||||||
std::string item_type_;
|
|
||||||
std::string dump_filename_;
|
|
||||||
std::string role_;
|
|
||||||
|
|
||||||
uint64_t samples_;
|
|
||||||
int64_t sampling_frequency_;
|
|
||||||
size_t item_size_;
|
|
||||||
|
|
||||||
unsigned int in_streams_;
|
|
||||||
unsigned int out_streams_;
|
|
||||||
|
|
||||||
bool repeat_;
|
|
||||||
bool dump_;
|
|
||||||
|
|
||||||
// Throttle control
|
|
||||||
bool enable_throttle_control_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "spir_gss6450_file_signal_source.h"
|
#include "spir_gss6450_file_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -25,9 +26,11 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
SpirGSS6450FileSignalSource::SpirGSS6450FileSignalSource(const ConfigurationInterface* configuration,
|
SpirGSS6450FileSignalSource::SpirGSS6450FileSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, uint32_t in_streams, uint32_t out_streams, Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
const std::string& role, uint32_t in_streams, uint32_t out_streams, Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Spir_GSS6450_File_Signal_Source"s), in_streams_(in_streams), out_streams_(out_streams)
|
||||||
{
|
{
|
||||||
const std::string default_filename("../data/my_capture.dat");
|
const std::string default_filename("../data/my_capture.dat");
|
||||||
const std::string default_dump_filename("../data/my_capture_dump.dat");
|
const std::string default_dump_filename("../data/my_capture_dump.dat");
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#define GNSS_SDR_SPIR_GSS6450_FILE_SIGNAL_SOURCE_H
|
#define GNSS_SDR_SPIR_GSS6450_FILE_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
|
||||||
#include "gnss_sdr_valve.h"
|
#include "gnss_sdr_valve.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
#include "unpack_spir_gss6450_samples.h"
|
#include "unpack_spir_gss6450_samples.h"
|
||||||
#include <gnuradio/blocks/deinterleave.h>
|
#include <gnuradio/blocks/deinterleave.h>
|
||||||
#include <gnuradio/blocks/endian_swap.h>
|
#include <gnuradio/blocks/endian_swap.h>
|
||||||
@ -50,23 +50,12 @@ class ConfigurationInterface;
|
|||||||
* \brief Class that reads signals samples from a file
|
* \brief Class that reads signals samples from a file
|
||||||
* and adapts it to a SignalSourceInterface
|
* and adapts it to a SignalSourceInterface
|
||||||
*/
|
*/
|
||||||
class SpirGSS6450FileSignalSource : public GNSSBlockInterface
|
class SpirGSS6450FileSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpirGSS6450FileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
SpirGSS6450FileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
||||||
uint32_t in_streams, uint32_t out_streams, Concurrent_Queue<pmt::pmt_t>* queue);
|
uint32_t in_streams, uint32_t out_streams, Concurrent_Queue<pmt::pmt_t>* queue);
|
||||||
|
|
||||||
~SpirGSS6450FileSignalSource() = default;
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Spir_GSS6450_File_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -114,7 +103,6 @@ private:
|
|||||||
std::vector<gr::blocks::throttle::sptr> throttle_vec_;
|
std::vector<gr::blocks::throttle::sptr> throttle_vec_;
|
||||||
std::string filename_;
|
std::string filename_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
std::string role_;
|
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
uint64_t samples_;
|
uint64_t samples_;
|
||||||
int64_t sampling_frequency_;
|
int64_t sampling_frequency_;
|
||||||
|
@ -9,296 +9,77 @@
|
|||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is part of GNSS-SDR.
|
* This file is part of GNSS-SDR.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "two_bit_cpx_file_signal_source.h"
|
#include "two_bit_cpx_file_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_flags.h"
|
|
||||||
#include "gnss_sdr_valve.h"
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <exception>
|
|
||||||
#include <fstream>
|
using namespace std::string_literals;
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
TwoBitCpxFileSignalSource::TwoBitCpxFileSignalSource(
|
TwoBitCpxFileSignalSource::TwoBitCpxFileSignalSource(
|
||||||
const ConfigurationInterface* configuration,
|
const ConfigurationInterface* configuration,
|
||||||
const std::string& role,
|
const std::string& role,
|
||||||
unsigned int in_streams,
|
unsigned int in_streams, unsigned int out_streams,
|
||||||
unsigned int out_streams,
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role),
|
: FileSourceBase(configuration, role, "Two_Bit_Cpx_File_Signal_Source"s, queue, "byte"s)
|
||||||
in_streams_(in_streams),
|
|
||||||
out_streams_(out_streams)
|
|
||||||
{
|
{
|
||||||
const std::string default_filename("../data/my_capture.dat");
|
if (in_streams > 0)
|
||||||
const std::string default_item_type("byte");
|
|
||||||
const std::string default_dump_filename("../data/my_capture_dump.dat");
|
|
||||||
|
|
||||||
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
|
|
||||||
sampling_frequency_ = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(0));
|
|
||||||
filename_ = configuration->property(role + ".filename", default_filename);
|
|
||||||
|
|
||||||
// override value with commandline flag, if present
|
|
||||||
if (FLAGS_signal_source != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_signal_source;
|
|
||||||
}
|
|
||||||
if (FLAGS_s != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_s;
|
|
||||||
}
|
|
||||||
|
|
||||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
|
||||||
repeat_ = configuration->property(role + ".repeat", false);
|
|
||||||
dump_ = configuration->property(role + ".dump", false);
|
|
||||||
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
|
|
||||||
enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false);
|
|
||||||
|
|
||||||
if (item_type_ == "byte")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(char);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(WARNING) << item_type_ << " unrecognized item type. Using byte.";
|
|
||||||
item_size_ = sizeof(char);
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
file_source_ = gr::blocks::file_source::make(item_size_, filename_.c_str(), repeat_);
|
|
||||||
unpack_byte_ = make_unpack_byte_2bit_cpx_samples();
|
|
||||||
inter_shorts_to_cpx_ = gr::blocks::interleaved_short_to_complex::make(false, true); // I/Q swap enabled
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr
|
|
||||||
<< "The receiver was configured to work with a file signal source\n"
|
|
||||||
<< "but the specified file is unreachable by GNSS-SDR.\n"
|
|
||||||
<< "Please modify your configuration file\n"
|
|
||||||
<< "and point SignalSource.filename to a valid raw data file. Then:\n"
|
|
||||||
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n"
|
|
||||||
<< "Examples of configuration files available at:\n"
|
|
||||||
<< GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/\n";
|
|
||||||
|
|
||||||
LOG(WARNING) << "file_signal_source: Unable to open the samples file "
|
|
||||||
<< filename_.c_str() << ", exiting the program.";
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
DLOG(INFO) << "file_source(" << file_source_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (samples_ == 0) // read all file
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
* BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File.
|
|
||||||
* A possible solution is to compute the file length in samples using file size, excluding the last 2 milliseconds, and enable always the
|
|
||||||
* valve block
|
|
||||||
*/
|
|
||||||
std::ifstream file(filename_.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
|
|
||||||
std::ifstream::pos_type size;
|
|
||||||
|
|
||||||
if (file.is_open())
|
|
||||||
{
|
|
||||||
size = file.tellg();
|
|
||||||
LOG(INFO) << "Total samples in the file= " << floor(static_cast<double>(size) / static_cast<double>(item_size()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "file_signal_source: Unable to open the samples file " << filename_.c_str() << '\n';
|
|
||||||
LOG(ERROR) << "file_signal_source: Unable to open the samples file " << filename_.c_str();
|
|
||||||
}
|
|
||||||
std::streamsize ss = std::cout.precision();
|
|
||||||
std::cout << std::setprecision(16);
|
|
||||||
std::cout << "Processing file " << filename_ << ", which contains " << size << " [bytes]\n";
|
|
||||||
std::cout.precision(ss);
|
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
int sample_packet_factor = 2; // 1 byte -> 2 samples
|
|
||||||
samples_ = floor(static_cast<double>(size) / static_cast<double>(item_size())) * sample_packet_factor;
|
|
||||||
samples_ = samples_ - ceil(0.002 * static_cast<double>(sampling_frequency_)); // process all the samples available in the file excluding the last 2 ms
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(samples_ > 0) << "File does not contain enough samples to process.";
|
|
||||||
const double signal_duration_s = static_cast<double>(samples_) * (1 / static_cast<double>(sampling_frequency_));
|
|
||||||
LOG(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";
|
|
||||||
|
|
||||||
valve_ = gnss_sdr_make_valve(sizeof(gr_complex), samples_, queue);
|
|
||||||
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
// sink_ = gr_make_file_sink(item_size_, dump_filename_.c_str());
|
|
||||||
sink_ = gr::blocks::file_sink::make(sizeof(gr_complex), dump_filename_.c_str());
|
|
||||||
DLOG(INFO) << "file_sink(" << sink_->unique_id() << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable_throttle_control_)
|
|
||||||
{
|
|
||||||
throttle_ = gr::blocks::throttle::make(sizeof(gr_complex), sampling_frequency_);
|
|
||||||
}
|
|
||||||
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_;
|
|
||||||
if (in_streams_ > 0)
|
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "A signal source does not have an input stream";
|
LOG(ERROR) << "A signal source does not have an input stream";
|
||||||
}
|
}
|
||||||
if (out_streams_ > 1)
|
if (out_streams > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one output stream";
|
LOG(ERROR) << "This implementation only supports one output stream";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TwoBitCpxFileSignalSource::connect(gr::top_block_sptr top_block)
|
std::tuple<size_t, bool> TwoBitCpxFileSignalSource::itemTypeToSize()
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
auto is_complex = false;
|
||||||
|
auto item_size = size_t(sizeof(char)); // default
|
||||||
|
|
||||||
|
if (item_type() == "byte")
|
||||||
{
|
{
|
||||||
if (enable_throttle_control_ == true)
|
item_size = sizeof(char);
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
top_block->connect(unpack_byte_, 0, inter_shorts_to_cpx_, 0);
|
|
||||||
top_block->connect(inter_shorts_to_cpx_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to throttle";
|
|
||||||
top_block->connect(throttle_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected throttle to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
top_block->connect(unpack_byte_, 0, inter_shorts_to_cpx_, 0);
|
|
||||||
top_block->connect(inter_shorts_to_cpx_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (enable_throttle_control_ == true)
|
LOG(WARNING) << item_type() << " unrecognized item type. Using byte.";
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
top_block->connect(unpack_byte_, 0, inter_shorts_to_cpx_, 0);
|
|
||||||
top_block->connect(inter_shorts_to_cpx_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to throttle";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(throttle_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
top_block->connect(unpack_byte_, 0, inter_shorts_to_cpx_, 0);
|
|
||||||
top_block->connect(inter_shorts_to_cpx_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected file source to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return std::make_tuple(item_size, is_complex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1 byte -> 2 samples
|
||||||
|
double TwoBitCpxFileSignalSource::packetsPerSample() const { return 2.0; }
|
||||||
|
gnss_shared_ptr<gr::block> TwoBitCpxFileSignalSource::source() const { return inter_shorts_to_cpx_; }
|
||||||
|
|
||||||
void TwoBitCpxFileSignalSource::disconnect(gr::top_block_sptr top_block)
|
|
||||||
|
void TwoBitCpxFileSignalSource::create_file_source_hook()
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
unpack_byte_ = make_unpack_byte_2bit_cpx_samples();
|
||||||
{
|
DLOG(INFO) << "unpack_byte_2bit_cpx_samples(" << unpack_byte_->unique_id() << ")";
|
||||||
if (enable_throttle_control_ == true)
|
inter_shorts_to_cpx_ = gr::blocks::interleaved_short_to_complex::make(false, true); // I/Q swap enabled
|
||||||
{
|
DLOG(INFO) << "interleaved_short_to_complex(" << inter_shorts_to_cpx_->unique_id() << ")";
|
||||||
top_block->disconnect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_byte_";
|
|
||||||
top_block->connect(unpack_byte_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_byte_ to throttle_";
|
|
||||||
top_block->disconnect(throttle_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected throttle to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_byte_";
|
|
||||||
top_block->disconnect(unpack_byte_, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_byte_ to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_byte_";
|
|
||||||
top_block->disconnect(unpack_byte_, 0, throttle_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_byte_ to throttle";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(unpack_byte_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected funpack_byte_ to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_byte_, 0);
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack_byte_";
|
|
||||||
top_block->disconnect(unpack_byte_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected unpack_byte_ to sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TwoBitCpxFileSignalSource::pre_connect_hook(gr::top_block_sptr top_block)
|
||||||
gr::basic_block_sptr TwoBitCpxFileSignalSource::get_left_block()
|
|
||||||
{
|
{
|
||||||
LOG(WARNING) << "Left block of a signal source should not be retrieved";
|
top_block->connect(file_source(), 0, unpack_byte_, 0);
|
||||||
// return gr_block_sptr();
|
top_block->connect(unpack_byte_, 0, inter_shorts_to_cpx_, 0);
|
||||||
return gr::blocks::file_source::sptr();
|
DLOG(INFO) << "connected file_source to unpacker";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TwoBitCpxFileSignalSource::pre_disconnect_hook(gr::top_block_sptr top_block)
|
||||||
gr::basic_block_sptr TwoBitCpxFileSignalSource::get_right_block()
|
|
||||||
{
|
{
|
||||||
if (samples_ > 0)
|
top_block->disconnect(file_source(), 0, unpack_byte_, 0);
|
||||||
{
|
top_block->disconnect(unpack_byte_, 0, inter_shorts_to_cpx_, 0);
|
||||||
return valve_;
|
DLOG(INFO) << "disconnected file_source from unpacker";
|
||||||
}
|
|
||||||
if (enable_throttle_control_ == true)
|
|
||||||
{
|
|
||||||
return throttle_;
|
|
||||||
}
|
|
||||||
return unpack_byte_;
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is part of GNSS-SDR.
|
* This file is part of GNSS-SDR.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
@ -20,17 +20,9 @@
|
|||||||
#ifndef GNSS_SDR_TWO_BIT_CPX_FILE_SIGNAL_SOURCE_H
|
#ifndef GNSS_SDR_TWO_BIT_CPX_FILE_SIGNAL_SOURCE_H
|
||||||
#define GNSS_SDR_TWO_BIT_CPX_FILE_SIGNAL_SOURCE_H
|
#define GNSS_SDR_TWO_BIT_CPX_FILE_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "file_source_base.h"
|
||||||
#include "gnss_block_interface.h"
|
|
||||||
#include "unpack_byte_2bit_cpx_samples.h"
|
#include "unpack_byte_2bit_cpx_samples.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
|
||||||
#include <gnuradio/blocks/file_source.h>
|
|
||||||
#include <gnuradio/blocks/interleaved_short_to_complex.h>
|
#include <gnuradio/blocks/interleaved_short_to_complex.h>
|
||||||
#include <gnuradio/blocks/throttle.h>
|
|
||||||
#include <gnuradio/hier_block2.h>
|
|
||||||
#include <pmt/pmt.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/** \addtogroup Signal_Source
|
/** \addtogroup Signal_Source
|
||||||
* \{ */
|
* \{ */
|
||||||
@ -44,7 +36,7 @@ class ConfigurationInterface;
|
|||||||
* \brief Class that reads signals samples from a file
|
* \brief Class that reads signals samples from a file
|
||||||
* and adapts it to a SignalSourceInterface
|
* and adapts it to a SignalSourceInterface
|
||||||
*/
|
*/
|
||||||
class TwoBitCpxFileSignalSource : public GNSSBlockInterface
|
class TwoBitCpxFileSignalSource : public FileSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TwoBitCpxFileSignalSource(const ConfigurationInterface* configuration,
|
TwoBitCpxFileSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -54,74 +46,18 @@ public:
|
|||||||
Concurrent_Queue<pmt::pmt_t>* queue);
|
Concurrent_Queue<pmt::pmt_t>* queue);
|
||||||
|
|
||||||
~TwoBitCpxFileSignalSource() = default;
|
~TwoBitCpxFileSignalSource() = default;
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
protected:
|
||||||
* \brief Returns "Two_Bit_Cpx_File_Signal_Source".
|
std::tuple<size_t, bool> itemTypeToSize() override;
|
||||||
*/
|
double packetsPerSample() const override;
|
||||||
inline std::string implementation() override
|
gnss_shared_ptr<gr::block> source() const override;
|
||||||
{
|
void create_file_source_hook() override;
|
||||||
return "Two_Bit_Cpx_File_Signal_Source";
|
void pre_connect_hook(gr::top_block_sptr top_block) override;
|
||||||
}
|
void pre_disconnect_hook(gr::top_block_sptr top_block) override;
|
||||||
|
|
||||||
inline size_t item_size() override
|
|
||||||
{
|
|
||||||
return item_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
inline std::string filename() const
|
|
||||||
{
|
|
||||||
return filename_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string item_type() const
|
|
||||||
{
|
|
||||||
return item_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool repeat() const
|
|
||||||
{
|
|
||||||
return repeat_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t sampling_frequency() const
|
|
||||||
{
|
|
||||||
return sampling_frequency_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t samples() const
|
|
||||||
{
|
|
||||||
return samples_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gr::blocks::file_source::sptr file_source_;
|
|
||||||
gr::blocks::interleaved_short_to_complex::sptr inter_shorts_to_cpx_;
|
|
||||||
unpack_byte_2bit_cpx_samples_sptr unpack_byte_;
|
unpack_byte_2bit_cpx_samples_sptr unpack_byte_;
|
||||||
gnss_shared_ptr<gr::block> valve_;
|
gr::blocks::interleaved_short_to_complex::sptr inter_shorts_to_cpx_;
|
||||||
gr::blocks::file_sink::sptr sink_;
|
|
||||||
gr::blocks::throttle::sptr throttle_;
|
|
||||||
std::string filename_;
|
|
||||||
std::string item_type_;
|
|
||||||
std::string dump_filename_;
|
|
||||||
std::string role_;
|
|
||||||
size_t item_size_;
|
|
||||||
uint64_t samples_;
|
|
||||||
int64_t sampling_frequency_;
|
|
||||||
unsigned int in_streams_;
|
|
||||||
unsigned int out_streams_;
|
|
||||||
bool repeat_;
|
|
||||||
bool dump_;
|
|
||||||
// Throttle control
|
|
||||||
bool enable_throttle_control_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
* This file is part of GNSS-SDR.
|
* This file is part of GNSS-SDR.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
@ -18,291 +18,122 @@
|
|||||||
|
|
||||||
#include "two_bit_packed_file_signal_source.h"
|
#include "two_bit_packed_file_signal_source.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
#include "gnss_sdr_flags.h"
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_valve.h"
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <gnuradio/blocks/char_to_float.h>
|
#include <gnuradio/blocks/char_to_float.h>
|
||||||
#include <exception>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
TwoBitPackedFileSignalSource::TwoBitPackedFileSignalSource(
|
TwoBitPackedFileSignalSource::TwoBitPackedFileSignalSource(
|
||||||
const ConfigurationInterface* configuration,
|
const ConfigurationInterface* configuration,
|
||||||
const std::string& role,
|
const std::string& role,
|
||||||
unsigned int in_streams,
|
unsigned int in_streams,
|
||||||
unsigned int out_streams,
|
unsigned int out_streams,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role),
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
in_streams_(in_streams),
|
: FileSourceBase(configuration, role, "Two_Bit_Packed_File_Signal_Source"s, queue, "byte"s), sample_type_(configuration->property(role + ".sample_type", "real"s)), // options: "real", "iq", "qi"
|
||||||
out_streams_(out_streams)
|
big_endian_items_(configuration->property(role + ".big_endian_items", true)),
|
||||||
|
big_endian_bytes_(configuration->property(role + ".big_endian_bytes", false)),
|
||||||
|
reverse_interleaving_(false)
|
||||||
{
|
{
|
||||||
const std::string default_filename("../data/my_capture.dat");
|
if (in_streams > 0)
|
||||||
const std::string default_item_type("byte");
|
|
||||||
const std::string default_dump_filename("../data/my_capture_dump.dat");
|
|
||||||
const std::string default_sample_type("real");
|
|
||||||
const double default_seconds_to_skip = 0.0;
|
|
||||||
|
|
||||||
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
|
|
||||||
sampling_frequency_ = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(0));
|
|
||||||
filename_ = configuration->property(role + ".filename", default_filename);
|
|
||||||
|
|
||||||
// override value with commandline flag, if present
|
|
||||||
if (FLAGS_signal_source != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_signal_source;
|
|
||||||
}
|
|
||||||
if (FLAGS_s != "-")
|
|
||||||
{
|
|
||||||
filename_ = FLAGS_s;
|
|
||||||
}
|
|
||||||
|
|
||||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
|
||||||
big_endian_items_ = configuration->property(role + ".big_endian_items", true);
|
|
||||||
big_endian_bytes_ = configuration->property(role + ".big_endian_bytes", false);
|
|
||||||
sample_type_ = configuration->property(role + ".sample_type", default_sample_type); // options: "real", "iq", "qi"
|
|
||||||
repeat_ = configuration->property(role + ".repeat", false);
|
|
||||||
dump_ = configuration->property(role + ".dump", false);
|
|
||||||
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
|
|
||||||
enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false);
|
|
||||||
const double seconds_to_skip = configuration->property(role + ".seconds_to_skip", default_seconds_to_skip);
|
|
||||||
int64_t bytes_to_skip = 0;
|
|
||||||
|
|
||||||
if (item_type_ == "byte")
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(char);
|
|
||||||
}
|
|
||||||
else if (item_type_ == "short")
|
|
||||||
{
|
|
||||||
// If we have shorts stored in little endian format, might as
|
|
||||||
// well read them in as bytes.
|
|
||||||
if (big_endian_items_)
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(int16_t);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item_size_ = sizeof(char);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(WARNING) << item_type_ << " unrecognized item type. Using byte.";
|
|
||||||
item_size_ = sizeof(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
reverse_interleaving_ = false;
|
|
||||||
is_complex_ = true;
|
|
||||||
if (sample_type_ == "real")
|
|
||||||
{
|
|
||||||
is_complex_ = false;
|
|
||||||
}
|
|
||||||
else if (sample_type_ == "iq")
|
|
||||||
{
|
|
||||||
is_complex_ = true;
|
|
||||||
}
|
|
||||||
else if (sample_type_ == "qi")
|
|
||||||
{
|
|
||||||
is_complex_ = true;
|
|
||||||
reverse_interleaving_ = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(WARNING) << sample_type_ << " unrecognized sample type. Assuming: "
|
|
||||||
<< (is_complex_ ? (reverse_interleaving_ ? "qi" : "iq") : "real");
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
file_source_ = gr::blocks::file_source::make(item_size_, filename_.c_str(), repeat_);
|
|
||||||
|
|
||||||
if (seconds_to_skip > 0)
|
|
||||||
{
|
|
||||||
bytes_to_skip = static_cast<int64_t>(
|
|
||||||
seconds_to_skip * sampling_frequency_ / 4);
|
|
||||||
if (is_complex_)
|
|
||||||
{
|
|
||||||
bytes_to_skip <<= 1;
|
|
||||||
}
|
|
||||||
file_source_->seek(bytes_to_skip, SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
unpack_samples_ = make_unpack_2bit_samples(big_endian_bytes_,
|
|
||||||
item_size_, big_endian_items_, reverse_interleaving_);
|
|
||||||
if (is_complex_)
|
|
||||||
{
|
|
||||||
char_to_float_ =
|
|
||||||
gr::blocks::interleaved_char_to_complex::make(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char_to_float_ =
|
|
||||||
gr::blocks::char_to_float::make();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr
|
|
||||||
<< "The receiver was configured to work with a file signal source\n"
|
|
||||||
<< "but the specified file is unreachable by GNSS-SDR.\n"
|
|
||||||
<< "Please modify your configuration file\n"
|
|
||||||
<< "and point SignalSource.filename to a valid raw data file. Then:\n"
|
|
||||||
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n"
|
|
||||||
<< "Examples of configuration files available at:\n"
|
|
||||||
<< GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/\n";
|
|
||||||
|
|
||||||
LOG(WARNING) << "file_signal_source: Unable to open the samples file "
|
|
||||||
<< filename_.c_str() << ", exiting the program.";
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
DLOG(INFO) << "file_source(" << file_source_->unique_id() << ")";
|
|
||||||
|
|
||||||
const size_t output_item_size = (is_complex_ ? sizeof(gr_complex) : sizeof(float));
|
|
||||||
|
|
||||||
if (samples_ == 0) // read all file
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
* BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File.
|
|
||||||
* A possible solution is to compute the file length in samples using file size, excluding the last 2 milliseconds, and enable always the
|
|
||||||
* valve block
|
|
||||||
*/
|
|
||||||
std::ifstream file(filename_.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
|
|
||||||
std::ifstream::pos_type size;
|
|
||||||
|
|
||||||
if (file.is_open())
|
|
||||||
{
|
|
||||||
size = file.tellg();
|
|
||||||
samples_ = floor(static_cast<double>(size) * (is_complex_ ? 2.0 : 4.0));
|
|
||||||
LOG(INFO) << "Total samples in the file= " << samples_; // 4 samples per byte
|
|
||||||
samples_ -= bytes_to_skip;
|
|
||||||
|
|
||||||
// Also skip the last two milliseconds:
|
|
||||||
samples_ -= ceil(0.002 * sampling_frequency_ / (is_complex_ ? 2.0 : 4.0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "file_signal_source: Unable to open the samples file " << filename_.c_str() << '\n';
|
|
||||||
LOG(ERROR) << "file_signal_source: Unable to open the samples file " << filename_.c_str();
|
|
||||||
}
|
|
||||||
std::streamsize ss = std::cout.precision();
|
|
||||||
std::cout << std::setprecision(16);
|
|
||||||
std::cout << "Processing file " << filename_ << ", which contains " << size << " [bytes]\n";
|
|
||||||
std::cout.precision(ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(samples_ > 0) << "File does not contain enough samples to process.";
|
|
||||||
double signal_duration_s;
|
|
||||||
signal_duration_s = static_cast<double>(samples_) * (1 / static_cast<double>(sampling_frequency_));
|
|
||||||
LOG(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";
|
|
||||||
|
|
||||||
valve_ = gnss_sdr_make_valve(output_item_size, samples_, queue);
|
|
||||||
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
|
|
||||||
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
// sink_ = gr_make_file_sink(item_size_, dump_filename_.c_str());
|
|
||||||
sink_ = gr::blocks::file_sink::make(output_item_size, dump_filename_.c_str());
|
|
||||||
DLOG(INFO) << "file_sink(" << sink_->unique_id() << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable_throttle_control_)
|
|
||||||
{
|
|
||||||
throttle_ = gr::blocks::throttle::make(output_item_size, sampling_frequency_);
|
|
||||||
}
|
|
||||||
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_;
|
|
||||||
if (in_streams_ > 0)
|
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "A signal source does not have an input stream";
|
LOG(ERROR) << "A signal source does not have an input stream";
|
||||||
}
|
}
|
||||||
if (out_streams_ > 1)
|
if (out_streams > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one output stream";
|
LOG(ERROR) << "This implementation only supports one output stream";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TwoBitPackedFileSignalSource::connect(gr::top_block_sptr top_block)
|
std::tuple<size_t, bool> TwoBitPackedFileSignalSource::itemTypeToSize()
|
||||||
{
|
{
|
||||||
gr::basic_block_sptr left_block = file_source_;
|
auto is_complex_t = false;
|
||||||
gr::basic_block_sptr right_block = unpack_samples_;
|
auto item_size = size_t(sizeof(char)); // default
|
||||||
|
|
||||||
top_block->connect(file_source_, 0, unpack_samples_, 0);
|
if (item_type() == "byte")
|
||||||
left_block = right_block;
|
{
|
||||||
|
item_size = sizeof(char);
|
||||||
|
}
|
||||||
|
else if (item_type() == "short")
|
||||||
|
{
|
||||||
|
// If we have shorts stored in little endian format, might as
|
||||||
|
// well read them in as bytes.
|
||||||
|
// TODO: this seems to make assumptions about the endianness of this machine
|
||||||
|
if (big_endian_items_)
|
||||||
|
{
|
||||||
|
item_size = sizeof(int16_t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// how can this be right? the number of samples is computed based on this value
|
||||||
|
item_size = sizeof(char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(WARNING) << item_type() << " unrecognized item type. Using byte.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// the complex-ness of the input is inferred from the output type
|
||||||
|
if (sample_type_ == "real")
|
||||||
|
{
|
||||||
|
is_complex_t = false;
|
||||||
|
}
|
||||||
|
else if (sample_type_ == "iq")
|
||||||
|
{
|
||||||
|
is_complex_t = true;
|
||||||
|
}
|
||||||
|
else if (sample_type_ == "qi")
|
||||||
|
{
|
||||||
|
is_complex_t = true;
|
||||||
|
reverse_interleaving_ = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(WARNING) << sample_type_ << " unrecognized sample type. Assuming: "
|
||||||
|
<< (is_complex_t ? (reverse_interleaving_ ? "qi" : "iq") : "real");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return std::make_tuple(item_size, is_complex_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each sample is 2 bits; if the item_type() is char, then the size is 8/2 = 4 packets per sample
|
||||||
|
// If the item_type() is short, then the size is 16/2 = 8 packets per sample
|
||||||
|
double TwoBitPackedFileSignalSource::packetsPerSample() const { return item_size() / 2.0; }
|
||||||
|
gnss_shared_ptr<gr::block> TwoBitPackedFileSignalSource::source() const { return char_to_float_; }
|
||||||
|
|
||||||
|
void TwoBitPackedFileSignalSource::create_file_source_hook()
|
||||||
|
{
|
||||||
|
unpack_samples_ = make_unpack_2bit_samples(big_endian_bytes_, item_size(),
|
||||||
|
big_endian_items_, reverse_interleaving_);
|
||||||
|
DLOG(INFO) << "unpack_byte_2bit_samples(" << unpack_samples_->unique_id() << ")";
|
||||||
|
|
||||||
|
if (is_complex())
|
||||||
|
{
|
||||||
|
char_to_float_ = gr::blocks::interleaved_char_to_complex::make(false);
|
||||||
|
DLOG(INFO) << "interleaved_char_to_complex(" << char_to_float_->unique_id() << ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char_to_float_ = gr::blocks::char_to_float::make();
|
||||||
|
DLOG(INFO) << "char_to_float(" << char_to_float_->unique_id() << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwoBitPackedFileSignalSource::pre_connect_hook(gr::top_block_sptr top_block)
|
||||||
|
{
|
||||||
|
top_block->connect(file_source(), 0, unpack_samples_, 0);
|
||||||
DLOG(INFO) << "connected file source to unpack samples";
|
DLOG(INFO) << "connected file source to unpack samples";
|
||||||
right_block = char_to_float_;
|
top_block->connect(unpack_samples_, 0, char_to_float_, 0);
|
||||||
top_block->connect(left_block, 0, right_block, 0);
|
|
||||||
left_block = right_block;
|
|
||||||
DLOG(INFO) << "connected unpack samples to char to float";
|
DLOG(INFO) << "connected unpack samples to char to float";
|
||||||
|
|
||||||
if (enable_throttle_control_)
|
|
||||||
{
|
|
||||||
right_block = throttle_;
|
|
||||||
top_block->connect(left_block, 0, right_block, 0);
|
|
||||||
left_block = right_block;
|
|
||||||
DLOG(INFO) << " connected to throttle";
|
|
||||||
}
|
|
||||||
|
|
||||||
top_block->connect(left_block, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "connected to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->connect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "connected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TwoBitPackedFileSignalSource::pre_disconnect_hook(gr::top_block_sptr top_block)
|
||||||
void TwoBitPackedFileSignalSource::disconnect(gr::top_block_sptr top_block)
|
|
||||||
{
|
{
|
||||||
gr::basic_block_sptr left_block = file_source_;
|
top_block->disconnect(file_source(), 0, unpack_samples_, 0);
|
||||||
gr::basic_block_sptr right_block = unpack_samples_;
|
|
||||||
|
|
||||||
top_block->disconnect(file_source_, 0, unpack_samples_, 0);
|
|
||||||
left_block = right_block;
|
|
||||||
|
|
||||||
DLOG(INFO) << "disconnected file source to unpack samples";
|
DLOG(INFO) << "disconnected file source to unpack samples";
|
||||||
right_block = char_to_float_;
|
top_block->disconnect(unpack_samples_, 0, char_to_float_, 0);
|
||||||
top_block->disconnect(left_block, 0, right_block, 0);
|
|
||||||
left_block = right_block;
|
|
||||||
DLOG(INFO) << "disconnected unpack samples to char to float";
|
DLOG(INFO) << "disconnected unpack samples to char to float";
|
||||||
|
|
||||||
if (enable_throttle_control_)
|
|
||||||
{
|
|
||||||
right_block = throttle_;
|
|
||||||
top_block->disconnect(left_block, 0, right_block, 0);
|
|
||||||
left_block = right_block;
|
|
||||||
DLOG(INFO) << " disconnected to throttle";
|
|
||||||
}
|
|
||||||
|
|
||||||
top_block->disconnect(left_block, 0, valve_, 0);
|
|
||||||
DLOG(INFO) << "disconnected to valve";
|
|
||||||
if (dump_)
|
|
||||||
{
|
|
||||||
top_block->disconnect(valve_, 0, sink_, 0);
|
|
||||||
DLOG(INFO) << "disconnected valve to file sink";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gr::basic_block_sptr TwoBitPackedFileSignalSource::get_left_block()
|
|
||||||
{
|
|
||||||
LOG(WARNING) << "Left block of a signal source should not be retrieved";
|
|
||||||
// return gr_block_sptr();
|
|
||||||
return gr::blocks::file_source::sptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gr::basic_block_sptr TwoBitPackedFileSignalSource::get_right_block()
|
|
||||||
{
|
|
||||||
return valve_;
|
|
||||||
}
|
}
|
||||||
|
@ -21,17 +21,9 @@
|
|||||||
#ifndef GNSS_SDR_TWO_BIT_PACKED_FILE_SIGNAL_SOURCE_H
|
#ifndef GNSS_SDR_TWO_BIT_PACKED_FILE_SIGNAL_SOURCE_H
|
||||||
#define GNSS_SDR_TWO_BIT_PACKED_FILE_SIGNAL_SOURCE_H
|
#define GNSS_SDR_TWO_BIT_PACKED_FILE_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "file_source_base.h"
|
||||||
#include "gnss_block_interface.h"
|
|
||||||
#include "unpack_2bit_samples.h"
|
#include "unpack_2bit_samples.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
|
||||||
#include <gnuradio/blocks/file_source.h>
|
|
||||||
#include <gnuradio/blocks/interleaved_char_to_complex.h>
|
#include <gnuradio/blocks/interleaved_char_to_complex.h>
|
||||||
#include <gnuradio/blocks/throttle.h>
|
|
||||||
#include <gnuradio/hier_block2.h>
|
|
||||||
#include <pmt/pmt.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
/** \addtogroup Signal_Source
|
/** \addtogroup Signal_Source
|
||||||
@ -46,7 +38,7 @@ class ConfigurationInterface;
|
|||||||
* \brief Class that reads signals samples from a file
|
* \brief Class that reads signals samples from a file
|
||||||
* and adapts it to a SignalSourceInterface
|
* and adapts it to a SignalSourceInterface
|
||||||
*/
|
*/
|
||||||
class TwoBitPackedFileSignalSource : public GNSSBlockInterface
|
class TwoBitPackedFileSignalSource : public FileSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TwoBitPackedFileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
TwoBitPackedFileSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
||||||
@ -54,54 +46,8 @@ public:
|
|||||||
Concurrent_Queue<pmt::pmt_t>* queue);
|
Concurrent_Queue<pmt::pmt_t>* queue);
|
||||||
|
|
||||||
~TwoBitPackedFileSignalSource() = default;
|
~TwoBitPackedFileSignalSource() = default;
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "Two_Bit_Packed_File_Signal_Source".
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "Two_Bit_Packed_File_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
|
||||||
{
|
|
||||||
return item_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
inline std::string filename() const
|
|
||||||
{
|
|
||||||
return filename_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string item_type() const
|
|
||||||
{
|
|
||||||
return item_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool repeat() const
|
|
||||||
{
|
|
||||||
return repeat_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64_t sampling_frequency() const
|
|
||||||
{
|
|
||||||
return sampling_frequency_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t samples() const
|
|
||||||
{
|
|
||||||
return samples_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private:
|
||||||
inline bool big_endian_items() const
|
inline bool big_endian_items() const
|
||||||
{
|
{
|
||||||
return big_endian_items_;
|
return big_endian_items_;
|
||||||
@ -112,41 +58,27 @@ public:
|
|||||||
return big_endian_bytes_;
|
return big_endian_bytes_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_complex() const
|
|
||||||
{
|
|
||||||
return is_complex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool reverse_interleaving() const
|
inline bool reverse_interleaving() const
|
||||||
{
|
{
|
||||||
return reverse_interleaving_;
|
return reverse_interleaving_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::tuple<size_t, bool> itemTypeToSize() override;
|
||||||
|
double packetsPerSample() const override;
|
||||||
|
gnss_shared_ptr<gr::block> source() const override;
|
||||||
|
void create_file_source_hook() override;
|
||||||
|
void pre_connect_hook(gr::top_block_sptr top_block) override;
|
||||||
|
void pre_disconnect_hook(gr::top_block_sptr top_block) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gr::blocks::file_source::sptr file_source_;
|
|
||||||
unpack_2bit_samples_sptr unpack_samples_;
|
|
||||||
gr::basic_block_sptr char_to_float_;
|
|
||||||
gnss_shared_ptr<gr::block> valve_;
|
|
||||||
gr::blocks::file_sink::sptr sink_;
|
|
||||||
gr::blocks::throttle::sptr throttle_;
|
|
||||||
std::string filename_;
|
|
||||||
std::string item_type_;
|
|
||||||
std::string dump_filename_;
|
|
||||||
std::string role_;
|
|
||||||
std::string sample_type_;
|
std::string sample_type_;
|
||||||
uint64_t samples_;
|
|
||||||
int64_t sampling_frequency_;
|
|
||||||
size_t item_size_;
|
|
||||||
unsigned int in_streams_;
|
|
||||||
unsigned int out_streams_;
|
|
||||||
bool big_endian_items_;
|
bool big_endian_items_;
|
||||||
bool big_endian_bytes_;
|
bool big_endian_bytes_;
|
||||||
bool is_complex_;
|
|
||||||
bool reverse_interleaving_;
|
bool reverse_interleaving_;
|
||||||
bool repeat_;
|
unpack_2bit_samples_sptr unpack_samples_;
|
||||||
bool dump_;
|
gnss_shared_ptr<gr::block> char_to_float_;
|
||||||
// Throttle control
|
|
||||||
bool enable_throttle_control_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "uhd_signal_source.h"
|
#include "uhd_signal_source.h"
|
||||||
#include "GPS_L1_CA.h"
|
#include "GPS_L1_CA.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_valve.h"
|
#include "gnss_sdr_valve.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <uhd/exception.hpp>
|
#include <uhd/exception.hpp>
|
||||||
@ -25,10 +26,13 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
|
||||||
UhdSignalSource::UhdSignalSource(const ConfigurationInterface* configuration,
|
UhdSignalSource::UhdSignalSource(const ConfigurationInterface* configuration,
|
||||||
const std::string& role, unsigned int in_stream, unsigned int out_stream,
|
const std::string& role, unsigned int in_stream, unsigned int out_stream,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream)
|
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "UHD_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
|
||||||
{
|
{
|
||||||
// DUMP PARAMETERS
|
// DUMP PARAMETERS
|
||||||
const std::string empty;
|
const std::string empty;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#define GNSS_SDR_UHD_SIGNAL_SOURCE_H
|
#define GNSS_SDR_UHD_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
#include "concurrent_queue.h"
|
#include "concurrent_queue.h"
|
||||||
#include "gnss_block_interface.h"
|
#include "signal_source_base.h"
|
||||||
#include <gnuradio/blocks/file_sink.h>
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
#include <gnuradio/hier_block2.h>
|
#include <gnuradio/hier_block2.h>
|
||||||
#include <gnuradio/uhd/usrp_source.h>
|
#include <gnuradio/uhd/usrp_source.h>
|
||||||
@ -38,7 +38,7 @@ class ConfigurationInterface;
|
|||||||
/*!
|
/*!
|
||||||
* \brief This class reads samples from a UHD device (see http://code.ettus.com/redmine/ettus/projects/uhd/wiki)
|
* \brief This class reads samples from a UHD device (see http://code.ettus.com/redmine/ettus/projects/uhd/wiki)
|
||||||
*/
|
*/
|
||||||
class UhdSignalSource : public GNSSBlockInterface
|
class UhdSignalSource : public SignalSourceBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UhdSignalSource(const ConfigurationInterface* configuration,
|
UhdSignalSource(const ConfigurationInterface* configuration,
|
||||||
@ -47,19 +47,6 @@ public:
|
|||||||
|
|
||||||
~UhdSignalSource() = default;
|
~UhdSignalSource() = default;
|
||||||
|
|
||||||
inline std::string role() override
|
|
||||||
{
|
|
||||||
return role_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns "UHD_Signal_Source"
|
|
||||||
*/
|
|
||||||
inline std::string implementation() override
|
|
||||||
{
|
|
||||||
return "UHD_Signal_Source";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t item_size() override
|
inline size_t item_size() override
|
||||||
{
|
{
|
||||||
return item_size_;
|
return item_size_;
|
||||||
@ -89,7 +76,6 @@ private:
|
|||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
std::string subdevice_;
|
std::string subdevice_;
|
||||||
std::string clock_source_;
|
std::string clock_source_;
|
||||||
std::string role_;
|
|
||||||
|
|
||||||
double sample_rate_;
|
double sample_rate_;
|
||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
|
65
src/core/interfaces/signal_source_interface.h
Normal file
65
src/core/interfaces/signal_source_interface.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*!
|
||||||
|
* \signal_source_interface.h
|
||||||
|
* \brief Header file of the interface to a signal_source GNSS block.
|
||||||
|
* \author Jim Melton, 2020. jim.melton(at)sncorp.com
|
||||||
|
*
|
||||||
|
* This header file contains the interface to an abstract class for
|
||||||
|
* signal sources. Since all its methods are virtual, this class
|
||||||
|
* cannot be instantiated directly, and a subclass can only be
|
||||||
|
* instantiated directly if all inherited pure virtual methods have
|
||||||
|
* been implemented by that class or a parent class.
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a software defined Global Navigation
|
||||||
|
* Satellite Systems receiver
|
||||||
|
*
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_SIGNAL_SOURCE_INTERFACE_H
|
||||||
|
#define GNSS_SDR_SIGNAL_SOURCE_INTERFACE_H
|
||||||
|
|
||||||
|
#include "gnss_block_interface.h"
|
||||||
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
/** \addtogroup Core
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup GNSS_Block_Interfaces GNSS block interfaces
|
||||||
|
* GNSS block interfaces.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
/*! \brief This abstract class represents an interface to signal_source GNSS block.
|
||||||
|
*
|
||||||
|
* Abstract class for signal sources. Since all its methods are virtual,
|
||||||
|
* this class cannot be instantiated directly, and a subclass can only be
|
||||||
|
* instantiated directly if all inherited pure virtual methods have been
|
||||||
|
* implemented by that class or a parent class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SignalSourceInterface : public GNSSBlockInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual size_t getRfChannels() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SignalSourceInterface()
|
||||||
|
{
|
||||||
|
VLOG(1) << "SignalSourceInterface: " << this << " ctor";
|
||||||
|
}
|
||||||
|
|
||||||
|
public: // required for polymorphic destruction
|
||||||
|
~SignalSourceInterface()
|
||||||
|
{
|
||||||
|
VLOG(1) << "SignalSourceInterface: " << this << " dtor";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -151,6 +151,7 @@ target_link_libraries(core_receiver
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
core_libs
|
core_libs
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
algorithms_libs
|
||||||
core_monitor
|
core_monitor
|
||||||
signal_source_adapters
|
signal_source_adapters
|
||||||
data_type_adapters
|
data_type_adapters
|
||||||
@ -169,8 +170,6 @@ target_link_libraries(core_receiver
|
|||||||
Armadillo::armadillo
|
Armadillo::armadillo
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(core_receiver PRIVATE ${CMAKE_SOURCE_DIR}/src/algorithms/libs)
|
|
||||||
|
|
||||||
if(ENABLE_ARMA_NO_DEBUG)
|
if(ENABLE_ARMA_NO_DEBUG)
|
||||||
target_compile_definitions(core_receiver
|
target_compile_definitions(core_receiver
|
||||||
PRIVATE -DARMA_NO_BOUND_CHECKING=1
|
PRIVATE -DARMA_NO_BOUND_CHECKING=1
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
class ConfigurationInterface;
|
class ConfigurationInterface;
|
||||||
class GNSSBlockInterface;
|
class GNSSBlockInterface;
|
||||||
|
class SignalSourceInterface;
|
||||||
class AcquisitionInterface;
|
class AcquisitionInterface;
|
||||||
class TrackingInterface;
|
class TrackingInterface;
|
||||||
class TelemetryDecoderInterface;
|
class TelemetryDecoderInterface;
|
||||||
@ -51,7 +52,7 @@ public:
|
|||||||
GNSSBlockFactory() = default;
|
GNSSBlockFactory() = default;
|
||||||
~GNSSBlockFactory() = default;
|
~GNSSBlockFactory() = default;
|
||||||
|
|
||||||
std::unique_ptr<GNSSBlockInterface> GetSignalSource(const ConfigurationInterface* configuration,
|
std::unique_ptr<SignalSourceInterface> GetSignalSource(const ConfigurationInterface* configuration,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue, int ID = -1);
|
Concurrent_Queue<pmt::pmt_t>* queue, int ID = -1);
|
||||||
|
|
||||||
std::unique_ptr<GNSSBlockInterface> GetSignalConditioner(const ConfigurationInterface* configuration, int ID = -1);
|
std::unique_ptr<GNSSBlockInterface> GetSignalConditioner(const ConfigurationInterface* configuration, int ID = -1);
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "gnss_satellite.h"
|
#include "gnss_satellite.h"
|
||||||
#include "gnss_sdr_make_unique.h"
|
#include "gnss_sdr_make_unique.h"
|
||||||
#include "gnss_synchro_monitor.h"
|
#include "gnss_synchro_monitor.h"
|
||||||
|
#include "signal_source_interface.h"
|
||||||
#include <boost/lexical_cast.hpp> // for boost::lexical_cast
|
#include <boost/lexical_cast.hpp> // for boost::lexical_cast
|
||||||
#include <boost/tokenizer.hpp> // for boost::tokenizer
|
#include <boost/tokenizer.hpp> // for boost::tokenizer
|
||||||
#include <glog/logging.h> // for LOG
|
#include <glog/logging.h> // for LOG
|
||||||
@ -100,50 +101,19 @@ void GNSSFlowgraph::init()
|
|||||||
// 1. read the number of RF front-ends available (one file_source per RF front-end)
|
// 1. read the number of RF front-ends available (one file_source per RF front-end)
|
||||||
sources_count_ = configuration_->property("Receiver.sources_count", 1);
|
sources_count_ = configuration_->property("Receiver.sources_count", 1);
|
||||||
|
|
||||||
int RF_Channels = 0;
|
|
||||||
int signal_conditioner_ID = 0;
|
int signal_conditioner_ID = 0;
|
||||||
|
|
||||||
if (sources_count_ > 1)
|
for (int i = 0; i < sources_count_; i++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < sources_count_; i++)
|
std::cout << "Creating source " << i << '\n';
|
||||||
|
sig_source_.push_back(block_factory->GetSignalSource(configuration_.get(), queue_.get(), i));
|
||||||
|
auto& src = sig_source_.back();
|
||||||
|
auto RF_Channels = src->getRfChannels();
|
||||||
|
std::cout << "RF Channels " << RF_Channels << '\n';
|
||||||
|
for (auto j = 0U; j < RF_Channels; ++j)
|
||||||
{
|
{
|
||||||
std::cout << "Creating source " << i << '\n';
|
sig_conditioner_.push_back(block_factory->GetSignalConditioner(configuration_.get(), signal_conditioner_ID));
|
||||||
sig_source_.push_back(block_factory->GetSignalSource(configuration_.get(), queue_.get(), i));
|
signal_conditioner_ID++;
|
||||||
// TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface.
|
|
||||||
// Include GetRFChannels in the interface to avoid read config parameters here
|
|
||||||
// read the number of RF channels for each front-end
|
|
||||||
RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1);
|
|
||||||
std::cout << "RF Channels " << RF_Channels << '\n';
|
|
||||||
for (int j = 0; j < RF_Channels; j++)
|
|
||||||
{
|
|
||||||
sig_conditioner_.push_back(block_factory->GetSignalConditioner(configuration_.get(), signal_conditioner_ID));
|
|
||||||
signal_conditioner_ID++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// backwards compatibility for old config files
|
|
||||||
sig_source_.push_back(block_factory->GetSignalSource(configuration_.get(), queue_.get(), -1));
|
|
||||||
// TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface.
|
|
||||||
// Include GetRFChannels in the interface to avoid read config parameters here
|
|
||||||
// read the number of RF channels for each front-end
|
|
||||||
if (sig_source_.at(0) != nullptr)
|
|
||||||
{
|
|
||||||
RF_Channels = configuration_->property(sig_source_.at(0)->role() + ".RF_channels", 0);
|
|
||||||
}
|
|
||||||
if (RF_Channels != 0)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < RF_Channels; j++)
|
|
||||||
{
|
|
||||||
sig_conditioner_.push_back(block_factory->GetSignalConditioner(configuration_.get(), signal_conditioner_ID));
|
|
||||||
signal_conditioner_ID++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// old config file, single signal source and single channel, not specified
|
|
||||||
sig_conditioner_.push_back(block_factory->GetSignalConditioner(configuration_.get(), -1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,65 +691,66 @@ int GNSSFlowgraph::disconnect_signal_sources()
|
|||||||
|
|
||||||
int GNSSFlowgraph::connect_signal_conditioners()
|
int GNSSFlowgraph::connect_signal_conditioners()
|
||||||
{
|
{
|
||||||
for (auto& sig : sig_conditioner_)
|
int error = 1; // this should be bool (true)
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
for (auto& sig : sig_conditioner_)
|
||||||
{
|
{
|
||||||
sig->connect(top_block_);
|
sig->connect(top_block_);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
DLOG(INFO) << "Signal Conditioner blocks successfully connected to the top_block";
|
||||||
|
error = 0; // false
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "Can't connect signal conditioner block internally: " << e.what();
|
||||||
|
top_block_->disconnect_all();
|
||||||
|
std::string reported_error(e.what());
|
||||||
|
if (std::string::npos != reported_error.find(std::string("itemsize mismatch")))
|
||||||
|
{
|
||||||
|
std::string replace_me("copy");
|
||||||
|
size_t pos = reported_error.find(replace_me);
|
||||||
|
while (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
size_t len = replace_me.length();
|
||||||
|
reported_error.replace(pos, len, "Pass_Through");
|
||||||
|
pos = reported_error.find(replace_me, pos + 1);
|
||||||
|
}
|
||||||
|
help_hint_ += " * Blocks within the Signal Conditioner are connected with mismatched input/ouput item size\n";
|
||||||
|
help_hint_ += " Reported error: " + reported_error + '\n';
|
||||||
|
help_hint_ += " Check the Signal Conditioner documentation at https://gnss-sdr.org/docs/sp-blocks/signal-conditioner/\n";
|
||||||
|
}
|
||||||
|
if (std::string::npos != reported_error.find(std::string("DataTypeAdapter")))
|
||||||
|
{
|
||||||
|
help_hint_ += " * The DataTypeAdapter implementation set in the configuration file does not exist\n";
|
||||||
|
help_hint_ += " Check the DataTypeAdapter documentation at https://gnss-sdr.org/docs/sp-blocks/data-type-adapter/\n";
|
||||||
|
}
|
||||||
|
if (std::string::npos != reported_error.find(std::string("InputFilter")))
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "Can't connect signal conditioner block internally: " << e.what();
|
|
||||||
top_block_->disconnect_all();
|
|
||||||
std::string reported_error(e.what());
|
|
||||||
if (std::string::npos != reported_error.find(std::string("itemsize mismatch")))
|
if (std::string::npos != reported_error.find(std::string("itemsize mismatch")))
|
||||||
{
|
{
|
||||||
std::string replace_me("copy");
|
help_hint_ += " * The configured InputFilter input/output item types are not well defined.\n";
|
||||||
size_t pos = reported_error.find(replace_me);
|
|
||||||
while (pos != std::string::npos)
|
|
||||||
{
|
|
||||||
size_t len = replace_me.length();
|
|
||||||
reported_error.replace(pos, len, "Pass_Through");
|
|
||||||
pos = reported_error.find(replace_me, pos + 1);
|
|
||||||
}
|
|
||||||
help_hint_ += " * Blocks within the Signal Conditioner are connected with mismatched input/ouput item size\n";
|
|
||||||
help_hint_ += " Reported error: " + reported_error + '\n';
|
|
||||||
help_hint_ += " Check the Signal Conditioner documentation at https://gnss-sdr.org/docs/sp-blocks/signal-conditioner/\n";
|
|
||||||
}
|
}
|
||||||
if (std::string::npos != reported_error.find(std::string("DataTypeAdapter")))
|
else
|
||||||
{
|
{
|
||||||
help_hint_ += " * The DataTypeAdapter implementation set in the configuration file does not exist\n";
|
help_hint_ += " * The InputFilter implementation set in the configuration file does not exist\n";
|
||||||
help_hint_ += " Check the DataTypeAdapter documentation at https://gnss-sdr.org/docs/sp-blocks/data-type-adapter/\n";
|
|
||||||
}
|
}
|
||||||
if (std::string::npos != reported_error.find(std::string("InputFilter")))
|
help_hint_ += " Check the InputFilter documentation at https://gnss-sdr.org/docs/sp-blocks/input-filter/\n";
|
||||||
|
}
|
||||||
|
if (std::string::npos != reported_error.find(std::string("Resampler")))
|
||||||
|
{
|
||||||
|
if (std::string::npos != reported_error.find(std::string("itemsize mismatch")))
|
||||||
{
|
{
|
||||||
if (std::string::npos != reported_error.find(std::string("itemsize mismatch")))
|
help_hint_ += " * The configured Resampler item type is not well defined.\n";
|
||||||
{
|
|
||||||
help_hint_ += " * The configured InputFilter input/output item types are not well defined.\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
help_hint_ += " * The InputFilter implementation set in the configuration file does not exist\n";
|
|
||||||
}
|
|
||||||
help_hint_ += " Check the InputFilter documentation at https://gnss-sdr.org/docs/sp-blocks/input-filter/\n";
|
|
||||||
}
|
}
|
||||||
if (std::string::npos != reported_error.find(std::string("Resampler")))
|
else
|
||||||
{
|
{
|
||||||
if (std::string::npos != reported_error.find(std::string("itemsize mismatch")))
|
help_hint_ += " * The Resampler implementation set in the configuration file does not exist\n";
|
||||||
{
|
|
||||||
help_hint_ += " * The configured Resampler item type is not well defined.\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
help_hint_ += " * The Resampler implementation set in the configuration file does not exist\n";
|
|
||||||
}
|
|
||||||
help_hint_ += " Check the Resampler documentation at https://gnss-sdr.org/docs/sp-blocks/resampler/\n";
|
|
||||||
}
|
}
|
||||||
return 1;
|
help_hint_ += " Check the Resampler documentation at https://gnss-sdr.org/docs/sp-blocks/resampler/\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DLOG(INFO) << "Signal Conditioner blocks successfully connected to the top_block";
|
return error;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1028,42 +999,40 @@ int GNSSFlowgraph::disconnect_fpga_sample_counter()
|
|||||||
|
|
||||||
int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners()
|
int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners()
|
||||||
{
|
{
|
||||||
int RF_Channels = 0;
|
|
||||||
unsigned int signal_conditioner_ID = 0;
|
unsigned int signal_conditioner_ID = 0;
|
||||||
for (int i = 0; i < sources_count_; i++)
|
for (int i = 0; i < sources_count_; i++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
auto& src = sig_source_.at(i);
|
||||||
|
|
||||||
// TODO: Remove this array implementation and create generic multistream connector
|
// TODO: Remove this array implementation and create generic multistream connector
|
||||||
// (if a signal source has more than 1 stream, then connect it to the multistream signal conditioner)
|
// (if a signal source has more than 1 stream, then connect it to the multistream signal conditioner)
|
||||||
if (sig_source_.at(i)->implementation() == "Raw_Array_Signal_Source")
|
if (src->implementation() == "Raw_Array_Signal_Source")
|
||||||
{
|
{
|
||||||
// Multichannel Array
|
// Multichannel Array
|
||||||
std::cout << "ARRAY MODE\n";
|
std::cout << "ARRAY MODE\n";
|
||||||
for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++)
|
for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++)
|
||||||
{
|
{
|
||||||
std::cout << "connecting ch " << j << '\n';
|
std::cout << "connecting ch " << j << '\n';
|
||||||
top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j);
|
top_block_->connect(src->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface.
|
auto RF_Channels = src->getRfChannels();
|
||||||
// Include GetRFChannels in the interface to avoid read config parameters here
|
|
||||||
// read the number of RF channels for each front-end
|
|
||||||
RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1);
|
|
||||||
|
|
||||||
for (int j = 0; j < RF_Channels; j++)
|
for (auto j = 0U; j < RF_Channels; ++j)
|
||||||
{
|
{
|
||||||
// Connect the multichannel signal source to multiple signal conditioners
|
// Connect the multichannel signal source to multiple signal conditioners
|
||||||
// GNURADIO max_streams=-1 means infinite ports!
|
// GNURADIO max_streams=-1 means infinite ports!
|
||||||
size_t output_size = sig_source_.at(i)->item_size();
|
size_t output_size = src->item_size();
|
||||||
size_t input_size = sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->sizeof_stream_item(0);
|
size_t input_size = sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->sizeof_stream_item(0);
|
||||||
// Check configuration inconsistencies
|
// Check configuration inconsistencies
|
||||||
if (output_size != input_size)
|
if (output_size != input_size)
|
||||||
{
|
{
|
||||||
help_hint_ += " * The Signal Source implementation " + sig_source_.at(i)->implementation() + " has an output with a ";
|
help_hint_ += " * The Signal Source implementation " + src->implementation() + " has an output with a ";
|
||||||
help_hint_ += sig_source_.at(i)->role() + ".item_size of " + std::to_string(output_size);
|
help_hint_ += src->role() + ".item_size of " + std::to_string(output_size);
|
||||||
help_hint_ += " bytes, but it is connected to the Signal Conditioner implementation ";
|
help_hint_ += " bytes, but it is connected to the Signal Conditioner implementation ";
|
||||||
help_hint_ += sig_conditioner_.at(signal_conditioner_ID)->implementation() + " with input item size of " + std::to_string(input_size) + " bytes.\n";
|
help_hint_ += sig_conditioner_.at(signal_conditioner_ID)->implementation() + " with input item size of " + std::to_string(input_size) + " bytes.\n";
|
||||||
help_hint_ += " Output ports must be connected to input ports with the same item size.\n";
|
help_hint_ += " Output ports must be connected to input ports with the same item size.\n";
|
||||||
@ -1071,12 +1040,12 @@ int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1 or sig_source_.at(i)->get_right_block()->output_signature()->max_streams() == -1)
|
if (src->get_right_block()->output_signature()->max_streams() > 1 or src->get_right_block()->output_signature()->max_streams() == -1)
|
||||||
{
|
{
|
||||||
if (sig_conditioner_.size() > signal_conditioner_ID)
|
if (sig_conditioner_.size() > signal_conditioner_ID)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j;
|
LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << signal_conditioner_ID;
|
||||||
top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
top_block_->connect(src->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1084,14 +1053,14 @@ int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners()
|
|||||||
if (j == 0)
|
if (j == 0)
|
||||||
{
|
{
|
||||||
// RF_channel 0 backward compatibility with single channel sources
|
// RF_channel 0 backward compatibility with single channel sources
|
||||||
LOG(INFO) << "connecting sig_source_ " << i << " stream " << 0 << " to conditioner " << j;
|
LOG(INFO) << "connecting sig_source_ " << i << " stream " << 0 << " to conditioner " << signal_conditioner_ID;
|
||||||
top_block_->connect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
top_block_->connect(src->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call)
|
// Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call)
|
||||||
LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j;
|
LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << signal_conditioner_ID;
|
||||||
top_block_->connect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
top_block_->connect(src->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signal_conditioner_ID++;
|
signal_conditioner_ID++;
|
||||||
@ -1127,46 +1096,44 @@ int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners()
|
|||||||
|
|
||||||
int GNSSFlowgraph::disconnect_signal_sources_from_signal_conditioners()
|
int GNSSFlowgraph::disconnect_signal_sources_from_signal_conditioners()
|
||||||
{
|
{
|
||||||
int RF_Channels = 0;
|
|
||||||
int signal_conditioner_ID = 0;
|
int signal_conditioner_ID = 0;
|
||||||
for (int i = 0; i < sources_count_; i++)
|
for (int i = 0; i < sources_count_; i++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
auto& src = sig_source_.at(i);
|
||||||
|
|
||||||
// TODO: Remove this array implementation and create generic multistream connector
|
// TODO: Remove this array implementation and create generic multistream connector
|
||||||
// (if a signal source has more than 1 stream, then connect it to the multistream signal conditioner)
|
// (if a signal source has more than 1 stream, then connect it to the multistream signal conditioner)
|
||||||
if (sig_source_.at(i)->implementation() == "Raw_Array_Signal_Source")
|
if (src->implementation() == "Raw_Array_Signal_Source")
|
||||||
{
|
{
|
||||||
// Multichannel Array
|
// Multichannel Array
|
||||||
for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++)
|
for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++)
|
||||||
{
|
{
|
||||||
top_block_->disconnect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j);
|
top_block_->disconnect(src->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface.
|
auto RF_Channels = src->getRfChannels();
|
||||||
// Include GetRFChannels in the interface to avoid read config parameters here
|
|
||||||
// read the number of RF channels for each front-end
|
|
||||||
RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1);
|
|
||||||
|
|
||||||
for (int j = 0; j < RF_Channels; j++)
|
for (auto j = 0U; j < RF_Channels; ++j)
|
||||||
{
|
{
|
||||||
if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1 or sig_source_.at(i)->get_right_block()->output_signature()->max_streams() == -1)
|
if (src->get_right_block()->output_signature()->max_streams() > 1 or src->get_right_block()->output_signature()->max_streams() == -1)
|
||||||
{
|
{
|
||||||
top_block_->disconnect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
top_block_->disconnect(src->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (j == 0)
|
if (j == 0)
|
||||||
{
|
{
|
||||||
// RF_channel 0 backward compatibility with single channel sources
|
// RF_channel 0 backward compatibility with single channel sources
|
||||||
top_block_->disconnect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
top_block_->disconnect(src->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call)
|
// Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call)
|
||||||
top_block_->disconnect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
top_block_->disconnect(src->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signal_conditioner_ID++;
|
signal_conditioner_ID++;
|
||||||
|
@ -53,6 +53,7 @@ class ChannelInterface;
|
|||||||
class ConfigurationInterface;
|
class ConfigurationInterface;
|
||||||
class GNSSBlockInterface;
|
class GNSSBlockInterface;
|
||||||
class Gnss_Satellite;
|
class Gnss_Satellite;
|
||||||
|
class SignalSourceInterface;
|
||||||
|
|
||||||
/*! \brief This class represents a GNSS flow graph.
|
/*! \brief This class represents a GNSS flow graph.
|
||||||
*
|
*
|
||||||
@ -230,7 +231,7 @@ private:
|
|||||||
std::shared_ptr<ConfigurationInterface> configuration_;
|
std::shared_ptr<ConfigurationInterface> configuration_;
|
||||||
std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> queue_;
|
std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> queue_;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<GNSSBlockInterface>> sig_source_;
|
std::vector<std::shared_ptr<SignalSourceInterface>> sig_source_;
|
||||||
std::vector<std::shared_ptr<GNSSBlockInterface>> sig_conditioner_;
|
std::vector<std::shared_ptr<GNSSBlockInterface>> sig_conditioner_;
|
||||||
std::vector<std::shared_ptr<ChannelInterface>> channels_;
|
std::vector<std::shared_ptr<ChannelInterface>> channels_;
|
||||||
std::shared_ptr<GNSSBlockInterface> observables_;
|
std::shared_ptr<GNSSBlockInterface> observables_;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "in_memory_configuration.h"
|
#include "in_memory_configuration.h"
|
||||||
#include "observables_interface.h"
|
#include "observables_interface.h"
|
||||||
#include "pvt_interface.h"
|
#include "pvt_interface.h"
|
||||||
|
#include "signal_source_interface.h"
|
||||||
#include "telemetry_decoder_interface.h"
|
#include "telemetry_decoder_interface.h"
|
||||||
#include "tracking_interface.h"
|
#include "tracking_interface.h"
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
@ -45,7 +46,7 @@ TEST(GNSSBlockFactoryTest, InstantiateFileSignalSource)
|
|||||||
// Example of a factory as a shared_ptr
|
// Example of a factory as a shared_ptr
|
||||||
std::shared_ptr<GNSSBlockFactory> factory = std::make_shared<GNSSBlockFactory>();
|
std::shared_ptr<GNSSBlockFactory> factory = std::make_shared<GNSSBlockFactory>();
|
||||||
// Example of a block as a shared_ptr
|
// Example of a block as a shared_ptr
|
||||||
std::shared_ptr<GNSSBlockInterface> signal_source = factory->GetSignalSource(configuration.get(), queue.get());
|
auto signal_source = factory->GetSignalSource(configuration.get(), queue.get());
|
||||||
EXPECT_STREQ("SignalSource", signal_source->role().c_str());
|
EXPECT_STREQ("SignalSource", signal_source->role().c_str());
|
||||||
EXPECT_STREQ("File_Signal_Source", signal_source->implementation().c_str());
|
EXPECT_STREQ("File_Signal_Source", signal_source->implementation().c_str());
|
||||||
}
|
}
|
||||||
@ -59,7 +60,7 @@ TEST(GNSSBlockFactoryTest, InstantiateWrongSignalSource)
|
|||||||
// Example of a factory as a unique_ptr
|
// Example of a factory as a unique_ptr
|
||||||
std::unique_ptr<GNSSBlockFactory> factory = std::make_unique<GNSSBlockFactory>();
|
std::unique_ptr<GNSSBlockFactory> factory = std::make_unique<GNSSBlockFactory>();
|
||||||
// Example of a block as a unique_ptr
|
// Example of a block as a unique_ptr
|
||||||
std::unique_ptr<GNSSBlockInterface> signal_source = factory->GetSignalSource(configuration.get(), queue.get());
|
auto signal_source = factory->GetSignalSource(configuration.get(), queue.get());
|
||||||
EXPECT_EQ(nullptr, signal_source);
|
EXPECT_EQ(nullptr, signal_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,8 +351,8 @@ TEST(GNSSBlockFactoryTest, InstantiateWrongPvt)
|
|||||||
{
|
{
|
||||||
std::shared_ptr<InMemoryConfiguration> configuration = std::make_shared<InMemoryConfiguration>();
|
std::shared_ptr<InMemoryConfiguration> configuration = std::make_shared<InMemoryConfiguration>();
|
||||||
configuration->set_property("PVT.implementation", "Pepito");
|
configuration->set_property("PVT.implementation", "Pepito");
|
||||||
std::unique_ptr<GNSSBlockFactory> factory = std::make_unique<GNSSBlockFactory>();
|
auto factory = std::make_unique<GNSSBlockFactory>();
|
||||||
std::shared_ptr<GNSSBlockInterface> pvt_ = factory->GetPVT(configuration.get());
|
std::shared_ptr<GNSSBlockInterface> pvt_ = factory->GetPVT(configuration.get());
|
||||||
std::shared_ptr<PvtInterface> pvt = std::dynamic_pointer_cast<PvtInterface>(pvt_);
|
auto pvt = std::dynamic_pointer_cast<PvtInterface>(pvt_);
|
||||||
EXPECT_EQ(nullptr, pvt);
|
EXPECT_EQ(nullptr, pvt);
|
||||||
}
|
}
|
||||||
|
@ -53,5 +53,9 @@ TEST(FileSignalSource, InstantiateFileNotExists)
|
|||||||
config->set_property("Test.item_type", "gr_complex");
|
config->set_property("Test.item_type", "gr_complex");
|
||||||
config->set_property("Test.repeat", "false");
|
config->set_property("Test.repeat", "false");
|
||||||
|
|
||||||
EXPECT_THROW({ auto uptr = std::make_shared<FileSignalSource>(config.get(), "Test", 0, 1, queue.get()); }, std::exception);
|
// the file existence test was moved from the ctor to the connect() call. The argument to
|
||||||
|
// connect doesn't matter, since the exception should be thrown sooner than any connections
|
||||||
|
auto top = gr::make_top_block("GNSSUnitTest");
|
||||||
|
auto uptr = std::make_shared<FileSignalSource>(config.get(), "Test", 0, 1, queue.get());
|
||||||
|
EXPECT_THROW({ uptr->connect(top); }, std::exception);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
#include "gps_iono.h"
|
#include "gps_iono.h"
|
||||||
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
|
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
|
||||||
#include "gps_utc_model.h"
|
#include "gps_utc_model.h"
|
||||||
#include <boost/any.hpp> // for bad_any_cast
|
#include "signal_source_interface.h" // for SignalSourceInterface
|
||||||
|
#include <boost/any.hpp> // for bad_any_cast
|
||||||
#include <boost/exception/exception.hpp>
|
#include <boost/exception/exception.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
@ -181,6 +182,10 @@ void wait_message()
|
|||||||
|
|
||||||
bool front_end_capture(const std::shared_ptr<ConfigurationInterface>& configuration)
|
bool front_end_capture(const std::shared_ptr<ConfigurationInterface>& configuration)
|
||||||
{
|
{
|
||||||
|
auto success = false;
|
||||||
|
|
||||||
|
std::string trace_step;
|
||||||
|
|
||||||
gr::top_block_sptr top_block;
|
gr::top_block_sptr top_block;
|
||||||
GNSSBlockFactory block_factory;
|
GNSSBlockFactory block_factory;
|
||||||
std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> queue;
|
std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> queue;
|
||||||
@ -188,43 +193,37 @@ bool front_end_capture(const std::shared_ptr<ConfigurationInterface>& configurat
|
|||||||
queue = std::make_shared<Concurrent_Queue<pmt::pmt_t>>();
|
queue = std::make_shared<Concurrent_Queue<pmt::pmt_t>>();
|
||||||
top_block = gr::make_top_block("Acquisition test");
|
top_block = gr::make_top_block("Acquisition test");
|
||||||
|
|
||||||
std::shared_ptr<GNSSBlockInterface> source;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Note: the block_factory returns a unique_ptr (what you would get with an "auto"
|
||||||
|
// declaration), but the flowgraph uses shared_ptr. Without further understanding of why
|
||||||
|
// it should matter in this context, used shared_ptr throughout
|
||||||
|
std::shared_ptr<SignalSourceInterface> source;
|
||||||
|
std::shared_ptr<GNSSBlockInterface> conditioner;
|
||||||
|
|
||||||
|
trace_step = "creating source";
|
||||||
source = block_factory.GetSignalSource(configuration.get(), queue.get());
|
source = block_factory.GetSignalSource(configuration.get(), queue.get());
|
||||||
}
|
|
||||||
catch (const boost::exception_ptr& e)
|
|
||||||
{
|
|
||||||
std::cout << "Exception caught in creating source " << e << '\n';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<GNSSBlockInterface> conditioner;
|
trace_step = "creating signal conditioner";
|
||||||
try
|
|
||||||
{
|
|
||||||
conditioner = block_factory.GetSignalConditioner(configuration.get());
|
conditioner = block_factory.GetSignalConditioner(configuration.get());
|
||||||
}
|
|
||||||
catch (const boost::exception_ptr& e)
|
|
||||||
{
|
|
||||||
std::cout << "Exception caught in creating signal conditioner " << e << '\n';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
gr::block_sptr sink;
|
|
||||||
sink = gr::blocks::file_sink::make(sizeof(gr_complex), "tmp_capture.dat");
|
|
||||||
|
|
||||||
// -- Find number of samples per spreading code ---
|
trace_step = "unexpected in setup code";
|
||||||
int64_t fs_in_ = configuration->property("GNSS-SDR.internal_fs_sps", 2048000);
|
|
||||||
int samples_per_code = round(fs_in_ / (GPS_L1_CA_CODE_RATE_CPS / GPS_L1_CA_CODE_LENGTH_CHIPS));
|
|
||||||
int nsamples = samples_per_code * 50;
|
|
||||||
|
|
||||||
int skip_samples = fs_in_ * 5; // skip 5 seconds
|
gr::block_sptr sink;
|
||||||
|
sink = gr::blocks::file_sink::make(sizeof(gr_complex), "tmp_capture.dat");
|
||||||
|
|
||||||
gr::block_sptr head = gr::blocks::head::make(sizeof(gr_complex), nsamples);
|
// -- Find number of samples per spreading code ---
|
||||||
|
int64_t fs_in_ = configuration->property("GNSS-SDR.internal_fs_sps", 2048000);
|
||||||
|
int samples_per_code = round(fs_in_ / (GPS_L1_CA_CODE_RATE_CPS / GPS_L1_CA_CODE_LENGTH_CHIPS));
|
||||||
|
int nsamples = samples_per_code * 50;
|
||||||
|
|
||||||
gr::block_sptr skiphead = gr::blocks::skiphead::make(sizeof(gr_complex), skip_samples);
|
int skip_samples = fs_in_ * 5; // skip 5 seconds
|
||||||
|
|
||||||
try
|
gr::block_sptr head = gr::blocks::head::make(sizeof(gr_complex), nsamples);
|
||||||
{
|
|
||||||
|
gr::block_sptr skiphead = gr::blocks::skiphead::make(sizeof(gr_complex), skip_samples);
|
||||||
|
|
||||||
|
trace_step = "connecting the GNU Radio blocks";
|
||||||
source->connect(top_block);
|
source->connect(top_block);
|
||||||
conditioner->connect(top_block);
|
conditioner->connect(top_block);
|
||||||
top_block->connect(source->get_right_block(), 0, conditioner->get_left_block(), 0);
|
top_block->connect(source->get_right_block(), 0, conditioner->get_left_block(), 0);
|
||||||
@ -232,14 +231,15 @@ bool front_end_capture(const std::shared_ptr<ConfigurationInterface>& configurat
|
|||||||
top_block->connect(skiphead, 0, head, 0);
|
top_block->connect(skiphead, 0, head, 0);
|
||||||
top_block->connect(head, 0, sink, 0);
|
top_block->connect(head, 0, sink, 0);
|
||||||
top_block->run();
|
top_block->run();
|
||||||
|
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (std::exception const& e)
|
||||||
{
|
{
|
||||||
std::cout << "Failure connecting the GNU Radio blocks " << e.what() << '\n';
|
std::cout << "Exception caught " << trace_step << ": " << e.what() << std::endl;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user