1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-10-31 07:13:03 +00:00

Merge with next

This commit is contained in:
Javier Arribas
2022-12-12 15:30:30 +01:00
187 changed files with 3423 additions and 1965 deletions

View File

@@ -6,15 +6,12 @@
# Optional drivers
set(OPT_DRIVER_SOURCES "")
set(OPT_DRIVER_HEADERS "")
if(ENABLE_RAW_UDP AND PCAP_FOUND)
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} custom_udp_signal_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} custom_udp_signal_source.h)
list(APPEND OPT_DRIVER_SOURCES custom_udp_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS custom_udp_signal_source.h)
endif()
if(ENABLE_PLUTOSDR)
##############################################
# ADALM-PLUTO (Analog Devices Inc.)
@@ -29,31 +26,27 @@ if(ENABLE_PLUTOSDR)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad936x_custom_signal_source.h)
endif()
if(ENABLE_FMCOMMS2)
###############################################
# FMCOMMS2 based SDR Hardware
###############################################
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} fmcomms2_signal_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} fmcomms2_signal_source.h)
list(APPEND OPT_DRIVER_SOURCES fmcomms2_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS fmcomms2_signal_source.h)
endif()
if(ENABLE_AD9361)
###############################################
# AD9361 DIRECT TO FPGA Hardware
###############################################
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} ad9361_fpga_signal_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} ad9361_fpga_signal_source.h)
list(APPEND OPT_DRIVER_SOURCES ad9361_fpga_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS ad9361_fpga_signal_source.h)
endif()
if(ENABLE_FLEXIBAND AND TELEORBIT_FOUND)
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} flexiband_signal_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} flexiband_signal_source.h)
list(APPEND OPT_DRIVER_SOURCES flexiband_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS flexiband_signal_source.h)
endif()
if(ENABLE_ARRAY)
##############################################
# DBFCTTC GNSS EXPERIMENTAL ARRAY PROTOTYPE
@@ -62,32 +55,30 @@ if(ENABLE_ARRAY)
message(" gr-dbfcttc not found, install it from https://github.com/gnss-sdr/gr-dbfcttc")
message(FATAL_ERROR "gr-dbfcttc required for building gnss-sdr with this option enabled")
endif()
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} raw_array_signal_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} raw_array_signal_source.h)
list(APPEND OPT_DRIVER_SOURCES raw_array_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS raw_array_signal_source.h)
endif()
if(ENABLE_OSMOSDR)
################################################################################
# OsmoSDR - https://osmocom.org/projects/gr-osmosdr/
################################################################################
if(GROSMOSDR_FOUND)
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} osmosdr_signal_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} osmosdr_signal_source.h)
list(APPEND OPT_DRIVER_SOURCES osmosdr_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS osmosdr_signal_source.h)
endif()
endif()
if(ENABLE_LIMESDR)
if(GRLIMESDR_FOUND)
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} limesdr_signal_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} limesdr_signal_source.h)
list(APPEND OPT_DRIVER_SOURCES limesdr_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS limesdr_signal_source.h)
endif()
endif()
if(ENABLE_UHD)
set(OPT_DRIVER_SOURCES ${OPT_DRIVER_SOURCES} uhd_signal_source.cc)
set(OPT_DRIVER_HEADERS ${OPT_DRIVER_HEADERS} uhd_signal_source.h)
list(APPEND OPT_DRIVER_SOURCES uhd_signal_source.cc)
list(APPEND OPT_DRIVER_HEADERS uhd_signal_source.h)
endif()
if(ENABLE_ZMQ)
@@ -95,7 +86,6 @@ if(ENABLE_ZMQ)
list(APPEND OPT_DRIVER_HEADERS zmq_signal_source.h)
endif()
set(SIGNAL_SOURCE_ADAPTER_SOURCES
signal_source_base.cc
file_source_base.cc
@@ -226,7 +216,6 @@ if(ENABLE_LIMESDR AND GRLIMESDR_FOUND)
)
endif()
if(ENABLE_AD9361 AND LIBIIO_FOUND)
target_link_libraries(signal_source_adapters
PRIVATE
@@ -310,8 +299,6 @@ target_compile_definitions(signal_source_adapters
PRIVATE -DGNSSSDR_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}"
)
set_property(TARGET signal_source_adapters
APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>

View File

@@ -610,7 +610,7 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
// rx signal vectors
std::vector<int8_t> input_samples(sample_block_size * 2); // complex samples
// pointer to DMA buffer
std::array<int8_t, BUFFER_SIZE> *dma_buffer;
int8_t *dma_buffer;
int nread_elements = 0; // num bytes read from the file corresponding to frequency band 1
bool run_DMA = true;
@@ -631,8 +631,8 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
// if only one file is enabled then clear the samples corresponding to the frequency band that is not used.
for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{
(*dma_buffer)[dma_index + (2 - dma_buff_offset_pos)] = 0;
(*dma_buffer)[dma_index + 1 + (2 - dma_buff_offset_pos)] = 0;
dma_buffer[dma_index + (2 - dma_buff_offset_pos)] = 0;
dma_buffer[dma_index + 1 + (2 - dma_buff_offset_pos)] = 0;
dma_index += 4;
}
}
@@ -673,8 +673,8 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{
// dma_buff_offset_pos is 1 for the L1 band and 0 for the other bands
(*dma_buffer)[dma_index + dma_buff_offset_pos] = input_samples[index0];
(*dma_buffer)[dma_index + 1 + dma_buff_offset_pos] = input_samples[index0 + 1];
dma_buffer[dma_index + dma_buff_offset_pos] = input_samples[index0];
dma_buffer[dma_index + 1 + dma_buff_offset_pos] = input_samples[index0 + 1];
dma_index += 4;
}
@@ -704,8 +704,8 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0_, cons
for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{
// filename2 is never the L1 band
(*dma_buffer)[dma_index] = input_samples[index0];
(*dma_buffer)[dma_index + 1] = input_samples[index0 + 1];
dma_buffer[dma_index] = input_samples[index0];
dma_buffer[dma_index + 1] = input_samples[index0 + 1];
dma_index += 4;
}
}

