Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into pps_lime

This commit is contained in:
Javier Arribas 2021-02-24 11:41:34 +01:00
commit ccc41b3851
29 changed files with 684 additions and 447 deletions

View File

@ -123,9 +123,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: install dependencies
run: |
python -m pip install --upgrade pip
pip install mako
run: sudo apt install python3-mako liborc-dev
- name: configure
run: cd build && cmake ../src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr
- name: build

View File

@ -326,13 +326,13 @@ set(GNSSSDR_PROTOBUF_MIN_VERSION "3.0.0")
################################################################################
set(GNSSSDR_GFLAGS_LOCAL_VERSION "2.2.2")
set(GNSSSDR_GLOG_LOCAL_VERSION "0.4.0")
set(GNSSSDR_ARMADILLO_LOCAL_VERSION "10.1.x")
set(GNSSSDR_ARMADILLO_LOCAL_VERSION "10.2.x")
set(GNSSSDR_GTEST_LOCAL_VERSION "1.10.0")
set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "master")
set(GNSSSDR_GPSTK_LOCAL_VERSION "8.0.0")
set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.19")
set(GNSSSDR_PUGIXML_LOCAL_VERSION "1.11.4")
set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "3.15.0")
set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "3.15.2")
set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.5.2")
set(GNSSSDR_MATHJAX_EXTERNAL_VERSION "2.7.7")

View File

@ -292,9 +292,9 @@ $ sudo apt-get install libblas-dev liblapack-dev # For Debian/Ubuntu/Linux
$ sudo yum install lapack-devel blas-devel # For Fedora/CentOS/RHEL
$ sudo zypper install lapack-devel blas-devel # For OpenSUSE
$ sudo pacman -S blas lapack # For Arch Linux
$ wget http://sourceforge.net/projects/arma/files/armadillo-10.1.2.tar.xz
$ tar xvfz armadillo-10.1.2.tar.xz
$ cd armadillo-10.1.2
$ wget http://sourceforge.net/projects/arma/files/armadillo-10.2.1.tar.xz
$ tar xvfz armadillo-10.2.1.tar.xz
$ cd armadillo-10.2.1
$ cmake .
$ make
$ sudo make install

View File

@ -10,77 +10,67 @@
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [samples per second].
GNSS-SDR.internal_fs_sps=4000000
GNSS-SDR.internal_fs_sps=12500000
GNSS-SDR.enable_FPGA=true
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=Pass_Through
SignalSource.filename=/datalogger/signals/Agilent/New York/4msps.dat ; <- PUT YOUR FILE HERE
SignalSource.item_type=ishort
SignalSource.sampling_frequency=4000000
SignalSource.implementation=Ad9361_Fpga_Signal_Source
SignalSource.sampling_frequency=12500000
SignalSource.freq=1575420000
SignalSource.repeat=false
SignalSource.dump=false
SignalSource.dump_filename=../data/signal_source.dat
SignalSource.enable_throttle_control=false
SignalSource.enable_FPGA=true
SignalSource.switch_position=2
SignalSource.gain_mode_rx1=slow_attack
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Pass_Through
SignalConditioner.item_type=cshort
SignalConditioner.enable_FPGA=true
;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=8
Channels.in_acquisition=1
Channel.signal=1C
Channel.enable_FPGA=true
Channels_1C.count=12
;######### ACQUISITION GLOBAL CONFIG ############
;######### GPS ACQUISITION CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition_Fpga
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat
Acquisition_1C.item_type=cshort
Acquisition_1C.coherent_integration_time_ms=1
Acquisition_1C.select_queue_Fpga=0;
Acquisition_1C.threshold=0.005
;Acquisition_1C.pfa=0.01
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=500
Acquisition_1C.threshold=2.0
Acquisition_1C.doppler_max=50000
Acquisition_1C.doppler_step=250
Acquisition_1C.make_two_steps=true
Acquisition_1C.second_nbins=3
Acquisition_1C.doppler_step2=250
Acquisition_1C.max_num_acqs=100
;######### TRACKING GLOBAL CONFIG ############
;######### TRACKING GPS CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking_Fpga
Tracking_1C.item_type=cshort
Tracking_1C.dump=false
Tracking_1C.dump_filename=../data/epl_tracking_ch_
Tracking_1C.pll_bw_hz=45.0;
Tracking_1C.extend_correlation_symbols=20
Tracking_1C.pll_bw_hz=35;
Tracking_1C.dll_bw_hz=2.0;
Tracking_1C.order=3;
Tracking_1C.pll_bw_narrow_hz=5.0;
Tracking_1C.dll_bw_narrow_hz=0.50;
Tracking_1C.fll_bw_hz=10
Tracking_1C.enable_fll_pull_in=true;
Tracking_1C.enable_fll_steady_state=false
Tracking_1C.high_dyn=true
Tracking_1C.dump=false
Tracking_1C.dump_filename=tracking_ch_
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=GPS_L1_CA_Observables
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=GPS_L1_CA_PVT
PVT.averaging_depth=100
PVT.flag_averaging=false
PVT.output_rate_ms=10
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
PVT.flag_nmea_tty_port=false;
PVT.nmea_dump_devname=/dev/pts/4
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single
PVT.iono_model=OFF
PVT.trop_model=OFF
PVT.raim_fde=1
PVT.output_rate_ms=20;
PVT.display_rate_ms=500;
PVT.elevation_mask=0;
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false
PVT.dump_filename=./PVT

View File

