mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-12-15 12:58:09 +00:00
feat: add signal source adapter for NTLab NT1065
This commit is contained in:
@@ -130,6 +130,7 @@ set(SIGNAL_SOURCE_ADAPTER_SOURCES
|
||||
labsat_signal_source.cc
|
||||
two_bit_cpx_file_signal_source.cc
|
||||
two_bit_packed_file_signal_source.cc
|
||||
ntlab_file_signal_source.cc
|
||||
four_bit_cpx_file_signal_source.cc
|
||||
file_timestamp_signal_source.cc
|
||||
${OPT_DRIVER_SOURCES}
|
||||
@@ -149,6 +150,7 @@ set(SIGNAL_SOURCE_ADAPTER_HEADERS
|
||||
labsat_signal_source.h
|
||||
two_bit_cpx_file_signal_source.h
|
||||
two_bit_packed_file_signal_source.h
|
||||
ntlab_file_signal_source.h
|
||||
four_bit_cpx_file_signal_source.h
|
||||
file_timestamp_signal_source.h
|
||||
${OPT_DRIVER_HEADERS}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*!
|
||||
* \file ntlab_file_signal_source.cc
|
||||
* \brief Interface of a class that reads signal samples from a file. Each
|
||||
* sample is two bits from multiple channels.
|
||||
*
|
||||
* \author Pedro Pereira, 2025 pereirapedrocp (at) gmail.com
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "ntlab_file_signal_source.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "gnss_sdr_string_literals.h"
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
MultiChannelTwoBitPackedFileSignalSource::MultiChannelTwoBitPackedFileSignalSource(
|
||||
const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams,
|
||||
Concurrent_Queue<pmt::pmt_t>* queue)
|
||||
: FileSourceBase(configuration, role, "ntlab_file_signal_source"s, queue, "byte"s),
|
||||
sample_type_(configuration->property(role + ".sample_type", "real"s))
|
||||
{
|
||||
int default_n_channlels_ = 4;
|
||||
n_channels_ = configuration->property(role + ".total_channels", default_n_channlels_);
|
||||
if (n_channels_ == 0)
|
||||
{
|
||||
n_channels_ = configuration->property(role + ".RF_channels", default_n_channlels_);
|
||||
}
|
||||
|
||||
if (in_streams > 0)
|
||||
{
|
||||
LOG(ERROR) << "A signal source does not have input streams";
|
||||
}
|
||||
if (out_streams > 1)
|
||||
{
|
||||
LOG(ERROR) << "This implementation only supports one output stream";
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<size_t, bool> MultiChannelTwoBitPackedFileSignalSource::itemTypeToSize()
|
||||
{
|
||||
auto is_complex_t = false;
|
||||
auto item_size = sizeof(char); // default
|
||||
|
||||
if (item_type() == "byte")
|
||||
{
|
||||
item_size = sizeof(char);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(WARNING) << "Configuration error: Unsupported item type. Using byte.";
|
||||
}
|
||||
|
||||
if (sample_type_ != "real")
|
||||
{
|
||||
is_complex_t = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(WARNING) << "Configuration error: Unsupported sample type. Using real.";
|
||||
}
|
||||
|
||||
return std::make_tuple(item_size, is_complex_t);
|
||||
}
|
||||
|
||||
double MultiChannelTwoBitPackedFileSignalSource::packetsPerSample() const
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
gnss_shared_ptr<gr::block> MultiChannelTwoBitPackedFileSignalSource::source() const
|
||||
{
|
||||
return unpack_samples_;
|
||||
}
|
||||
|
||||
void MultiChannelTwoBitPackedFileSignalSource::create_file_source_hook()
|
||||
{
|
||||
unpack_samples_ = make_unpack_ntlab_2bit_samples(item_size(), n_channels_);
|
||||
DLOG(INFO) << "unpack_byte_2bit_samples(" << unpack_samples_->unique_id() << ")";
|
||||
}
|
||||
|
||||
void MultiChannelTwoBitPackedFileSignalSource::pre_connect_hook(gr::top_block_sptr top_block)
|
||||
{
|
||||
top_block->connect(file_source(), 0, unpack_samples_, 0);
|
||||
DLOG(INFO) << "connected file source to samples unpacker";
|
||||
|
||||
for (int n = 1; n < n_channels_; n++)
|
||||
{
|
||||
top_block->connect(unpack_samples_, n, valve(), n);
|
||||
DLOG(INFO) << "connected samples unpacker to valve port " << n;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiChannelTwoBitPackedFileSignalSource::pre_disconnect_hook(gr::top_block_sptr top_block)
|
||||
{
|
||||
top_block->disconnect(file_source(), 0, unpack_samples_, 0);
|
||||
DLOG(INFO) << "disconnected file source of samples unpacker";
|
||||
|
||||
for (int n = 1; n < n_channels_; n++)
|
||||
{
|
||||
top_block->disconnect(unpack_samples_, n, valve(), n);
|
||||
DLOG(INFO) << "disconnected samples unpacker of valve port " << n;
|
||||
}
|
||||
}
|
||||
|
||||
gr::basic_block_sptr MultiChannelTwoBitPackedFileSignalSource::get_left_block()
|
||||
{
|
||||
LOG(WARNING) << "Left block of a signal source should not be retrieved";
|
||||
return gr::block_sptr();
|
||||
}
|
||||
|
||||
gr::basic_block_sptr MultiChannelTwoBitPackedFileSignalSource::get_right_block()
|
||||
{
|
||||
return valve();
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*!
|
||||
* \file ntlab_file_signal_source.h
|
||||
* \brief Interface of a class that reads signal samples from a file. Each
|
||||
* sample is two bits from multiple channels.
|
||||
*
|
||||
* \author Pedro Pereira, 2025 pereirapedrocp (at) gmail.com
|
||||
*
|
||||
* This class represents a file signal source.
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* 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_NTLAB_FILE_SIGNAL_SOURCE_H
|
||||
#define GNSS_SDR_NTLAB_FILE_SIGNAL_SOURCE_H
|
||||
|
||||
#include "file_source_base.h"
|
||||
#include "unpack_ntlab_2bit_samples.h"
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
|
||||
/** \addtogroup Signal_Source
|
||||
* \{ */
|
||||
/** \addtogroup Signal_Source_adapters
|
||||
* \{ */
|
||||
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief Class that reads signals samples from a file
|
||||
* and adapts it to a SignalSourceInterface
|
||||
*/
|
||||
class MultiChannelTwoBitPackedFileSignalSource : public FileSourceBase
|
||||
{
|
||||
public:
|
||||
MultiChannelTwoBitPackedFileSignalSource(const ConfigurationInterface* configuration,
|
||||
const std::string& role, unsigned int in_streams,
|
||||
unsigned int out_streams, Concurrent_Queue<pmt::pmt_t>* queue);
|
||||
|
||||
~MultiChannelTwoBitPackedFileSignalSource() = default;
|
||||
|
||||
gr::basic_block_sptr get_left_block() override;
|
||||
gr::basic_block_sptr get_right_block() override;
|
||||
|
||||
protected:
|
||||
std::tuple<size_t, bool> itemTypeToSize() override;
|
||||
double packetsPerSample() const override;
|
||||
gnss_shared_ptr<gr::block> source() const override;
|
||||
void create_file_source_hook() override;
|
||||
void pre_connect_hook(gr::top_block_sptr top_block) override;
|
||||
void pre_disconnect_hook(gr::top_block_sptr top_block) override;
|
||||
|
||||
private:
|
||||
std::string sample_type_;
|
||||
unpack_ntlab_2bit_samples_sptr unpack_samples_;
|
||||
int n_channels_;
|
||||
};
|
||||
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_NTLAB_FILE_SIGNAL_SOURCE_H
|
||||
@@ -29,6 +29,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
||||
unpack_short_byte_samples.cc
|
||||
rtl_tcp_signal_source_c.cc
|
||||
unpack_2bit_samples.cc
|
||||
unpack_ntlab_2bit_samples.cc
|
||||
unpack_spir_gss6450_samples.cc
|
||||
labsat23_source.cc
|
||||
${OPT_DRIVER_SOURCES}
|
||||
@@ -43,6 +44,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_HEADERS
|
||||
unpack_short_byte_samples.h
|
||||
rtl_tcp_signal_source_c.h
|
||||
unpack_2bit_samples.h
|
||||
unpack_ntlab_2bit_samples.h
|
||||
unpack_spir_gss6450_samples.h
|
||||
labsat23_source.h
|
||||
${OPT_DRIVER_HEADERS}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*!
|
||||
* \file unpack_ntlab_2bit_samples.cc
|
||||
*
|
||||
* \brief Unpacks multichannel 2-bit samples into 4 real-valued floats
|
||||
* per input byte.
|
||||
* \author Pedro Pereira pereirapedrocp (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 "unpack_ntlab_2bit_samples.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
|
||||
|
||||
unpack_ntlab_2bit_samples_sptr make_unpack_ntlab_2bit_samples(size_t item_size,
|
||||
int nchannels)
|
||||
{
|
||||
return unpack_ntlab_2bit_samples_sptr(
|
||||
new unpack_ntlab_2bit_samples(item_size,
|
||||
nchannels));
|
||||
}
|
||||
|
||||
|
||||
unpack_ntlab_2bit_samples::unpack_ntlab_2bit_samples(size_t item_size,
|
||||
int nchannels)
|
||||
: sync_interpolator("unpack_ntlab_2bit_samples",
|
||||
gr::io_signature::make(1, 1, item_size),
|
||||
gr::io_signature::make(nchannels, nchannels, sizeof(float)),
|
||||
1), // we make 4 floats out for every byte in
|
||||
item_size_(item_size),
|
||||
nchannels_(nchannels)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int unpack_ntlab_2bit_samples::work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
auto const *in = reinterpret_cast<signed char const *>(input_items[0]);
|
||||
|
||||
float *out[4];
|
||||
for (int n = 0; n < nchannels_; ++n)
|
||||
{
|
||||
out[n] = static_cast<float *>(output_items[n]);
|
||||
}
|
||||
|
||||
const int nbytes = noutput_items;
|
||||
|
||||
for (int i = 0; i < nbytes; ++i)
|
||||
{
|
||||
// Unpack each of the four 2-bit samples in the byte 'b' into four real-valued outputs.
|
||||
//
|
||||
// The NTLAB format encodes samples as sign+magnitude pairs in each byte:
|
||||
// bits 7-6 = [M0 S0] -> sample 0
|
||||
// bits 5-4 = [M1 S1] -> sample 1
|
||||
// bits 3-2 = [M2 S2] -> sample 2
|
||||
// bits 1-0 = [M3 S3] -> sample 3
|
||||
//
|
||||
// Here we loop over channel index n = 0...3, compute the bit shift to extract
|
||||
// the two bits for that channel (shift = 6,4,2,0), then:
|
||||
// - M = magnitude bit (1->|sample|=3, 0->|sample|=1)
|
||||
// - S = sign bit (1->positive, 0->negative)
|
||||
// We reconstruct the signed sample value (+/-1 or +/-3) and store it in out[n][i].
|
||||
uint8_t b = static_cast<uint8_t>(in[i]);
|
||||
for (int n = 0; n < nchannels_; ++n)
|
||||
{
|
||||
int shift = 2 * (3 - n); // 6, 4, 2, 0
|
||||
int M = (b >> (shift + 1)) & 0x1; // magnitude bit
|
||||
int S = (b >> shift) & 0x1; // sign bit
|
||||
int mag = M ? 3 : 1;
|
||||
int val = S ? +mag : -mag;
|
||||
out[n][i] = static_cast<float>(val);
|
||||
}
|
||||
}
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*!
|
||||
* \file unpack_ntlab_2bit_samples.h
|
||||
*
|
||||
* \brief Unpacks multichannel 2-bit samples into 4 real-valued floats
|
||||
* per input byte.
|
||||
* \author Pedro Pereira pereirapedrocp (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_UNPACK_NTLAB_2BIT_SAMPLES_H
|
||||
#define GNSS_SDR_UNPACK_NTLAB_2BIT_SAMPLES_H
|
||||
|
||||
#include "gnss_block_interface.h"
|
||||
#include <gnuradio/sync_interpolator.h>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
/** \addtogroup Signal_Source
|
||||
* \{ */
|
||||
/** \addtogroup Signal_Source_gnuradio_blocks
|
||||
* \{ */
|
||||
|
||||
|
||||
class unpack_ntlab_2bit_samples;
|
||||
|
||||
using unpack_ntlab_2bit_samples_sptr = gnss_shared_ptr<unpack_ntlab_2bit_samples>;
|
||||
|
||||
unpack_ntlab_2bit_samples_sptr make_unpack_ntlab_2bit_samples(
|
||||
size_t item_size,
|
||||
int nchannels = 4);
|
||||
|
||||
/*!
|
||||
* \brief This class implements conversion between byte packet multichannel samples
|
||||
* to 2bit samples 1 byte = 4 2bit samples
|
||||
*/
|
||||
class unpack_ntlab_2bit_samples : public gr::sync_interpolator
|
||||
{
|
||||
public:
|
||||
~unpack_ntlab_2bit_samples() = default;
|
||||
|
||||
unpack_ntlab_2bit_samples(size_t item_size,
|
||||
int nchannels);
|
||||
|
||||
int work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
|
||||
private:
|
||||
friend unpack_ntlab_2bit_samples_sptr make_unpack_ntlab_2bit_samples_sptr(
|
||||
size_t item_size,
|
||||
int nchannels);
|
||||
|
||||
std::vector<int8_t> work_buffer_;
|
||||
size_t item_size_;
|
||||
int nchannels_;
|
||||
};
|
||||
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_UNPACK_NTLAB_2BIT_SAMPLES_H
|
||||
Reference in New Issue
Block a user