View File

@@ -23,7 +23,11 @@
#include "concurrent_queue.h"
#include "fpga_buffer_monitor.h"
#include "fpga_dma.h"
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
#include "fpga_dma-proxy.h"
#else
#include "fpga_ezdma.h"
#endif
#include "fpga_dynamic_bit_selection.h"
#include "fpga_switch.h"
#include "gnss_block_interface.h"

View File

@@ -25,17 +25,22 @@
using namespace std::string_literals;
CustomUDPSignalSource::CustomUDPSignalSource(const ConfigurationInterface* configuration,
const std::string& role, unsigned int in_stream, unsigned int out_stream,
const std::string& role,
unsigned int in_stream,
unsigned int out_stream,
Concurrent_Queue<pmt::pmt_t>* queue __attribute__((unused)))
: SignalSourceBase(configuration, role, "Custom_UDP_Signal_Source"s),
item_size_(sizeof(gr_complex)),
RF_channels_(configuration->property(role + ".RF_channels", 1)),
channels_in_udp_(configuration->property(role + ".channels_in_udp", 1)),
in_stream_(in_stream),
out_stream_(out_stream)
out_stream_(out_stream),
IQ_swap_(configuration->property(role + ".IQ_swap", false)),
dump_(configuration->property(role + ".dump", false))
{
// DUMP PARAMETERS
const std::string default_dump_file("./data/signal_source.dat");
const std::string default_item_type("gr_complex");
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file);
// network PARAMETERS
@@ -47,10 +52,6 @@ CustomUDPSignalSource::CustomUDPSignalSource(const ConfigurationInterface* confi
int port = configuration->property(role + ".port", default_port);
int payload_bytes = configuration->property(role + ".payload_bytes", 1024);
RF_channels_ = configuration->property(role + ".RF_channels", 1);
channels_in_udp_ = configuration->property(role + ".channels_in_udp", 1);
IQ_swap_ = configuration->property(role + ".IQ_swap", false);
const std::string default_sample_type("cbyte");
const std::string sample_type = configuration->property(role + ".sample_type", default_sample_type);
item_type_ = configuration->property(role + ".item_type", default_item_type);

View File

@@ -74,9 +74,8 @@ private:
int channels_in_udp_;
unsigned int in_stream_;
unsigned int out_stream_;
bool dump_;
bool IQ_swap_;
bool dump_;
};