@ -54,7 +54,12 @@ SPDX-FileCopyrightText: 2011-2021 Carles Fernandez-Prades <carles.fernandez@cttc
inconsistencies in the configuration file.
- Fix segmentation fault if the RINEX output was disabled.
- Added a feature that optionally enables the remote monitoring of GPS and
Galileo ephemeris using UDP and protobuffers.
Galileo ephemeris using UDP and
[Protocol Buffers](https://developers.google.com/protocol-buffers).
- Now building the software passing the `-DENABLE_FPGA=ON` to CMake does not
make the receiver unusable when running on non-FPGA-enabled platforms. On
FPGA-enabled platforms, now it is possible to run non-FPGA-enabled
configurations.
&nbsp;

View File

@ -17,18 +17,18 @@
<xs:complexType>
<xs:sequence>
<xs:element type="xs:byte" name="PRN"/>
<xs:element type="xs:int" name="toa"/>
<xs:element type="xs:byte" name="WNa"/>
<xs:element type="xs:byte" name="IODa"/>
<xs:element type="xs:float" name="delta_i"/>
<xs:element type="xs:byte" name="toa"/>
<xs:element type="xs:byte" name="WNa"/>
<xs:element type="xs:float" name="M_0"/>
<xs:element type="xs:float" name="ecc"/>
<xs:element type="xs:float" name="delta_sqrtA"/>
<xs:element type="xs:float" name="sqrtA"/>
<xs:element type="xs:float" name="OMEGA_0"/>
<xs:element type="xs:float" name="omega"/>
<xs:element type="xs:float" name="OMEGAdot"/>
<xs:element type="xs:float" name="af0"/>
<xs:element type="xs:float" name="af1"/>
<xs:element type="xs:byte" name="IODa"/>
<xs:element type="xs:byte" name="E5b_HS"/>
<xs:element type="xs:byte" name="E1B_HS"/>
<xs:element type="xs:byte" name="E5a_HS"/>

View File

@ -26,10 +26,10 @@
<xs:element type="xs:float" name="OMEGA_0"/>
<xs:element type="xs:float" name="omega"/>
<xs:element type="xs:float" name="OMEGAdot"/>
<xs:element type="xs:byte" name="SV_health"/>
<xs:element type="xs:byte" name="AS_status"/>
<xs:element type="xs:float" name="af0"/>
<xs:element type="xs:float" name="af1"/>
<xs:element type="xs:byte" name="SV_health"/>
<xs:element type="xs:byte" name="AS_status"/>
</xs:sequence>
<xs:attribute type="xs:byte" name="class_id" use="optional"/>
<xs:attribute type="xs:byte" name="tracking_level" use="optional"/>

View File

@ -454,8 +454,7 @@ alm_t alm_to_rtklib(const Galileo_Almanac& gal_alm)
toa.time = gal_alm.toa;
toa.sec = 0.0;
rtklib_alm.toa = toa;
rtklib_alm.A = 5440.588203494 + gal_alm.delta_sqrtA;
rtklib_alm.A = rtklib_alm.A * rtklib_alm.A;
rtklib_alm.A = gal_alm.sqrtA * gal_alm.sqrtA;
rtklib_alm.e = gal_alm.ecc;
rtklib_alm.i0 = (gal_alm.delta_i + 56.0 / 180.0) * GNSS_PI;
rtklib_alm.OMG0 = gal_alm.OMEGA_0 * GNSS_PI;

View File

@ -157,6 +157,8 @@ target_include_directories(signal_source_adapters
if(ENABLE_FPGA OR ENABLE_AD9361)
target_link_libraries(signal_source_adapters
PUBLIC
signal_source_libs
PRIVATE
core_libs
)

View File

@ -23,6 +23,7 @@
#include "GPS_L1_CA.h"
#include "GPS_L5.h"
#include "ad9361_manager.h"
#include "command_event.h"
#include "configuration_interface.h"
#include "gnss_sdr_flags.h"
#include "gnss_sdr_string_literals.h"
@ -35,6 +36,7 @@
#include <exception> // for exceptions
#include <fcntl.h> // for open, O_WRONLY
#include <fstream> // for std::ifstream
#include <iomanip> // for std::setprecision
#include <iostream> // for cout
#include <string> // for string manipulation
#include <thread> // for std::chrono
@ -48,8 +50,10 @@ using namespace std::string_literals;
Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(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), in_stream_(in_stream), out_stream_(out_stream)
: SignalSourceBase(configuration, role, "Ad9361_Fpga_Signal_Source"s), in_stream_(in_stream), out_stream_(out_stream), queue_(queue)
{
// initialize the variables that are used in real-time mode
const std::string default_gain_mode("slow_attack");
const double default_tx_attenuation_db = -10.0;
const double default_manual_gain_rx1 = 64.0;
@ -92,14 +96,77 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
rf_shutdown_ = configuration->property(role + ".rf_shutdown", FLAGS_rf_shutdown);
// initialize the variables that are used in post-processing mode
enable_DMA_ = false;
const int l1_band = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_1B.count", 0);
// by default the DMA transfers samples corresponding to two frequency bands to the FPGA
num_freq_bands_ = 2;
dma_buff_offset_pos_ = 0;
// if only one input file is specified in the configuration file then:
// if there is at least one channel assigned to frequency band 1 then the DMA transfers the samples to the L1 frequency band channels
// otherwise the DMA transfers the samples to the L2/L5 frequency band channels
if (filename1.empty())
{
num_freq_bands_ = 1;
if (l1_band != 0)
{
dma_buff_offset_pos_ = 2;
}
}
const double default_seconds_to_skip = 0.0;
const std::string empty_string;
filename0 = configuration->property(role + ".filename", empty_string);
// override value with commandline flag, if present
if (FLAGS_signal_source != "-")
{
filename0 = FLAGS_signal_source;
}
if (FLAGS_s != "-")
{
filename0 = FLAGS_s;
}
if (filename0.empty())
{
filename0 = configuration->property(role + ".filename0", empty_string);
filename1 = configuration->property(role + ".filename1", empty_string);
}
samples_ = configuration->property(role + ".samples", static_cast<uint64_t>(0));
const double seconds_to_skip = configuration->property(role + ".seconds_to_skip", default_seconds_to_skip);
const size_t header_size = configuration->property(role + ".header_size", 0);
std::string item_type = "ibyte"; // for now only the ibyte format is supported
item_size_ = sizeof(int8_t);
repeat_ = configuration->property(role + ".repeat", false);
if (seconds_to_skip > 0)
{
samples_to_skip_ = static_cast<int64_t>(seconds_to_skip * sample_rate_) * 2;
}
if (header_size > 0)
{
samples_to_skip_ += header_size;
}
// check the switch status (determines real-time mode or post-processing mode)
std::string device_io_name; // Switch UIO device file
// Switch UIO device file
std::string device_io_name;
// find the uio device file corresponding to the switch.
if (find_uio_dev_file_name(device_io_name, switch_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << switch_device_name << std::endl;
throw std::exception();
std::cerr << "Cannot find the FPGA uio device file corresponding to device name " << switch_device_name << '\n';
item_size_ = 0;
return;
}
switch_position_ = configuration->property(role + ".switch_position", 0);
@ -113,55 +180,102 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
switch_fpga = std::make_shared<Fpga_Switch>(device_io_name);
switch_fpga->set_switch_position(switch_position_);
item_size_ = sizeof(gr_complex);
std::cout << "Sample rate: " << sample_rate_ << " Sps\n";
enable_ovf_check_buffer_monitor_active_ = false; // check buffer overflow and buffer monitor disabled by default
if (switch_position_ == 0) // Inject file(s) via DMA
{
enable_DMA_ = true;
const std::string empty_string;
filename_rx1 = configuration->property(role + ".filename", empty_string);
// override value with commandline flag, if present
if (FLAGS_signal_source != "-")
if (samples_ == 0) // read all file
{
filename_rx1 = FLAGS_signal_source;
}
if (FLAGS_s != "-")
{
filename_rx1 = FLAGS_s;
/*!
* BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File.
* A possible solution is to compute the file length in samples using file size, excluding the last 100 milliseconds, and enable always the
* valve block
*/
std::ifstream file(filename0.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
std::ifstream::pos_type size;
if (file.is_open())
{
size = file.tellg();
DLOG(INFO) << "Total samples in the file= " << floor(static_cast<double>(size) / static_cast<double>(item_size_));
}
else
{
std::cerr << "SignalSource: Unable to open the samples file " << filename0.c_str() << '\n';
item_size_ = 0;
return;
}
std::streamsize ss = std::cout.precision();
std::cout << std::setprecision(16);
std::cout << "Processing file " << filename0 << ", which contains " << static_cast<double>(size) << " [bytes]\n";
std::cout.precision(ss);
if (size > 0)
{
const int64_t bytes_to_skip = samples_to_skip_ * item_size_;
const int64_t bytes_to_process = static_cast<int64_t>(size) - bytes_to_skip;
samples_ = floor(static_cast<double>(bytes_to_process) / static_cast<double>(item_size_) - ceil(0.002 * static_cast<double>(sample_rate_))); // process all the samples available in the file excluding at least the last 1 ms
}
if (!filename1.empty())
{
std::ifstream file(filename1.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
std::ifstream::pos_type size;
if (file.is_open())
{
size = file.tellg();
DLOG(INFO) << "Total samples in the file= " << floor(static_cast<double>(size) / static_cast<double>(item_size_));
}
else
{
std::cerr << "SignalSource: Unable to open the samples file " << filename1.c_str() << '\n';
item_size_ = 0;
return;
}
std::streamsize ss = std::cout.precision();
std::cout << std::setprecision(16);
std::cout << "Processing file " << filename1 << ", which contains " << static_cast<double>(size) << " [bytes]\n";
std::cout.precision(ss);
uint64_t samples_rx2 = 0;
if (size > 0)
{
const int64_t bytes_to_skip = samples_to_skip_ * item_size_;
const int64_t bytes_to_process = static_cast<int64_t>(size) - bytes_to_skip;
samples_rx2 = floor(static_cast<double>(bytes_to_process) / static_cast<double>(item_size_) - ceil(0.002 * static_cast<double>(sample_rate_))); // process all the samples available in the file excluding at least the last 1 ms
}
samples_ = std::min(samples_, samples_rx2);
}
}
if (filename_rx1.empty())
{
filename_rx1 = configuration->property(role + ".filename0", empty_string);
filename_rx2 = configuration->property(role + ".filename1", empty_string);
}
const int l1_band = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_1B.count", 0);
CHECK(samples_ > 0) << "File does not contain enough samples to process.";
double signal_duration_s = (static_cast<double>(samples_) * (1 / static_cast<double>(sample_rate_))) / 2.0;
const int l2_band = configuration->property("Channels_L5.count", 0) +
configuration->property("Channels_5X.count", 0) +
configuration->property("Channels_2S.count", 0);
DLOG(INFO) << "Total number samples to be processed= " << samples_ << " GNSS signal duration= " << signal_duration_s << " [s]";
std::cout << "GNSS signal recorded time to be processed: " << signal_duration_s << " [s]\n";
if (l1_band != 0)
if (filename1.empty())
{
freq_band = "L1";
DLOG(INFO) << "File source filename " << filename0;
}
if (l2_band != 0 && l1_band == 0)
else
{
freq_band = "L2";
}
if (l1_band != 0 && l2_band != 0)
{
freq_band = "L1L2";
DLOG(INFO) << "File source filename rx1 " << filename0;
DLOG(INFO) << "File source filename rx2 " << filename1;
}
DLOG(INFO) << "Samples " << samples_;
DLOG(INFO) << "Sampling frequency " << sample_rate_;
DLOG(INFO) << "Item type " << item_type;
DLOG(INFO) << "Item size " << item_size_;
DLOG(INFO) << "Repeat " << repeat_;
}
if (switch_position_ == 2) // Real-time via AD9361
{
std::cout << "Sample rate: " << sample_rate_ << " Sps\n";
enable_ovf_check_buffer_monitor_active_ = false; // check buffer overflow and buffer monitor disabled by default
// some basic checks
if ((rf_port_select_ != "A_BALANCED") and (rf_port_select_ != "B_BALANCED") and (rf_port_select_ != "A_N") and (rf_port_select_ != "B_N") and (rf_port_select_ != "B_P") and (rf_port_select_ != "C_N") and (rf_port_select_ != "C_P") and (rf_port_select_ != "TX_MONITOR1") and (rf_port_select_ != "TX_MONITOR2") and (rf_port_select_ != "TX_MONITOR1_2"))
{
@ -262,7 +376,9 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
}
catch (const std::runtime_error &e)
{
std::cout << "Exception cached when configuring the RX chain: " << e.what() << '\n';
std::cerr << "Exception cached when configuring the RX chain: " << e.what() << '\n';
item_size_ = 0;
return;
}
// LOCAL OSCILLATOR DDS GENERATOR FOR DUAL FREQUENCY OPERATION
if (enable_dds_lo_ == true)
@ -295,7 +411,9 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
}
catch (const std::runtime_error &e)
{
std::cout << "Exception cached when configuring the TX carrier: " << e.what() << '\n';
std::cerr << "Exception cached when configuring the TX carrier: " << e.what() << '\n';
item_size_ = 0;
return;
}
}
@ -311,12 +429,12 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
// find the uio device file corresponding to the buffer monitor
if (find_uio_dev_file_name(device_io_name_buffer_monitor, buffer_monitor_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << buffer_monitor_device_name << std::endl;
throw std::exception();
std::cerr << "Cannot find the FPGA uio device file corresponding to device name " << buffer_monitor_device_name << '\n';
item_size_ = 0;
return;
}
uint32_t num_freq_bands = (freq_band.compare("L1L2")) ? 1 : 2;
buffer_monitor_fpga = std::make_shared<Fpga_buffer_monitor>(device_io_name_buffer_monitor, num_freq_bands, dump_, dump_filename);
buffer_monitor_fpga = std::make_shared<Fpga_buffer_monitor>(device_io_name_buffer_monitor, num_freq_bands_, dump_, dump_filename);
thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); });
}
@ -329,15 +447,17 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
// find the uio device file corresponding to the dynamic bit selector 0 module.
if (find_uio_dev_file_name(device_io_name_dyn_bit_sel_0, dyn_bit_sel_device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << dyn_bit_sel_device_name << std::endl;
throw std::exception();
std::cerr << "Cannot find the FPGA uio device file corresponding to device name " << dyn_bit_sel_device_name << '\n';
item_size_ = 0;
return;
}
// find the uio device file corresponding to the dynamic bit selector 1 module.
if (find_uio_dev_file_name(device_io_name_dyn_bit_sel_1, dyn_bit_sel_device_name, 1) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << dyn_bit_sel_device_name << std::endl;
throw std::exception();
std::cerr << "Cannot find the FPGA uio device file corresponding to device name " << dyn_bit_sel_device_name << '\n';
item_size_ = 0;
return;
}
dynamic_bit_selection_fpga = std::make_shared<Fpga_dynamic_bit_selection>(device_io_name_dyn_bit_sel_0, device_io_name_dyn_bit_sel_1);
thread_dynamic_bit_selection = std::thread([&] { run_dynamic_bit_selection_process(); });
@ -418,202 +538,177 @@ Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
}
}
void Ad9361FpgaSignalSource::start()
{
thread_file_to_dma = std::thread([&] { run_DMA_process(freq_band, filename_rx1, filename_rx2); });
thread_file_to_dma = std::thread([&] { run_DMA_process(filename0, filename1, samples_to_skip_, item_size_, samples_, repeat_, dma_buff_offset_pos_, queue_); });
}
void Ad9361FpgaSignalSource::run_DMA_process(const std::string &FreqBand, const std::string &Filename1, const std::string &Filename2)
void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0, const std::string &filename1, uint64_t &samples_to_skip, size_t &item_size, uint64_t &samples, bool &repeat, uint32_t &dma_buff_offset_pos, Concurrent_Queue<pmt::pmt_t> *queue)
{
const int MAX_INPUT_SAMPLES_TOTAL = 16384;
int max_value = 0;
std::ifstream infile1;
infile1.exceptions(std::ifstream::failbit | std::ifstream::badbit);
// open the files
try
{
infile1.open(Filename1, std::ios::binary);
infile1.open(filename0, std::ios::binary);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception opening file " << Filename1 << '\n';
std::cerr << "Exception opening file " << filename0 << '\n';
// stop the receiver
queue->push(pmt::make_any(command_event_make(200, 0)));
return;
}
std::ifstream infile2;
infile2.exceptions(std::ifstream::failbit | std::ifstream::badbit);
if (!filename1.empty())
{
infile2.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
infile2.open(filename1, std::ios::binary);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception opening file " << filename1 << '\n';
// stop the receiver
queue->push(pmt::make_any(command_event_make(200, 0)));
return;
}
}
// skip the initial samples if needed
uint64_t bytes_to_skeep = samples_to_skip * item_size;
try
{
infile2.open(Filename2, std::ios::binary);
infile1.ignore(bytes_to_skeep);
}
catch (const std::ifstream::failure &e)
{
// could not exist
}
// rx signal
std::vector<int8_t> input_samples(MAX_INPUT_SAMPLES_TOTAL * 2);
std::vector<int8_t> input_samples2(MAX_INPUT_SAMPLES_TOTAL * 2);
std::vector<int8_t> input_samples_dma(MAX_INPUT_SAMPLES_TOTAL * 2 * 2);
int nread_elements = 0; // num bytes read from the file corresponding to frequency band 1
int nread_elements2 = 0; // num bytes read from the file corresponding to frequency band 2
int file_completed = 0;
int num_transferred_bytes;
//**************************************************************************
// Open DMA device
//**************************************************************************
const int tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 0)
{
std::cout << "Cannot open loop device\n";
std::cerr << "Exception skipping initial samples file " << filename0 << '\n';
// stop the receiver
queue->push(pmt::make_any(command_event_make(200, 0)));
return;
}
//**************************************************************************
// Open input file
//**************************************************************************
int nsamples = 0;
while (file_completed == 0)
if (!filename1.empty())
{
unsigned int dma_index = 0;
if (FreqBand == "L1")
try
{
try
{
infile1.read(reinterpret_cast<char *>(input_samples.data()), MAX_INPUT_SAMPLES_TOTAL * 2);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception reading file " << Filename1 << '\n';
}
if (infile1)
{
nread_elements = MAX_INPUT_SAMPLES_TOTAL * 2;
}
else
{
nread_elements = infile1.gcount();
}
nsamples += (nread_elements / 2);
for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{
// channel 1 (queue 1)
input_samples_dma[dma_index] = 0;
input_samples_dma[dma_index + 1] = 0;
// channel 0 (queue 0)
input_samples_dma[dma_index + 2] = input_samples[index0];
input_samples_dma[dma_index + 3] = input_samples[index0 + 1];
dma_index += 4;
}
infile2.ignore(bytes_to_skeep);
}
else if (FreqBand == "L2")
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception skipping initial samples file " << filename1 << '\n';
// stop the receiver
queue->push(pmt::make_any(command_event_make(200, 0)));
return;
}
}
// rx signal vectors
std::vector<int8_t> input_samples(sample_block_size * 2); // complex samples
std::vector<int8_t> input_samples_dma(sample_block_size * 4); // complex samples, two frequency bands
int nread_elements = 0; // num bytes read from the file corresponding to frequency band 1
bool run_DMA = true;
int num_transferred_bytes;
// Open DMA device
const int tx_fd = open("/dev/loop_tx", O_WRONLY);
if (tx_fd < 0)
{
std::cerr << "Cannot open loop device\n";
// stop the receiver
queue->push(pmt::make_any(command_event_make(200, 0)));
return;
}
// if only one frequency band is used then clear the samples corresponding to the unused frequency band
uint32_t dma_index = 0;
if (num_freq_bands_ == 1)
{
// 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)
{
input_samples_dma[dma_index + (2 - dma_buff_offset_pos)] = 0;
input_samples_dma[dma_index + 1 + (2 - dma_buff_offset_pos)] = 0;
dma_index += 4;
}
}
uint64_t nbytes_remaining = samples * item_size;
uint32_t read_buffer_size = sample_block_size * 2; // complex samples
// run the DMA
while (run_DMA)
{
if (nbytes_remaining < read_buffer_size)
{
read_buffer_size = nbytes_remaining;
}
nbytes_remaining = nbytes_remaining - read_buffer_size;
// read filename 0
try
{
infile1.read(reinterpret_cast<char *>(input_samples.data()), read_buffer_size);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception reading file " << filename0 << '\n';
break;
}
if (infile1)
{
nread_elements = read_buffer_size;
}
else
{
// FLAG AS ERROR !! IT SHOULD NEVER HAPPEN
nread_elements = infile1.gcount();
}
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
input_samples_dma[dma_index + dma_buff_offset_pos] = input_samples[index0];
input_samples_dma[dma_index + 1 + dma_buff_offset_pos] = input_samples[index0 + 1];
dma_index += 4;
}
// read filename 1 (if enabled)
dma_index = 0;
if (num_freq_bands_ > 1)
{
try
{
infile1.read(reinterpret_cast<char *>(input_samples.data()), MAX_INPUT_SAMPLES_TOTAL * 2);
infile1.read(reinterpret_cast<char *>(input_samples.data()), read_buffer_size);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception reading file " << Filename1 << '\n';
std::cerr << "Exception reading file " << filename1 << '\n';
break;
}
if (infile1)
{
nread_elements = MAX_INPUT_SAMPLES_TOTAL * 2;
nread_elements = read_buffer_size;
}
else
{
// FLAG AS ERROR !! IT SHOULD NEVER HAPPEN
nread_elements = infile1.gcount();
}
nsamples += (nread_elements / 2);
for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{
// channel 1 (queue 1)
// filename2 is never the L1 band
input_samples_dma[dma_index] = input_samples[index0];
input_samples_dma[dma_index + 1] = input_samples[index0 + 1];
// channel 0 (queue 0)
input_samples_dma[dma_index + 2] = 0;
input_samples_dma[dma_index + 3] = 0;
dma_index += 4;
}
}
else if (FreqBand == "L1L2")
{
try
{
infile1.read(reinterpret_cast<char *>(input_samples.data()), MAX_INPUT_SAMPLES_TOTAL * 2);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception reading file " << Filename1 << '\n';
}
if (infile1)
{
nread_elements = MAX_INPUT_SAMPLES_TOTAL * 2;
}
else
{
nread_elements = infile1.gcount();
}
try
{
infile2.read(reinterpret_cast<char *>(input_samples2.data()), MAX_INPUT_SAMPLES_TOTAL * 2);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception reading file " << Filename1 << '\n';
}
if (infile2)
{
nread_elements2 = MAX_INPUT_SAMPLES_TOTAL * 2;
}
else
{
nread_elements2 = infile2.gcount();
}
if (nread_elements > nread_elements2)
{
nread_elements = nread_elements2; // take the smallest
}
nsamples += (nread_elements / 2);
for (int index0 = 0; index0 < (nread_elements); index0 += 2)
{
if (input_samples[index0] > max_value)
{
max_value = input_samples[index0];
}
else if (-input_samples[index0] > max_value)
{
max_value = -input_samples[index0];
}
if (input_samples[index0 + 1] > max_value)
{
max_value = input_samples[index0 + 1];
}
else if (-input_samples[index0 + 1] > max_value)
{
max_value = -input_samples[index0 + 1];
}
// channel 1 (queue 1)
input_samples_dma[dma_index] = input_samples2[index0];
input_samples_dma[dma_index + 1] = input_samples2[index0 + 1];
// channel 0 (queue 0)
input_samples_dma[dma_index + 2] = input_samples[index0];
input_samples_dma[dma_index + 3] = input_samples[index0 + 1];
dma_index += 4;
}
}
@ -625,21 +720,75 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &FreqBand, const
if (num_bytes_sent != num_transferred_bytes)
{
std::cerr << "Error: DMA could not send all the required samples\n";
break;
}
// Throttle the DMA
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
if (nread_elements != MAX_INPUT_SAMPLES_TOTAL * 2)
if (nbytes_remaining == 0)
{
file_completed = 1;
}
if (repeat)
{
// read the file again
nbytes_remaining = samples * item_size;
read_buffer_size = sample_block_size * 2;
try
{
infile1.seekg(0);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception resetting the position of the next byte to be extracted to zero " << filename0 << '\n';
break;
}
// skip the initial samples if needed
uint64_t bytes_to_skeep = samples_to_skip * item_size;
try
{
infile1.ignore(bytes_to_skeep);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception skipping initial samples file " << filename0 << '\n';
break;
}
if (!filename1.empty())
{
try
{
infile2.seekg(0);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception setting the position of the next byte to be extracted to zero " << filename1 << '\n';
break;
}
try
{
infile2.ignore(bytes_to_skeep);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception skipping initial samples file " << filename1 << '\n';
break;
}
}
}
else
{
// the input file is completely processed. Stop the receiver.
run_DMA = false;
}
}
std::unique_lock<std::mutex> lock(dma_mutex);
if (enable_DMA_ == false)
{
file_completed = true;
run_DMA = false;
}
lock.unlock();
}
@ -652,15 +801,26 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &FreqBand, const
try
{
infile1.close();
if (FreqBand == "L1L2")
{
infile2.close();
}
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception closing files " << Filename1 << " and " << Filename2 << '\n';
std::cerr << "Exception closing file " << filename0 << '\n';
}
if (num_freq_bands_ > 1)
{
try
{
infile2.close();
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception closing file " << filename1 << '\n';
}
}
// Stop the receiver
queue->push(pmt::make_any(command_event_make(200, 0)));
}
@ -682,6 +842,7 @@ void Ad9361FpgaSignalSource::run_dynamic_bit_selection_process()
}
}
void Ad9361FpgaSignalSource::run_buffer_monitor_process()
{
bool enable_ovf_check_buffer_monitor_active = true;

View File

@ -67,15 +67,22 @@ private:
const std::string buffer_monitor_device_name = "buffer_monitor"; // buffer monitor device name
const std::string default_dump_filename = std::string("FPGA_buffer_monitor_dump.dat");
// perform dynamic bit selection every 500 ms by default
static const uint32_t Gain_control_period_ms = 500;
const uint32_t Gain_control_period_ms = 500;
// check buffer overflow and perform buffer monitoring every 1s by default
static const uint32_t buffer_monitor_period_ms = 1000;
const uint32_t buffer_monitor_period_ms = 1000;
// buffer overflow and buffer monitoring initial delay
static const uint32_t buffer_monitoring_initial_delay_ms = 2000;
const uint32_t buffer_monitoring_initial_delay_ms = 2000;
// sample block size when running in post-processing mode
const int sample_block_size = 16384;
void run_DMA_process(const std::string &FreqBand,
const std::string &Filename1,
const std::string &Filename2);
void run_DMA_process(const std::string &Filename1,
const std::string &Filename2,
uint64_t &samples_to_skip,
size_t &item_size,
uint64_t &samples,
bool &repeat,
uint32_t &dma_buff_offset_pos,
Concurrent_Queue<pmt::pmt_t> *queue);
void run_dynamic_bit_selection_process();
void run_buffer_monitor_process();
@ -95,9 +102,8 @@ private:
std::string filter_file_;
std::string filter_source_;
std::string filter_filename_;
std::string filename_rx1;
std::string filename_rx2;
std::string freq_band;
std::string filename0;
std::string filename1;
std::mutex dma_mutex;
std::mutex dynamic_bit_selection_mutex;
@ -133,9 +139,17 @@ private:
bool enable_DMA_;
bool enable_dynamic_bit_selection_;
bool enable_ovf_check_buffer_monitor_active_;
bool enable_ovf_check_buffer_monitor_;
bool dump_;
bool rf_shutdown_;
// post-processing mode
uint64_t samples_;
uint64_t samples_to_skip_;
bool repeat_;
uint32_t num_freq_bands_;
uint32_t dma_buff_offset_pos_;
Concurrent_Queue<pmt::pmt_t> *queue_;
};

