mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-11-10 20:10:05 +00:00
Merge branch 'ft/ion-metadata-standard-signal-source' of https://github.com/castle055/gnss-sdr into castle055-ft/ion-metadata-standard-signal-source
This commit is contained in:
commit
deec6f0cfe
@ -57,6 +57,8 @@ option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal
|
||||
|
||||
option(ENABLE_ZMQ "Enable GNU Radio ZeroMQ Messaging, requires gr-zeromq" ON)
|
||||
|
||||
option(ENABLE_ION "Enable ION GNSS-SDR Metadata Standard signal source" ON)
|
||||
|
||||
# Performance analysis tools
|
||||
option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF)
|
||||
|
||||
@ -1422,6 +1424,19 @@ else()
|
||||
endif()
|
||||
|
||||
|
||||
################################################################################
|
||||
# ION GNSS-SDR Metadata Standard
|
||||
################################################################################
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
gnss_metadata_standard
|
||||
GIT_REPOSITORY https://github.com/IonMetadataWorkingGroup/GNSS-Metadata-Standard
|
||||
GIT_TAG master
|
||||
SOURCE_DIR ${GNSSSDR_BINARY_DIR}/thirdparty/gnss-metadata-standard
|
||||
CMAKE_ARGS -DABSL_PROPAGATE_CXX_STD=ON -ABSL_BUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX=${GNSSSDR_BINARY_DIR}/gnss-metadata-standard ${ABSEIL_TOOLCHAIN_FILE}
|
||||
BINARY_DIR ${GNSSSDR_BINARY_DIR}/gnss-metadata-standard
|
||||
)
|
||||
FetchContent_MakeAvailable(gnss_metadata_standard)
|
||||
|
||||
################################################################################
|
||||
# Abseil C++ - https://abseil.io/docs/cpp/
|
||||
|
@ -119,6 +119,7 @@ set(SIGNAL_SOURCE_ADAPTER_SOURCES
|
||||
two_bit_packed_file_signal_source.cc
|
||||
four_bit_cpx_file_signal_source.cc
|
||||
file_timestamp_signal_source.cc
|
||||
ion_gsms_signal_source.cc
|
||||
${OPT_DRIVER_SOURCES}
|
||||
)
|
||||
|
||||
@ -138,6 +139,7 @@ set(SIGNAL_SOURCE_ADAPTER_HEADERS
|
||||
two_bit_packed_file_signal_source.h
|
||||
four_bit_cpx_file_signal_source.h
|
||||
file_timestamp_signal_source.h
|
||||
ion_gsms_signal_source.h
|
||||
${OPT_DRIVER_HEADERS}
|
||||
)
|
||||
|
||||
|
121
src/algorithms/signal_source/adapters/ion_gsms_signal_source.cc
Normal file
121
src/algorithms/signal_source/adapters/ion_gsms_signal_source.cc
Normal file
@ -0,0 +1,121 @@
|
||||
/*!
|
||||
* \file ion_gsms_signal_source.h
|
||||
* \brief GNSS-SDR Signal Source that reads sample streams following ION's GNSS-SDR metadata standard
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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 "ion_gsms_signal_source.h"
|
||||
#include "gnss_sdr_flags.h"
|
||||
#include "gnss_sdr_string_literals.h"
|
||||
#include <gnuradio/blocks/copy.h>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
std::vector<std::string> parse_comma_list(const std::string& str)
|
||||
{
|
||||
std::vector<std::string> list{};
|
||||
std::size_t prev_comma_at{0};
|
||||
|
||||
while (prev_comma_at < str.size())
|
||||
{
|
||||
std::size_t comma_at = str.find_first_of(',', prev_comma_at);
|
||||
if (comma_at == std::string::npos)
|
||||
{
|
||||
comma_at = str.size();
|
||||
}
|
||||
list.emplace_back(str.substr(prev_comma_at, (comma_at - prev_comma_at)));
|
||||
prev_comma_at = comma_at + 1;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
IONGSMSSignalSource::IONGSMSSignalSource(const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams,
|
||||
Concurrent_Queue<pmt::pmt_t>* queue __attribute__((unused)))
|
||||
: SignalSourceBase(configuration, role, "ION_GSMS_Signal_Source"s),
|
||||
metadata_file_(configuration->property(role + ".metadata_filename"s, "../data/example_capture_metadata.sdrx"s)),
|
||||
stream_ids_(parse_comma_list(configuration->property(role + ".streams"s, ""s))),
|
||||
metadata_(metadata_file_),
|
||||
timestamp_clock_offset_ms_(configuration->property(role + ".timestamp_clock_offset_ms"s, 0.0)),
|
||||
in_streams_(in_streams),
|
||||
out_streams_(out_streams)
|
||||
{
|
||||
if (in_streams > 0)
|
||||
{
|
||||
LOG(ERROR) << "A signal source does not have an input stream";
|
||||
}
|
||||
|
||||
sources_ = metadata_.make_stream_sources(configuration, role, stream_ids_);
|
||||
|
||||
for (const auto& source : sources_)
|
||||
{
|
||||
for (std::size_t i = 0; i < source->output_stream_count(); ++i)
|
||||
{
|
||||
copy_blocks_.push_back(gr::blocks::copy::make(source->output_stream_item_size(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IONGSMSSignalSource::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
std::size_t cumulative_index = 0;
|
||||
for (const auto& source : sources_)
|
||||
{
|
||||
for (std::size_t i = 0; i < source->output_stream_count(); ++i, ++cumulative_index)
|
||||
{
|
||||
top_block->connect(source, i, copy_blocks_[cumulative_index], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IONGSMSSignalSource::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
std::size_t cumulative_index = 0;
|
||||
for (const auto& source : sources_)
|
||||
{
|
||||
for (std::size_t i = 0; i < source->output_stream_count(); ++i, ++cumulative_index)
|
||||
{
|
||||
top_block->disconnect(source, i, copy_blocks_[cumulative_index], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gr::basic_block_sptr IONGSMSSignalSource::get_left_block()
|
||||
{
|
||||
LOG(WARNING) << "Trying to get signal source left block.";
|
||||
// return gr_basic_block_sptr();
|
||||
return IONGSMSFileSource::sptr();
|
||||
}
|
||||
|
||||
gr::basic_block_sptr IONGSMSSignalSource::get_right_block()
|
||||
{
|
||||
return get_right_block(0);
|
||||
}
|
||||
|
||||
gr::basic_block_sptr IONGSMSSignalSource::get_right_block(int RF_channel)
|
||||
{
|
||||
return copy_blocks_[RF_channel];
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*!
|
||||
* \file ion_gsms_signal_source.h
|
||||
* \brief GNSS-SDR Signal Source that reads sample streams following ION's GNSS-SDR metadata standard
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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_ION_METADATA_STANDARD_SIGNAL_SOURCE_H
|
||||
#define GNSS_SDR_ION_METADATA_STANDARD_SIGNAL_SOURCE_H
|
||||
|
||||
#include "configuration_interface.h"
|
||||
#include "file_source_base.h"
|
||||
#include "gnss_sdr_timestamp.h"
|
||||
#include "ion_gsms.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/** \addtogroup Signal_Source
|
||||
* \{ */
|
||||
/** \addtogroup Signal_Source_adapters
|
||||
* \{ */
|
||||
|
||||
/*!
|
||||
* \brief Class that reads signals samples from a file
|
||||
* and adapts it to a SignalSourceInterface
|
||||
*/
|
||||
class IONGSMSSignalSource : public SignalSourceBase
|
||||
{
|
||||
public:
|
||||
IONGSMSSignalSource(const ConfigurationInterface* configuration, const std::string& role,
|
||||
unsigned int in_streams, unsigned int out_streams,
|
||||
Concurrent_Queue<pmt::pmt_t>* queue);
|
||||
|
||||
~IONGSMSSignalSource() override = default;
|
||||
|
||||
protected:
|
||||
// std::tuple<size_t, bool> itemTypeToSize() override;
|
||||
// double packetsPerSample() const override;
|
||||
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;
|
||||
gr::basic_block_sptr get_right_block(int RF_channel) override;
|
||||
|
||||
inline size_t item_size() override
|
||||
{
|
||||
return (*sources_.begin())->output_stream_item_size(0);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string metadata_file_;
|
||||
std::vector<std::string> stream_ids_;
|
||||
std::vector<IONGSMSFileSource::sptr> sources_;
|
||||
std::vector<gnss_shared_ptr<gr::block>> copy_blocks_;
|
||||
IONGSMSMetadataHandler metadata_;
|
||||
|
||||
gnss_shared_ptr<Gnss_Sdr_Timestamp> timestamp_block_;
|
||||
std::string timestamp_file_;
|
||||
double timestamp_clock_offset_ms_;
|
||||
|
||||
uint32_t in_streams_;
|
||||
uint32_t out_streams_;
|
||||
};
|
||||
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_ION_METADATA_STANDARD_SIGNAL_SOURCE_H
|
@ -7,9 +7,10 @@
|
||||
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES "")
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS "")
|
||||
|
||||
if(ENABLE_FMCOMMS2 OR ENABLE_AD9361)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad9361_manager.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad9361_manager.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ad9361_manager.h)
|
||||
endif()
|
||||
|
||||
if(ENABLE_MAX2771)
|
||||
@ -36,12 +37,23 @@ endif()
|
||||
|
||||
if(ENABLE_PLUTOSDR)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_samples.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_samples.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ad936x_iio_samples.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_custom.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_custom.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} pps_samplestamp.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ad936x_iio_custom.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} pps_samplestamp.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ppstcprx.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ppstcprx.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ppstcprx.h)
|
||||
endif()
|
||||
|
||||
if(ENABLE_ION)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ion_gsms.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ion_gsms.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ion_gsms_chunk_data.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ion_gsms_chunk_data.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ion_gsms_metadata_handler.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ion_gsms_metadata_handler.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ion_gsms_stream_encodings.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} ion_gsms_chunk_unpacking_ctx.h)
|
||||
endif()
|
||||
|
||||
|
||||
@ -139,6 +151,11 @@ if(ENABLE_CLANG_TIDY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_ION)
|
||||
target_include_directories(signal_source_libs PUBLIC ${GNSSSDR_BINARY_DIR}/thirdparty/gnss-metadata-standard/source/api/inc)
|
||||
target_link_libraries(signal_source_libs PUBLIC api xml)
|
||||
endif()
|
||||
|
||||
set_property(TARGET signal_source_libs APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
)
|
||||
|
159
src/algorithms/signal_source/libs/ion_gsms.cc
Normal file
159
src/algorithms/signal_source/libs/ion_gsms.cc
Normal file
@ -0,0 +1,159 @@
|
||||
/*!
|
||||
* \file ion_gsms.cc
|
||||
* \brief GNU Radio block that reads a Block from a file following ION's GNSS-SDR metadata standard
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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 "ion_gsms.h"
|
||||
#include "gnuradio/block.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
IONGSMSFileSource::IONGSMSFileSource(
|
||||
const ConfigurationInterface* configuration __attribute__((unused)),
|
||||
const std::string& role __attribute__((unused)),
|
||||
const std::filesystem::path& metadata_filepath,
|
||||
const GnssMetadata::File& file,
|
||||
const GnssMetadata::Block& block,
|
||||
const std::vector<std::string>& stream_ids)
|
||||
: gr::sync_block(
|
||||
"ion_gsms_file_source",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
make_output_signature(block, stream_ids)),
|
||||
file_metadata_(file),
|
||||
block_metadata_(block),
|
||||
io_buffer_offset_(0),
|
||||
maximum_item_rate_(0),
|
||||
chunk_cycle_length_(0)
|
||||
{
|
||||
std::filesystem::path data_filepath = metadata_filepath.parent_path() / file.Url().Value();
|
||||
fd_ = std::fopen(data_filepath.c_str(), "rb");
|
||||
std::size_t block_offset = file.Offset();
|
||||
std::fseek(fd_, file.Offset() + block_offset + block.SizeHeader(), SEEK_SET);
|
||||
|
||||
std::size_t output_stream_offset = 0;
|
||||
for (const auto& chunk : block.Chunks())
|
||||
{
|
||||
chunk_data_.emplace_back(std::make_shared<IONGSMSChunkData>(chunk, stream_ids, output_stream_offset));
|
||||
chunk_cycle_length_ += chunk.CountWords() * chunk.SizeWord();
|
||||
const std::size_t out_count = chunk_data_.back()->output_stream_count();
|
||||
output_stream_offset += out_count;
|
||||
for (std::size_t i = 0; i < out_count; ++i)
|
||||
{
|
||||
output_stream_item_sizes_.push_back(chunk_data_.back()->output_stream_item_size(i));
|
||||
maximum_item_rate_ = std::max(chunk_data_.back()->output_stream_item_rate(i), maximum_item_rate_);
|
||||
}
|
||||
}
|
||||
output_stream_count_ = output_stream_offset;
|
||||
}
|
||||
|
||||
IONGSMSFileSource::~IONGSMSFileSource()
|
||||
{
|
||||
std::fclose(fd_);
|
||||
}
|
||||
|
||||
int IONGSMSFileSource::work(
|
||||
int noutput_items,
|
||||
gr_vector_const_void_star& input_items __attribute__((unused)),
|
||||
gr_vector_void_star& output_items)
|
||||
{
|
||||
const std::size_t max_sample_output = std::floor((noutput_items - 1.0) / maximum_item_rate_);
|
||||
io_buffer_.resize(max_sample_output * chunk_cycle_length_);
|
||||
io_buffer_offset_ = 0;
|
||||
std::fread(io_buffer_.data(), sizeof(decltype(io_buffer_)::value_type), io_buffer_.size(), fd_);
|
||||
|
||||
items_produced_.resize(output_items.size());
|
||||
for (int& i : items_produced_)
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
||||
while (io_buffer_offset_ < io_buffer_.size())
|
||||
{
|
||||
for (auto& c : chunk_data_)
|
||||
{
|
||||
auto* chunk = c.get();
|
||||
io_buffer_offset_ += chunk->read_from_buffer(io_buffer_.data(), io_buffer_offset_);
|
||||
chunk->write_to_output(output_items, items_produced_);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < items_produced_.size(); ++i)
|
||||
{
|
||||
produce(i, items_produced_[i]);
|
||||
}
|
||||
|
||||
return WORK_CALLED_PRODUCE;
|
||||
}
|
||||
|
||||
std::size_t IONGSMSFileSource::output_stream_count() const
|
||||
{
|
||||
return output_stream_count_;
|
||||
}
|
||||
|
||||
std::size_t IONGSMSFileSource::output_stream_item_size(std::size_t stream_index) const
|
||||
{
|
||||
return output_stream_item_sizes_[stream_index];
|
||||
}
|
||||
|
||||
|
||||
gr::io_signature::sptr IONGSMSFileSource::make_output_signature(const GnssMetadata::Block& block, const std::vector<std::string>& stream_ids)
|
||||
{
|
||||
int nstreams = 0;
|
||||
std::vector<int> item_sizes{};
|
||||
|
||||
for (const auto& chunk : block.Chunks())
|
||||
{
|
||||
for (const auto& lump : chunk.Lumps())
|
||||
{
|
||||
for (const auto& stream : lump.Streams())
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto& stream_id : stream_ids)
|
||||
{
|
||||
if (stream_id == stream.Id())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
++nstreams;
|
||||
std::size_t sample_bitsize = stream.Packedbits() / stream.RateFactor();
|
||||
if (stream.Packedbits() >= 2 * stream.RateFactor() * stream.Quantization())
|
||||
{
|
||||
// Samples have 'Complex' format
|
||||
sample_bitsize /= 2;
|
||||
}
|
||||
item_sizes.push_back(bits_to_item_size(sample_bitsize));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gr::io_signature::makev(
|
||||
nstreams,
|
||||
nstreams,
|
||||
item_sizes);
|
||||
}
|
74
src/algorithms/signal_source/libs/ion_gsms.h
Normal file
74
src/algorithms/signal_source/libs/ion_gsms.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*!
|
||||
* \file ion_gsms.h
|
||||
* \brief GNU Radio block that reads a Block from a file following ION's GNSS-SDR metadata standard
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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_ION_GNSS_SDR_METADATA_STANDARD_H
|
||||
#define GNSS_SDR_ION_GNSS_SDR_METADATA_STANDARD_H
|
||||
|
||||
#include "configuration_interface.h"
|
||||
#include "gnss_block_interface.h"
|
||||
#include "ion_gsms_chunk_data.h"
|
||||
#include <gnuradio/block.h>
|
||||
#include <gnuradio/sync_block.h>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class IONGSMSFileSource : public gr::sync_block
|
||||
{
|
||||
public:
|
||||
using sptr = gnss_shared_ptr<IONGSMSFileSource>;
|
||||
|
||||
IONGSMSFileSource(
|
||||
const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
const std::filesystem::path& metadata_filepath,
|
||||
const GnssMetadata::File& file,
|
||||
const GnssMetadata::Block& block,
|
||||
const std::vector<std::string>& stream_ids);
|
||||
|
||||
~IONGSMSFileSource() override;
|
||||
|
||||
int work(
|
||||
int noutput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items) override;
|
||||
|
||||
std::size_t output_stream_count() const;
|
||||
std::size_t output_stream_item_size(std::size_t stream_index) const;
|
||||
|
||||
private:
|
||||
static gr::io_signature::sptr make_output_signature(const GnssMetadata::Block& block, const std::vector<std::string>& stream_ids);
|
||||
|
||||
private:
|
||||
const GnssMetadata::File& file_metadata_;
|
||||
const GnssMetadata::Block& block_metadata_;
|
||||
FILE* fd_;
|
||||
std::vector<uint8_t> io_buffer_;
|
||||
std::size_t io_buffer_offset_;
|
||||
std::vector<int> items_produced_;
|
||||
std::size_t output_stream_count_;
|
||||
std::vector<std::size_t> output_stream_item_sizes_;
|
||||
std::size_t maximum_item_rate_;
|
||||
std::vector<std::shared_ptr<IONGSMSChunkData>> chunk_data_;
|
||||
std::size_t chunk_cycle_length_;
|
||||
};
|
||||
|
||||
#include "ion_gsms_metadata_handler.h"
|
||||
|
||||
|
||||
#endif // GNSS_SDR_ION_GNSS_SDR_METADATA_STANDARD_H
|
266
src/algorithms/signal_source/libs/ion_gsms_chunk_data.cc
Normal file
266
src/algorithms/signal_source/libs/ion_gsms_chunk_data.cc
Normal file
@ -0,0 +1,266 @@
|
||||
/*!
|
||||
* \file ion_gsms_chunk_data.cc
|
||||
* \brief Holds logic for reading and decoding samples from a chunk
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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 "ion_gsms_chunk_data.h"
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
IONGSMSChunkData::IONGSMSChunkData(const GnssMetadata::Chunk& chunk, const std::vector<std::string>& stream_ids, std::size_t output_stream_offset)
|
||||
: chunk_(chunk),
|
||||
sizeword_(chunk_.SizeWord()),
|
||||
countwords_(chunk_.CountWords())
|
||||
{
|
||||
with_word_type(sizeword_, [&]<typename WordType> {
|
||||
buffer_ = new WordType[countwords_];
|
||||
});
|
||||
|
||||
const std::size_t total_bitsize = sizeword_ * countwords_ * 8;
|
||||
std::size_t used_bitsize = 0;
|
||||
std::size_t output_streams = 0;
|
||||
for (const auto& lump : chunk.Lumps())
|
||||
{
|
||||
for (const auto& stream : lump.Streams())
|
||||
{
|
||||
used_bitsize += stream.Packedbits();
|
||||
|
||||
bool found = false;
|
||||
for (const auto& stream_id : stream_ids)
|
||||
{
|
||||
if (stream_id == stream.Id())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
streams_.emplace_back(lump, stream, GnssMetadata::encoding_from_string(stream.Encoding()), output_streams + output_stream_offset);
|
||||
++output_streams;
|
||||
std::size_t sample_bitsize = stream.Packedbits() / stream.RateFactor();
|
||||
std::size_t sample_rate = stream.RateFactor();
|
||||
if (stream.Packedbits() >= 2 * stream.RateFactor() * stream.Quantization())
|
||||
{
|
||||
// Samples have 'Complex' format
|
||||
sample_bitsize /= 2;
|
||||
sample_rate *= 2;
|
||||
}
|
||||
output_stream_item_size_.push_back(bits_to_item_size(sample_bitsize));
|
||||
output_stream_item_rate_.push_back(sample_rate);
|
||||
}
|
||||
else
|
||||
{
|
||||
streams_.emplace_back(lump, stream, GnssMetadata::encoding_from_string(stream.Encoding()), -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output_stream_count_ = output_streams;
|
||||
padding_bitsize_ = total_bitsize - used_bitsize;
|
||||
}
|
||||
|
||||
|
||||
IONGSMSChunkData::~IONGSMSChunkData()
|
||||
{
|
||||
with_word_type(sizeword_, [&]<typename WordType> {
|
||||
delete[] static_cast<WordType*>(buffer_);
|
||||
});
|
||||
}
|
||||
|
||||
std::size_t IONGSMSChunkData::read_from_buffer(uint8_t* buffer, std::size_t offset)
|
||||
{
|
||||
memset(buffer_, 0, sizeword_ * countwords_);
|
||||
memcpy(buffer_, &buffer[offset], sizeword_ * countwords_);
|
||||
return sizeword_ * countwords_;
|
||||
}
|
||||
|
||||
void IONGSMSChunkData::write_to_output(gr_vector_void_star& outputs, std::vector<int>& output_items)
|
||||
{
|
||||
switch (sizeword_)
|
||||
{
|
||||
case 1:
|
||||
unpack_words<int8_t>(outputs, output_items);
|
||||
break;
|
||||
case 2:
|
||||
unpack_words<int16_t>(outputs, output_items);
|
||||
break;
|
||||
case 4:
|
||||
unpack_words<int32_t>(outputs, output_items);
|
||||
break;
|
||||
case 8:
|
||||
unpack_words<int64_t>(outputs, output_items);
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown word size (" << std::to_string(sizeword_) << "), unpacking nothing.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::size_t IONGSMSChunkData::output_stream_count() const
|
||||
{
|
||||
return output_stream_count_;
|
||||
}
|
||||
|
||||
std::size_t IONGSMSChunkData::output_stream_item_size(std::size_t stream_index) const
|
||||
{
|
||||
return output_stream_item_size_[stream_index];
|
||||
}
|
||||
|
||||
std::size_t IONGSMSChunkData::output_stream_item_rate(std::size_t stream_index) const
|
||||
{
|
||||
return output_stream_item_rate_[stream_index];
|
||||
}
|
||||
|
||||
|
||||
template <typename WT>
|
||||
void IONGSMSChunkData::unpack_words(gr_vector_void_star& outputs, std::vector<int>& output_items)
|
||||
{
|
||||
WT* data = static_cast<WT*>(buffer_);
|
||||
// TODO - Swap endiannes if needed
|
||||
|
||||
IONGSMSChunkUnpackingCtx<WT> ctx{
|
||||
chunk_.Shift(),
|
||||
data,
|
||||
countwords_,
|
||||
};
|
||||
|
||||
// Head padding
|
||||
if (padding_bitsize_ > 0 && chunk_.Padding() == GnssMetadata::Chunk::Head)
|
||||
{
|
||||
ctx.shift_padding(padding_bitsize_);
|
||||
}
|
||||
|
||||
// Samples
|
||||
for (const auto& [lump, stream, encoding, output_index] : streams_)
|
||||
{
|
||||
if (output_index == -1)
|
||||
{
|
||||
// skip stream
|
||||
ctx.shift_padding(stream.Packedbits());
|
||||
}
|
||||
else
|
||||
{
|
||||
output_items[output_index] += write_stream_samples(ctx, lump, stream, encoding, &outputs[output_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename WT>
|
||||
std::size_t IONGSMSChunkData::write_stream_samples(
|
||||
IONGSMSChunkUnpackingCtx<WT>& ctx,
|
||||
const GnssMetadata::Lump& lump,
|
||||
const GnssMetadata::IonStream& stream,
|
||||
const GnssMetadata::StreamEncoding stream_encoding,
|
||||
void** out)
|
||||
{
|
||||
std::size_t sample_bitsize = stream.Packedbits() / stream.RateFactor();
|
||||
std::size_t sample_count = stream.RateFactor();
|
||||
|
||||
if (stream.Packedbits() >= 2 * stream.RateFactor() * stream.Quantization())
|
||||
{
|
||||
// Samples have 'Complex' format
|
||||
sample_bitsize /= 2;
|
||||
sample_count *= 2;
|
||||
}
|
||||
|
||||
if (sample_bitsize <= 8)
|
||||
{
|
||||
write_n_samples<WT, int8_t>(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, (int8_t**)(out));
|
||||
}
|
||||
else if (sample_bitsize <= 16)
|
||||
{
|
||||
write_n_samples<WT, int16_t>(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, (int16_t**)(out));
|
||||
}
|
||||
else if (sample_bitsize <= 32)
|
||||
{
|
||||
write_n_samples<WT, int32_t>(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, (int32_t**)(out));
|
||||
}
|
||||
else if (sample_bitsize <= 64)
|
||||
{
|
||||
write_n_samples<WT, int64_t>(ctx, lump.Shift(), sample_bitsize, sample_count, stream_encoding, (int64_t**)(out));
|
||||
}
|
||||
|
||||
return sample_count;
|
||||
}
|
||||
|
||||
template <typename WT, typename OT>
|
||||
void IONGSMSChunkData::write_n_samples(
|
||||
IONGSMSChunkUnpackingCtx<WT>& ctx,
|
||||
GnssMetadata::Lump::LumpShift lump_shift,
|
||||
uint8_t sample_bitsize,
|
||||
std::size_t sample_count,
|
||||
GnssMetadata::StreamEncoding stream_encoding,
|
||||
OT** out)
|
||||
{
|
||||
if (lump_shift == GnssMetadata::Lump::shiftRight)
|
||||
{
|
||||
auto* sample = static_cast<OT*>(*out);
|
||||
sample += sample_count;
|
||||
for (std::size_t i = 0; i < sample_count; ++i)
|
||||
{
|
||||
*sample = 0;
|
||||
ctx.shift_sample(sample_bitsize, sample);
|
||||
decode_sample(sample_bitsize, sample, stream_encoding);
|
||||
--sample;
|
||||
}
|
||||
}
|
||||
else // if (lump_shift == GnssMetadata::Lump::shiftLeft || lump_shift == GnssMetadata::Lump::shiftUndefined)
|
||||
{
|
||||
auto* sample = static_cast<OT*>(*out);
|
||||
for (std::size_t i = 0; i < sample_count; ++i)
|
||||
{
|
||||
*sample = 0;
|
||||
ctx.shift_sample(sample_bitsize, sample);
|
||||
decode_sample(sample_bitsize, sample, stream_encoding);
|
||||
++sample;
|
||||
}
|
||||
}
|
||||
|
||||
(*out) += sample_count;
|
||||
}
|
||||
|
||||
|
||||
// Static utilities
|
||||
void IONGSMSChunkData::decode_sample(const uint8_t sample_bitsize, auto* sample, const GnssMetadata::StreamEncoding encoding)
|
||||
{
|
||||
using SampleType = std::remove_pointer_t<decltype(sample)>;
|
||||
switch (sample_bitsize)
|
||||
{
|
||||
case 2:
|
||||
*sample = GnssMetadata::two_bit_look_up<SampleType>[encoding][*sample];
|
||||
break;
|
||||
case 3:
|
||||
*sample = GnssMetadata::three_bit_look_up<SampleType>[encoding][*sample];
|
||||
break;
|
||||
case 4:
|
||||
*sample = GnssMetadata::four_bit_look_up<SampleType>[encoding][*sample];
|
||||
break;
|
||||
case 5:
|
||||
*sample = GnssMetadata::five_bit_look_up<SampleType>[encoding][*sample];
|
||||
break;
|
||||
default:
|
||||
// TODO - Is this an error that can happen?
|
||||
// for now we'll just do nothing, if the sample is this wide it may need no decoding
|
||||
break;
|
||||
}
|
||||
}
|
155
src/algorithms/signal_source/libs/ion_gsms_chunk_data.h
Normal file
155
src/algorithms/signal_source/libs/ion_gsms_chunk_data.h
Normal file
@ -0,0 +1,155 @@
|
||||
/*!
|
||||
* \file ion_gsms_chunk_data.h
|
||||
* \brief Holds logic for reading and decoding samples from a chunk
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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 ION_GSM_CHUNK_DATA_H
|
||||
#define ION_GSM_CHUNK_DATA_H
|
||||
|
||||
#include "GnssMetadata.h"
|
||||
#include "ion_gsms_chunk_unpacking_ctx.h"
|
||||
#include "ion_gsms_stream_encodings.h"
|
||||
#include <gnuradio/block.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
inline std::size_t bits_to_item_size(const std::size_t bit_count)
|
||||
{
|
||||
if (bit_count <= 8)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (bit_count <= 16)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
if (bit_count <= 32)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
if (bit_count <= 64)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
// You are asking too much of this humble processor
|
||||
LOG(ERROR) << "Item size too large (" << std::to_string(bit_count) << "), returning nonsense.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
void with_word_type(const uint8_t word_size, auto&& callback)
|
||||
{
|
||||
switch (word_size)
|
||||
{
|
||||
case 1:
|
||||
callback.template operator()<int8_t>();
|
||||
break;
|
||||
case 2:
|
||||
callback.template operator()<int16_t>();
|
||||
break;
|
||||
case 4:
|
||||
callback.template operator()<int32_t>();
|
||||
break;
|
||||
case 8:
|
||||
callback.template operator()<int64_t>();
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown word size (" << std::to_string(word_size) << "), returning nonsense.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class IONGSMSChunkData
|
||||
{
|
||||
public:
|
||||
IONGSMSChunkData(const GnssMetadata::Chunk& chunk, const std::vector<std::string>& stream_ids, std::size_t output_stream_offset);
|
||||
|
||||
~IONGSMSChunkData();
|
||||
|
||||
IONGSMSChunkData(const IONGSMSChunkData& rhl) = delete;
|
||||
IONGSMSChunkData& operator=(const IONGSMSChunkData& rhl) = delete;
|
||||
|
||||
IONGSMSChunkData(IONGSMSChunkData&& rhl) = delete;
|
||||
IONGSMSChunkData& operator=(IONGSMSChunkData&& rhl) = delete;
|
||||
|
||||
std::size_t read_from_buffer(uint8_t* buffer, std::size_t offset);
|
||||
|
||||
void write_to_output(gr_vector_void_star& outputs, std::vector<int>& output_items);
|
||||
|
||||
std::size_t output_stream_count() const;
|
||||
std::size_t output_stream_item_size(std::size_t stream_index) const;
|
||||
std::size_t output_stream_item_rate(std::size_t stream_index) const;
|
||||
|
||||
private:
|
||||
template <typename WT>
|
||||
void unpack_words(gr_vector_void_star& outputs, std::vector<int>& output_items);
|
||||
|
||||
template <typename WT>
|
||||
std::size_t write_stream_samples(
|
||||
IONGSMSChunkUnpackingCtx<WT>& ctx,
|
||||
const GnssMetadata::Lump& lump,
|
||||
const GnssMetadata::IonStream& stream,
|
||||
GnssMetadata::StreamEncoding stream_encoding,
|
||||
void** out);
|
||||
|
||||
template <typename WT, typename OT>
|
||||
void write_n_samples(
|
||||
IONGSMSChunkUnpackingCtx<WT>& ctx,
|
||||
GnssMetadata::Lump::LumpShift lump_shift,
|
||||
uint8_t sample_bitsize,
|
||||
std::size_t sample_count,
|
||||
GnssMetadata::StreamEncoding stream_encoding,
|
||||
OT** out);
|
||||
|
||||
static void decode_sample(uint8_t sample_bitsize, auto* sample, GnssMetadata::StreamEncoding encoding);
|
||||
|
||||
private:
|
||||
const GnssMetadata::Chunk& chunk_;
|
||||
uint8_t sizeword_;
|
||||
uint8_t countwords_;
|
||||
uint8_t padding_bitsize_;
|
||||
std::size_t output_stream_count_;
|
||||
std::vector<std::size_t> output_stream_item_size_;
|
||||
std::vector<std::size_t> output_stream_item_rate_;
|
||||
|
||||
struct stream_metadata_t
|
||||
{
|
||||
const GnssMetadata::Lump& lump;
|
||||
const GnssMetadata::IonStream& stream;
|
||||
GnssMetadata::StreamEncoding stream_encoding;
|
||||
int output_index = -1;
|
||||
|
||||
stream_metadata_t(
|
||||
const GnssMetadata::Lump& lump_,
|
||||
const GnssMetadata::IonStream& stream_,
|
||||
GnssMetadata::StreamEncoding stream_encoding_,
|
||||
int output_index_ = -1) : lump(lump_),
|
||||
stream(stream_),
|
||||
stream_encoding(stream_encoding_),
|
||||
output_index(output_index_)
|
||||
{
|
||||
}
|
||||
};
|
||||
std::vector<stream_metadata_t> streams_;
|
||||
|
||||
void* buffer_;
|
||||
};
|
||||
|
||||
#endif // ION_GSM_CHUNK_DATA_H
|
179
src/algorithms/signal_source/libs/ion_gsms_chunk_unpacking_ctx.h
Normal file
179
src/algorithms/signal_source/libs/ion_gsms_chunk_unpacking_ctx.h
Normal file
@ -0,0 +1,179 @@
|
||||
/*!
|
||||
* \file ion_gsms_chunk_unpacking_ctx.h
|
||||
* \brief Holds state and provides utilities for unpacking samples from a chunk
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* This is a template class, and thus, its member functions must be defined in the header file.
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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 ION_GSM_CHUNK_UNPACKING_CTX_H
|
||||
#define ION_GSM_CHUNK_UNPACKING_CTX_H
|
||||
|
||||
#include "GnssMetadata.h"
|
||||
#include <gnuradio/block.h>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
template <typename WT>
|
||||
struct IONGSMSChunkUnpackingCtx
|
||||
{
|
||||
static constexpr uint8_t word_bitsize_ = sizeof(WT) * 8;
|
||||
|
||||
const GnssMetadata::Chunk::WordShift word_shift_direction_;
|
||||
WT* iterator_; // Not owned by this class, MUST NOT destroy
|
||||
WT current_word_;
|
||||
uint8_t bitshift_ = 0;
|
||||
|
||||
IONGSMSChunkUnpackingCtx(
|
||||
const GnssMetadata::Chunk::WordShift word_shift,
|
||||
WT* data_buffer,
|
||||
uint8_t data_buffer_word_count) : word_shift_direction_(word_shift)
|
||||
{
|
||||
if (word_shift_direction_ == GnssMetadata::Chunk::Left)
|
||||
{
|
||||
iterator_ = data_buffer;
|
||||
}
|
||||
else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
|
||||
{
|
||||
iterator_ = &data_buffer[data_buffer_word_count];
|
||||
}
|
||||
advance_word(); // Initializes current_word_
|
||||
}
|
||||
|
||||
void advance_word()
|
||||
{
|
||||
WT word = *iterator_;
|
||||
if (word_shift_direction_ == GnssMetadata::Chunk::Left)
|
||||
{
|
||||
++iterator_;
|
||||
}
|
||||
else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
|
||||
{
|
||||
--iterator_;
|
||||
}
|
||||
|
||||
current_word_ = word;
|
||||
}
|
||||
|
||||
void shift_current_word(uint8_t n)
|
||||
{
|
||||
if ((n % word_bitsize_) == 0)
|
||||
{
|
||||
for (uint8_t i = 0; i < (n / word_bitsize_); ++i)
|
||||
{
|
||||
advance_word();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (word_shift_direction_ == GnssMetadata::Chunk::Left)
|
||||
{
|
||||
current_word_ <<= n;
|
||||
}
|
||||
else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
|
||||
{
|
||||
current_word_ >>= n;
|
||||
}
|
||||
|
||||
bitshift_ += n;
|
||||
if (bitshift_ >= word_bitsize_)
|
||||
{
|
||||
advance_word();
|
||||
bitshift_ -= word_bitsize_;
|
||||
}
|
||||
}
|
||||
|
||||
void shift_padding(uint8_t n_bits)
|
||||
{
|
||||
if (n_bits == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n_bits + (bitshift_ % word_bitsize_)) >= word_bitsize_)
|
||||
{
|
||||
const uint8_t bits_shifted = word_bitsize_ - (bitshift_ % word_bitsize_);
|
||||
|
||||
shift_current_word(bits_shifted);
|
||||
shift_padding(n_bits - bits_shifted);
|
||||
}
|
||||
else
|
||||
{
|
||||
shift_current_word(n_bits);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OT>
|
||||
void shift_sample(const uint8_t sample_bitsize, OT* output, uint8_t output_bit_offset = 0)
|
||||
{
|
||||
if (sample_bitsize % word_bitsize_ == 0)
|
||||
{
|
||||
const uint8_t words_per_sample = sample_bitsize / word_bitsize_;
|
||||
for (uint8_t i = 0; i < words_per_sample; ++i)
|
||||
{
|
||||
if (word_shift_direction_ == GnssMetadata::Chunk::Left)
|
||||
{
|
||||
*output |= (current_word_ << ((words_per_sample - 1 - i) * word_bitsize_));
|
||||
}
|
||||
else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
|
||||
{
|
||||
*output |= (current_word_ << (i * word_bitsize_));
|
||||
// TODO - reverse bit order of sample? maybe?
|
||||
}
|
||||
advance_word();
|
||||
}
|
||||
}
|
||||
else if ((sample_bitsize + (bitshift_ % word_bitsize_)) > word_bitsize_)
|
||||
{
|
||||
const uint8_t bits_shifted = word_bitsize_ - (bitshift_ % word_bitsize_);
|
||||
|
||||
if (word_shift_direction_ == GnssMetadata::Chunk::Left)
|
||||
{
|
||||
WT mask = ~((1 << (word_bitsize_ - bits_shifted)) - 1);
|
||||
*output |= ((current_word_ & mask) >> output_bit_offset);
|
||||
}
|
||||
else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
|
||||
{
|
||||
WT mask = ((1 << (bits_shifted)) - 1);
|
||||
*output |= (current_word_ & mask) << output_bit_offset;
|
||||
// TODO - reverse bit order of sample? maybe?
|
||||
}
|
||||
|
||||
shift_current_word(bits_shifted);
|
||||
shift_sample(sample_bitsize - bits_shifted, output, bits_shifted);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (word_shift_direction_ == GnssMetadata::Chunk::Left)
|
||||
{
|
||||
WT mask = ~((1 << (word_bitsize_ - sample_bitsize)) - 1);
|
||||
OT sample = (current_word_ & mask) >> (word_bitsize_ - sample_bitsize);
|
||||
*output |= (sample) >> output_bit_offset;
|
||||
}
|
||||
else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
|
||||
{
|
||||
WT mask = ((1 << (sample_bitsize)) - 1);
|
||||
*output |= (current_word_ & mask) << output_bit_offset;
|
||||
// TODO - reverse bit order of sample? maybe?
|
||||
}
|
||||
|
||||
shift_current_word(sample_bitsize);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ION_GSM_CHUNK_UNPACKING_CTX_H
|
119
src/algorithms/signal_source/libs/ion_gsms_metadata_handler.cc
Normal file
119
src/algorithms/signal_source/libs/ion_gsms_metadata_handler.cc
Normal file
@ -0,0 +1,119 @@
|
||||
/*!
|
||||
* \file ion_gsms_metadata_handler.cc
|
||||
* \brief Build instances of IONGSMSFileSource as needed given a list of stream ids
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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 "ion_gsms.h"
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
IONGSMSMetadataHandler::IONGSMSMetadataHandler(const std::string& metadata_filepath)
|
||||
: metadata_filepath_(metadata_filepath)
|
||||
{
|
||||
load_metadata();
|
||||
}
|
||||
|
||||
const std::string& IONGSMSMetadataHandler::metadata_filepath() const
|
||||
{
|
||||
return metadata_filepath_;
|
||||
}
|
||||
|
||||
void IONGSMSMetadataHandler::load_metadata()
|
||||
{
|
||||
try
|
||||
{
|
||||
GnssMetadata::XmlProcessor xml_proc;
|
||||
if (!xml_proc.Load(metadata_filepath_.c_str(), false, metadata_))
|
||||
{
|
||||
LOG(ERROR) << "Could not load XML metadata file:";
|
||||
}
|
||||
}
|
||||
catch (GnssMetadata::ApiException& e)
|
||||
{
|
||||
LOG(ERROR) << "API Exception while loading XML metadata file: " << std::to_string(e.Error());
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
LOG(ERROR) << "Exception while loading XML metadata file: " << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<IONGSMSFileSource::sptr> IONGSMSMetadataHandler::make_stream_sources(const ConfigurationInterface* configuration, const std::string& role, const std::vector<std::string>& stream_ids) const
|
||||
{
|
||||
std::vector<IONGSMSFileSource::sptr> sources{};
|
||||
for (const auto& file : metadata_.Files())
|
||||
{
|
||||
for (const auto& lane : metadata_.Lanes())
|
||||
{
|
||||
if (lane.Id() == file.Lane().Id())
|
||||
{
|
||||
for (const auto& block : lane.Blocks())
|
||||
{
|
||||
bool block_done = false;
|
||||
for (const auto& chunk : block.Chunks())
|
||||
{
|
||||
for (const auto& lump : chunk.Lumps())
|
||||
{
|
||||
for (const auto& stream : lump.Streams())
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto& stream_id : stream_ids)
|
||||
{
|
||||
if (stream_id == stream.Id())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
auto source = gnss_make_shared<IONGSMSFileSource>(
|
||||
configuration,
|
||||
role,
|
||||
metadata_filepath_,
|
||||
file,
|
||||
block,
|
||||
stream_ids);
|
||||
|
||||
sources.push_back(source);
|
||||
|
||||
// This file source will take care of any other matching streams in this block
|
||||
// We can skip the rest of this block
|
||||
block_done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (block_done)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (block_done)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sources;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*!
|
||||
* \file ion_gsms_metadata_handler.h
|
||||
* \brief Build instances of IONGSMSFileSource as needed given a list of stream ids
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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 ION_GSMS_METADATA_HANDLER_H
|
||||
#define ION_GSMS_METADATA_HANDLER_H
|
||||
|
||||
#include "GnssMetadata.h"
|
||||
#include "configuration_interface.h"
|
||||
#include <gnuradio/block.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
class IONGSMSMetadataHandler
|
||||
{
|
||||
public:
|
||||
explicit IONGSMSMetadataHandler(const std::string& metadata_filepath);
|
||||
|
||||
std::vector<IONGSMSFileSource::sptr> make_stream_sources(const ConfigurationInterface* configuration, const std::string& role, const std::vector<std::string>& stream_ids) const;
|
||||
|
||||
public: // Getters
|
||||
const std::string& metadata_filepath() const;
|
||||
|
||||
private: // Private methods
|
||||
void load_metadata();
|
||||
|
||||
private: // State
|
||||
std::string metadata_filepath_;
|
||||
GnssMetadata::Metadata metadata_;
|
||||
};
|
||||
|
||||
#endif // ION_GSMS_METADATA_HANDLER_H
|
168
src/algorithms/signal_source/libs/ion_gsms_stream_encodings.h
Normal file
168
src/algorithms/signal_source/libs/ion_gsms_stream_encodings.h
Normal file
@ -0,0 +1,168 @@
|
||||
/*!
|
||||
* \file ion_gsms_stream_encodings.h
|
||||
* \brief Implements look up tables for all encodings in the standard
|
||||
* \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
|
||||
*
|
||||
* These tables are taken from the stardard's official document.
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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 ION_GSM_STREAM_ENCODINGS_H
|
||||
#define ION_GSM_STREAM_ENCODINGS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
namespace GnssMetadata
|
||||
{
|
||||
|
||||
using StreamEncoding = unsigned char;
|
||||
|
||||
namespace StreamEncodings
|
||||
{
|
||||
|
||||
constexpr unsigned char SIGN = 0;
|
||||
constexpr unsigned char OB = 1;
|
||||
constexpr unsigned char SM = 2;
|
||||
constexpr unsigned char MS = 3;
|
||||
constexpr unsigned char TC = 4;
|
||||
constexpr unsigned char OG = 5;
|
||||
constexpr unsigned char OBA = 6;
|
||||
constexpr unsigned char SMA = 7;
|
||||
constexpr unsigned char MSA = 8;
|
||||
constexpr unsigned char TCA = 9;
|
||||
constexpr unsigned char OGA = 10;
|
||||
constexpr unsigned char FP = 11;
|
||||
|
||||
} // namespace StreamEncodings
|
||||
|
||||
inline StreamEncoding encoding_from_string(const std::string& str)
|
||||
{
|
||||
if (str == "SIGN")
|
||||
{
|
||||
return StreamEncodings::SIGN;
|
||||
}
|
||||
if (str == "OB")
|
||||
{
|
||||
return StreamEncodings::OB;
|
||||
}
|
||||
if (str == "SM")
|
||||
{
|
||||
return StreamEncodings::SM;
|
||||
}
|
||||
if (str == "MS")
|
||||
{
|
||||
return StreamEncodings::MS;
|
||||
}
|
||||
if (str == "TC")
|
||||
{
|
||||
return StreamEncodings::TC;
|
||||
}
|
||||
if (str == "OG")
|
||||
{
|
||||
return StreamEncodings::OG;
|
||||
}
|
||||
if (str == "OBA")
|
||||
{
|
||||
return StreamEncodings::OBA;
|
||||
}
|
||||
if (str == "SMA")
|
||||
{
|
||||
return StreamEncodings::SMA;
|
||||
}
|
||||
if (str == "MSA")
|
||||
{
|
||||
return StreamEncodings::MSA;
|
||||
}
|
||||
if (str == "TCA")
|
||||
{
|
||||
return StreamEncodings::TCA;
|
||||
}
|
||||
if (str == "OGA")
|
||||
{
|
||||
return StreamEncodings::OGA;
|
||||
}
|
||||
if (str == "FP")
|
||||
{
|
||||
return StreamEncodings::FP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T two_bit_look_up[11][4]{
|
||||
{}, // [0]
|
||||
{-2, -1, 0, 1}, // [1 /*OB*/]
|
||||
{0, 1, 0, -1}, // [2 /*SM*/]
|
||||
{0, 0, 1, -1}, // [3 /*MS*/]
|
||||
{0, 1, -2, -1}, // [4 /*TC*/]
|
||||
{-2, -1, 1, 0}, // [5 /*OG*/]
|
||||
{-3, -1, 1, 3}, // [6 /*OBA*/]
|
||||
{1, 3, -1, -3}, // [7 /*SMA*/]
|
||||
{1, -1, 3, -3}, // [8 /*MSA*/]
|
||||
{1, 3, -3, -1}, // [9 /*TCA*/]
|
||||
{-3, -1, 3, 1}, // [10 /*OGA*/]
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline T three_bit_look_up[11][8]{
|
||||
{}, // [0]
|
||||
{-4, -3, -2, -1, 0, 1, 2, 3}, // [1 /*OB*/]
|
||||
{0, 1, 2, 3, 0, -1, -2, -3}, // [2 /*SM*/]
|
||||
{0, 0, 1, -1, 0, 0, 1, -1}, // [3 /*MS*/]
|
||||
{0, 1, 2, 3, -4, -3, -2, -1}, // [4 /*TC*/]
|
||||
{-4, -3, -1, -2, 3, 2, 0, 1}, // [5 /*OG*/]
|
||||
{-7, -5, -3, -1, 1, 3, 5, 7}, // [6 /*OBA*/]
|
||||
{1, 3, 5, 7, -1, -3, -5, -7}, // [7 /*SMA*/]
|
||||
{1, -1, 3, -3, 5, -5, 7, -7}, // [8 /*MSA*/]
|
||||
{1, 3, 5, 7, -7, -5, -3, -1}, // [9 /*TCA*/]
|
||||
{-7, -5, -1, -3, 7, 5, 1, 3}, // [10 /*OGA*/]
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline T four_bit_look_up[11][16]{
|
||||
{}, // [0]
|
||||
{-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}, // [1 /*OB*/]
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7}, // [2 /*SM*/]
|
||||
{0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1}, // [3 /*MS*/]
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1}, // [4 /*TC*/]
|
||||
{-8, -7, -5, -6, -1, -2, -4, -3, 7, 6, 4, 5, 0, 1, 3, 2}, // [5 /*OG*/]
|
||||
{-15, -13, -11, -9, -7, -5, -3, -1, 1, 3, 5, 7, 9, 11, 13, 15}, // [6 /*OBA*/]
|
||||
{1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15}, // [7 /*SMA*/]
|
||||
{1, -1, 3, -3, 5, -5, 7, -7, 9, -9, 11, -11, 13, -13, 15, -15}, // [8 /*MSA*/]
|
||||
{1, 3, 5, 7, 9, 11, 13, 15, -15, -13, -11, -9, -7, -5, -3, -1}, // [9 /*TCA*/]
|
||||
{-15, -13, -9, -11, -1, -3, -7, -5, 15, 13, 9, 11, 1, 3, 7, 5}, // [10 /*OGA*/]
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline T five_bit_look_up[11][32]{
|
||||
{}, // [0]
|
||||
{-16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, // [1 /*OB*/]
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15}, // [2 /*SM*/]
|
||||
{0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, 1, -1}, // [3 /*MS*/]
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1}, // [4 /*TC*/]
|
||||
{-16, -15, -13, -14, -9, -10, -12, -11, -1, -2, -4, -3, -8, -7, -5, -6, 15, 14, 12, 13, 8, 9, 11, 10, 0, 1, 3, 2, 7, 6, 4, 5}, // [5 /*OG*/]
|
||||
{-31, -29, -27, -25, -23, -21, -19, -17, -15, -13, -11, -9, -7, -5, -3, -1, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // [6 /*OBA*/]
|
||||
{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, -1, -3, -5, -7, -9, -11, -13, -15, -17, -19, -21, -23, -25, -27, -29, -31}, // [7 /*SMA*/]
|
||||
{1, -1, 3, -3, 5, -5, 7, -7, 9, -9, 11, -11, 13, -13, 15, -15, 17, -17, 19, -19, 21, -21, 23, -23, 25, -25, 27, -27, 29, -29, 31, -31}, // [8 /*MSA*/]
|
||||
{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, -31, -29, -27, -25, -23, -21, -19, -17, -15, -13, -11, -9, -7, -5, -3, -1}, // [9 /*TCA*/]
|
||||
{-31, -29, -25, -27, -17, -19, -23, -21, -1, -3, -7, -5, -15, -13, -9, -11, 31, 29, 25, 27, 17, 19, 23, 21, 1, 3, 7, 5, 15, 13, 9, 11}, // [10 /*OGA*/]
|
||||
};
|
||||
|
||||
} // namespace GnssMetadata
|
||||
|
||||
#endif // ION_GSM_STREAM_ENCODINGS_H
|
@ -70,6 +70,10 @@ if(ENABLE_FPGA)
|
||||
target_compile_definitions(core_receiver PUBLIC -DENABLE_FPGA=1)
|
||||
endif()
|
||||
|
||||
if(ENABLE_ION)
|
||||
target_compile_definitions(core_receiver PRIVATE -DENABLE_ION_SOURCE=1)
|
||||
endif()
|
||||
|
||||
if(GNURADIO_USES_STD_POINTERS)
|
||||
target_compile_definitions(core_receiver PUBLIC -DGNURADIO_USES_STD_POINTERS=1)
|
||||
endif()
|
||||
|
@ -196,6 +196,11 @@
|
||||
#include "gps_l1_ca_dll_pll_tracking_gpu.h"
|
||||
#endif
|
||||
|
||||
#if ENABLE_ION_SOURCE
|
||||
#undef Owner
|
||||
#include "ion_gsms_signal_source.h"
|
||||
#endif
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace
|
||||
@ -759,7 +764,14 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_ION_SOURCE
|
||||
else if (implementation == "ION_GSMS_Signal_Source")
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<IONGSMSSignalSource>(configuration, role, in_streams,
|
||||
out_streams, queue);
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
#if RAW_ARRAY_DRIVER
|
||||
else if (implementation == "Raw_Array_Signal_Source")
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user