View File

@@ -25,17 +25,21 @@
using namespace std::string_literals;
LabsatSignalSource::LabsatSignalSource(const ConfigurationInterface* configuration,
const std::string& role, unsigned int in_stream, unsigned int out_stream, Concurrent_Queue<pmt::pmt_t>* queue)
: SignalSourceBase(configuration, role, "Labsat_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
const std::string& role,
unsigned int in_stream,
unsigned int out_stream,
Concurrent_Queue<pmt::pmt_t>* queue)
: SignalSourceBase(configuration, role, "Labsat_Signal_Source"s),
in_stream_(in_stream),
out_stream_(out_stream),
enable_throttle_control_(configuration->property(role + ".enable_throttle_control", false)),
dump_(configuration->property(role + ".dump", false))
{
const std::string default_item_type("gr_complex");
const std::string default_dump_file("./labsat_output.dat");
item_type_ = configuration->property(role + ".item_type", default_item_type);
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file);
enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false);
const int64_t sampling_frequency_deprecated = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(16368000));
const int64_t throttle_frequency_sps = configuration->property(role + ".throttle_frequency_sps", static_cast<int64_t>(sampling_frequency_deprecated));

View File

@@ -34,29 +34,30 @@ RtlTcpSignalSource::RtlTcpSignalSource(const ConfigurationInterface* configurati
unsigned int in_stream,
unsigned int out_stream,
Concurrent_Queue<pmt::pmt_t>* queue)
: SignalSourceBase(configuration, role, "RtlTcp_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream)
: SignalSourceBase(configuration, role, "RtlTcp_Signal_Source"s),
samples_(configuration->property(role + ".samples", static_cast<uint64_t>(0))),
rf_gain_(configuration->property(role + ".rf_gain", 40.0)),
sample_rate_(configuration->property(role + ".sampling_frequency", 2000000)),
freq_(configuration->property(role + ".freq", static_cast<int>(GPS_L1_FREQ_HZ))),
gain_(configuration->property(role + ".gain", 40)),
if_gain_(configuration->property(role + ".if_gain", 40)),
in_stream_(in_stream),
out_stream_(out_stream),
AGC_enabled_(configuration->property(role + ".AGC_enabled", true)),
flip_iq_(configuration->property(role + ".flip_iq", false)),
dump_(configuration->property(role + ".dump", false))
{
// DUMP PARAMETERS
const std::string default_dump_file("./data/signal_source.dat");
const std::string default_item_type("gr_complex");
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename",
default_dump_file);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file);
// rtl_tcp PARAMETERS
const std::string default_address("127.0.0.1");
const int16_t default_port = 1234;
AGC_enabled_ = configuration->property(role + ".AGC_enabled", true);
freq_ = configuration->property(role + ".freq", static_cast<int>(GPS_L1_FREQ_HZ));
gain_ = configuration->property(role + ".gain", 40);
rf_gain_ = configuration->property(role + ".rf_gain", 40.0);
if_gain_ = configuration->property(role + ".if_gain", 40);
sample_rate_ = configuration->property(role + ".sampling_frequency", 2000000);
item_type_ = configuration->property(role + ".item_type", default_item_type);
address_ = configuration->property(role + ".address", default_address);
port_ = configuration->property(role + ".port", default_port);
flip_iq_ = configuration->property(role + ".flip_iq", false);
if (item_type_ == "short")
{

View File

@@ -78,11 +78,11 @@ private:
std::string address_;
size_t item_size_;
uint64_t samples_;
double rf_gain_;
int sample_rate_;
int freq_;
int gain_;
int if_gain_;
double rf_gain_;
unsigned int in_stream_;
unsigned int out_stream_;
int16_t port_;

View File

@@ -29,27 +29,29 @@
using namespace std::string_literals;
SpirGSS6450FileSignalSource::SpirGSS6450FileSignalSource(const ConfigurationInterface* configuration,
const std::string& role, uint32_t in_streams, uint32_t out_streams, Concurrent_Queue<pmt::pmt_t>* queue)
const std::string& role,
uint32_t in_streams,
uint32_t out_streams,
Concurrent_Queue<pmt::pmt_t>* queue)
: SignalSourceBase(configuration, role, "Spir_GSS6450_File_Signal_Source"s),
item_type_("int"),
samples_(configuration->property(role + ".samples", static_cast<uint64_t>(0))),
sampling_frequency_(configuration->property(role + ".sampling_frequency", static_cast<int64_t>(0))),
item_size_(sizeof(int32_t)),
in_streams_(in_streams),
out_streams_(out_streams)
out_streams_(out_streams),
adc_bits_(configuration->property(role + ".adc_bits", 4)),
n_channels_(configuration->property(role + ".total_channels", 1)),
sel_ch_(configuration->property(role + ".sel_ch", 1)),
repeat_(configuration->property(role + ".repeat", false)),
dump_(configuration->property(role + ".dump", false)),
enable_throttle_control_(configuration->property(role + ".enable_throttle_control", false)),
endian_swap_(configuration->property(role + ".endian", false))
{
const std::string default_filename("../data/my_capture.dat");
const std::string default_dump_filename("../data/my_capture_dump.dat");
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
sampling_frequency_ = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(0));
filename_ = configuration->property(role + ".filename", default_filename);
repeat_ = configuration->property(role + ".repeat", false);
dump_ = configuration->property(role + ".dump", false);
endian_swap_ = configuration->property(role + ".endian", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
enable_throttle_control_ = configuration->property(role + ".enable_throttle_control", false);
adc_bits_ = configuration->property(role + ".adc_bits", 4);
n_channels_ = configuration->property(role + ".total_channels", 1);
sel_ch_ = configuration->property(role + ".sel_ch", 1);
const int64_t bytes_seek = configuration->property(role + ".bytes_to_skip", static_cast<int64_t>(65536));
const double sample_size_byte = static_cast<double>(adc_bits_) / 4.0;
@@ -190,7 +192,6 @@ void SpirGSS6450FileSignalSource::connect(gr::top_block_sptr top_block)
if (n_channels_ > 1)
{
uint32_t aux = 0;
for (int32_t i = 0; i < n_channels_; i++)
{
if (i != (sel_ch_ - 1))
@@ -204,8 +205,6 @@ void SpirGSS6450FileSignalSource::connect(gr::top_block_sptr top_block)
{
top_block->connect(deint_, i, unpack_spir_vec_.at(i), 0);
}
aux++;
}
}
}
@@ -251,7 +250,6 @@ void SpirGSS6450FileSignalSource::disconnect(gr::top_block_sptr top_block)
}
if (n_channels_ > 1)
{
uint32_t aux = 0;
for (int32_t i = 0; i < n_channels_; i++)
{
if (i != (sel_ch_ - 1))
@@ -265,8 +263,6 @@ void SpirGSS6450FileSignalSource::disconnect(gr::top_block_sptr top_block)
{
top_block->disconnect(deint_, i, unpack_spir_vec_.at(i), 0);
}
aux++;
}
}
}