View File

@ -23,7 +23,6 @@
*/
#include "fpga_buffer_monitor.h"
#include "command_event.h"
#include "gnss_sdr_create_directory.h"
#include "gnss_sdr_filesystem.h"
#include <glog/logging.h>

View File

@ -25,10 +25,8 @@
#ifndef GNSS_SDR_FPGA_BUFFER_MONITOR_H
#define GNSS_SDR_FPGA_BUFFER_MONITOR_H
#include "concurrent_queue.h"
#include <pmt/pmt.h> // pmt
#include <cstdint> // for int32_t
#include <fstream> // for string, ofstream
#include <cstdint> // for int32_t
#include <fstream> // for string, ofstream
/** \addtogroup Signal_Source
* \{ */

View File

@ -201,9 +201,9 @@ void Gnss_Sdr_Supl_Client::read_supl_data()
{
/* TS 44.031: GPSTOW, range 0-604799.92, resolution 0.08 sec, 23-bit presentation */
gps_time.tow = static_cast<double>(assist.time.gps_tow) * 0.08;
gps_time.d_Week = static_cast<double>(assist.time.gps_week);
gps_time.d_tv_sec = static_cast<double>(assist.time.stamp.tv_sec);
gps_time.d_tv_usec = static_cast<double>(assist.time.stamp.tv_usec);
gps_time.week = static_cast<double>(assist.time.gps_week);
gps_time.seconds = static_cast<double>(assist.time.stamp.tv_sec);
gps_time.microseconds = static_cast<double>(assist.time.stamp.tv_usec);
gps_time.valid = true;
}
@ -871,7 +871,7 @@ bool Gnss_Sdr_Supl_Client::read_gal_almanac_from_gsa(const std::string& file_nam
gal_alm.delta_i = std::stod(almanac.child("almanac").child_value("deltai"));
gal_alm.M_0 = std::stod(almanac.child("almanac").child_value("m0"));
gal_alm.ecc = std::stod(almanac.child("almanac").child_value("ecc"));
gal_alm.delta_sqrtA = std::stod(almanac.child("almanac").child_value("aSqRoot"));
gal_alm.sqrtA = std::stod(almanac.child("almanac").child_value("aSqRoot"));
gal_alm.OMEGA_0 = std::stod(almanac.child("almanac").child_value("omega0"));
gal_alm.omega = std::stod(almanac.child("almanac").child_value("w"));
gal_alm.OMEGAdot = std::stod(almanac.child("almanac").child_value("omegaDot"));

View File

@ -19,10 +19,11 @@
#include "gnss_sdr_filesystem.h"
#include <algorithm> // sort
#include <cstdlib> // atoi, size_t
#include <fstream> // ifstream
#include <iostream> // cout
#include <locale> // isdigit
#include <sstream> // std::stringstream
#include <exception>
#include <fstream> // ifstream
#include <iostream> // cout
#include <locale> // isdigit
#include <sstream> // std::stringstream
#include <vector>
@ -188,7 +189,15 @@ int32_t find_uio_num(const std::string &device_name, uint32_t device_num)
int32_t find_uio_dev_file_name(std::string &device_file_name, const std::string &device_name, uint32_t device_num)
{
int32_t uio_num = find_uio_num(device_name, device_num);
int32_t uio_num = 0;
try
{
uio_num = find_uio_num(device_name, device_num);
}
catch (const std::exception &e)
{
return -1;
}
if (uio_num >= 0)
{
std::stringstream device_file_name_tmp;

View File

@ -209,7 +209,7 @@ void ControlThread::init()
// Make an educated guess
time_t rawtime;
time(&rawtime);
agnss_ref_time_.d_tv_sec = rawtime;
agnss_ref_time_.seconds = rawtime;
agnss_ref_time_.valid = true;
}
else
@ -220,8 +220,8 @@ void ControlThread::init()
};
if (strptime(ref_time_str.c_str(), "%d/%m/%Y %H:%M:%S", &tm) != nullptr)
{
agnss_ref_time_.d_tv_sec = timegm(&tm);
if (agnss_ref_time_.d_tv_sec > 0)
agnss_ref_time_.seconds = timegm(&tm);
if (agnss_ref_time_.seconds > 0)
{
agnss_ref_time_.valid = true;
}
@ -883,7 +883,7 @@ void ControlThread::assist_GNSS()
time_t ref_rx_utc_time = 0;
if (agnss_ref_time_.valid == true)
{
ref_rx_utc_time = static_cast<time_t>(agnss_ref_time_.d_tv_sec);
ref_rx_utc_time = static_cast<time_t>(agnss_ref_time_.seconds);
}
const std::vector<std::pair<int, Gnss_Satellite>> visible_sats = get_visible_sats(ref_rx_utc_time, ref_LLH);

View File

@ -75,6 +75,7 @@ GNSSFlowgraph::GNSSFlowgraph(std::shared_ptr<ConfigurationInterface> configurati
configuration_ = std::move(configuration);
queue_ = std::move(queue);
multiband_ = GNSSFlowgraph::is_multiband();
enable_fpga_offloading_ = configuration_->property("GNSS-SDR.enable_FPGA", false);
init();
}
@ -107,17 +108,22 @@ void GNSSFlowgraph::init()
{
std::cout << "Creating source " << i << '\n';
sig_source_.push_back(block_factory->GetSignalSource(configuration_.get(), queue_.get(), i));
auto& src = sig_source_.back();
auto RF_Channels = src->getRfChannels();
std::cout << "RF Channels " << RF_Channels << '\n';
for (auto j = 0U; j < RF_Channels; ++j)
if (enable_fpga_offloading_ == false)
{
sig_conditioner_.push_back(block_factory->GetSignalConditioner(configuration_.get(), signal_conditioner_ID));
signal_conditioner_ID++;
auto& src = sig_source_.back();
auto RF_Channels = src->getRfChannels();
std::cout << "RF Channels " << RF_Channels << '\n';
for (auto j = 0U; j < RF_Channels; ++j)
{
sig_conditioner_.push_back(block_factory->GetSignalConditioner(configuration_.get(), signal_conditioner_ID));
signal_conditioner_ID++;
}
}
}
signal_conditioner_connected_ = std::vector<bool>(sig_conditioner_.size(), false);
if (!sig_conditioner_.empty())
{
signal_conditioner_connected_ = std::vector<bool>(sig_conditioner_.size(), false);
}
observables_ = block_factory->GetObservables(configuration_.get());
@ -242,13 +248,14 @@ void GNSSFlowgraph::start()
return;
}
#if ENABLE_FPGA
// start the DMA if the receiver is in post-processing mode
if (configuration_->property(sig_source_.at(0)->role() + ".switch_position", 0) == 0)
if (enable_fpga_offloading_ == true)
{
sig_source_.at(0)->start();
// start the DMA if the receiver is in post-processing mode
if (configuration_->property(sig_source_.at(0)->role() + ".switch_position", 0) == 0)
{
sig_source_.at(0)->start();
}
}
#endif
running_ = true;
}
@ -261,10 +268,12 @@ void GNSSFlowgraph::stop()
chan->stop_channel(); // stop the acquisition or tracking operation
}
top_block_->stop();
#if ENABLE_FPGA
#else
top_block_->wait();
#endif
if (enable_fpga_offloading_ == false)
{
top_block_->wait();
}
running_ = false;
}
@ -293,16 +302,28 @@ void GNSSFlowgraph::connect()
}
#if ENABLE_FPGA
if (connect_fpga_flowgraph() != 0)
if (enable_fpga_offloading_ == true)
{
LOG(ERROR) << "Unable to connect flowgraph with FPFA off-loading";
print_help();
return;
if (connect_fpga_flowgraph() != 0)
{
std::cerr << "Unable to connect flowgraph with FPGA off-loading\n";
print_help();
return;
}
}
else
{
if (connect_desktop_flowgraph() != 0)
{
std::cerr << "Unable to connect flowgraph\n";
print_help();
return;
}
}
#else
if (connect_desktop_flowgraph() != 0)
{
LOG(ERROR) << "Unable to connect flowgraph";
std::cerr << "Unable to connect flowgraph\n";
print_help();
return;
}
@ -326,9 +347,19 @@ void GNSSFlowgraph::disconnect()
connected_ = false;
#if ENABLE_FPGA
if (disconnect_fpga_flowgraph() != 0)
if (enable_fpga_offloading_ == true)
{
return;
if (disconnect_fpga_flowgraph() != 0)
{
return;
}
}
else
{
if (disconnect_desktop_flowgraph() != 0)
{
return;
}
}
#else
if (disconnect_desktop_flowgraph() != 0)
@ -343,9 +374,6 @@ void GNSSFlowgraph::disconnect()
int GNSSFlowgraph::connect_desktop_flowgraph()
{
#if ENABLE_FPGA
return 0;
#else
// Connect blocks to the top_block
if (connect_signal_sources() != 0)
{
@ -424,15 +452,11 @@ int GNSSFlowgraph::connect_desktop_flowgraph()
LOG(INFO) << "The GNU Radio flowgraph for the current GNSS-SDR configuration has been successfully connected";
return 0;
#endif
}
int GNSSFlowgraph::disconnect_desktop_flowgraph()
{
#if ENABLE_FPGA
return 0;
#else
// Disconnect blocks between them
if (disconnect_signal_sources_from_signal_conditioners() != 0)
{
@ -491,14 +515,32 @@ int GNSSFlowgraph::disconnect_desktop_flowgraph()
}
return 0;
#endif
}
#if ENABLE_FPGA
int GNSSFlowgraph::connect_fpga_flowgraph()
{
// Check that the Signal Source has been instantiated successfully
for (auto& src : sig_source_)
{
if (src == nullptr)
{
help_hint_ += " * Undefined SignalSource.implementation in the configuration file.\n";
return 1;
}
if (src->item_size() == 0)
{
help_hint_ += " * The global configuration parameter GNSS-SDR.enable_FPGA is set to true,\n";
help_hint_ += " but gnss-sdr does not appear to be executed in an FPGA-equipped platform,\n";
help_hint_ += " or there are some required files that are missing.\n";
return 1;
}
}
// Connect blocks to the top_block
if (connect_channels() != 0)
{
return 1;
@ -519,19 +561,9 @@ int GNSSFlowgraph::connect_fpga_flowgraph()
// Connect the counter
if (sig_source_.at(0) != nullptr)
{
if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false)
if (connect_fpga_sample_counter() != 0)
{
if (connect_sample_counter() != 0)
{
return 1;
}
}
else
{
if (connect_fpga_sample_counter() != 0)
{
return 1;
}
return 1;
}
}
else
@ -546,11 +578,6 @@ int GNSSFlowgraph::connect_fpga_flowgraph()
return 1;
}
if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false)
{
check_signal_conditioners();
}
assign_channels();
if (connect_observables_to_pvt() != 0)
@ -572,27 +599,9 @@ int GNSSFlowgraph::connect_fpga_flowgraph()
int GNSSFlowgraph::disconnect_fpga_flowgraph()
{
if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false)
if (disconnect_fpga_sample_counter() != 0)
{
if (disconnect_signal_sources_from_signal_conditioners() != 0)
{
return 1;
}
}
if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false)
{
if (disconnect_sample_counter() != 0)
{
return 1;
}
}
else
{
if (disconnect_fpga_sample_counter() != 0)
{
return 1;
}
return 1;
}
if (disconnect_monitors() != 0)
@ -610,16 +619,6 @@ int GNSSFlowgraph::disconnect_fpga_flowgraph()
return 1;
}
if (disconnect_signal_sources() != 0)
{
return 1;
}
if (disconnect_signal_conditioners() != 0)
{
return 1;
}
if (disconnect_channels() != 0)
{
return 1;
@ -971,7 +970,16 @@ int GNSSFlowgraph::connect_fpga_sample_counter()
}
catch (const std::exception& e)
{
LOG(ERROR) << "Can't connect FPGA sample counter: " << e.what();
std::string reported_error(e.what());
if (std::string::npos != reported_error.find(std::string("filesystem")))
{
help_hint_ += " * The global configuration parameter GNSS-SDR.enable_FPGA is set to true,\n";
help_hint_ += " but gnss-sdr does not appear to be executed in an FPGA-equipped platform.\n";
}
else
{
LOG(ERROR) << reported_error;
}
top_block_->disconnect_all();
return 1;
}
@ -999,6 +1007,13 @@ int GNSSFlowgraph::disconnect_fpga_sample_counter()
int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners()
{
if (enable_fpga_offloading_)
{
help_hint_ += " * The global configuration parameter GNSS-SDR.enable_FPGA is set to true,\n";
help_hint_ += " but gnss-sdr was not compiled with the -DENABLE_FPGA=ON building option.\n";
top_block_->disconnect_all();
return 1;
}
unsigned int signal_conditioner_ID = 0;
for (int i = 0; i < sources_count_; i++)
{

View File

@ -297,6 +297,7 @@ private:
bool enable_monitor_;
bool enable_acquisition_monitor_;
bool enable_tracking_monitor_;
bool enable_fpga_offloading_;
};

View File

@ -27,6 +27,7 @@ set(SYSTEM_PARAMETERS_SOURCES
)
set(SYSTEM_PARAMETERS_HEADERS
gnss_almanac.h
gnss_ephemeris.h
gnss_satellite.h
gnss_signal.h

View File

@ -39,9 +39,9 @@ public:
Agnss_Ref_Time() = default;
double tow{};
double d_Week{};
double d_tv_sec{};
double d_tv_usec{};
double week{};
double seconds{};
double microseconds{};
bool valid{};
template <class Archive>
@ -56,9 +56,9 @@ public:
{
};
archive& BOOST_SERIALIZATION_NVP(tow);
archive& BOOST_SERIALIZATION_NVP(d_Week);
archive& BOOST_SERIALIZATION_NVP(d_tv_sec);
archive& BOOST_SERIALIZATION_NVP(d_tv_usec);
archive& BOOST_SERIALIZATION_NVP(week);
archive& BOOST_SERIALIZATION_NVP(seconds);
archive& BOOST_SERIALIZATION_NVP(microseconds);
archive& BOOST_SERIALIZATION_NVP(valid);
}
};

