mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-02-07 14:40:12 +00:00
Add the MAX2771_EVKIT FPGA signal source and the ENABLE_FPGA_MAX2771_EVKIT flag to enable it.
This commit is contained in:
parent
ac7bdc919b
commit
d24c35854a
@ -44,6 +44,8 @@ option(ENABLE_AD936X_SDR "Enable the use of AD936X front-ends using libiio, requ
|
|||||||
|
|
||||||
option(ENABLE_AD9361 "Enable the use of AD9361 direct to FPGA hardware, requires libiio" OFF)
|
option(ENABLE_AD9361 "Enable the use of AD9361 direct to FPGA hardware, requires libiio" OFF)
|
||||||
|
|
||||||
|
option(ENABLE_FPGA_MAX2771_EVKIT "Enable the use of MAX2771 EVKIT direct to FPGA hardware" OFF)
|
||||||
|
|
||||||
option(ENABLE_RAW_UDP "Enable the use of high-optimized custom UDP packet sample source, requires libpcap" OFF)
|
option(ENABLE_RAW_UDP "Enable the use of high-optimized custom UDP packet sample source, requires libpcap" OFF)
|
||||||
|
|
||||||
option(ENABLE_FLEXIBAND "Enable the use of the signal source adater for the Teleorbit Flexiband GNU Radio driver" OFF)
|
option(ENABLE_FLEXIBAND "Enable the use of the signal source adater for the Teleorbit Flexiband GNU Radio driver" OFF)
|
||||||
@ -3552,6 +3554,7 @@ add_feature_info(ENABLE_LIMESDR ENABLE_LIMESDR "Enables Limesdr_Signal_Source. R
|
|||||||
add_feature_info(ENABLE_FMCOMMS2 ENABLE_FMCOMMS2 "Enables Fmcomms2_Signal_Source for FMCOMMS2/3/4 devices. Requires gr-iio and libad9361-dev.")
|
add_feature_info(ENABLE_FMCOMMS2 ENABLE_FMCOMMS2 "Enables Fmcomms2_Signal_Source for FMCOMMS2/3/4 devices. Requires gr-iio and libad9361-dev.")
|
||||||
add_feature_info(ENABLE_PLUTOSDR ENABLE_PLUTOSDR "Enables Plutosdr_Signal_Source for using ADALM-PLUTO boards. Requires gr-iio.")
|
add_feature_info(ENABLE_PLUTOSDR ENABLE_PLUTOSDR "Enables Plutosdr_Signal_Source for using ADALM-PLUTO boards. Requires gr-iio.")
|
||||||
add_feature_info(ENABLE_AD9361 ENABLE_AD9361 "Enables Ad9361_Fpga_Signal_Source for devices with the AD9361 chipset. Requires libiio and libad9361-dev.")
|
add_feature_info(ENABLE_AD9361 ENABLE_AD9361 "Enables Ad9361_Fpga_Signal_Source for devices with the AD9361 chipset. Requires libiio and libad9361-dev.")
|
||||||
|
add_feature_info(ENABLE_FPGA_MAX2771_EVKIT ENABLE_FPGA_MAX2771_EVKIT "Enables MAX2771_evkit_fpga_signal_source for devices with the MAX2771 chipset.")
|
||||||
add_feature_info(ENABLE_AD936X_SDR ENABLE_AD936X_SDR "Enables Ad936x_Iio_Signal_Source to access AD936X front-ends using libiio. Requires libiio and libad9361-dev.")
|
add_feature_info(ENABLE_AD936X_SDR ENABLE_AD936X_SDR "Enables Ad936x_Iio_Signal_Source to access AD936X front-ends using libiio. Requires libiio and libad9361-dev.")
|
||||||
add_feature_info(ENABLE_RAW_UDP ENABLE_RAW_UDP "Enables Custom_UDP_Signal_Source for custom UDP packet sample source. Requires libpcap.")
|
add_feature_info(ENABLE_RAW_UDP ENABLE_RAW_UDP "Enables Custom_UDP_Signal_Source for custom UDP packet sample source. Requires libpcap.")
|
||||||
add_feature_info(ENABLE_FLEXIBAND ENABLE_FLEXIBAND "Enables Flexiband_Signal_Source for using Teleorbit's Flexiband RF front-end. Requires gr-teleorbit.")
|
add_feature_info(ENABLE_FLEXIBAND ENABLE_FLEXIBAND "Enables Flexiband_Signal_Source for using Teleorbit's Flexiband RF front-end. Requires gr-teleorbit.")
|
||||||
|
@ -41,6 +41,14 @@ if(ENABLE_AD9361)
|
|||||||
list(APPEND OPT_DRIVER_HEADERS ad9361_fpga_signal_source.h)
|
list(APPEND OPT_DRIVER_HEADERS ad9361_fpga_signal_source.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_FPGA_MAX2771_EVKIT)
|
||||||
|
###############################################
|
||||||
|
# MAX2771 EVKIT DIRECT TO FPGA Hardware
|
||||||
|
###############################################
|
||||||
|
list(APPEND OPT_DRIVER_SOURCES max2771_evkit_fpga_signal_source.cc)
|
||||||
|
list(APPEND OPT_DRIVER_HEADERS max2771_evkit_fpga_signal_source.h)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_FPGA)
|
if(ENABLE_FPGA)
|
||||||
###############################################
|
###############################################
|
||||||
# FPGA DMA source
|
# FPGA DMA source
|
||||||
@ -159,7 +167,7 @@ target_include_directories(signal_source_adapters
|
|||||||
${GNSSSDR_SOURCE_DIR}/src/core/interfaces
|
${GNSSSDR_SOURCE_DIR}/src/core/interfaces
|
||||||
)
|
)
|
||||||
|
|
||||||
if(ENABLE_FPGA OR ENABLE_AD9361)
|
if(ENABLE_FPGA OR ENABLE_AD9361 OR ENABLE_FPGA_MAX2771_EVKIT)
|
||||||
target_link_libraries(signal_source_adapters
|
target_link_libraries(signal_source_adapters
|
||||||
PUBLIC
|
PUBLIC
|
||||||
signal_source_libs
|
signal_source_libs
|
||||||
|
@ -0,0 +1,468 @@
|
|||||||
|
/*!
|
||||||
|
* \file max2771_evkit_fpga_signal_source.cc
|
||||||
|
* \brief Signal source for the MAX2771EVKIT evaluation board connected directly
|
||||||
|
* to FPGA accelerators.
|
||||||
|
* This source implements only the MAX2771 control. It is NOT compatible with
|
||||||
|
* conventional SDR acquisition and tracking blocks.
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "max2771_evkit_fpga_signal_source.h"
|
||||||
|
#include "GPS_L1_CA.h"
|
||||||
|
#include "GPS_L2C.h"
|
||||||
|
#include "GPS_L5.h"
|
||||||
|
#include "configuration_interface.h"
|
||||||
|
#include "gnss_sdr_flags.h"
|
||||||
|
#include "gnss_sdr_string_literals.h"
|
||||||
|
#include <algorithm> // for std::max
|
||||||
|
#include <chrono> // for std::chrono
|
||||||
|
#include <cmath> // for std::floor
|
||||||
|
#include <exception> // for std::exception
|
||||||
|
#include <iostream> // for std::cout
|
||||||
|
|
||||||
|
#if USE_GLOG_AND_GFLAGS
|
||||||
|
#include <glog/logging.h>
|
||||||
|
#else
|
||||||
|
#include <absl/log/check.h>
|
||||||
|
#include <absl/log/log.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
MAX2771EVKITFpgaSignalSource::MAX2771EVKITFpgaSignalSource(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, "Ad9361_Fpga_Signal_Source"s),
|
||||||
|
freq_(configuration->property(role + ".freq", static_cast<uint64_t>(GPS_L1_FREQ_HZ))),
|
||||||
|
sample_rate_(configuration->property(role + ".sampling_frequency", default_sampling_rate)),
|
||||||
|
in_stream_(in_stream),
|
||||||
|
out_stream_(out_stream),
|
||||||
|
bandwidth_(configuration->property(role + ".bandwidth", default_bandwidth)),
|
||||||
|
filter_order_(configuration->property(role + ".filter_order", default_filter_order)),
|
||||||
|
gain_in_(configuration->property(role + ".PGA_gain", default_PGA_gain_value)),
|
||||||
|
item_size_(sizeof(int8_t)),
|
||||||
|
chipen_(true),
|
||||||
|
if_filter_gain_(configuration->property(role + ".enable_IF_filter_gain", true)),
|
||||||
|
LNA_active_(configuration->property(role + ".LNA_active", false)),
|
||||||
|
enable_agc_(configuration->property(role + ".enable_AGC", true)),
|
||||||
|
enable_ovf_check_buffer_monitor_active_(true),
|
||||||
|
dump_(configuration->property(role + ".dump", false)),
|
||||||
|
#if USE_GLOG_AND_GFLAGS
|
||||||
|
rf_shutdown_(configuration->property(role + ".rf_shutdown", FLAGS_rf_shutdown))
|
||||||
|
#else
|
||||||
|
rf_shutdown_(configuration->property(role + ".rf_shutdown", absl::GetFlag(FLAGS_rf_shutdown)))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// some basic checks
|
||||||
|
if (freq_ != GPS_L1_FREQ_HZ and freq_ != GPS_L2_FREQ_HZ and freq_ != GPS_L5_FREQ_HZ)
|
||||||
|
{
|
||||||
|
std::cout << "Configuration parameter freq should take values " << GPS_L1_FREQ_HZ << ", " << GPS_L2_FREQ_HZ << ", or " << GPS_L5_FREQ_HZ << "\n";
|
||||||
|
std::cout << "Error: provided value freq = " << freq_ << " is not among valid values\n";
|
||||||
|
std::cout << " This parameter has been set to its default value freq = " << GPS_L1_FREQ_HZ << '\n';
|
||||||
|
LOG(WARNING) << "Invalid configuration value for freq parameter. Set to freq = " << GPS_L1_FREQ_HZ;
|
||||||
|
freq_ = GPS_L1_FREQ_HZ;
|
||||||
|
}
|
||||||
|
if (sample_rate_ != 4092000 and sample_rate_ != 8184000 and sample_rate_ != 16368000 and sample_rate_ != 32736000)
|
||||||
|
{
|
||||||
|
std::cout << "Configuration parameter sampling_frequency should take values 4092000, 8184000, 16368000, or 32736000\n";
|
||||||
|
std::cout << "Error: provided value sampling_frequency = " << sample_rate_ << " is not among valid values\n";
|
||||||
|
std::cout << " This parameter has been set to its default value sampling_frequency = " << default_sampling_rate << '\n';
|
||||||
|
LOG(WARNING) << "Invalid configuration value for sampling_frequency parameter. Set to sampling_frequency = " << default_sampling_rate;
|
||||||
|
sample_rate_ = default_sampling_rate;
|
||||||
|
}
|
||||||
|
if (bandwidth_ != 2500000 and bandwidth_ != 4200000 and bandwidth_ != 8700000 and bandwidth_ != 16400000 and bandwidth_ != 23400000 and bandwidth_ != 36000000)
|
||||||
|
{
|
||||||
|
std::cout << "Configuration parameter bandwidth can only take the following values: 2500000, 4200000, 8700000, 16400000, 23400000, and 36000000 Hz\n";
|
||||||
|
std::cout << "Error: provided value bandwidth = " << bandwidth_ << " is not among valid values\n";
|
||||||
|
std::cout << " This parameter has been set to its default value bandwidth = " << default_bandwidth << '\n';
|
||||||
|
LOG(WARNING) << "Invalid configuration value for bandwidth parameter. Set to bandwidth = " << default_bandwidth;
|
||||||
|
bandwidth_ = default_bandwidth;
|
||||||
|
}
|
||||||
|
if (filter_order_ != 3 and filter_order_ != 5)
|
||||||
|
{
|
||||||
|
std::cout << "Configuration parameter filter_order should take values 3 or 5\n";
|
||||||
|
std::cout << "Error: provided value filter_order = " << filter_order_ << " is not among valid values\n";
|
||||||
|
std::cout << " This parameter has been set to its default value filter_order = " << default_filter_order << '\n';
|
||||||
|
LOG(WARNING) << "Invalid configuration value for filter_order parameter. Set to filter_order = " << default_filter_order;
|
||||||
|
filter_order_ = default_filter_order;
|
||||||
|
}
|
||||||
|
if (gain_in_ > max_PGA_gain_value)
|
||||||
|
{
|
||||||
|
std::cout << "Configuration parameter PGA_gain should be up to " << max_PGA_gain_value << "\n";
|
||||||
|
std::cout << "Error: provided value PGA_gain = " << gain_in_ << " is not among valid values\n";
|
||||||
|
std::cout << " This parameter has been set to its default value PGA_gain = " << default_PGA_gain_value << '\n';
|
||||||
|
LOG(WARNING) << "Invalid configuration value for PGA_gain parameter. Set to PGA_gain = " << default_PGA_gain_value;
|
||||||
|
gain_in_ = default_PGA_gain_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> register_values = setup_regs();
|
||||||
|
|
||||||
|
spidev_fpga = std::make_shared<Fpga_spidev>();
|
||||||
|
|
||||||
|
if (spidev_fpga->SPI_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot open SPI device\n";
|
||||||
|
// stop the receiver
|
||||||
|
queue->push(pmt::make_any(command_event_make(200, 0)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configure(register_values))
|
||||||
|
{
|
||||||
|
std::cerr << "Error configuring the MAX2771 device " << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spidev_fpga->SPI_close())
|
||||||
|
{
|
||||||
|
std::cerr << "Error closing SPI device " << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename);
|
||||||
|
|
||||||
|
buffer_monitor_fpga = std::make_shared<Fpga_buffer_monitor>(NUM_FREQ_BANDS, dump_, dump_filename);
|
||||||
|
thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); });
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> MAX2771EVKITFpgaSignalSource::setup_regs(void)
|
||||||
|
{
|
||||||
|
std::vector<uint32_t> register_values = std::vector<uint32_t>(MAX2771_NUM_REGS);
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t LNA_mode = (LNA_active_) ? 0x0 : 0x2;
|
||||||
|
|
||||||
|
uint32_t Filter_Bandwidth;
|
||||||
|
|
||||||
|
switch (bandwidth_)
|
||||||
|
{
|
||||||
|
case 2500000:
|
||||||
|
Filter_Bandwidth = 0x0;
|
||||||
|
break;
|
||||||
|
case 4200000:
|
||||||
|
Filter_Bandwidth = 0x2;
|
||||||
|
break;
|
||||||
|
case 8700000:
|
||||||
|
Filter_Bandwidth = 0x1;
|
||||||
|
break;
|
||||||
|
case 16400000:
|
||||||
|
Filter_Bandwidth = 0x7;
|
||||||
|
break;
|
||||||
|
case 23400000:
|
||||||
|
Filter_Bandwidth = 0x3;
|
||||||
|
break;
|
||||||
|
case 36000000:
|
||||||
|
Filter_Bandwidth = 0x4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Filter_Bandwidth = 0x0; // default bandwidth
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t chipen_select = (chipen_) ? 0x1 : 0x0;
|
||||||
|
uint32_t Filter_order_sel = (filter_order_ == 5) ? 0x0 : 0x1;
|
||||||
|
uint32_t IF_filter_gain_sel = (if_filter_gain_) ? 0x1 : 0x0;
|
||||||
|
|
||||||
|
register_values[0] = // configuration 1 register
|
||||||
|
(chipen_select << 31) +
|
||||||
|
(IDLE << 30) +
|
||||||
|
(0x8 << 26) + // reserved
|
||||||
|
(0x8 << 22) + // reserved
|
||||||
|
(0x2 << 20) + // reserved
|
||||||
|
(0x1 << 18) + // reserved
|
||||||
|
(MIXPOLE << 17) +
|
||||||
|
(LNA_mode << 15) +
|
||||||
|
(MIXERMODE << 13) +
|
||||||
|
(FCEN << 6) +
|
||||||
|
(Filter_Bandwidth << 3) +
|
||||||
|
(Filter_order_sel << 2) +
|
||||||
|
(FCENX << 1) +
|
||||||
|
IF_filter_gain_sel;
|
||||||
|
|
||||||
|
uint32_t AGC_mode = (enable_agc_) ? 0x0 : 0x2;
|
||||||
|
|
||||||
|
register_values[1] = // configuration 2 register
|
||||||
|
(0x0 << 31) + // reserved
|
||||||
|
(0x1 << 29) + // reserved
|
||||||
|
(ANAIMON << 28) +
|
||||||
|
(IQEN << 27) +
|
||||||
|
(GAINREF << 15) +
|
||||||
|
(SPI_SDIO_CONFIG << 13) +
|
||||||
|
(AGC_mode << 11) +
|
||||||
|
(FORMAT << 9) +
|
||||||
|
(BITS << 6) +
|
||||||
|
(DRVCFG << 4) +
|
||||||
|
(0x1 << 3) + // reserved
|
||||||
|
(0x0 << 2) + // reserved
|
||||||
|
DIEID;
|
||||||
|
|
||||||
|
register_values[2] = // configuration 3 register
|
||||||
|
(0x0 << 28) + //reserved
|
||||||
|
(gain_in_ << 22) +
|
||||||
|
(0x1 << 21) + // reserved
|
||||||
|
(HILOADEN << 20) +
|
||||||
|
(0x1 << 19) + // reserved
|
||||||
|
(0x1 << 18) + // reserved
|
||||||
|
(0x1 << 17) + // reserved
|
||||||
|
(0x1 << 16) + // reserved
|
||||||
|
(FHIPEN << 15) +
|
||||||
|
(0x0 << 14) + // reserved
|
||||||
|
(PGAIEN << 13) +
|
||||||
|
(PGAQEN << 12) +
|
||||||
|
(STRMEN << 11) +
|
||||||
|
(STRMSTART << 10) +
|
||||||
|
(STRMSTOP << 9) +
|
||||||
|
(0x7 << 6) + // reserved
|
||||||
|
(STRMBITS << 4) +
|
||||||
|
(STAMPEN << 3) +
|
||||||
|
(TIMESYNCEN << 2) +
|
||||||
|
(DATASYNCEN << 1) +
|
||||||
|
STRMRST;
|
||||||
|
|
||||||
|
uint32_t clock_out_div_ratio;
|
||||||
|
|
||||||
|
switch (sample_rate_)
|
||||||
|
{
|
||||||
|
case 4092000:
|
||||||
|
clock_out_div_ratio = 0x1; // XTAL frequency /4
|
||||||
|
break;
|
||||||
|
case 8184000:
|
||||||
|
clock_out_div_ratio = 0x2; // XTAL frequency /2
|
||||||
|
break;
|
||||||
|
case 16368000:
|
||||||
|
clock_out_div_ratio = 0x3; // XTAL frequency
|
||||||
|
break;
|
||||||
|
case 32736000:
|
||||||
|
clock_out_div_ratio = 0x0; // XTAL Frequency x2
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
clock_out_div_ratio = 0x1; // default XTAL frequency
|
||||||
|
}
|
||||||
|
|
||||||
|
register_values[3] = // PLL configuration register
|
||||||
|
(clock_out_div_ratio << 29) +
|
||||||
|
(LOBAND << 28) +
|
||||||
|
(0x1 << 27) + // reserved
|
||||||
|
(0x0 << 26) + // reserved
|
||||||
|
(0x0 << 25) + // reserved
|
||||||
|
(REFOUTEN << 24) +
|
||||||
|
(0x1 << 23) + // reserved
|
||||||
|
(0x0 << 21) + // reserved
|
||||||
|
(IXTAL << 19) +
|
||||||
|
(0x10 << 14) + // reserved
|
||||||
|
(0x0 << 13) + // reserved
|
||||||
|
(0x0 << 10) + //reserved
|
||||||
|
(ICP << 9) +
|
||||||
|
(0x0 << 8) + // reserved
|
||||||
|
(0x0 << 7) + // reserved
|
||||||
|
(0x0 << 4) + // reserved
|
||||||
|
(INT_PLL << 3) +
|
||||||
|
(PWRSAV << 2) +
|
||||||
|
(0x0 << 1) + // reserved
|
||||||
|
0x0; // reserved
|
||||||
|
|
||||||
|
uint32_t freq_sel;
|
||||||
|
switch (freq_)
|
||||||
|
{
|
||||||
|
case static_cast<uint64_t>(GPS_L1_FREQ_HZ):
|
||||||
|
freq_sel = 0x604;
|
||||||
|
break;
|
||||||
|
case static_cast<uint64_t>(GPS_L2_FREQ_HZ):
|
||||||
|
freq_sel = 0x4B0;
|
||||||
|
break;
|
||||||
|
case static_cast<uint64_t>(GPS_L5_FREQ_HZ):
|
||||||
|
freq_sel = 0x47E;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
freq_sel = 0x604;
|
||||||
|
}
|
||||||
|
//uint32_t freq_sel = (freq_ == GPS_L1_FREQ_HZ) ? 0x604 :
|
||||||
|
register_values[4] = // PLL integer division register
|
||||||
|
(0x0 << 28) + //reserved
|
||||||
|
(freq_sel << 13) +
|
||||||
|
(RDIV << 3) +
|
||||||
|
0x0; // reserved
|
||||||
|
|
||||||
|
register_values[5] = // PLL fractional division register
|
||||||
|
(0x0 << 28) + // reserved
|
||||||
|
(FDIV << 8) +
|
||||||
|
(0x7 << 4) + // reserved
|
||||||
|
(0x0 << 3) + // reserved
|
||||||
|
(0x0 << 2) + // reserved
|
||||||
|
(0x0 << 1) + // reserved
|
||||||
|
0x0; // reserved
|
||||||
|
|
||||||
|
register_values[6] = // DSP interface register
|
||||||
|
(0x0 << 28) + // reserved
|
||||||
|
0x8000000; // reserved
|
||||||
|
|
||||||
|
register_values[7] = // clock configuration 1 register
|
||||||
|
(0x0 << 29) + // reserved
|
||||||
|
(EXTADCCLK << 28) +
|
||||||
|
(REFCLK_L_CNT << 16) +
|
||||||
|
(REFCLK_M_CNT << 4) +
|
||||||
|
(FCLKIN << 3) +
|
||||||
|
(ADCCLK << 2) +
|
||||||
|
(0x1 << 1) + //reserved
|
||||||
|
MODE;
|
||||||
|
|
||||||
|
register_values[8] = TEST_MODE_1_REG_VAL; // test mode 1 register
|
||||||
|
|
||||||
|
register_values[9] = TEST_MODE_2_REG_VAL; // test mode 2 register
|
||||||
|
|
||||||
|
register_values[10] = // clock configuration 2 register
|
||||||
|
(0x0 << 29) + // reserved
|
||||||
|
(0x0 << 28) + // reserved
|
||||||
|
(ADCCLK_L_CNT << 16) +
|
||||||
|
(ADCCLK_M_CNT << 4) +
|
||||||
|
(PRE_FRACDIV_SEL << 3) +
|
||||||
|
(CLKOUT_SEL << 2) +
|
||||||
|
0x0; // reserved
|
||||||
|
|
||||||
|
return register_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MAX2771EVKITFpgaSignalSource::configure(std::vector<uint32_t> register_values)
|
||||||
|
{
|
||||||
|
// write the registers
|
||||||
|
std::cerr << "Configuring MAX2771 registers" << std::endl;
|
||||||
|
uint32_t status = 0;
|
||||||
|
for (uint32_t k = 0; k < register_values.size(); k++)
|
||||||
|
{
|
||||||
|
status = spidev_fpga->write_reg32(k, register_values[k]);
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
std::cerr << "Error writing the MAX2771 registers" << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the registers and verify that the values are correctly written
|
||||||
|
std::vector<uint32_t> reg_read = std::vector<uint32_t>(register_values.size());
|
||||||
|
|
||||||
|
for (uint8_t n = 0; n < register_values.size(); ++n)
|
||||||
|
{
|
||||||
|
status = spidev_fpga->read_reg32(n, ®_read[n]);
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
std::cerr << "Error reading the MAX2771 registers" << std::endl;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (reg_read[n] != register_values[n])
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Failed to verify the MAX2771 registers " << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MAX2771EVKITFpgaSignalSource::~MAX2771EVKITFpgaSignalSource()
|
||||||
|
{
|
||||||
|
/* cleanup and exit */
|
||||||
|
|
||||||
|
if (rf_shutdown_)
|
||||||
|
{
|
||||||
|
chipen_ = false;
|
||||||
|
std::cout << "* MAX2771 Disabling RX streaming channels\n";
|
||||||
|
std::vector<uint32_t> register_values = setup_regs();
|
||||||
|
|
||||||
|
if (spidev_fpga->SPI_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot open SPI device\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (configure(register_values))
|
||||||
|
{
|
||||||
|
std::cerr << "Error disabling the MAX2771 device " << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spidev_fpga->SPI_close())
|
||||||
|
{
|
||||||
|
std::cerr << "Error closing SPI device " << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable buffer overflow checking and buffer monitoring
|
||||||
|
std::unique_lock<std::mutex> lock_buffer_monitor(buffer_monitor_mutex);
|
||||||
|
enable_ovf_check_buffer_monitor_active_ = false;
|
||||||
|
lock_buffer_monitor.unlock();
|
||||||
|
|
||||||
|
if (thread_buffer_monitor.joinable())
|
||||||
|
{
|
||||||
|
thread_buffer_monitor.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MAX2771EVKITFpgaSignalSource::run_buffer_monitor_process()
|
||||||
|
{
|
||||||
|
bool enable_ovf_check_buffer_monitor_active = true;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitoring_initial_delay_ms));
|
||||||
|
|
||||||
|
while (enable_ovf_check_buffer_monitor_active)
|
||||||
|
{
|
||||||
|
buffer_monitor_fpga->check_buffer_overflow_and_monitor_buffer_status();
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms));
|
||||||
|
std::unique_lock<std::mutex> lock(buffer_monitor_mutex);
|
||||||
|
if (enable_ovf_check_buffer_monitor_active_ == false)
|
||||||
|
{
|
||||||
|
enable_ovf_check_buffer_monitor_active = false;
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MAX2771EVKITFpgaSignalSource::connect(gr::top_block_sptr top_block)
|
||||||
|
{
|
||||||
|
if (top_block)
|
||||||
|
{ /* top_block is not null */
|
||||||
|
};
|
||||||
|
DLOG(INFO) << "AD9361 FPGA source nothing to connect";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MAX2771EVKITFpgaSignalSource::disconnect(gr::top_block_sptr top_block)
|
||||||
|
{
|
||||||
|
if (top_block)
|
||||||
|
{ /* top_block is not null */
|
||||||
|
};
|
||||||
|
DLOG(INFO) << "AD9361 FPGA source nothing to disconnect";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gr::basic_block_sptr MAX2771EVKITFpgaSignalSource::get_left_block()
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Trying to get signal source left block.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gr::basic_block_sptr MAX2771EVKITFpgaSignalSource::get_right_block()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
/*!
|
||||||
|
* \file max2771_evkit_fpga_signal_source.h
|
||||||
|
* \brief Signal source for the MAX2771EVKIT evaluation board connected directly
|
||||||
|
* to FPGA accelerators.
|
||||||
|
* This source implements only the MAX2771 control. It is NOT compatible with
|
||||||
|
* conventional SDR acquisition and tracking blocks.
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_MAX2771_EVKIT_FPGA_SIGNAL_SOURCE_H
|
||||||
|
#define GNSS_SDR_MAX2771_EVKIT_FPGA_SIGNAL_SOURCE_H
|
||||||
|
|
||||||
|
#include "command_event.h"
|
||||||
|
#include "concurrent_queue.h"
|
||||||
|
#include "fpga_buffer_monitor.h"
|
||||||
|
#include "fpga_spidev.h"
|
||||||
|
#include "gnss_block_interface.h"
|
||||||
|
#include "signal_source_base.h"
|
||||||
|
#include <pmt/pmt.h> // for pmt::pmt_t
|
||||||
|
#include <cstdint> // for fixed-width integer types
|
||||||
|
#include <memory> // for smart pointers
|
||||||
|
#include <mutex> // for mutex
|
||||||
|
#include <string> // for strings
|
||||||
|
#include <thread> // for threads
|
||||||
|
|
||||||
|
|
||||||
|
/** \addtogroup Signal_Source
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Signal_Source_adapters
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigurationInterface;
|
||||||
|
|
||||||
|
class MAX2771EVKITFpgaSignalSource : public SignalSourceBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MAX2771EVKITFpgaSignalSource(const ConfigurationInterface *configuration,
|
||||||
|
const std::string &role, unsigned int in_stream,
|
||||||
|
unsigned int out_stream, Concurrent_Queue<pmt::pmt_t> *queue);
|
||||||
|
|
||||||
|
~MAX2771EVKITFpgaSignalSource();
|
||||||
|
|
||||||
|
std::vector<uint32_t> setup_regs(void);
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string default_dump_filename = std::string("FPGA_buffer_monitor_dump.dat");
|
||||||
|
const uint64_t default_bandwidth = 2500000;
|
||||||
|
const uint32_t default_filter_order = 5;
|
||||||
|
const uint64_t default_sampling_rate = 4092000;
|
||||||
|
const uint32_t default_PGA_gain_value = 0x3A; // default PGA gain when AGC is off
|
||||||
|
// max PGA gain value
|
||||||
|
const uint32_t max_PGA_gain_value = 0x3F;
|
||||||
|
// check buffer overflow and perform buffer monitoring every 1s by default
|
||||||
|
const uint32_t buffer_monitor_period_ms = 1000;
|
||||||
|
// buffer overflow and buffer monitoring initial delay
|
||||||
|
const uint32_t buffer_monitoring_initial_delay_ms = 2000;
|
||||||
|
// MAX2771 number of configuration registers
|
||||||
|
const uint32_t MAX2771_NUM_REGS = 11;
|
||||||
|
// MAX2771 configuration register fields
|
||||||
|
const uint32_t NUM_FREQ_BANDS = 1;
|
||||||
|
const uint32_t IDLE = 0x0; // Idle mode disabled
|
||||||
|
const uint32_t MIXPOLE = 0x0; // set the passive filter pole at mixer output at 13 MHz.
|
||||||
|
const uint32_t MIXERMODE = 0x0; // L1 band enabled
|
||||||
|
const uint32_t FCEN = 0x58; // Center frequency not used when in low-pass filter mode. Set to default value.
|
||||||
|
const uint32_t FCENX = 0x0; // POlyphase filter selection set to Lowpass filter
|
||||||
|
const uint32_t ANAIMON = 0x0; // analog monitor disabled
|
||||||
|
const uint32_t IQEN = 0x1; // I and Q channels enable
|
||||||
|
const uint32_t GAINREF = 0xAA; // AGC Gain ref
|
||||||
|
const uint32_t SPI_SDIO_CONFIG = 0x0; // SPI SDIO config when tri-stated: nothing applied
|
||||||
|
const uint32_t FORMAT = 0x1; // sign and magnitude
|
||||||
|
const uint32_t BITS = 0x2; // number of bits in the ADC = 2
|
||||||
|
const uint32_t DRVCFG = 0x0; // output driver configuration = CMOS Logic
|
||||||
|
const uint32_t DIEID = 0x0; // identifies version of IC
|
||||||
|
const uint32_t HILOADEN = 0x0; // disable output driver for high loads
|
||||||
|
const uint32_t FHIPEN = 0x1; // enable highpass coupling between filter and PGA.
|
||||||
|
const uint32_t PGAIEN = 0x1; // I-Channel PGA Enable
|
||||||
|
const uint32_t PGAQEN = 0x1; // Q-Channel PGA Enable
|
||||||
|
const uint32_t STRMEN = 0x0; // disable DSP interface for serial streaming of data
|
||||||
|
const uint32_t STRMSTART = 0x0; // the rising edge of this bit enables data streaming to the output, clock, data, sync and frame sync outputs.
|
||||||
|
const uint32_t STRMSTOP = 0x0; // the rising edge of this bit disables data streaming to the output, clock, data sync and frame sync outputs.
|
||||||
|
const uint32_t STRMBITS = 0x1; // number of bits to be streamed: I MSB, I LSB
|
||||||
|
const uint32_t STAMPEN = 0x1; // enable frame number insertion
|
||||||
|
const uint32_t TIMESYNCEN = 0x1; // enable the output of the time sync pulses at all times when streaming is enabled.
|
||||||
|
const uint32_t DATASYNCEN = 0x0; // disable the sync pulses at the DATASYNC output
|
||||||
|
const uint32_t STRMRST = 0x0; // counter reset not active
|
||||||
|
const uint32_t LOBAND = 0x0; // L1 band
|
||||||
|
const uint32_t REFOUTEN = 0x1; // Output clock buffer enable
|
||||||
|
const uint32_t IXTAL = 0x1; // XTAL osscillator/buffer set to normal current
|
||||||
|
const uint32_t ICP = 0x0; // charge pump current selection set to 0.5 mA
|
||||||
|
const uint32_t INT_PLL = 0x1; // PLL mode set to integer-N PLL
|
||||||
|
const uint32_t PWRSAV = 0x0; // PLL power save mode disabled
|
||||||
|
const uint32_t RDIV = 0x10; // Set the PLL reference division ratio such that the L1 band is tuned to 1575.42 Mhz
|
||||||
|
const uint32_t FDIV = 0x80000; // PLL fractional division ratio not used. Set to default value
|
||||||
|
const uint32_t EXTADCCLK = 0x0; // use internally generated clock
|
||||||
|
const uint32_t REFCLK_L_CNT = 0x100; // set the L counter of the reference clock configuration to its default value
|
||||||
|
const uint32_t REFCLK_M_CNT = 0x61B; // set the M counter of the reference clock configuration to its default value
|
||||||
|
const uint32_t FCLKIN = 0x0; // fractional clock divider set to default value
|
||||||
|
const uint32_t ADCCLK = 0x0; // ADC clock selection set to reference clock divider/multiplier
|
||||||
|
const uint32_t MODE = 0x0; // DSP interface mode selection
|
||||||
|
const uint32_t ADCCLK_L_CNT = 0x100; // set the L counter of the ADC clock configuration to its default value
|
||||||
|
const uint32_t ADCCLK_M_CNT = 0x61B; // set the M counter of the ADC clock configuration to its default value
|
||||||
|
const uint32_t PRE_FRACDIV_SEL = 0x0; // bypass fractional clock divider
|
||||||
|
const uint32_t CLKOUT_SEL = 0x1; // CLKOUT selection set to ADC clock
|
||||||
|
// MAX2771 configuration register registers
|
||||||
|
const uint32_t TEST_MODE_1_REG_VAL = 0x01E0F401; // reserved
|
||||||
|
const uint32_t TEST_MODE_2_REG_VAL = 0x00000002;
|
||||||
|
|
||||||
|
bool configure(std::vector<uint32_t> register_values);
|
||||||
|
void run_buffer_monitor_process();
|
||||||
|
|
||||||
|
|
||||||
|
std::thread thread_buffer_monitor;
|
||||||
|
|
||||||
|
std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_fpga;
|
||||||
|
std::shared_ptr<Fpga_spidev> spidev_fpga;
|
||||||
|
|
||||||
|
std::mutex buffer_monitor_mutex;
|
||||||
|
|
||||||
|
uint64_t freq_; // frequency of local oscillator
|
||||||
|
uint64_t sample_rate_;
|
||||||
|
|
||||||
|
uint32_t in_stream_;
|
||||||
|
uint32_t out_stream_;
|
||||||
|
uint32_t bandwidth_; // 2500000, 4200000, 8700000, 16400000, 23400000, 36000000
|
||||||
|
uint32_t filter_order_; //3, 5
|
||||||
|
uint32_t gain_in_; // 0 to 0x3F
|
||||||
|
|
||||||
|
size_t item_size_; // 1
|
||||||
|
|
||||||
|
bool chipen_; // chip enable
|
||||||
|
bool if_filter_gain_; // true, false
|
||||||
|
bool LNA_active_; // true, false
|
||||||
|
bool enable_agc_; // true, false
|
||||||
|
bool enable_ovf_check_buffer_monitor_active_;
|
||||||
|
bool dump_;
|
||||||
|
bool rf_shutdown_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
/** \} */
|
||||||
|
#endif // GNSS_SDR_MAX2771_EVKIT_FPGA_SIGNAL_SOURCE_H
|
@ -12,17 +12,24 @@ if(ENABLE_FMCOMMS2 OR ENABLE_AD9361)
|
|||||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad9361_manager.h)
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad9361_manager.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_FPGA OR ENABLE_AD9361)
|
if(ENABLE_FPGA_MAX2771_EVKIT)
|
||||||
|
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_spidev.cc)
|
||||||
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_spidev.h)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_FPGA)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_switch.cc)
|
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_switch.cc)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_switch.h)
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_switch.h)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dynamic_bit_selection.cc)
|
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dynamic_bit_selection.cc)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dynamic_bit_selection.h)
|
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-proxy.cc)
|
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)
|
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dma-proxy.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_AD9361 OR ENABLE_FPGA_MAX2771_EVKIT)
|
||||||
|
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)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_PLUTOSDR)
|
if(ENABLE_PLUTOSDR)
|
||||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_samples.cc)
|
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} ad936x_iio_samples.cc)
|
||||||
|
131
src/algorithms/signal_source/libs/fpga_spidev.cc
Normal file
131
src/algorithms/signal_source/libs/fpga_spidev.cc
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*!
|
||||||
|
* \file fpga_spidev.cc
|
||||||
|
* \brief FPGA SPI control.
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fpga_spidev.h"
|
||||||
|
#include <cstring> // for memset()
|
||||||
|
#include <fcntl.h> // for open(), O_RDWR
|
||||||
|
#include <iostream> // for std::cerr
|
||||||
|
#include <linux/spi/spidev.h> // spidev driver
|
||||||
|
#include <sys/ioctl.h> // for ioctl()
|
||||||
|
#include <unistd.h> // for close()
|
||||||
|
|
||||||
|
|
||||||
|
int Fpga_spidev::SPI_open()
|
||||||
|
{
|
||||||
|
if ((d_fd = open(SPI_DEVICE_NAME.c_str(), O_RDWR)) < 0)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to open the " << SPI_DEVICE_NAME << " device file \n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
int32_t mode = 0;
|
||||||
|
|
||||||
|
ret = ioctl(d_fd, SPI_IOC_WR_MODE32, &mode);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "can't set spi mode\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ioctl(d_fd, SPI_IOC_RD_MODE32, &mode); // le digo al spi "algo"
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "can't set spi mode\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fpga_spidev::write_reg32(char addr, uint32_t data)
|
||||||
|
{
|
||||||
|
uint8_t data_buffer[2];
|
||||||
|
uint8_t recv_buffer[4];
|
||||||
|
int res = 0;
|
||||||
|
struct spi_ioc_transfer xfer[2];
|
||||||
|
memset(xfer, 0, sizeof(xfer));
|
||||||
|
xfer[0].bits_per_word = 8;
|
||||||
|
xfer[0].speed_hz = SPI_SPEED;
|
||||||
|
xfer[1].bits_per_word = 8;
|
||||||
|
xfer[1].speed_hz = SPI_SPEED;
|
||||||
|
|
||||||
|
memset(&recv_buffer, 0, sizeof(recv_buffer));
|
||||||
|
memset(&data_buffer, 0, sizeof(data_buffer));
|
||||||
|
|
||||||
|
data_buffer[1] = addr << 4 | 0 << 3;
|
||||||
|
xfer[0].tx_buf = (unsigned long)data_buffer;
|
||||||
|
xfer[0].len = 2;
|
||||||
|
|
||||||
|
// Would use memcpy but 'data' is in little endian
|
||||||
|
((char*)recv_buffer)[0] = ((char*)&data)[3];
|
||||||
|
((char*)recv_buffer)[1] = ((char*)&data)[2];
|
||||||
|
((char*)recv_buffer)[2] = ((char*)&data)[1];
|
||||||
|
((char*)recv_buffer)[3] = ((char*)&data)[0];
|
||||||
|
|
||||||
|
xfer[1].tx_buf = (unsigned long)recv_buffer;
|
||||||
|
xfer[1].len = 4;
|
||||||
|
res = ioctl(d_fd, SPI_IOC_MESSAGE(2), xfer);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
std::cout << "Error sending SPI message\n";
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fpga_spidev::read_reg32(uint8_t addr, uint32_t* copy_to)
|
||||||
|
{
|
||||||
|
uint8_t data_buffer[2];
|
||||||
|
uint8_t recv_buffer[4];
|
||||||
|
int res;
|
||||||
|
struct spi_ioc_transfer xfer[2];
|
||||||
|
memset(xfer, 0, sizeof(xfer));
|
||||||
|
xfer[0].bits_per_word = 8;
|
||||||
|
xfer[0].speed_hz = SPI_SPEED;
|
||||||
|
xfer[1].bits_per_word = 8;
|
||||||
|
xfer[1].speed_hz = SPI_SPEED;
|
||||||
|
|
||||||
|
memset(&recv_buffer, 0, sizeof(recv_buffer));
|
||||||
|
memset(&data_buffer, 0, sizeof(data_buffer));
|
||||||
|
|
||||||
|
data_buffer[1] = addr << 4 | 1 << 3;
|
||||||
|
xfer[0].tx_buf = (unsigned long)data_buffer;
|
||||||
|
xfer[0].len = 2;
|
||||||
|
|
||||||
|
xfer[1].rx_buf = (unsigned long)recv_buffer;
|
||||||
|
xfer[1].len = 4;
|
||||||
|
res = ioctl(d_fd, SPI_IOC_MESSAGE(2), xfer);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
std::cout << "Error sending SPI message\n";
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the register data is received in the reverse order
|
||||||
|
uint32_t tmp_result = 0;
|
||||||
|
for (uint32_t k = 0; k < 4; ++k)
|
||||||
|
{
|
||||||
|
tmp_result = tmp_result + ((recv_buffer[3 - k]) << 8 * k);
|
||||||
|
}
|
||||||
|
*copy_to = tmp_result;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Fpga_spidev::SPI_close() const
|
||||||
|
{
|
||||||
|
return close(d_fd);
|
||||||
|
}
|
61
src/algorithms/signal_source/libs/fpga_spidev.h
Normal file
61
src/algorithms/signal_source/libs/fpga_spidev.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*!
|
||||||
|
* \file fpga_spidev.h
|
||||||
|
* \brief FPGA SPI control.
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_FPGA_SPIDEV_H
|
||||||
|
#define GNSS_SDR_FPGA_SPIDEV_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Fpga_spidev
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief Default constructor.
|
||||||
|
*/
|
||||||
|
Fpga_spidev() = default;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Default destructor.
|
||||||
|
*/
|
||||||
|
~Fpga_spidev() = default;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief write a register through the SPI.
|
||||||
|
*/
|
||||||
|
int write_reg32(char addr, uint32_t data);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief read a register through the SPI.
|
||||||
|
*/
|
||||||
|
int read_reg32(uint8_t addr, uint32_t* copy_to);
|
||||||
|
/*!
|
||||||
|
* \brief Open the SPI device driver.
|
||||||
|
*/
|
||||||
|
int SPI_open(void);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Close the SPI device driver
|
||||||
|
*/
|
||||||
|
int SPI_close(void) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const uint32_t SPI_SPEED = 250000;
|
||||||
|
const std::string SPI_DEVICE_NAME = std::string("/dev/spidev2.0"); // Switch UIO device name
|
||||||
|
|
||||||
|
int d_fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GNSS_SDR_FPGA_SPIDEV_H
|
@ -98,6 +98,10 @@ if(ENABLE_AD9361)
|
|||||||
target_compile_definitions(core_receiver PRIVATE -DAD9361_DRIVER=1)
|
target_compile_definitions(core_receiver PRIVATE -DAD9361_DRIVER=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_FPGA_MAX2771_EVKIT)
|
||||||
|
target_compile_definitions(core_receiver PRIVATE -DFPGA_MAX2771_EVKIT_DRIVER=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(ENABLE_OSMOSDR)
|
if(ENABLE_OSMOSDR)
|
||||||
if(GROSMOSDR_FOUND)
|
if(GROSMOSDR_FOUND)
|
||||||
target_compile_definitions(core_receiver PRIVATE -DOSMOSDR_DRIVER=1)
|
target_compile_definitions(core_receiver PRIVATE -DOSMOSDR_DRIVER=1)
|
||||||
|
@ -171,6 +171,10 @@
|
|||||||
#include "ad9361_fpga_signal_source.h"
|
#include "ad9361_fpga_signal_source.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if FPGA_MAX2771_EVKIT_DRIVER
|
||||||
|
#include "max2771_evkit_fpga_signal_source.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LIMESDR_DRIVER
|
#if LIMESDR_DRIVER
|
||||||
#include "limesdr_signal_source.h"
|
#include "limesdr_signal_source.h"
|
||||||
#endif
|
#endif
|
||||||
@ -813,8 +817,6 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_FPGA and AD9361_DRIVER
|
#if ENABLE_FPGA and AD9361_DRIVER
|
||||||
// The AD9361_DRIVER Driver must be instantiated last. In this way, when using the FPGA, and when using the GNSS receiver
|
|
||||||
// in post-processing mode, the receiver is configured and ready when the DMA starts sending samples to the receiver.
|
|
||||||
else if (implementation == "Ad9361_Fpga_Signal_Source")
|
else if (implementation == "Ad9361_Fpga_Signal_Source")
|
||||||
{
|
{
|
||||||
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<Ad9361FpgaSignalSource>(configuration, role, in_streams,
|
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<Ad9361FpgaSignalSource>(configuration, role, in_streams,
|
||||||
@ -823,6 +825,15 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_FPGA and FPGA_MAX2771_EVKIT_DRIVER
|
||||||
|
else if (implementation == "MAX2771_evkit_Fpga_Signal_Source")
|
||||||
|
{
|
||||||
|
std::unique_ptr<GNSSBlockInterface> block_ = std::make_unique<MAX2771EVKITFpgaSignalSource>(configuration, role, in_streams,
|
||||||
|
out_streams, queue);
|
||||||
|
block = std::move(block_);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_FPGA
|
#if ENABLE_FPGA
|
||||||
else if (implementation == "DMA_Fpga_Signal_Source")
|
else if (implementation == "DMA_Fpga_Signal_Source")
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user