View File

@@ -5,11 +5,9 @@
# SPDX-License-Identifier: BSD-3-Clause
set(OPT_DRIVER_SOURCES "")
set(OPT_DRIVER_HEADERS "")
if(ENABLE_RAW_UDP AND PCAP_FOUND)
set(OPT_DRIVER_SOURCES gr_complex_ip_packet_source.cc)
set(OPT_DRIVER_HEADERS gr_complex_ip_packet_source.h)
list(APPEND OPT_DRIVER_SOURCES gr_complex_ip_packet_source.cc)
list(APPEND OPT_DRIVER_HEADERS gr_complex_ip_packet_source.h)
endif()
if(ENABLE_AD936X_SDR)
@@ -23,7 +21,6 @@ if(ENABLE_PLUTOSDR)
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
@@ -38,7 +35,6 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
${OPT_DRIVER_SOURCES}
)
set(SIGNAL_SOURCE_GR_BLOCKS_HEADERS
fifo_reader.h
unpack_byte_2bit_samples.h
@@ -147,6 +143,17 @@ else()
)
endif()
if(Boost_VERSION_STRING VERSION_GREATER "1.57.99")
target_compile_definitions(signal_source_gr_blocks
PRIVATE
-DHAS_BOOST_ENDIAN=1
)
target_link_libraries(signal_source_gr_blocks
PRIVATE
Boost::headers
)
endif()
if(ENABLE_CLANG_TIDY)
if(CLANG_TIDY_EXE)
set_target_properties(signal_source_gr_blocks

View File

@@ -32,6 +32,10 @@
#include <sstream>
#include <utility>
#if HAS_BOOST_ENDIAN
#include <boost/endian/conversion.hpp>
#endif
labsat23_source_sptr labsat23_make_source_sptr(const char *signal_file_basename, const std::vector<int> &channel_selector, Concurrent_Queue<pmt::pmt_t> *queue, bool digital_io_enabled)
{
@@ -737,7 +741,8 @@ void labsat23_source::decode_ls3w_register(uint64_t input, std::vector<gr_comple
{
std::bitset<64> bs(input);
// Reverse, since register are written to file as 64-bit little endian words
// Earlier samples are written in the MSBs of the register. Bit-reverse the register
// for easier indexing. Note this bit-reverses individual samples as well for quant > 1 bit
for (std::size_t i = 0; i < 32; ++i)
{
bool t = bs[i];
@@ -1074,14 +1079,20 @@ int labsat23_source::general_work(int noutput_items,
std::size_t output_pointer = 0;
for (int i = 0; i < registers_to_read; i++)
{
uint64_t read_register = 0ULL;
// Labsat3W writes its 64-bit shift register to files in little endian. Read and convert to host endianness.
#if HAS_BOOST_ENDIAN
binary_input_file.read(reinterpret_cast<char *>(&read_register), sizeof(read_register));
boost::endian::little_to_native_inplace(read_register);
#else
std::array<char, 8> memory_block{};
binary_input_file.read(memory_block.data(), 8);
uint64_t read_register = 0ULL;
for (int k = 7; k >= 0; --k)
{
read_register <<= 8;
read_register |= uint64_t(memory_block[k]);
read_register |= uint64_t(memory_block[k]); // This is buggy if the MSB of the char is set.
}
#endif
if (binary_input_file.gcount() == 8)
{

View File

@@ -19,8 +19,13 @@ if(ENABLE_FPGA OR ENABLE_AD9361)
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dynamic_bit_selection.h)
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_buffer_monitor.cc)
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_buffer_monitor.h)
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dma.cc)
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dma.h)
if(ARCH_64BITS)
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dma-proxy.cc)
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dma-proxy.h)
else()
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_ezdma.cc)
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_ezdma.h)
endif()
endif()