View File

@ -18,6 +18,7 @@
#ifndef GNSS_SDR_BEIDOU_DNAV_ALMANAC_H
#define GNSS_SDR_BEIDOU_DNAV_ALMANAC_H
#include "gnss_almanac.h"
#include <boost/serialization/nvp.hpp>
/** \addtogroup Core
@ -29,7 +30,7 @@
/*!
* \brief This class is a storage for the BeiDou D1 almanac
*/
class Beidou_Dnav_Almanac
class Beidou_Dnav_Almanac : public Gnss_Almanac
{
public:
/*!
@ -37,18 +38,7 @@ public:
*/
Beidou_Dnav_Almanac() = default;
unsigned int PRN{}; //!< SV PRN NUMBER
double delta_i{};
double toa{}; //!< Almanac data reference time of week [s]
double M_0{}; //!< Mean Anomaly at Reference Time [semi-circles]
double ecc{}; //!< Eccentricity [dimensionless]
double sqrtA{}; //!< Square Root of the Semi-Major Axis [sqrt(m)]
double OMEGA_0{}; //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
double omega{}; //!< Argument of Perigee [semi-cicles]
double OMEGAdot{}; //!< Rate of Right Ascension [semi-circles/s]
int SV_health{}; //!< SV Health
double af0{}; //!< Coefficient 0 of code phase offset model [s]
double af1{}; //!< Coefficient 1 of code phase offset model [s/s]
int SV_health{}; //!< SV Health
template <class Archive>
@ -60,17 +50,16 @@ public:
ar& BOOST_SERIALIZATION_NVP(PRN);
ar& BOOST_SERIALIZATION_NVP(delta_i);
ar& BOOST_SERIALIZATION_NVP(toa);
// ar& BOOST_SERIALIZATION_NVP(WNa);
ar& BOOST_SERIALIZATION_NVP(WNa);
ar& BOOST_SERIALIZATION_NVP(M_0);
ar& BOOST_SERIALIZATION_NVP(ecc);
ar& BOOST_SERIALIZATION_NVP(sqrtA);
ar& BOOST_SERIALIZATION_NVP(OMEGA_0);
ar& BOOST_SERIALIZATION_NVP(omega);
ar& BOOST_SERIALIZATION_NVP(OMEGAdot);
ar& BOOST_SERIALIZATION_NVP(SV_health);
// ar& BOOST_SERIALIZATION_NVP(AS_status);
ar& BOOST_SERIALIZATION_NVP(af0);
ar& BOOST_SERIALIZATION_NVP(af1);
ar& BOOST_SERIALIZATION_NVP(SV_health);
}
};

