mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 15:23:04 +00:00 
			
		
		
		
	Merge branch 'lenhart-fifo_source' into next
This commit is contained in:
		
							
								
								
									
										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, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Carles Fernandez
					Carles Fernandez