View File

@@ -111,11 +111,11 @@ Fpga_buffer_monitor::Fpga_buffer_monitor(const std::string &device_name,
{
try
{
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
d_dump_file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
d_dump_file.open(dump_filename_.c_str(), std::ios::out | std::ios::binary);
LOG(INFO) << "FPGA buffer monitor dump enabled. Log file: " << dump_filename_.c_str();
}
catch (const std::ifstream::failure &e)
catch (const std::ofstream::failure &e)
{
LOG(WARNING) << "Exception opening FPGA buffer monitor dump file " << e.what();
}

View File

@@ -1,5 +1,5 @@
/*!
* \file fpga_dma.cc
* \file fpga_dma-proxy.cc
* \brief FPGA DMA control. This code is based in the Xilinx DMA proxy test application:
* https://github.com/Xilinx-Wiki-Projects/software-prototypes/tree/master/linux-user-space-dma/Software
* \author Marc Majoral, mmajoral(at)cttc.es
@@ -15,7 +15,7 @@
* -----------------------------------------------------------------------------
*/
#include "fpga_dma.h"
#include "fpga_dma-proxy.h"
#include <fcntl.h>
#include <iostream> // for std::cerr
#include <sys/ioctl.h> // for ioctl()
@@ -24,7 +24,6 @@
int Fpga_DMA::DMA_open()
{
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
tx_channel.fd = open("/dev/dma_proxy_tx", O_RDWR);
if (tx_channel.fd < 1)
{
@@ -40,61 +39,29 @@ int Fpga_DMA::DMA_open()
return -1;
}
#else // 32-bit processor architecture
tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 1)
{
return tx_fd;
}
// note: a problem was identified with the DMA: when switching from tx to rx or rx to tx mode
// the DMA transmission may hang. This problem will be fixed soon.
// for the moment this problem can be avoided by closing and opening the DMA a second time
if (close(tx_fd) < 0)
{
std::cerr << "Error closing loop device " << '\n';
return -1;
}
// open the DMA a second time
tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 1)
{
std::cerr << "Cannot open loop device\n";
// stop the receiver
return tx_fd;
}
#endif
return 0;
}
std::array<int8_t, BUFFER_SIZE> *Fpga_DMA::get_buffer_address() // NOLINT(readability-make-member-function-const)
int8_t *Fpga_DMA::get_buffer_address() // NOLINT(readability-make-member-function-const)
{
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
return &tx_channel.buf_ptr[0].buffer;
#else // 32-bit processor architecture
return &buffer;
#endif
return tx_channel.buf_ptr[0].buffer;
}
int Fpga_DMA::DMA_write(int nbytes) const
{
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
int buffer_id = 0;
tx_channel.buf_ptr[0].length = nbytes;
// start DMA transfer
if (ioctl(tx_channel.fd, START_XFER, &buffer_id))
if (ioctl(tx_channel.fd, _IOW('a', 'b', int32_t *), &buffer_id)) // start transfer
{
std::cerr << "Error starting tx DMA transfer " << '\n';
return -1;
}
// wait for completion of DMA transfer
if (ioctl(tx_channel.fd, FINISH_XFER, &buffer_id))
if (ioctl(tx_channel.fd, _IOW('a', 'a', int32_t *), &buffer_id)) // finish transfer
{
std::cerr << "Error detecting end of DMA transfer " << '\n';
return -1;
@@ -105,27 +72,16 @@ int Fpga_DMA::DMA_write(int nbytes) const
std::cerr << "Proxy DMA Tx transfer error " << '\n';
return -1;
}
#else // 32-bit processor architecture
const int num_bytes_sent = write(tx_fd, buffer.data(), nbytes);
if (num_bytes_sent != nbytes)
{
return -1;
}
#endif
return 0;
}
int Fpga_DMA::DMA_close() const
{
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
if (munmap(tx_channel.buf_ptr, sizeof(struct channel_buffer)))
{
std::cerr << "Failed to unmap DMA tx channel " << '\n';
return -1;
}
return close(tx_channel.fd);
#else // 32-bit processor architecture
return close(tx_fd);
#endif
}