View File

@ -18,8 +18,8 @@
#ifndef GNSS_SDR_GALILEO_ALMANAC_H
#define GNSS_SDR_GALILEO_ALMANAC_H
#include "gnss_almanac.h"
#include <boost/serialization/nvp.hpp>
#include <cstdint>
/** \addtogroup Core
* \{ */
@ -30,7 +30,7 @@
/*!
* \brief This class is a storage for the Galileo SV ALMANAC data
*/
class Galileo_Almanac
class Galileo_Almanac : public Gnss_Almanac
{
public:
/*!
@ -38,19 +38,7 @@ public:
*/
Galileo_Almanac() = default;
uint32_t PRN{}; //!< SV PRN NUMBER
int32_t toa{};
int32_t WNa{};
int32_t IODa{};
double delta_i{}; //!< Inclination at reference time relative to i0 = 56º [semi-circles]
double M_0{}; //!< Mean Anomaly at Reference Time [semi-circles]
double ecc{}; //!< Eccentricity [dimensionless]
double delta_sqrtA{}; //!< Square Root of the Semi-Major Axis [sqrt(m)]
double OMEGA_0{}; //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
double omega{}; //!< Argument of Perigee [semi-cicles]
double OMEGAdot{}; //!< Rate of Right Ascension [semi-circles/s]
double af0{}; //!< Coefficient 0 of code phase offset model [s]
double af1{}; //!< Coefficient 1 of code phase offset model [s/s]
int32_t E5b_HS{};
int32_t E1B_HS{};
int32_t E5a_HS{};
@ -63,18 +51,18 @@ public:
{
};
ar& BOOST_SERIALIZATION_NVP(PRN);
ar& BOOST_SERIALIZATION_NVP(delta_i);
ar& BOOST_SERIALIZATION_NVP(toa);
ar& BOOST_SERIALIZATION_NVP(WNa);
ar& BOOST_SERIALIZATION_NVP(IODa);
ar& BOOST_SERIALIZATION_NVP(delta_i);
ar& BOOST_SERIALIZATION_NVP(M_0);
ar& BOOST_SERIALIZATION_NVP(ecc);
ar& BOOST_SERIALIZATION_NVP(delta_sqrtA);
ar& BOOST_SERIALIZATION_NVP(sqrtA);
ar& BOOST_SERIALIZATION_NVP(OMEGA_0);
ar& BOOST_SERIALIZATION_NVP(omega);
ar& BOOST_SERIALIZATION_NVP(OMEGAdot);
ar& BOOST_SERIALIZATION_NVP(af0);
ar& BOOST_SERIALIZATION_NVP(af1);
ar& BOOST_SERIALIZATION_NVP(IODa);
ar& BOOST_SERIALIZATION_NVP(E5b_HS);
ar& BOOST_SERIALIZATION_NVP(E1B_HS);
ar& BOOST_SERIALIZATION_NVP(E5a_HS);

View File

@ -19,6 +19,7 @@
Galileo_Almanac Galileo_Almanac_Helper::get_almanac(int i) const
{
Galileo_Almanac galileo_almanac;
const double sqrtAnominal = 5440.588203494; // square root of Galileo nominal orbit semi-major axis
switch (i)
{
case 1:
@ -29,7 +30,7 @@ Galileo_Almanac Galileo_Almanac_Helper::get_almanac(int i) const
galileo_almanac.delta_i = this->delta_i_7;
galileo_almanac.M_0 = this->M0_7;
galileo_almanac.ecc = this->e_7;
galileo_almanac.delta_sqrtA = this->DELTA_A_7;
galileo_almanac.sqrtA = sqrtAnominal + this->DELTA_A_7;
galileo_almanac.OMEGA_0 = this->Omega0_7;
galileo_almanac.omega = this->omega_7;
galileo_almanac.OMEGAdot = this->Omega_dot_7;
@ -48,7 +49,7 @@ Galileo_Almanac Galileo_Almanac_Helper::get_almanac(int i) const
galileo_almanac.delta_i = this->delta_i_8;
galileo_almanac.M_0 = this->M0_9;
galileo_almanac.ecc = this->e_8;
galileo_almanac.delta_sqrtA = this->DELTA_A_8;
galileo_almanac.sqrtA = sqrtAnominal + this->DELTA_A_8;
galileo_almanac.OMEGA_0 = this->Omega0_8;
galileo_almanac.omega = this->omega_8;
galileo_almanac.OMEGAdot = this->Omega_dot_8;
@ -66,7 +67,7 @@ Galileo_Almanac Galileo_Almanac_Helper::get_almanac(int i) const
galileo_almanac.delta_i = this->delta_i_9;
galileo_almanac.M_0 = this->M0_10;
galileo_almanac.ecc = this->e_9;
galileo_almanac.delta_sqrtA = this->DELTA_A_9;
galileo_almanac.sqrtA = sqrtAnominal + this->DELTA_A_9;
galileo_almanac.OMEGA_0 = this->Omega0_10;
galileo_almanac.omega = this->omega_9;
galileo_almanac.OMEGAdot = this->Omega_dot_10;

View File

@ -0,0 +1,57 @@
/*!
* \file gnss_almanac.h
* \brief Base class for GNSS almanac storage
* \author Carles Fernandez, 2021. cfernandez(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)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GNSS_ALMANAC_H
#define GNSS_SDR_GNSS_ALMANAC_H
#include <cstdint>
/** \addtogroup Core
* \{ */
/** \addtogroup System_Parameters
* \{ */
/*!
* \brief Base class for GNSS almanac storage
*/
class Gnss_Almanac
{
public:
/*!
* Default constructor
*/
Gnss_Almanac() = default;
uint32_t PRN{}; //!< SV PRN NUMBER
double delta_i{}; //!< Inclination Angle at Reference Time (relative to i_0 = 0.30 semi-circles)
int32_t toa{}; //!< Almanac data reference time of week [s]
int32_t WNa{}; //!< Almanac week number
double M_0{}; //!< Mean Anomaly at Reference Time [semi-circles]
double ecc{}; //!< Eccentricity [dimensionless]
double sqrtA{}; //!< Square Root of the Semi-Major Axis [sqrt(m)]
double OMEGA_0{}; //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
double omega{}; //!< Argument of Perigee [semi-cicles]
double OMEGAdot{}; //!< Rate of Right Ascension [semi-circles/s]
double af0{}; //!< Coefficient 0 of code phase offset model [s]
double af1{}; //!< Coefficient 1 of code phase offset model [s/s]
};
/** \} */
/** \} */
#endif // GNSS_SDR_GNSS_ALMANAC_H

View File

@ -184,7 +184,7 @@ double Gnss_Ephemeris::sv_clock_relativistic_term(double transmitTime) const
{
n0 = sqrt(GALILEO_GM / (a * a * a));
}
if (this->System == 'E')
else if (this->System == 'E')
{
n0 = sqrt(BEIDOU_GM / (a * a * a));
}
@ -225,7 +225,7 @@ double Gnss_Ephemeris::sv_clock_relativistic_term(double transmitTime) const
{
dtr_ = GALILEO_F * this->ecc * this->sqrtA * sek;
}
if (this->System == 'B')
else if (this->System == 'B')
{
dtr_ = BEIDOU_F * this->ecc * this->sqrtA * sek;
}

View File

@ -18,8 +18,8 @@
#ifndef GNSS_SDR_GPS_ALMANAC_H
#define GNSS_SDR_GPS_ALMANAC_H
#include "gnss_almanac.h"
#include <boost/serialization/nvp.hpp>
#include <cstdint>
/** \addtogroup Core
* \{ */
@ -32,7 +32,7 @@
*
* See https://www.gps.gov/technical/icwg/IS-GPS-200L.pdf Appendix II
*/
class Gps_Almanac
class Gps_Almanac : public Gnss_Almanac
{
public:
/*!
@ -40,20 +40,8 @@ public:
*/
Gps_Almanac() = default;
uint32_t PRN{}; //!< SV PRN NUMBER
double delta_i{}; //!< Inclination Angle at Reference Time (relative to i_0 = 0.30 semi-circles)
int32_t toa{}; //!< Almanac data reference time of week (Ref. 20.3.3.4.3 IS-GPS-200L) [s]
int32_t WNa{}; //!< Almanac week number
double M_0{}; //!< Mean Anomaly at Reference Time [semi-circles]
double ecc{}; //!< Eccentricity [dimensionless]
double sqrtA{}; //!< Square Root of the Semi-Major Axis [sqrt(m)]
double OMEGA_0{}; //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
double omega{}; //!< Argument of Perigee [semi-cicles]
double OMEGAdot{}; //!< Rate of Right Ascension [semi-circles/s]
int32_t SV_health{}; //!< SV Health
int32_t AS_status{}; //!< Anti-Spoofing Flags and SV Configuration
double af0{}; //!< Coefficient 0 of code phase offset model [s]
double af1{}; //!< Coefficient 1 of code phase offset model [s/s]
template <class Archive>
@ -72,10 +60,10 @@ public:
ar& BOOST_SERIALIZATION_NVP(OMEGA_0);
ar& BOOST_SERIALIZATION_NVP(omega);
ar& BOOST_SERIALIZATION_NVP(OMEGAdot);
ar& BOOST_SERIALIZATION_NVP(SV_health);
ar& BOOST_SERIALIZATION_NVP(AS_status);
ar& BOOST_SERIALIZATION_NVP(af0);
ar& BOOST_SERIALIZATION_NVP(af1);
ar& BOOST_SERIALIZATION_NVP(SV_health);
ar& BOOST_SERIALIZATION_NVP(AS_status);
}
};

View File

@ -136,7 +136,7 @@ DECLARE_string(log_dir);
// #include "unit-tests/signal-processing-blocks/acquisition/beidou_b3i_pcps_acquisition_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc"
#include "unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc"
// #include "unit-tests/signal-processing-blocks/pvt/rtklib_solver_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_kf_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l2_m_dll_pll_tracking_test.cc"

View File

@ -1,6 +1,6 @@
/*!
* \file galileo_e1_pcps_acquisition_test_fpga.cc
* \brief This class implements an acquisition test Galileo FPFA acquisition
* \brief This class implements an acquisition test Galileo FPGA acquisition
* \authors <ul>
* <li> Marc Majoral, 2019. mmajoral(at)cttc.cat
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com

View File

@ -1,7 +1,7 @@
/*!
* \file serdes_monitor_pvt_test.cc
* \brief Implements Unit Test for the serdes_monitor_pvt class.
* \author Carles Fernandez_prades, 2019. cfernandez(at)cttc.es
* \author Carles Fernandez-Prades, 2019. cfernandez(at)cttc.es
*
* -----------------------------------------------------------------------------
*
@ -20,7 +20,7 @@
TEST(Serdes_Monitor_Pvt_Test, Simpletest)
{
std::shared_ptr<Monitor_Pvt> monitor = std::make_shared<Monitor_Pvt>(Monitor_Pvt());
auto monitor = std::make_shared<Monitor_Pvt>(Monitor_Pvt());
double true_latitude = 23.4;
monitor->latitude = true_latitude;
@ -29,13 +29,35 @@ TEST(Serdes_Monitor_Pvt_Test, Simpletest)
gnss_sdr::MonitorPvt mon;
mon.ParseFromString(serialized_data);
serdes.readProtobuffer(mon);
gnss_sdr::GalileoEphemeris ephgal;
Serdes_Galileo_Eph gal_serdes = Serdes_Galileo_Eph();
gal_serdes.readProtobuffer(ephgal);
double read_latitude = mon.latitude();
EXPECT_NEAR(true_latitude, read_latitude, 0.000001);
}
TEST(Serdes_Monitor_Pvt_Test, GalileoEphemerisSerdes)
{
auto eph = std::make_shared<Galileo_Ephemeris>();
int true_tow = 12345;
eph->tow = true_tow;
Serdes_Galileo_Eph gal_serdes = Serdes_Galileo_Eph();
std::string serialized_data = gal_serdes.createProtobuffer(eph);
gnss_sdr::GalileoEphemeris ephgal;
ephgal.ParseFromString(serialized_data);
double true_delta_n = 0.33;
ephgal.set_delta_n(true_delta_n);
int read_tow = ephgal.tow();
EXPECT_EQ(true_tow, read_tow);
double read_delta_n = ephgal.delta_n();
EXPECT_NEAR(true_delta_n, read_delta_n, 0.000001);
auto eph2 = gal_serdes.readProtobuffer(ephgal);
double read2_delta_n = eph2.delta_n;
int read2_tow = eph2.tow;
EXPECT_EQ(true_tow, read2_tow);
EXPECT_NEAR(true_delta_n, read2_delta_n, 0.000001);
}