mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-14 12:10:34 +00:00
Adding new Ad936x custom signal source, initial commit, experimental
This commit is contained in:
parent
d31f0c39dc
commit
6311530cb4
@ -21,6 +21,12 @@ if(ENABLE_PLUTOSDR)
|
||||
##############################################
|
||||
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} plutosdr_signal_source.cc)
|
||||
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} plutosdr_signal_source.h)
|
||||
|
||||
##############################################
|
||||
# CUSTOM AD936X IIO SOURCE
|
||||
##############################################
|
||||
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ad936x_custom_signal_source.cc)
|
||||
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_custom_signal_source.h)
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -0,0 +1,325 @@
|
||||
/*!
|
||||
* \file ad936x_custom_signal_source.cc
|
||||
* \brief A direct IIO custom front-end gnss-sdr signal source for the AD936x AD front-end family with special FPGA custom functionalities.
|
||||
* \author Javier Arribas, jarribas(at)cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "ad936x_custom_signal_source.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "gnss_frequencies.h"
|
||||
#include "gnss_sdr_string_literals.h"
|
||||
#include "gnss_sdr_valve.h"
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <glog/logging.h>
|
||||
#include <gnuradio/blocks/file_sink.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
Ad936xCustomSignalSource::Ad936xCustomSignalSource(const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_stream,
|
||||
unsigned int out_stream,
|
||||
Concurrent_Queue<pmt::pmt_t>* queue __attribute__((unused)))
|
||||
: SignalSourceBase(configuration, role, "Ad936x_Custom_Signal_Source"s),
|
||||
in_stream_(in_stream),
|
||||
out_stream_(out_stream),
|
||||
item_type_(configuration->property(role + ".item_type", std::string("gr_complex"))),
|
||||
samples_(configuration->property(role + ".samples", int64_t(0))),
|
||||
dump_(configuration->property(role + ".dump", false)),
|
||||
dump_filename_(configuration->property(role + ".dump_filename", std::string("./data/signal_source.dat"))),
|
||||
pluto_uri_(configuration->property(role + ".pluto_uri", std::string("local"))),
|
||||
board_type_(configuration->property(role + ".board_type", std::string("single_ad9361"))),
|
||||
sample_rate_(configuration->property(role + ".sampling_frequency", 4.0e6)),
|
||||
bandwidth_(configuration->property(role + ".bandwidth", configuration->property(role + ".sampling_frequency", 4.0e6) / 1.1)),
|
||||
freq_(configuration->property(role + ".freq", FREQ1)),
|
||||
freq_2ch(configuration->property(role + ".freq_2ch", FREQ1)),
|
||||
rf_port_select_(configuration->property(role + ".rf_port_select", std::string("A_BALANCED"))),
|
||||
rf_filter(configuration->property(role + ".rf_filter", std::string("none"))),
|
||||
gain_mode_rx0_(configuration->property(role + ".gain_mode_rx0", std::string("slow_attack"))),
|
||||
gain_mode_rx1_(configuration->property(role + ".gain_mode_rx1", std::string("slow_attack"))),
|
||||
rf_gain_rx0_(configuration->property(role + ".gain_rx0", 40.0)),
|
||||
rf_gain_rx1_(configuration->property(role + ".gain_rx1", 40.0)),
|
||||
enable_ch0(configuration->property(role + ".enable_ch0", true)),
|
||||
enable_ch1(configuration->property(role + ".enable_ch1", false)),
|
||||
PPS_mode_(configuration->property(role + ".PPS_mode", false)),
|
||||
fe_ip_(configuration->property(role + ".fe_ip", std::string("192.168.2.1"))),
|
||||
fe_ctlport_(configuration->property(role + ".fe_ctlport", int32_t(10000))),
|
||||
ssize_(configuration->property(role + ".ssize", int32_t(16))),
|
||||
bshift_(configuration->property(role + ".bshift", int64_t(0))),
|
||||
spattern_(configuration->property(role + ".spattern", false)),
|
||||
inverted_spectrum_ch0_(configuration->property(role + ".inverted_spectrum_ch0", false)),
|
||||
inverted_spectrum_ch1_(configuration->property(role + ".inverted_spectrum_ch1", false))
|
||||
|
||||
|
||||
{
|
||||
if (item_type_ == "gr_complex")
|
||||
{
|
||||
item_size_ = sizeof(gr_complex);
|
||||
// 1. Make the driver instance
|
||||
bool customsamplesize = false;
|
||||
if (ssize_ != 16 or spattern_ == true) customsamplesize = true;
|
||||
|
||||
ad936x_iio_source = ad936x_iio_make_source_sptr(
|
||||
pluto_uri_,
|
||||
board_type_,
|
||||
bandwidth_,
|
||||
sample_rate_,
|
||||
freq_,
|
||||
rf_port_select_,
|
||||
rf_filter,
|
||||
gain_mode_rx0_,
|
||||
gain_mode_rx1_,
|
||||
rf_gain_rx0_,
|
||||
rf_gain_rx1_,
|
||||
enable_ch0,
|
||||
enable_ch1,
|
||||
freq_2ch,
|
||||
PPS_mode_,
|
||||
customsamplesize,
|
||||
fe_ip_,
|
||||
fe_ctlport_,
|
||||
ssize_,
|
||||
bshift_,
|
||||
spattern_);
|
||||
|
||||
n_channels = 1;
|
||||
if (enable_ch0 == true and enable_ch1 == true)
|
||||
{
|
||||
n_channels = 2;
|
||||
}
|
||||
|
||||
for (int n = 0; n < n_channels; n++)
|
||||
{
|
||||
if (ssize_ == 16)
|
||||
{
|
||||
gr_interleaved_short_to_complex_.push_back(gr::blocks::interleaved_short_to_complex::make());
|
||||
}
|
||||
else if (ssize_ == 8)
|
||||
{
|
||||
gr_interleaved_char_to_complex_.push_back(gr::blocks::interleaved_char_to_complex::make());
|
||||
}
|
||||
else if (ssize_ == 4)
|
||||
{
|
||||
gr_interleaved_short_to_complex_.push_back(gr::blocks::interleaved_short_to_complex::make(false, false));
|
||||
unpack_byte_fourbits.push_back(make_unpack_byte_4bit_samples());
|
||||
}
|
||||
else if (ssize_ == 2)
|
||||
{
|
||||
gr_interleaved_short_to_complex_.push_back(gr::blocks::interleaved_short_to_complex::make(false, false));
|
||||
unpack_byte_twobits.push_back(make_unpack_byte_2bit_cpx_samples());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR) << item_type_ << " unrecognized item type";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (dump_)
|
||||
{
|
||||
for (int n = 0; n < n_channels; n++)
|
||||
{
|
||||
DLOG(INFO) << "Dumping output into file " << (dump_filename_ + "c_h" + std::to_string(n) + ".bin");
|
||||
sink_.emplace_back(gr::blocks::file_sink::make(item_size_, (dump_filename_ + "_ch" + std::to_string(n) + ".bin").c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
if (in_stream_ > 0)
|
||||
{
|
||||
LOG(ERROR) << "A signal source does not have an input stream";
|
||||
}
|
||||
if (out_stream_ > 1)
|
||||
{
|
||||
LOG(ERROR) << "This implementation only supports one output stream";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ad936xCustomSignalSource::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
for (int n = 0; n < n_channels; n++)
|
||||
{
|
||||
if (ssize_ == 16)
|
||||
{
|
||||
top_block->connect(ad936x_iio_source, n, gr_interleaved_short_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to gr_interleaved_short_to_complex for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->connect(gr_interleaved_short_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
else if (ssize_ == 8)
|
||||
{
|
||||
top_block->connect(ad936x_iio_source, n, gr_interleaved_char_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to gr_interleaved_char_to_complex_ for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->connect(gr_interleaved_char_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
else if (ssize_ == 4)
|
||||
{
|
||||
top_block->connect(ad936x_iio_source, n, unpack_byte_fourbits.at(n), 0);
|
||||
top_block->connect(unpack_byte_fourbits.at(n), 0, gr_interleaved_short_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to unpack_byte_fourbits for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->connect(gr_interleaved_short_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
else if (ssize_ == 2)
|
||||
{
|
||||
top_block->connect(ad936x_iio_source, n, unpack_byte_twobits.at(n), 0);
|
||||
top_block->connect(unpack_byte_twobits.at(n), 0, gr_interleaved_short_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to unpack_byte_fourbits for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->connect(gr_interleaved_short_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
top_block->connect(ad936x_iio_source, n, gr_interleaved_short_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to gr_interleaved_short_to_complex for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->connect(gr_interleaved_short_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ad936xCustomSignalSource::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
for (int n = 0; n < n_channels; n++)
|
||||
{
|
||||
if (ssize_ == 16)
|
||||
{
|
||||
top_block->disconnect(ad936x_iio_source, n, gr_interleaved_short_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to gr_interleaved_short_to_complex for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->disconnect(gr_interleaved_short_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
else if (ssize_ == 8)
|
||||
{
|
||||
top_block->disconnect(ad936x_iio_source, n, gr_interleaved_char_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to gr_interleaved_char_to_complex_ for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->disconnect(gr_interleaved_char_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
else if (ssize_ == 4)
|
||||
{
|
||||
top_block->disconnect(ad936x_iio_source, n, unpack_byte_fourbits.at(n), 0);
|
||||
top_block->disconnect(unpack_byte_fourbits.at(n), 0, gr_interleaved_short_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to unpack_byte_fourbits for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->connect(gr_interleaved_short_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
else if (ssize_ == 2)
|
||||
{
|
||||
top_block->disconnect(ad936x_iio_source, n, unpack_byte_twobits.at(n), 0);
|
||||
top_block->disconnect(unpack_byte_twobits.at(n), 0, gr_interleaved_short_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to unpack_byte_fourbits for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->disconnect(gr_interleaved_short_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
top_block->disconnect(ad936x_iio_source, n, gr_interleaved_short_to_complex_.at(n), 0);
|
||||
DLOG(INFO) << "connected ad936x_iio_source source to gr_interleaved_short_to_complex for channel " << n;
|
||||
if (dump_)
|
||||
{
|
||||
top_block->disconnect(gr_interleaved_short_to_complex_.at(n), 0, sink_.at(n), 0);
|
||||
DLOG(INFO) << "connected source to file sink";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr Ad936xCustomSignalSource::get_left_block()
|
||||
{
|
||||
LOG(WARNING) << "Trying to get signal source left block.";
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr Ad936xCustomSignalSource::get_right_block()
|
||||
{
|
||||
if (ssize_ == 16)
|
||||
{
|
||||
return gr_interleaved_short_to_complex_.at(0);
|
||||
}
|
||||
else if (ssize_ == 8)
|
||||
{
|
||||
return gr_interleaved_char_to_complex_.at(0);
|
||||
}
|
||||
else if (ssize_ == 4)
|
||||
{
|
||||
return gr_interleaved_short_to_complex_.at(0);
|
||||
}
|
||||
else if (ssize_ == 2)
|
||||
{
|
||||
return gr_interleaved_short_to_complex_.at(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return gr_interleaved_short_to_complex_.at(0);
|
||||
}
|
||||
}
|
||||
|
||||
gr::basic_block_sptr Ad936xCustomSignalSource::get_right_block(int RF_channel)
|
||||
{
|
||||
if (ssize_ == 16)
|
||||
{
|
||||
return gr_interleaved_short_to_complex_.at(RF_channel);
|
||||
}
|
||||
else if (ssize_ == 8)
|
||||
{
|
||||
return gr_interleaved_char_to_complex_.at(RF_channel);
|
||||
}
|
||||
else if (ssize_ == 4)
|
||||
{
|
||||
return gr_interleaved_short_to_complex_.at(RF_channel);
|
||||
}
|
||||
else if (ssize_ == 2)
|
||||
{
|
||||
return gr_interleaved_short_to_complex_.at(RF_channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
return gr_interleaved_short_to_complex_.at(RF_channel);
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*!
|
||||
* \file ad936x_custom_signal_source.h
|
||||
* \brief A direct IIO custom front-end gnss-sdr signal source for the AD936x AD front-end family with special FPGA custom functionalities.
|
||||
* \author Javier Arribas, jarribas(at)cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_Ad936xCustom_SIGNAL_SOURCE_H
|
||||
#define GNSS_SDR_Ad936xCustom_SIGNAL_SOURCE_H
|
||||
|
||||
#include "ad936x_iio_source.h"
|
||||
#include "concurrent_queue.h"
|
||||
#include "conjugate_cc.h"
|
||||
#include "signal_source_base.h"
|
||||
#include "unpack_byte_2bit_cpx_samples.h"
|
||||
#include "unpack_byte_4bit_samples.h"
|
||||
#include <gnuradio/blocks/file_sink.h>
|
||||
#include <gnuradio/blocks/interleaved_char_to_complex.h>
|
||||
#include <gnuradio/blocks/interleaved_short_to_complex.h>
|
||||
#include <pmt/pmt.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/** \addtogroup Signal_Source
|
||||
* \{ */
|
||||
/** \addtogroup Signal_Source_adapters
|
||||
* \{ */
|
||||
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class instantiates the Ad936xCustom gnuradio signal source.
|
||||
* It has support also for a customized Ad936xCustom firmware and signal source to support PPS samplestamp reading.
|
||||
*/
|
||||
class Ad936xCustomSignalSource : public SignalSourceBase
|
||||
{
|
||||
public:
|
||||
Ad936xCustomSignalSource(const ConfigurationInterface* configuration,
|
||||
const std::string& role, unsigned int in_stream,
|
||||
unsigned int out_stream, Concurrent_Queue<pmt::pmt_t>* queue);
|
||||
|
||||
~Ad936xCustomSignalSource() = default;
|
||||
|
||||
inline size_t item_size() override
|
||||
{
|
||||
return item_size_;
|
||||
}
|
||||
|
||||
void connect(gr::top_block_sptr top_block) override;
|
||||
void disconnect(gr::top_block_sptr top_block) override;
|
||||
gr::basic_block_sptr get_left_block() override;
|
||||
gr::basic_block_sptr get_right_block() override;
|
||||
gr::basic_block_sptr get_right_block(int RF_channel) override;
|
||||
|
||||
private:
|
||||
unsigned int in_stream_;
|
||||
unsigned int out_stream_;
|
||||
gr::block_sptr ad936x_iio_source;
|
||||
std::vector<gr::blocks::file_sink::sptr> sink_;
|
||||
std::vector<std::string> filename_vec_;
|
||||
|
||||
std::vector<gr::blocks::interleaved_short_to_complex::sptr> gr_interleaved_short_to_complex_;
|
||||
std::vector<gr::blocks::interleaved_char_to_complex::sptr> gr_interleaved_char_to_complex_;
|
||||
std::vector<unpack_byte_4bit_samples_sptr> unpack_byte_fourbits;
|
||||
std::vector<unpack_byte_2bit_cpx_samples_sptr> unpack_byte_twobits;
|
||||
|
||||
|
||||
std::string item_type_;
|
||||
size_t item_size_;
|
||||
int64_t samples_;
|
||||
bool dump_;
|
||||
std::string dump_filename_;
|
||||
|
||||
// Front-end settings
|
||||
std::string pluto_uri_;
|
||||
std::string board_type_;
|
||||
long long sample_rate_;
|
||||
long long bandwidth_;
|
||||
long long freq_;
|
||||
long long freq_2ch;
|
||||
std::string rf_port_select_;
|
||||
std::string rf_filter;
|
||||
std::string gain_mode_rx0_;
|
||||
std::string gain_mode_rx1_;
|
||||
double rf_gain_rx0_;
|
||||
double rf_gain_rx1_;
|
||||
bool enable_ch0;
|
||||
bool enable_ch1;
|
||||
bool PPS_mode_;
|
||||
std::string fe_ip_;
|
||||
int fe_ctlport_;
|
||||
int ssize_;
|
||||
int bshift_;
|
||||
bool spattern_;
|
||||
bool inverted_spectrum_ch0_;
|
||||
bool inverted_spectrum_ch1_;
|
||||
|
||||
|
||||
int n_channels;
|
||||
};
|
||||
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_Ad936xCustom_SIGNAL_SOURCE_H
|
@ -17,6 +17,13 @@ if(ENABLE_AD936X_SDR)
|
||||
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} gr_complex_ip_packet_source.h)
|
||||
endif()
|
||||
|
||||
|
||||
if(ENABLE_PLUTOSDR)
|
||||
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ad936x_iio_source.cc)
|
||||
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_iio_source.h)
|
||||
endif()
|
||||
|
||||
|
||||
set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
||||
fifo_reader.cc
|
||||
unpack_byte_2bit_samples.cc
|
||||
|
@ -1,16 +1,14 @@
|
||||
/*!
|
||||
* \file ad936x_iio_source.cc
|
||||
*
|
||||
* \brief Unpacks capture files in the LabSat 2 (ls2), LabSat 3 (ls3), or LabSat
|
||||
* 3 Wideband (LS3W) formats.
|
||||
* \author Javier Arribas jarribas (at) cttc.es
|
||||
* \brief A direct IIO custom front-end gnss-sdr signal gnuradio block for the AD936x AD front-end family with special FPGA custom functionalities.
|
||||
* \author Javier Arribas, jarribas(at)cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
@ -19,12 +17,13 @@
|
||||
|
||||
#include "ad936x_iio_source.h"
|
||||
#include "INIReader.h"
|
||||
#include "ad936x_iio_samples.h"
|
||||
#include "command_event.h"
|
||||
#include "gnss_sdr_make_unique.h"
|
||||
#include "pps_samplestamp.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <exception>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
@ -33,64 +32,245 @@
|
||||
#include <utility>
|
||||
|
||||
|
||||
ad936x_iio_source_sptr ad936x_iio_make_source_sptr(Concurrent_Queue<pmt::pmt_t> *queue,
|
||||
std::string pluto_device_uri,
|
||||
std::string board_type,
|
||||
ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
||||
std::string pluto_uri_,
|
||||
std::string board_type_,
|
||||
long long bandwidth_,
|
||||
long long sample_rate_,
|
||||
std::vector<std::string> ch_list,
|
||||
std::vector<std::string> ch_gain_mode,
|
||||
std::vector<double> ch_gain_db,
|
||||
std::vector<long int> ch_freq_hz,
|
||||
int ch_sample_size,
|
||||
int ch_sample_bits_shift)
|
||||
long long freq_,
|
||||
std::string rf_port_select_,
|
||||
std::string rf_filter,
|
||||
std::string gain_mode_rx0_,
|
||||
std::string gain_mode_rx1_,
|
||||
double rf_gain_rx0_,
|
||||
double rf_gain_rx1_,
|
||||
bool enable_ch0,
|
||||
bool enable_ch1,
|
||||
long long freq_2ch,
|
||||
bool ppsmode_,
|
||||
bool customsamplesize_,
|
||||
std::string fe_ip_,
|
||||
int fe_ctlport_,
|
||||
int ssize_,
|
||||
int bshift_,
|
||||
bool spattern_)
|
||||
{
|
||||
return ad936x_iio_source_sptr(new ad936x_iio_source(*queue,
|
||||
pluto_device_uri,
|
||||
board_type,
|
||||
return ad936x_iio_source_sptr(new ad936x_iio_source(
|
||||
pluto_uri_,
|
||||
board_type_,
|
||||
bandwidth_,
|
||||
sample_rate_,
|
||||
ch_list,
|
||||
ch_gain_mode,
|
||||
ch_gain_db,
|
||||
ch_freq_hz,
|
||||
ch_sample_size,
|
||||
ch_sample_bits_shift));
|
||||
freq_,
|
||||
rf_port_select_,
|
||||
rf_filter,
|
||||
gain_mode_rx0_,
|
||||
gain_mode_rx1_,
|
||||
rf_gain_rx0_,
|
||||
rf_gain_rx1_,
|
||||
enable_ch0,
|
||||
enable_ch1,
|
||||
freq_2ch,
|
||||
ppsmode_,
|
||||
customsamplesize_,
|
||||
fe_ip_,
|
||||
fe_ctlport_,
|
||||
ssize_,
|
||||
bshift_,
|
||||
spattern_));
|
||||
}
|
||||
|
||||
|
||||
ad936x_iio_source::ad936x_iio_source(Concurrent_Queue<pmt::pmt_t> *queue,
|
||||
std::string pluto_device_uri,
|
||||
std::string board_type,
|
||||
ad936x_iio_source::ad936x_iio_source(
|
||||
std::string pluto_uri_,
|
||||
std::string board_type_,
|
||||
long long bandwidth_,
|
||||
long long sample_rate_,
|
||||
std::vector<std::string> ch_list,
|
||||
std::vector<std::string> ch_gain_mode,
|
||||
std::vector<double> ch_gain_db,
|
||||
std::vector<long int> ch_freq_hz,
|
||||
int ch_sample_size,
|
||||
int ch_sample_bits_shift) : gr::block("ad936x_iio_source",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 3, sizeof(gr_complex)))
|
||||
long long freq_,
|
||||
std::string rf_port_select_,
|
||||
std::string rf_filter,
|
||||
std::string gain_mode_rx0_,
|
||||
std::string gain_mode_rx1_,
|
||||
double rf_gain_rx0_,
|
||||
double rf_gain_rx1_,
|
||||
bool enable_ch0,
|
||||
bool enable_ch1,
|
||||
long long freq_2ch,
|
||||
bool ppsmode_,
|
||||
bool customsamplesize_,
|
||||
std::string fe_ip_,
|
||||
int fe_ctlport_,
|
||||
int ssize_,
|
||||
int bshift_,
|
||||
bool spattern_) : gr::block("ad936x_iio_source",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 4, sizeof(int16_t)))
|
||||
{
|
||||
}
|
||||
ad936x_custom = std::make_unique<ad936x_iio_custom>(0, 0);
|
||||
try
|
||||
{
|
||||
if (ad936x_custom->initialize_device(pluto_uri_, board_type_) == true)
|
||||
{
|
||||
//configure channels
|
||||
if (ad936x_custom->init_config_ad9361_rx(bandwidth_,
|
||||
sample_rate_,
|
||||
freq_,
|
||||
rf_port_select_,
|
||||
rf_filter,
|
||||
gain_mode_rx0_,
|
||||
gain_mode_rx1_,
|
||||
rf_gain_rx0_,
|
||||
rf_gain_rx1_,
|
||||
enable_ch0,
|
||||
enable_ch1,
|
||||
freq_2ch) == true)
|
||||
{
|
||||
std::cout << "ad936x_iio_source HW configured OK!\n";
|
||||
|
||||
//PPS FPGA Samplestamp information from TCP server
|
||||
pps_rx = std::make_shared<pps_tcp_rx>();
|
||||
ppsqueue = std::shared_ptr<Concurrent_Queue<PpsSamplestamp>>(new Concurrent_Queue<PpsSamplestamp>());
|
||||
|
||||
pps_rx->set_pps_samplestamp_queue(ppsqueue);
|
||||
ad936x_custom->set_pps_samplestamp_queue(ppsqueue);
|
||||
|
||||
//start PPS RX thread
|
||||
if (ppsmode_ == true or customsamplesize_ == true)
|
||||
{
|
||||
pps_rx_thread = std::thread(&pps_tcp_rx::receive_pps, pps_rx, fe_ip_, fe_ctlport_);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
//configure custom FPGA options
|
||||
switch (ssize_)
|
||||
{
|
||||
case 16:
|
||||
{
|
||||
std::cout << "FPGA sample size set to 16 bits per sample.\n";
|
||||
if (pps_rx->send_cmd("ssize=16\n") == false) std::cout << "cmd send error!\n";
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
std::cout << "FPGA sample size set to 8 bits per sample.\n";
|
||||
if (pps_rx->send_cmd("ssize=8\n") == false) std::cout << "cmd send error!\n";
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
std::cout << "FPGA sample size set to 4 bits per sample.\n";
|
||||
if (pps_rx->send_cmd("ssize=4\n") == false) std::cout << "cmd send error!\n";
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
std::cout << "FPGA sample size set to 2 bits per sample.\n";
|
||||
if (pps_rx->send_cmd("ssize=2\n") == false) std::cout << "cmd send error!\n";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
std::cout << "WARNING: Unsupported ssize. FPGA sample size set to 16 bits per sample.\n";
|
||||
if (pps_rx->send_cmd("ssize=16") == false) std::cout << "cmd send error!\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (bshift_ >= 0 and bshift_ <= 14)
|
||||
{
|
||||
std::cout << "FPGA sample bits shift left set to " + std::to_string(bshift_) + " positions.\n";
|
||||
if (pps_rx->send_cmd("bshift=" + std::to_string(bshift_) + "\n") == false) std::cout << "cmd send error!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "WARNING: Unsupported bshift. FPGA sample bits shift left set to 0.\n";
|
||||
if (pps_rx->send_cmd("bshift=0\n") == false) std::cout << "cmd send error!\n";
|
||||
}
|
||||
|
||||
if (spattern_ == true)
|
||||
{
|
||||
std::cout << "FPGA debug sample pattern is active!.\n";
|
||||
if (pps_rx->send_cmd("spattern=1\n") == false) std::cout << "cmd send error!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "FPGA debug sample pattern disabled.\n";
|
||||
if (pps_rx->send_cmd("spattern=0\n") == false) std::cout << "cmd send error!\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "PPS mode NOT enabled, not configuring PlutoSDR custom timestamping FPGA IP.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "ad936x_iio_source IIO initialization error." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "ad936x_iio_source IIO initialization error." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
catch (std::exception const &ex)
|
||||
{
|
||||
std::cerr << "STD exception: " << ex.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "Unexpected catch" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//set_min_noutput_items(IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES * 2);
|
||||
set_min_output_buffer(IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES * 2);
|
||||
//std::cout << "max_output_buffer " << min_output_buffer(0) << " min_noutput_items: " << min_noutput_items() << "\n";
|
||||
}
|
||||
|
||||
ad936x_iio_source::~ad936x_iio_source()
|
||||
{
|
||||
// Terminate PPS thread
|
||||
if (pps_rx_thread.joinable())
|
||||
{
|
||||
pthread_t id = pps_rx_thread.native_handle();
|
||||
pps_rx_thread.detach();
|
||||
pthread_cancel(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ad936x_iio_source::start()
|
||||
{
|
||||
return ad936x_custom->start_sample_rx(false);
|
||||
}
|
||||
|
||||
bool ad936x_iio_source::stop()
|
||||
{
|
||||
ad936x_custom->stop_record();
|
||||
return true;
|
||||
}
|
||||
|
||||
int ad936x_iio_source::general_work(int noutput_items,
|
||||
__attribute__((unused)) gr_vector_int &ninput_items,
|
||||
__attribute__((unused)) gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
std::vector<gr_complex *> out;
|
||||
for (auto &output_item : output_items)
|
||||
std::shared_ptr<ad936x_iio_samples> current_buffer;
|
||||
ad936x_iio_samples *current_samples;
|
||||
ad936x_custom->pop_sample_buffer(current_buffer);
|
||||
current_samples = current_buffer.get();
|
||||
|
||||
//I and Q samples are interleaved in buffer: IQIQIQ...
|
||||
|
||||
for (size_t n = 0; n < ad936x_custom->n_channels; n++)
|
||||
{
|
||||
out.push_back(reinterpret_cast<gr_complex *>(output_item));
|
||||
if (output_items.size() > n) // check if the output channel is connected
|
||||
{
|
||||
memcpy(reinterpret_cast<void *>(output_items[n]), reinterpret_cast<void *>(current_samples->buffer[n]), current_samples->n_bytes[n]);
|
||||
produce(n, current_samples->n_samples[n]);
|
||||
}
|
||||
}
|
||||
std::cout << "Warning!!\n";
|
||||
return 0;
|
||||
|
||||
ad936x_custom->push_sample_buffer(current_buffer);
|
||||
return this->WORK_CALLED_PRODUCE;
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
/*!
|
||||
* \file ad936x_iio_source.h
|
||||
*
|
||||
* \brief signal source to receive samples from the AD936x FE family over libiio, including special custom functionalities in FPGA firmware.
|
||||
* \author Javier Arribas jarribas (at) cttc.es
|
||||
* \brief A direct IIO custom front-end gnss-sdr signal gnuradio block for the AD936x AD front-end family with special FPGA custom functionalities.
|
||||
* \author Javier Arribas, jarribas(at)cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
@ -15,19 +14,22 @@
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_AD9361_IIO_SOURCE_H
|
||||
#define GNSS_SDR_AD9361_IIO_SOURCE_H
|
||||
|
||||
#ifndef GNSS_SDR_AD936X_IIO_SOURCE_H
|
||||
#define GNSS_SDR_AD936X_IIO_SOURCE_H
|
||||
|
||||
#include "ad936x_iio_custom.h"
|
||||
#include "concurrent_queue.h"
|
||||
#include "gnss_block_interface.h"
|
||||
#include "ppstcprx.h"
|
||||
#include <gnuradio/block.h>
|
||||
#include <iio.h>
|
||||
#include <pmt/pmt.h>
|
||||
#include <ad9361.h> //multichip sync and high level functions
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
/** \addtogroup Signal_Source
|
||||
@ -41,17 +43,27 @@ class ad936x_iio_source;
|
||||
using ad936x_iio_source_sptr = gnss_shared_ptr<ad936x_iio_source>;
|
||||
|
||||
ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
||||
Concurrent_Queue<pmt::pmt_t> *queue,
|
||||
std::string pluto_device_uri,
|
||||
std::string board_type,
|
||||
std::string pluto_uri_,
|
||||
std::string board_type_,
|
||||
long long bandwidth_,
|
||||
long long sample_rate_,
|
||||
std::vector<std::string> ch_list,
|
||||
std::vector<std::string> ch_gain_mode,
|
||||
std::vector<double> ch_gain_db,
|
||||
std::vector<long int> ch_freq_hz,
|
||||
int ch_sample_size,
|
||||
int ch_sample_bits_shift);
|
||||
long long freq_,
|
||||
std::string rf_port_select_,
|
||||
std::string rf_filter,
|
||||
std::string gain_mode_rx0_,
|
||||
std::string gain_mode_rx1_,
|
||||
double rf_gain_rx0_,
|
||||
double rf_gain_rx1_,
|
||||
bool enable_ch0,
|
||||
bool enable_ch1,
|
||||
long long freq_2ch,
|
||||
bool ppsmode_,
|
||||
bool customsamplesize_,
|
||||
std::string fe_ip_,
|
||||
int fe_ctlport_,
|
||||
int ssize_,
|
||||
int bshift_,
|
||||
bool spattern_);
|
||||
|
||||
/*!
|
||||
* \brief This class implements conversion between Labsat 2, 3 and 3 Wideband
|
||||
@ -62,6 +74,11 @@ class ad936x_iio_source : public gr::block
|
||||
public:
|
||||
~ad936x_iio_source();
|
||||
|
||||
//! start the sample transmission
|
||||
bool start();
|
||||
//! stop the sample transmission
|
||||
bool stop();
|
||||
|
||||
int general_work(int noutput_items,
|
||||
gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
@ -69,32 +86,60 @@ public:
|
||||
|
||||
private:
|
||||
friend ad936x_iio_source_sptr ad936x_iio_make_source_sptr(
|
||||
Concurrent_Queue<pmt::pmt_t> *queue,
|
||||
std::string pluto_device_uri,
|
||||
std::string board_type,
|
||||
std::string pluto_uri_,
|
||||
std::string board_type_,
|
||||
long long bandwidth_,
|
||||
long long sample_rate_,
|
||||
std::vector<std::string> ch_list,
|
||||
std::vector<std::string> ch_gain_mode,
|
||||
std::vector<double> ch_gain_db,
|
||||
std::vector<long int> ch_freq_hz,
|
||||
int ch_sample_size,
|
||||
int ch_sample_bits_shift);
|
||||
long long freq_,
|
||||
std::string rf_port_select_,
|
||||
std::string rf_filter,
|
||||
std::string gain_mode_rx0_,
|
||||
std::string gain_mode_rx1_,
|
||||
double rf_gain_rx0_,
|
||||
double rf_gain_rx1_,
|
||||
bool enable_ch0,
|
||||
bool enable_ch1,
|
||||
long long freq_2ch,
|
||||
bool ppsmode_,
|
||||
bool customsamplesize_,
|
||||
std::string fe_ip_,
|
||||
int fe_ctlport_,
|
||||
int ssize_,
|
||||
int bshift_,
|
||||
bool spattern_);
|
||||
|
||||
ad936x_iio_source(Concurrent_Queue<pmt::pmt_t> *queue,
|
||||
std::string pluto_device_uri,
|
||||
std::string board_type,
|
||||
ad936x_iio_source(
|
||||
std::string pluto_uri_,
|
||||
std::string board_type_,
|
||||
long long bandwidth_,
|
||||
long long sample_rate_,
|
||||
std::vector<std::string> ch_list,
|
||||
std::vector<std::string> ch_gain_mode,
|
||||
std::vector<double> ch_gain_db,
|
||||
std::vector<long int> ch_freq_hz,
|
||||
int ch_sample_size,
|
||||
int ch_sample_bits_shift);
|
||||
long long freq_,
|
||||
std::string rf_port_select_,
|
||||
std::string rf_filter,
|
||||
std::string gain_mode_rx0_,
|
||||
std::string gain_mode_rx1_,
|
||||
double rf_gain_rx0_,
|
||||
double rf_gain_rx1_,
|
||||
bool enable_ch0,
|
||||
bool enable_ch1,
|
||||
long long freq_2ch,
|
||||
bool ppsmode_,
|
||||
bool customsamplesize_,
|
||||
std::string fe_ip_,
|
||||
int fe_ctlport_,
|
||||
int ssize_,
|
||||
int bshift_,
|
||||
bool spattern_);
|
||||
|
||||
std::thread pps_rx_thread;
|
||||
|
||||
|
||||
std::unique_ptr<ad936x_iio_custom> ad936x_custom;
|
||||
std::shared_ptr<pps_tcp_rx> pps_rx;
|
||||
std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> ppsqueue;
|
||||
};
|
||||
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_AD9361_IIO_SOURCE_H
|
||||
#endif // GNSS_SDR_AD936X_IIO_SOURCE_H
|
||||
|
@ -8,8 +8,8 @@
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES "")
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS "")
|
||||
if(ENABLE_FMCOMMS2 OR ENABLE_AD9361)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ad9361_manager.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ad9361_manager.h)
|
||||
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)
|
||||
endif()
|
||||
|
||||
if(ENABLE_FPGA OR ENABLE_AD9361)
|
||||
@ -23,6 +23,18 @@ if(ENABLE_FPGA OR ENABLE_AD9361)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dma.h)
|
||||
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_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_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ppstcprx.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ppstcprx.h)
|
||||
endif()
|
||||
|
||||
|
||||
set(SIGNAL_SOURCE_LIB_SOURCES
|
||||
rtl_tcp_commands.cc
|
||||
rtl_tcp_dongle_info.cc
|
||||
@ -88,7 +100,7 @@ if(GNURADIO_USES_SPDLOG)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_FMCOMMS2 OR ENABLE_AD9361)
|
||||
if(ENABLE_FMCOMMS2 OR ENABLE_AD9361 OR ENABLE_PLUTOSDR)
|
||||
target_link_libraries(signal_source_libs
|
||||
PUBLIC
|
||||
Iio::iio
|
||||
|
1195
src/algorithms/signal_source/libs/ad936x_iio_custom.cc
Normal file
1195
src/algorithms/signal_source/libs/ad936x_iio_custom.cc
Normal file
File diff suppressed because it is too large
Load Diff
144
src/algorithms/signal_source/libs/ad936x_iio_custom.h
Normal file
144
src/algorithms/signal_source/libs/ad936x_iio_custom.h
Normal file
@ -0,0 +1,144 @@
|
||||
/*!
|
||||
* \file ad936x_iio_custom.h
|
||||
* \brief A direct IIO custom front-end driver for the AD936x AD front-end family with special FPGA custom functionalities.
|
||||
* \author Javier Arribas, jarribas(at)cttc.es
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SRC_LIBS_ad936x_iio_custom_H_
|
||||
#define SRC_LIBS_ad936x_iio_custom_H_
|
||||
|
||||
#include "concurrent_queue.h"
|
||||
#include "gnss_time.h"
|
||||
#include "pps_samplestamp.h"
|
||||
#include <boost/atomic.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <iio/iio.h>
|
||||
#else
|
||||
#include <iio.h>
|
||||
#endif
|
||||
|
||||
#include "ad936x_iio_samples.h"
|
||||
#include <ad9361.h> //multichip sync and high level functions
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
class ad936x_iio_custom
|
||||
{
|
||||
public:
|
||||
ad936x_iio_custom(int debug_level_, int log_level_);
|
||||
virtual ~ad936x_iio_custom();
|
||||
bool initialize_device(std::string pluto_device_uri, std::string board_type);
|
||||
|
||||
bool init_config_ad9361_rx(long long bandwidth_,
|
||||
long long sample_rate_,
|
||||
long long freq_,
|
||||
std::string rf_port_select_,
|
||||
std::string rf_filter,
|
||||
std::string gain_mode_rx0_,
|
||||
std::string gain_mode_rx1_,
|
||||
double rf_gain_rx0_,
|
||||
double rf_gain_rx1_,
|
||||
bool enable_ch0,
|
||||
bool enable_ch1,
|
||||
long long freq_2ch);
|
||||
|
||||
bool calibrate(int ch, double bw_hz);
|
||||
|
||||
double get_rx_gain(int ch_num);
|
||||
bool setRXGain(int ch_num, std::string gain_mode, double gain_dB);
|
||||
|
||||
bool set_antenna_port(int ch, int antenna_idx);
|
||||
double get_frequency(int ch);
|
||||
bool set_frequency(int ch, double freq_hz);
|
||||
|
||||
bool start_sample_rx(bool ppsmode);
|
||||
void stop_record();
|
||||
|
||||
void set_gnsstime_queue(std::shared_ptr<Concurrent_Queue<GnssTime>> queue);
|
||||
void set_pps_samplestamp_queue(std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> queue);
|
||||
|
||||
bool get_rx_frequency(long long &freq_hz);
|
||||
bool set_rx_frequency(long long freq_hz);
|
||||
bool read_die_temp(double &temp_c);
|
||||
|
||||
void pop_sample_buffer(std::shared_ptr<ad936x_iio_samples> ¤t_buffer);
|
||||
|
||||
void push_sample_buffer(std::shared_ptr<ad936x_iio_samples> ¤t_buffer);
|
||||
|
||||
int n_channels;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Concurrent_Queue<GnssTime>> GnssTime_queue;
|
||||
std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> Pps_queue;
|
||||
bool check_device();
|
||||
bool get_iio_param(iio_device *dev, const std::string ¶m, std::string &value);
|
||||
void configure_params(struct iio_device *phy,
|
||||
const std::vector<std::string> ¶ms);
|
||||
void set_params_rx(struct iio_device *phy_device,
|
||||
unsigned long long frequency,
|
||||
unsigned long samplerate, unsigned long bandwidth,
|
||||
bool quadrature, bool rfdc, bool bbdc,
|
||||
std::string gain1, double gain1_value,
|
||||
std::string gain2, double gain2_value,
|
||||
std::string port_select);
|
||||
|
||||
bool config_ad9361_dds(uint64_t freq_rf_tx_hz_,
|
||||
double tx_attenuation_db_,
|
||||
int64_t freq_dds_tx_hz_,
|
||||
double scale_dds_,
|
||||
double phase_dds_deg_);
|
||||
|
||||
void get_PPS_timestamp();
|
||||
void capture(const std::vector<std::string> &channels);
|
||||
|
||||
bool select_rf_filter(std::string rf_filter);
|
||||
|
||||
void monitor_thread_fn();
|
||||
|
||||
void PlutoTxEnable(bool txon);
|
||||
void setPlutoGpo(int p);
|
||||
|
||||
//Device structure
|
||||
struct iio_context *ctx;
|
||||
struct iio_device *phy;
|
||||
struct iio_device *stream_dev;
|
||||
struct iio_device *dds_dev;
|
||||
|
||||
//stream
|
||||
|
||||
uint64_t sample_rate_sps;
|
||||
|
||||
|
||||
int debug_level;
|
||||
int log_level;
|
||||
bool PPS_mode;
|
||||
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv;
|
||||
|
||||
boost::atomic<bool> receive_samples;
|
||||
|
||||
boost::atomic<bool> fpga_overflow;
|
||||
//using queues of smart pointers to preallocated buffers
|
||||
Concurrent_Queue<std::shared_ptr<ad936x_iio_samples>> free_buffers;
|
||||
Concurrent_Queue<std::shared_ptr<ad936x_iio_samples>> used_buffers;
|
||||
|
||||
std::thread capture_samples_thread;
|
||||
std::thread overflow_monitor_thread;
|
||||
std::thread capture_time_thread;
|
||||
};
|
||||
|
||||
#endif /* SRC_LIBS_ad936x_iio_custom_H_ */
|
26
src/algorithms/signal_source/libs/ad936x_iio_samples.cc
Normal file
26
src/algorithms/signal_source/libs/ad936x_iio_samples.cc
Normal file
@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* \file ad936x_iio_samples.cc
|
||||
* \brief A class that holds a custom sample buffer for Analog Devices AD936x family front-ends.
|
||||
* \author Javier Arribas, jarribas(at)cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "ad936x_iio_samples.h"
|
||||
|
||||
ad936x_iio_samples::ad936x_iio_samples()
|
||||
{
|
||||
for (int n = 0; n < IIO_MAX_CH; n++)
|
||||
{
|
||||
n_bytes[n] = 0;
|
||||
n_samples[n] = 0;
|
||||
}
|
||||
}
|
41
src/algorithms/signal_source/libs/ad936x_iio_samples.h
Normal file
41
src/algorithms/signal_source/libs/ad936x_iio_samples.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*!
|
||||
* \file ad936x_iio_samples.h
|
||||
* \brief A class that holds a custom sample buffer for Analog Devices AD936x family front-ends.
|
||||
* \author Javier Arribas, jarribas(at)cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SRC_LIBS_ad936x_iio_samples_H_
|
||||
#define SRC_LIBS_ad936x_iio_samples_H_
|
||||
|
||||
#define IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES 32768 * 2
|
||||
|
||||
#define IIO_INPUTRAMFIFOSIZE 512
|
||||
|
||||
#define IIO_MAX_CH 4
|
||||
#define IIO_MAX_BYTES_PER_CHANNEL IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES * 2 * 2 //(2-bytes per I + 2-bytes per Q)
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
class ad936x_iio_samples
|
||||
{
|
||||
public:
|
||||
ad936x_iio_samples();
|
||||
uint32_t n_bytes[IIO_MAX_CH];
|
||||
uint32_t n_samples[IIO_MAX_CH];
|
||||
int16_t buffer[IIO_MAX_CH][IIO_DEFAULTAD936XAPIFIFOSIZE_SAMPLES * 2]; //16 bits I,Q samples buffers
|
||||
};
|
||||
|
||||
#endif
|
20
src/algorithms/signal_source/libs/pps_samplestamp.h
Normal file
20
src/algorithms/signal_source/libs/pps_samplestamp.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2022 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IIOPPS_PPS_SAMPLESTAMP_H
|
||||
#define IIOPPS_PPS_SAMPLESTAMP_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class PpsSamplestamp
|
||||
{
|
||||
public:
|
||||
uint64_t samplestamp; //PPS rising edge samples counter from the beginning of rx stream opperation. Notice that it is reseted to zero if sample buffer overflow is detected on the FPGA side
|
||||
uint32_t overflow_reg; // >0 indicates overflow situation in the FPGA RX buffer
|
||||
};
|
||||
|
||||
#endif
|
154
src/algorithms/signal_source/libs/ppstcprx.cc
Normal file
154
src/algorithms/signal_source/libs/ppstcprx.cc
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* ppstcprx.cc
|
||||
*
|
||||
* Created on: 28 feb 2022
|
||||
* Author: javier
|
||||
*/
|
||||
|
||||
#include "ppstcprx.h"
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
pps_tcp_rx::pps_tcp_rx()
|
||||
{
|
||||
// TODO Auto-generated constructor stub
|
||||
is_connected = false;
|
||||
clientSd = -1;
|
||||
}
|
||||
|
||||
pps_tcp_rx::~pps_tcp_rx()
|
||||
{
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
void pps_tcp_rx::set_pps_samplestamp_queue(std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> queue)
|
||||
{
|
||||
Pps_queue = std::move(queue);
|
||||
}
|
||||
|
||||
bool pps_tcp_rx::send_cmd(std::string cmd)
|
||||
{
|
||||
if (is_connected == true)
|
||||
{
|
||||
// send call sends the data you specify as second param and it's length as 3rd param, also returns how many bytes were actually sent
|
||||
auto bytes_sent = send(clientSd, cmd.data(), cmd.length(), 0);
|
||||
if (bytes_sent <= 0)
|
||||
{
|
||||
std::cerr << "Connection terminated...\n";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "sent bytes..\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void pps_tcp_rx::receive_pps(std::string ip_address, int port)
|
||||
{
|
||||
//create a message buffer
|
||||
char buf[1500];
|
||||
//setup a socket and connection tools
|
||||
sockaddr_in sendSockAddr;
|
||||
sendSockAddr.sin_family = AF_INET;
|
||||
sendSockAddr.sin_addr.s_addr =
|
||||
inet_addr(ip_address.c_str());
|
||||
sendSockAddr.sin_port = htons(port);
|
||||
clientSd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
//try to connect...
|
||||
int status = connect(clientSd,
|
||||
(sockaddr *)&sendSockAddr, sizeof(sendSockAddr));
|
||||
if (status < 0)
|
||||
{
|
||||
std::cout << "pps_tcp_rx: Error connecting to PPS TCP server IP " << ip_address << " at port " << port << std::endl;
|
||||
return;
|
||||
}
|
||||
std::string new_pps_line;
|
||||
|
||||
is_connected = true;
|
||||
while (true)
|
||||
{
|
||||
int numBytesRead = recv(clientSd, buf, sizeof(buf), 0);
|
||||
if (numBytesRead > 0)
|
||||
{
|
||||
for (int i = 0; i < numBytesRead; i++)
|
||||
{
|
||||
char c = buf[i];
|
||||
if (c == '\n')
|
||||
{
|
||||
if (new_pps_line.length() > 0)
|
||||
{
|
||||
//std::cout << "pps_tcp_rx debug: " << new_pps_line << "\n";
|
||||
//parse string and push PPS data to the PPS queue
|
||||
std::stringstream ss(new_pps_line);
|
||||
std::vector<std::string> data;
|
||||
while (ss.good())
|
||||
{
|
||||
std::string substr;
|
||||
std::getline(ss, substr, ',');
|
||||
data.push_back(substr);
|
||||
}
|
||||
if (data.size() >= 2)
|
||||
{
|
||||
PpsSamplestamp new_pps;
|
||||
//sample counter
|
||||
std::size_t found = data.at(0).find("sc=");
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
try
|
||||
{
|
||||
new_pps.samplestamp = std::strtoul(data.at(0).substr(found + 3).c_str(), NULL, 0);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
std::cout << "pps_tcp_rx debug: sc parse error str " << data.at(0) << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "pps_tcp_rx debug: sc parse error str " << data.at(0) << "\n";
|
||||
}
|
||||
found = data.at(1).find("o=");
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
try
|
||||
{
|
||||
new_pps.overflow_reg = std::stoi(data.at(1).substr(found + 2).c_str(), NULL, 0);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
std::cout << "pps_tcp_rx debug: o parse error str " << data.at(0) << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "pps_tcp_rx debug: o parse error str " << data.at(1) << "\n";
|
||||
}
|
||||
Pps_queue->push(new_pps);
|
||||
//std::cout << "pps_tcp_rx debug: pps pushed!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "pps_tcp_rx debug: protocol error!\n";
|
||||
}
|
||||
new_pps_line = "";
|
||||
}
|
||||
}
|
||||
else
|
||||
new_pps_line += c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "pps_tcp_rx: Socket disconnected!\n!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
is_connected = false;
|
||||
}
|
34
src/algorithms/signal_source/libs/ppstcprx.h
Normal file
34
src/algorithms/signal_source/libs/ppstcprx.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* ppstcprx.h
|
||||
*
|
||||
* Created on: 28 feb 2022
|
||||
* Author: javier
|
||||
*/
|
||||
|
||||
#ifndef SRC_LIBS_PPSTCPRX_H_
|
||||
#define SRC_LIBS_PPSTCPRX_H_
|
||||
#include "concurrent_queue.h"
|
||||
#include "pps_samplestamp.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
class pps_tcp_rx
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> Pps_queue;
|
||||
int clientSd;
|
||||
|
||||
public:
|
||||
volatile bool is_connected;
|
||||
pps_tcp_rx();
|
||||
virtual ~pps_tcp_rx();
|
||||
|
||||
void receive_pps(std::string ip_address, int port);
|
||||
bool send_cmd(std::string cmd);
|
||||
|
||||
void set_pps_samplestamp_queue(std::shared_ptr<Concurrent_Queue<PpsSamplestamp>> queue);
|
||||
};
|
||||
|
||||
#endif /* SRC_LIBS_PPSTCPRX_H_ */
|
@ -55,6 +55,18 @@ public:
|
||||
return the_queue.empty();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(the_mutex);
|
||||
return the_queue.size();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(the_mutex);
|
||||
the_queue = std::queue<Data>();
|
||||
}
|
||||
|
||||
bool try_pop(Data& popped_value)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(the_mutex);
|
||||
|
@ -153,6 +153,7 @@
|
||||
#endif
|
||||
|
||||
#if PLUTOSDR_DRIVER
|
||||
#include "ad936x_custom_signal_source.h"
|
||||
#include "plutosdr_signal_source.h"
|
||||
#endif
|
||||
|
||||
@ -775,6 +776,12 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
||||
out_streams, queue);
|
||||
block = std::move(block_);
|
||||
}
|
||||
else if (implementation == "Ad936x_Custom_Signal_Source")
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<Ad936xCustomSignalSource>(configuration, role, in_streams,
|
||||
out_streams, queue);
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FMCOMMS2_DRIVER
|
||||
|
Loading…
Reference in New Issue
Block a user