View File

@@ -1,5 +1,5 @@
/*!
* \file fpga_dma.h
* \file fpga_dma-proxy.h
* \brief FPGA DMA control. This code is based in the Xilinx DMA proxy test application:
* https://github.com/Xilinx-Wiki-Projects/software-prototypes/tree/master/linux-user-space-dma/Software
* \author Marc Majoral, mmajoral(at)cttc.es
@@ -15,45 +15,11 @@
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_FPGA_DMA_PROXY_H
#define GNSS_SDR_FPGA_DMA_PROXY_H
#ifndef GNSS_SDR_FPGA_DMA_H
#define GNSS_SDR_FPGA_DMA_H
#include <array> // for std::array
#include <cstdint> // for std::int8_t
#define BUFFER_SIZE (128 * 1024) /* must match driver exactly */
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
#define TX_BUFFER_COUNT 1 /* app only, must be <= to the number in the driver */
#define FINISH_XFER _IOW('a', 'a', int32_t *)
#define START_XFER _IOW('a', 'b', int32_t *)
// channel buffer structure
struct channel_buffer
{
std::array<int8_t, BUFFER_SIZE> buffer;
enum proxy_status
{
PROXY_NO_ERROR = 0,
PROXY_BUSY = 1,
PROXY_TIMEOUT = 2,
PROXY_ERROR = 3
} status;
unsigned int length;
} __attribute__((aligned(1024))); /* 64 byte alignment required for DMA, but 1024 handy for viewing memory */
// internal DMA channel data structure
struct channel
{
struct channel_buffer *buf_ptr;
int fd;
};
#endif
/*!
* \brief Class that controls the switch DMA in the FPGA
*/
@@ -78,7 +44,7 @@ public:
/*!
* \brief Obtain DMA buffer address.
*/
std::array<int8_t, BUFFER_SIZE> *get_buffer_address(void); // NOLINT(readability-make-member-function-const)
int8_t *get_buffer_address(void); // NOLINT(readability-make-member-function-const)
/*!
* \brief Transfer DMA data
@@ -91,11 +57,30 @@ public:
int DMA_close(void) const;
private:
#if INTPTR_MAX == INT64_MAX // 64-bit processor architecture
static const uint32_t DMA_MAX_BUFFER_SIZE = (128 * 1024); /* must match driver exactly */
static const uint32_t TX_BUFFER_COUNT = 1;
// channel buffer structure
struct channel_buffer
{
int8_t buffer[DMA_MAX_BUFFER_SIZE];
enum proxy_status
{
PROXY_NO_ERROR = 0,
PROXY_BUSY = 1,
PROXY_TIMEOUT = 2,
PROXY_ERROR = 3
} status;
unsigned int length;
} __attribute__((aligned(1024))); /* 64 byte alignment required for DMA, but 1024 handy for viewing memory */
// internal DMA channel data structure
struct channel
{
struct channel_buffer *buf_ptr;
int fd;
};
channel tx_channel;
#else // 32-bit processor architecture
std::array<int8_t, BUFFER_SIZE> buffer;
int tx_fd;
#endif
};
#endif // GNSS_SDR_FPGA_DMA_H
#endif // GNSS_SDR_FPGA_DMA_PROXY_H

