mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-01-18 21:23:02 +00:00
Merge branch 'lenhart-fifo_source' into next
This commit is contained in:
commit
f767f792bd
1
AUTHORS
1
AUTHORS
@ -54,6 +54,7 @@ Gerald LaMountain gerald@gece.neu.edu Contributor
|
|||||||
Jim Melton jim.melton@sncorp.com Contributor
|
Jim Melton jim.melton@sncorp.com Contributor
|
||||||
Josh Schindehette jschindehette@geontech.com Contributor
|
Josh Schindehette jschindehette@geontech.com Contributor
|
||||||
Leonardo Tonetto tonetto.dev@gmail.com Contributor
|
Leonardo Tonetto tonetto.dev@gmail.com Contributor
|
||||||
|
Malte Lenhart malte.lenhart@mailbox.org Contributor
|
||||||
Mara Branzanti mara.branzanti@gmail.com Contributor
|
Mara Branzanti mara.branzanti@gmail.com Contributor
|
||||||
Marc Molina marc.molina.pena@gmail.com Contributor
|
Marc Molina marc.molina.pena@gmail.com Contributor
|
||||||
Marc Sales marcsales92@gmail.com Contributor
|
Marc Sales marcsales92@gmail.com Contributor
|
||||||
|
56
conf/gnss-sdr_GPS_L1_fifo.conf
Normal file
56
conf/gnss-sdr_GPS_L1_fifo.conf
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
; This is a GNSS-SDR configuration file
|
||||||
|
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
|
||||||
|
; SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
; SPDX-FileCopyrightText: (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
|
|
||||||
|
; You can define your own receiver and invoke it by doing
|
||||||
|
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf
|
||||||
|
;
|
||||||
|
|
||||||
|
[GNSS-SDR]
|
||||||
|
|
||||||
|
;######### GLOBAL OPTIONS ##################
|
||||||
|
GNSS-SDR.internal_fs_sps=25000000
|
||||||
|
|
||||||
|
;######### SIGNAL_SOURCE CONFIG ############
|
||||||
|
SignalSource.implementation=Fifo_Signal_Source
|
||||||
|
SignalSource.filename=fifo.fifo ; example usage: mkfifo fifo.fifo && cat path_to.bin >> fifo.fifo
|
||||||
|
SignalSource.sample_type=ishort; ; sample representation in fifo stream - will always output gr_complex
|
||||||
|
SignalSource.dump=false
|
||||||
|
;SignalSource.dump_filename=dump
|
||||||
|
|
||||||
|
;######### SIGNAL_CONDITIONER CONFIG ############
|
||||||
|
SignalConditioner.implementation=Pass_Through
|
||||||
|
|
||||||
|
;######### CHANNELS GLOBAL CONFIG ############
|
||||||
|
Channels_1C.count=8
|
||||||
|
Channels.in_acquisition=1
|
||||||
|
Channel.signal=1C
|
||||||
|
|
||||||
|
;######### ACQUISITION GLOBAL CONFIG ############
|
||||||
|
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
|
||||||
|
Acquisition_1C.item_type=gr_complex
|
||||||
|
Acquisition_1C.pfa=0.01
|
||||||
|
Acquisition_1C.doppler_max=10000
|
||||||
|
Acquisition_1C.doppler_step=250
|
||||||
|
|
||||||
|
;######### TRACKING GLOBAL CONFIG ############
|
||||||
|
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
|
||||||
|
Tracking_1C.item_type=gr_complex
|
||||||
|
Tracking_1C.pll_bw_hz=40.0;
|
||||||
|
Tracking_1C.dll_bw_hz=4.0;
|
||||||
|
|
||||||
|
;######### TELEMETRY DECODER GPS CONFIG ############
|
||||||
|
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
|
||||||
|
|
||||||
|
;######### OBSERVABLES CONFIG ############
|
||||||
|
Observables.implementation=Hybrid_Observables
|
||||||
|
|
||||||
|
;######### PVT CONFIG ############
|
||||||
|
PVT.implementation=RTKLIB_PVT
|
||||||
|
PVT.positioning_mode=Single
|
||||||
|
PVT.output_rate_ms=100
|
||||||
|
PVT.display_rate_ms=500
|
||||||
|
PVT.iono_model=Broadcast
|
||||||
|
PVT.trop_model=Saastamoinen
|
||||||
|
PVT.output_path=./files
|
@ -62,6 +62,11 @@ SPDX-FileCopyrightText: 2011-2021 Carles Fernandez-Prades <carles.fernandez@cttc
|
|||||||
|
|
||||||
### Improvements in Usability:
|
### Improvements in Usability:
|
||||||
|
|
||||||
|
- Added a new `Fifo_Signal_Source` implementation that allows using a
|
||||||
|
[Unix FIFO](https://en.wikipedia.org/wiki/Named_pipe) as a signal source, thus
|
||||||
|
allowing to multiplex signal streams outside of `gnss-sdr`, letting another
|
||||||
|
program to hold access to the receiver, or allowing signal sources that are
|
||||||
|
not supported by `gnss-sdr` but can dump the signal to a FIFO.
|
||||||
- Avoid segmentation faults in the flow graph connection and/or starting due to
|
- Avoid segmentation faults in the flow graph connection and/or starting due to
|
||||||
some common inconsistencies in the configuration file.
|
some common inconsistencies in the configuration file.
|
||||||
- Provide hints to the user in case of failed flow graph connection due to
|
- Provide hints to the user in case of failed flow graph connection due to
|
||||||
|
@ -272,7 +272,7 @@ void signal_generator_c::generate_codes()
|
|||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < vector_length_; i++)
|
for (unsigned int i = 0; i < vector_length_; i++)
|
||||||
{
|
{
|
||||||
sampled_code_pilot_[sat][i] *= sqrt(std::pow(10.0F, CN0_dB_[sat] / 10.0F) / BW_BB_ / 2.0F);
|
sampled_code_pilot_[sat][i] *= std::sqrt(std::pow(10.0F, CN0_dB_[sat] / 10.0F) / BW_BB_ / 2.0F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ void signal_generator_c::generate_codes()
|
|||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < vector_length_; i++)
|
for (unsigned int i = 0; i < vector_length_; i++)
|
||||||
{
|
{
|
||||||
sampled_code_pilot_[sat][i] *= sqrt(std::pow(10.0F, CN0_dB_[sat] / 10.0F) / BW_BB_ / 2.0F);
|
sampled_code_pilot_[sat][i] *= std::sqrt(std::pow(10.0F, CN0_dB_[sat] / 10.0F) / BW_BB_ / 2.0F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,7 @@ set(SIGNAL_SOURCE_ADAPTER_SOURCES
|
|||||||
signal_source_base.cc
|
signal_source_base.cc
|
||||||
file_source_base.cc
|
file_source_base.cc
|
||||||
file_signal_source.cc
|
file_signal_source.cc
|
||||||
|
fifo_signal_source.cc
|
||||||
multichannel_file_signal_source.cc
|
multichannel_file_signal_source.cc
|
||||||
gen_signal_source.cc
|
gen_signal_source.cc
|
||||||
nsr_file_signal_source.cc
|
nsr_file_signal_source.cc
|
||||||
@ -111,6 +112,7 @@ set(SIGNAL_SOURCE_ADAPTER_HEADERS
|
|||||||
signal_source_base.h
|
signal_source_base.h
|
||||||
file_source_base.h
|
file_source_base.h
|
||||||
file_signal_source.h
|
file_signal_source.h
|
||||||
|
fifo_signal_source.h
|
||||||
multichannel_file_signal_source.h
|
multichannel_file_signal_source.h
|
||||||
gen_signal_source.h
|
gen_signal_source.h
|
||||||
nsr_file_signal_source.h
|
nsr_file_signal_source.h
|
||||||
|
93
src/algorithms/signal_source/adapters/fifo_signal_source.cc
Normal file
93
src/algorithms/signal_source/adapters/fifo_signal_source.cc
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*!
|
||||||
|
* \file fifo_signal_source.cc
|
||||||
|
*
|
||||||
|
* \brief Implementation of the class for retrieving samples through a Unix FIFO
|
||||||
|
* \author Malte Lenhart, 2021. malte.lenhart(at)mailbox.org
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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 "fifo_signal_source.h"
|
||||||
|
#include "configuration_interface.h"
|
||||||
|
#include "fifo_reader.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
|
#include <glog/logging.h>
|
||||||
|
#include <gnuradio/blocks/file_sink.h>
|
||||||
|
#include <gnuradio/blocks/file_source.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
FifoSignalSource::FifoSignalSource(ConfigurationInterface const* configuration,
|
||||||
|
std::string const& role, unsigned int in_streams, unsigned int out_streams,
|
||||||
|
[[maybe_unused]] Concurrent_Queue<pmt::pmt_t>* queue)
|
||||||
|
: SignalSourceBase(configuration, role, "Fifo_Signal_Source"s),
|
||||||
|
item_size_(sizeof(gr_complex)), // currenty output item size is always gr_complex
|
||||||
|
fifo_reader_(FifoReader::make(configuration->property(role + ".filename"s, "../data/example_capture.dat"s),
|
||||||
|
configuration->property(role + ".sample_type"s, "ishort"s))),
|
||||||
|
dump_(configuration->property(role + ".dump", false)),
|
||||||
|
dump_filename_(configuration->property(role + ".dump_filename"s, "./data/signal_source.dat"s))
|
||||||
|
{
|
||||||
|
if (dump_)
|
||||||
|
{
|
||||||
|
DLOG(INFO) << "Dumping output into file " << (dump_filename_ + ".bin"s);
|
||||||
|
file_sink_ = gr::blocks::file_sink::make(item_size_, (dump_filename_ + ".bin").c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_streams > 0)
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "A signal source does not have an input stream";
|
||||||
|
}
|
||||||
|
if (out_streams > 1)
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "This implementation only supports one output stream";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FifoSignalSource::connect(gr::top_block_sptr top_block)
|
||||||
|
{
|
||||||
|
// here we could add a throttle as done in the file_source_base if required
|
||||||
|
if (dump_)
|
||||||
|
{
|
||||||
|
top_block->connect(fifo_reader_, 0, file_sink_, 0);
|
||||||
|
DLOG(INFO) << "connected source to file sink";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FifoSignalSource::disconnect(gr::top_block_sptr top_block)
|
||||||
|
{
|
||||||
|
if (dump_)
|
||||||
|
{
|
||||||
|
top_block->disconnect(fifo_reader_, 0, file_sink_, 0);
|
||||||
|
DLOG(INFO) << "disconnected source from file sink";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t FifoSignalSource::item_size()
|
||||||
|
{
|
||||||
|
return item_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gr::basic_block_sptr FifoSignalSource::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 FifoSignalSource::get_right_block()
|
||||||
|
{
|
||||||
|
return fifo_reader_;
|
||||||
|
}
|
79
src/algorithms/signal_source/adapters/fifo_signal_source.h
Normal file
79
src/algorithms/signal_source/adapters/fifo_signal_source.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*!
|
||||||
|
* \file fifo_signal_source.h
|
||||||
|
*
|
||||||
|
* \brief Header file of the class for retrieving samples through a Unix FIFO
|
||||||
|
* \author Malte Lenhart, 2021. malte.lenhart(at)mailbox.org
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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_FIFO_SIGNAL_SOURCE_H
|
||||||
|
#define GNSS_SDR_FIFO_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
|
#include "concurrent_queue.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
|
#include <pmt/pmt.h>
|
||||||
|
|
||||||
|
|
||||||
|
/** \addtogroup Signal_Source
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Signal_Source_adapters
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
// forward declaration to avoid include in header
|
||||||
|
class ConfigurationInterface;
|
||||||
|
|
||||||
|
//! \brief Class that reads a sample stream from a Unix FIFO.
|
||||||
|
//!
|
||||||
|
//! 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
|
||||||
|
//!
|
||||||
|
//! .sample_type - data type read out from the FIFO. default ishort ;
|
||||||
|
//! - note: not output format. that is always gr_complex
|
||||||
|
//!
|
||||||
|
//! .dump - whether to archive input data
|
||||||
|
//!
|
||||||
|
//! .dump_filename - if dumping, path to file for output
|
||||||
|
//!
|
||||||
|
class FifoSignalSource : public SignalSourceBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FifoSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
||||||
|
unsigned int in_streams, unsigned int out_streams,
|
||||||
|
Concurrent_Queue<pmt::pmt_t>* queue);
|
||||||
|
|
||||||
|
~FifoSignalSource() = default;
|
||||||
|
|
||||||
|
//! override methods from GNSSBlockInterface
|
||||||
|
void connect(gr::top_block_sptr top_block) override;
|
||||||
|
void disconnect(gr::top_block_sptr top_block) override;
|
||||||
|
size_t item_size() override;
|
||||||
|
gr::basic_block_sptr get_left_block() override;
|
||||||
|
gr::basic_block_sptr get_right_block() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
private:
|
||||||
|
//! output size - always gr_complex
|
||||||
|
const size_t item_size_;
|
||||||
|
//! internal fifo_reader_ class acts as signal source
|
||||||
|
const gnss_shared_ptr<gr::block> fifo_reader_;
|
||||||
|
|
||||||
|
gnss_shared_ptr<gr::block> file_sink_;
|
||||||
|
const bool dump_;
|
||||||
|
const std::string dump_filename_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
/** \} */
|
||||||
|
#endif // GNSS_SDR_FIFO_SIGNAL_SOURCE_H
|
@ -261,7 +261,7 @@ uint64_t FileSourceBase::samples() const
|
|||||||
|
|
||||||
std::tuple<size_t, bool> FileSourceBase::itemTypeToSize()
|
std::tuple<size_t, bool> FileSourceBase::itemTypeToSize()
|
||||||
{
|
{
|
||||||
auto is_complex_t = false;
|
auto is_interleaved = false;
|
||||||
auto item_size = size_t(0);
|
auto item_size = size_t(0);
|
||||||
|
|
||||||
if (item_type_ == "gr_complex")
|
if (item_type_ == "gr_complex")
|
||||||
@ -279,7 +279,7 @@ std::tuple<size_t, bool> FileSourceBase::itemTypeToSize()
|
|||||||
else if (item_type_ == "ishort")
|
else if (item_type_ == "ishort")
|
||||||
{
|
{
|
||||||
item_size = sizeof(int16_t);
|
item_size = sizeof(int16_t);
|
||||||
is_complex_t = true;
|
is_interleaved = true;
|
||||||
}
|
}
|
||||||
else if (item_type_ == "byte")
|
else if (item_type_ == "byte")
|
||||||
{
|
{
|
||||||
@ -288,7 +288,7 @@ std::tuple<size_t, bool> FileSourceBase::itemTypeToSize()
|
|||||||
else if (item_type_ == "ibyte")
|
else if (item_type_ == "ibyte")
|
||||||
{
|
{
|
||||||
item_size = sizeof(int8_t);
|
item_size = sizeof(int8_t);
|
||||||
is_complex_t = true;
|
is_interleaved = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -297,7 +297,7 @@ std::tuple<size_t, bool> FileSourceBase::itemTypeToSize()
|
|||||||
item_size = sizeof(gr_complex);
|
item_size = sizeof(gr_complex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_tuple(item_size, is_complex_t);
|
return std::make_tuple(item_size, is_interleaved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ size_t FileSourceBase::samplesToSkip() const
|
|||||||
|
|
||||||
size_t FileSourceBase::computeSamplesInFile() const
|
size_t FileSourceBase::computeSamplesInFile() const
|
||||||
{
|
{
|
||||||
auto n_samples = size_t(samples());
|
auto n_samples = static_cast<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 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)
|
if (n_samples == 0)
|
||||||
@ -467,7 +467,7 @@ gnss_shared_ptr<gr::block> FileSourceBase::create_valve()
|
|||||||
if (samples() > 0)
|
if (samples() > 0)
|
||||||
{
|
{
|
||||||
// if a number of samples is specified, honor it by creating a valve
|
// if a number of samples is specified, honor it by creating a valve
|
||||||
// In practice, this is always true
|
// in practice, this is always true
|
||||||
valve_ = gnss_sdr_make_valve(source_item_size(), samples(), queue_);
|
valve_ = gnss_sdr_make_valve(source_item_size(), samples(), queue_);
|
||||||
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
|
DLOG(INFO) << "valve(" << valve_->unique_id() << ")";
|
||||||
|
|
||||||
@ -499,7 +499,7 @@ void FileSourceBase::create_valve_hook() {}
|
|||||||
void FileSourceBase::create_sink_hook() {}
|
void FileSourceBase::create_sink_hook() {}
|
||||||
|
|
||||||
|
|
||||||
// Subclass hooks for connection/disconnectino
|
// Subclass hooks for connection/disconnection
|
||||||
void FileSourceBase::pre_connect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {} // NOLINT(performance-unnecessary-value-param)
|
void FileSourceBase::pre_connect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {} // NOLINT(performance-unnecessary-value-param)
|
||||||
void FileSourceBase::post_connect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {} // NOLINT(performance-unnecessary-value-param)
|
void FileSourceBase::post_connect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {} // NOLINT(performance-unnecessary-value-param)
|
||||||
void FileSourceBase::pre_disconnect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {} // NOLINT(performance-unnecessary-value-param)
|
void FileSourceBase::pre_disconnect_hook(gr::top_block_sptr top_block [[maybe_unused]]) {} // NOLINT(performance-unnecessary-value-param)
|
||||||
|
@ -14,6 +14,7 @@ endif()
|
|||||||
|
|
||||||
|
|
||||||
set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
||||||
|
fifo_reader.cc
|
||||||
unpack_byte_2bit_samples.cc
|
unpack_byte_2bit_samples.cc
|
||||||
unpack_byte_2bit_cpx_samples.cc
|
unpack_byte_2bit_cpx_samples.cc
|
||||||
unpack_byte_4bit_samples.cc
|
unpack_byte_4bit_samples.cc
|
||||||
@ -27,6 +28,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
|||||||
|
|
||||||
|
|
||||||
set(SIGNAL_SOURCE_GR_BLOCKS_HEADERS
|
set(SIGNAL_SOURCE_GR_BLOCKS_HEADERS
|
||||||
|
fifo_reader.h
|
||||||
unpack_byte_2bit_samples.h
|
unpack_byte_2bit_samples.h
|
||||||
unpack_byte_2bit_cpx_samples.h
|
unpack_byte_2bit_cpx_samples.h
|
||||||
unpack_byte_4bit_samples.h
|
unpack_byte_4bit_samples.h
|
||||||
|
114
src/algorithms/signal_source/gnuradio_blocks/fifo_reader.cc
Normal file
114
src/algorithms/signal_source/gnuradio_blocks/fifo_reader.cc
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*!
|
||||||
|
* \file fifo_reader.cc
|
||||||
|
*
|
||||||
|
* \brief Implementation of the class to retrieve samples from an existing Unix FIFO
|
||||||
|
* \author Malte Lenhart, 2021. malte.lenhart(at)mailbox.org
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fifo_reader.h"
|
||||||
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
// initial construction; pass to private constructor
|
||||||
|
FifoReader::sptr FifoReader::make(const std::string &file_name, const std::string &sample_type)
|
||||||
|
{
|
||||||
|
return gnuradio::get_initial_sptr(new FifoReader(file_name, sample_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
// private constructor called by ::make
|
||||||
|
FifoReader::FifoReader(const std::string &file_name, const std::string &sample_type)
|
||||||
|
: gr::sync_block("fifo_reader",
|
||||||
|
gr::io_signature::make(0, 0, 0), // no input
|
||||||
|
gr::io_signature::make(1, 1, sizeof(gr_complex))), // <+MIN_OUT+>, <+MAX_OUT+>, sizeof(<+OTYPE+>)
|
||||||
|
file_name_(file_name),
|
||||||
|
sample_type_(sample_type)
|
||||||
|
{
|
||||||
|
DLOG(INFO) << "Starting FifoReader";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FifoReader::start()
|
||||||
|
{
|
||||||
|
fifo_.open(file_name_, std::ios::binary);
|
||||||
|
if (!fifo_.is_open())
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "Error opening FIFO";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// work loop
|
||||||
|
// taken from here: https://stackoverflow.com/questions/25546619/work-with-fifo-in-c-blocking-read
|
||||||
|
int FifoReader::work(int noutput_items,
|
||||||
|
__attribute__((unused)) gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items)
|
||||||
|
{
|
||||||
|
if (output_items.size() > 1)
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "FifoReader connected to too many outputs";
|
||||||
|
}
|
||||||
|
|
||||||
|
// read samples out
|
||||||
|
size_t items_retrieved = 0;
|
||||||
|
if (sample_type_ == "ishort")
|
||||||
|
{
|
||||||
|
// ishort == int16_t
|
||||||
|
items_retrieved = read_interleaved<int16_t>(noutput_items, output_items);
|
||||||
|
}
|
||||||
|
else if (sample_type_ == "gr_complex")
|
||||||
|
{
|
||||||
|
LOG(WARNING) << sample_type_ << " is not yet tested. Please consider removing this warning if tested successfully";
|
||||||
|
items_retrieved = read_gr_complex(noutput_items, output_items);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// please see gr_complex_ip_packet_source for inspiration on how to implement other sample types
|
||||||
|
LOG(ERROR) << sample_type_ << " is unfortunately not yet implemented as sample type";
|
||||||
|
}
|
||||||
|
|
||||||
|
// we return varying number of data -> call produce & return flag
|
||||||
|
produce(0, items_retrieved);
|
||||||
|
return this->WORK_CALLED_PRODUCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read gr_complex items from fifo
|
||||||
|
// this fct has duplicate code with the templated read_interleaved fct in header
|
||||||
|
size_t FifoReader::read_gr_complex(int noutput_items, gr_vector_void_star &output_items)
|
||||||
|
{
|
||||||
|
size_t items_retrieved = 0;
|
||||||
|
for (int n = 0; n < noutput_items; n++)
|
||||||
|
{
|
||||||
|
gr_complex sample;
|
||||||
|
fifo_.read(reinterpret_cast<char *>(&sample), sizeof(sample));
|
||||||
|
if (fifo_.good())
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_items.at(0))[n] = sample;
|
||||||
|
items_retrieved++;
|
||||||
|
}
|
||||||
|
else if (fifo_.eof())
|
||||||
|
{
|
||||||
|
fifo_.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fifo_error_output();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items_retrieved;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FifoReader::fifo_error_output() const
|
||||||
|
{
|
||||||
|
LOG(ERROR) << "unhandled FIFO event";
|
||||||
|
}
|
99
src/algorithms/signal_source/gnuradio_blocks/fifo_reader.h
Normal file
99
src/algorithms/signal_source/gnuradio_blocks/fifo_reader.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*!
|
||||||
|
* \file fifo_reader.h
|
||||||
|
*
|
||||||
|
* \brief Header file to retrieve samples from an existing Unix FIFO
|
||||||
|
* \author Malte Lenhart, 2021. malte.lenhart(at)mailbox.org
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_FIFO_READER_H_
|
||||||
|
#define GNSS_SDR_FIFO_READER_H_
|
||||||
|
|
||||||
|
#include "gnss_block_interface.h"
|
||||||
|
#include <gnuradio/sync_block.h>
|
||||||
|
#include <fstream> // std::ifstream
|
||||||
|
|
||||||
|
/** \addtogroup Signal_Source
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Signal_Source_gnuradio_blocks
|
||||||
|
* \{ */
|
||||||
|
class FifoReader : virtual public gr::sync_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! \brief static function to create a class instance
|
||||||
|
using sptr = gnss_shared_ptr<FifoReader>;
|
||||||
|
static sptr make(const std::string &file_name, const std::string &sample_type);
|
||||||
|
|
||||||
|
~FifoReader() = default;
|
||||||
|
|
||||||
|
//! initialize istream resource for FIFO
|
||||||
|
bool start();
|
||||||
|
|
||||||
|
// gnu radio work cycle function
|
||||||
|
int work(int noutput_items,
|
||||||
|
gr_vector_const_void_star &input_items,
|
||||||
|
gr_vector_void_star &output_items);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! \brief Constructor
|
||||||
|
//! private constructor called by function make
|
||||||
|
//! (gr handles this with public and private header pair)
|
||||||
|
FifoReader(const std::string &file_name, const std::string &sample_type);
|
||||||
|
|
||||||
|
size_t read_gr_complex(int noutput_items, gr_vector_void_star &output_items);
|
||||||
|
//! function to read data out of FIFO which is stored as interleaved I/Q stream.
|
||||||
|
//! template argument determines sample_type
|
||||||
|
template <typename Type>
|
||||||
|
size_t read_interleaved(int noutput_items, gr_vector_void_star &output_items)
|
||||||
|
{
|
||||||
|
size_t items_retrieved = 0;
|
||||||
|
for (int n = 0; n < noutput_items; n++)
|
||||||
|
{
|
||||||
|
// TODO: try if performance increases if we copy larger chunks to vector.
|
||||||
|
// how to read from stream: https://en.cppreference.com/w/cpp/io/basic_ifstream
|
||||||
|
std::array<char, 4> buffer; // gr_complex is 32bit = 4*char
|
||||||
|
fifo_.read(reinterpret_cast<char *>(&buffer[0]), buffer.size());
|
||||||
|
if (fifo_.good())
|
||||||
|
{
|
||||||
|
Type real;
|
||||||
|
Type imag;
|
||||||
|
memcpy(&real, &buffer[0], sizeof(real));
|
||||||
|
memcpy(&imag, &buffer[2], sizeof(imag));
|
||||||
|
static_cast<gr_complex *>(output_items.at(0))[n] = gr_complex(real, imag);
|
||||||
|
items_retrieved++;
|
||||||
|
}
|
||||||
|
else if (fifo_.eof())
|
||||||
|
{
|
||||||
|
fifo_.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fifo_error_output();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items_retrieved;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! this function moves logging output from this header into the source file
|
||||||
|
//! thereby eliminating the need to include glog/logging.h in this header
|
||||||
|
void fifo_error_output() const;
|
||||||
|
|
||||||
|
const std::string file_name_;
|
||||||
|
const std::string sample_type_;
|
||||||
|
std::ifstream fifo_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
/** \} */
|
||||||
|
#endif /* GNSS_SDR_FIFO_READER_H_ */
|
@ -104,6 +104,7 @@ Gr_Complex_Ip_Packet_Source::Gr_Complex_Ip_Packet_Source(std::string src_device,
|
|||||||
gr::io_signature::make(1, 4, item_size)) // 1 to 4 baseband complex channels
|
gr::io_signature::make(1, 4, item_size)) // 1 to 4 baseband complex channels
|
||||||
{
|
{
|
||||||
std::cout << "Start Ethernet packet capture\n";
|
std::cout << "Start Ethernet packet capture\n";
|
||||||
|
std::cout << "Overflow events will be indicated by o's\n";
|
||||||
|
|
||||||
d_n_baseband_channels = n_baseband_channels;
|
d_n_baseband_channels = n_baseband_channels;
|
||||||
if (wire_sample_type == "cbyte")
|
if (wire_sample_type == "cbyte")
|
||||||
@ -121,6 +122,11 @@ Gr_Complex_Ip_Packet_Source::Gr_Complex_Ip_Packet_Source(std::string src_device,
|
|||||||
d_wire_sample_type = 3;
|
d_wire_sample_type = 3;
|
||||||
d_bytes_per_sample = d_n_baseband_channels * 8;
|
d_bytes_per_sample = d_n_baseband_channels * 8;
|
||||||
}
|
}
|
||||||
|
else if (wire_sample_type == "ishort")
|
||||||
|
{
|
||||||
|
d_wire_sample_type = 4;
|
||||||
|
d_bytes_per_sample = d_n_baseband_channels * 4;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Unknown wire sample type\n";
|
std::cout << "Unknown wire sample type\n";
|
||||||
@ -307,7 +313,7 @@ void Gr_Complex_Ip_Packet_Source::pcap_callback(__attribute__((unused)) u_char *
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// notify overflow
|
// notify overflow
|
||||||
std::cout << "O" << std::flush;
|
std::cout << "o" << std::flush;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,6 +403,25 @@ void Gr_Complex_Ip_Packet_Source::demux_samples(const gr_vector_void_star &outpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 4: // interleaved short samples
|
||||||
|
for (const auto &output_item : output_items)
|
||||||
|
{
|
||||||
|
int16_t real;
|
||||||
|
int16_t imag;
|
||||||
|
memcpy(&real, &fifo_buff[fifo_read_ptr], sizeof(real));
|
||||||
|
fifo_read_ptr += 2; // two bytes in short
|
||||||
|
memcpy(&imag, &fifo_buff[fifo_read_ptr], sizeof(imag));
|
||||||
|
fifo_read_ptr += 2; // two bytes in short
|
||||||
|
if (d_IQ_swap)
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(real, imag);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_cast<gr_complex *>(output_item)[n] = gr_complex(imag, real);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
std::cout << "Unknown wire sample type\n";
|
std::cout << "Unknown wire sample type\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -422,36 +447,20 @@ int Gr_Complex_Ip_Packet_Source::work(int noutput_items,
|
|||||||
|
|
||||||
if (output_items.size() > static_cast<uint64_t>(d_n_baseband_channels))
|
if (output_items.size() > static_cast<uint64_t>(d_n_baseband_channels))
|
||||||
{
|
{
|
||||||
std::cout << "Configuration error: more baseband channels connected than the available in the UDP source\n";
|
std::cout << "Configuration error: more baseband channels connected than available in the UDP source\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
int num_samples_readed;
|
int num_samples_readed;
|
||||||
int bytes_requested;
|
int bytes_requested;
|
||||||
switch (d_wire_sample_type)
|
|
||||||
|
bytes_requested = noutput_items * d_bytes_per_sample;
|
||||||
|
if (bytes_requested < fifo_items)
|
||||||
{
|
{
|
||||||
case 1: // complex byte samples
|
num_samples_readed = noutput_items; // read all
|
||||||
case 2: // complex 4 bits samples
|
}
|
||||||
case 3: // complex float samples
|
else
|
||||||
bytes_requested = noutput_items * d_bytes_per_sample;
|
{
|
||||||
if (bytes_requested < fifo_items)
|
num_samples_readed = fifo_items / d_bytes_per_sample; // read what we have
|
||||||
{
|
|
||||||
num_samples_readed = noutput_items; // read all
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
num_samples_readed = fifo_items / d_bytes_per_sample; // read what we have
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default: // complex byte samples
|
|
||||||
bytes_requested = noutput_items * d_bytes_per_sample;
|
|
||||||
if (bytes_requested < fifo_items)
|
|
||||||
{
|
|
||||||
num_samples_readed = noutput_items; // read all
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
num_samples_readed = fifo_items / d_bytes_per_sample; // read what we have
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes_requested = num_samples_readed * d_bytes_per_sample;
|
bytes_requested = num_samples_readed * d_bytes_per_sample;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
#include "direct_resampler_conditioner.h"
|
#include "direct_resampler_conditioner.h"
|
||||||
|
#include "fifo_signal_source.h"
|
||||||
#include "file_signal_source.h"
|
#include "file_signal_source.h"
|
||||||
#include "fir_filter.h"
|
#include "fir_filter.h"
|
||||||
#include "freq_xlating_fir_filter.h"
|
#include "freq_xlating_fir_filter.h"
|
||||||
@ -647,6 +648,12 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SIGNAL SOURCES ----------------------------------------------------------
|
// SIGNAL SOURCES ----------------------------------------------------------
|
||||||
|
else if (implementation == "Fifo_Signal_Source")
|
||||||
|
{
|
||||||
|
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<FifoSignalSource>(configuration, role, in_streams,
|
||||||
|
out_streams, queue);
|
||||||
|
block = std::move(block_);
|
||||||
|
}
|
||||||
else if (implementation == "File_Signal_Source")
|
else if (implementation == "File_Signal_Source")
|
||||||
{
|
{
|
||||||
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<FileSignalSource>(configuration, role, in_streams,
|
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<FileSignalSource>(configuration, role, in_streams,
|
||||||
|
Loading…
Reference in New Issue
Block a user