View File

@@ -0,0 +1,68 @@
/*!
* \file fpga_edma.cc
* \brief FPGA DMA control using the ezdma (See https://github.com/jeremytrimble/ezdma).
* \author Marc Majoral, mmajoral(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 "fpga_ezdma.h"
#include <fcntl.h>
#include <iostream> // for std::cerr
#include <unistd.h>
int Fpga_DMA::DMA_open()
{
tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 1)
{
return tx_fd;
}
// note: a problem was identified with the DMA: when switching from tx to rx or rx to tx mode
// the DMA transmission may hang. This problem will be fixed soon.
// for the moment this problem can be avoided by closing and opening the DMA a second time
if (close(tx_fd) < 0)
{
std::cerr << "Error closing loop device " << '\n';
return -1;
}
// open the DMA a second time
tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 1)
{
std::cerr << "Cannot open loop device\n";
// stop the receiver
return tx_fd;
}
return 0;
}
int8_t *Fpga_DMA::get_buffer_address()
{
return buffer;
}
int Fpga_DMA::DMA_write(int nbytes) const
{
const int num_bytes_sent = write(tx_fd, buffer, nbytes);
if (num_bytes_sent != nbytes)
{
return -1;
}
return 0;
}
int Fpga_DMA::DMA_close() const
{
return close(tx_fd);
}

View File

@@ -0,0 +1,64 @@
/*!
* \file fpga_ezdma.h
* \brief FPGA DMA control using the ezdma (See https://github.com/jeremytrimble/ezdma).
* \author Marc Majoral, mmajoral(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_FPGA_EDMA_H
#define GNSS_SDR_FPGA_EDMA_H
#include <cstdint> // for std::int8_t
/*!
* \brief Class that controls the switch DMA in the FPGA
*/
class Fpga_DMA
{
public:
/*!
* \brief Default constructor.
*/
Fpga_DMA() = default;
/*!
* \brief Default destructor.
*/
~Fpga_DMA() = default;
/*!
* \brief Open the DMA device driver.
*/
int DMA_open(void);
/*!
* \brief Obtain DMA buffer address.
*/
int8_t *get_buffer_address(void); // NOLINT(readability-make-member-function-const)
/*!
* \brief Transfer DMA data
*/
int DMA_write(int nbytes) const;
/*!
* \brief Close the DMA device driver
*/
int DMA_close(void) const;
private:
static const uint32_t DMA_MAX_BUFFER_SIZE = 4 * 16384; // 4-channel 16384-sample buffers
int8_t buffer[DMA_MAX_BUFFER_SIZE];
int tx_fd;
};
#endif // GNSS_SDR_FPGA_EDMA_H