diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index c943e0f58..b9a33105f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b7e627037..10092b46d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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")
 
diff --git a/README.md b/README.md
index 767f0b407..220912c66 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/conf/gnss-sdr_GPS_L1_FPGA.conf b/conf/gnss-sdr_GPS_L1_FPGA.conf
index 52a2d883d..c18b357b8 100644
--- a/conf/gnss-sdr_GPS_L1_FPGA.conf
+++ b/conf/gnss-sdr_GPS_L1_FPGA.conf
@@ -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
diff --git a/docs/changelog.md b/docs/changelog.md
index 228b27c78..c3ba94f56 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -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;
 
diff --git a/docs/xml-schemas/gal_almanac_map.xsd b/docs/xml-schemas/gal_almanac_map.xsd
index 2f6343fc3..26c82568b 100644
--- a/docs/xml-schemas/gal_almanac_map.xsd
+++ b/docs/xml-schemas/gal_almanac_map.xsd
@@ -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"/>
diff --git a/docs/xml-schemas/gps_almanac_map.xsd b/docs/xml-schemas/gps_almanac_map.xsd
index dea16fd14..f6814c34e 100644
--- a/docs/xml-schemas/gps_almanac_map.xsd
+++ b/docs/xml-schemas/gps_almanac_map.xsd
@@ -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"/>
diff --git a/src/algorithms/libs/rtklib/rtklib_conversions.cc b/src/algorithms/libs/rtklib/rtklib_conversions.cc
index a8a7f81ba..e7a088941 100644
--- a/src/algorithms/libs/rtklib/rtklib_conversions.cc
+++ b/src/algorithms/libs/rtklib/rtklib_conversions.cc
@@ -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;
diff --git a/src/algorithms/signal_source/adapters/CMakeLists.txt b/src/algorithms/signal_source/adapters/CMakeLists.txt
index c3d27001a..984144f0d 100644
--- a/src/algorithms/signal_source/adapters/CMakeLists.txt
+++ b/src/algorithms/signal_source/adapters/CMakeLists.txt
@@ -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
     )
diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc
index 43e4461c0..6f6d03056 100644
--- a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc
+++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.cc
@@ -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;
diff --git a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h
index e9e1dccf0..2818a6722 100644
--- a/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h
+++ b/src/algorithms/signal_source/adapters/ad9361_fpga_signal_source.h
@@ -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_;
 };
 
 
diff --git a/src/algorithms/signal_source/libs/fpga_buffer_monitor.cc b/src/algorithms/signal_source/libs/fpga_buffer_monitor.cc
index b5799f9d2..e98988137 100644
--- a/src/algorithms/signal_source/libs/fpga_buffer_monitor.cc
+++ b/src/algorithms/signal_source/libs/fpga_buffer_monitor.cc
@@ -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>
diff --git a/src/algorithms/signal_source/libs/fpga_buffer_monitor.h b/src/algorithms/signal_source/libs/fpga_buffer_monitor.h
index 778585a58..c9631c0eb 100644
--- a/src/algorithms/signal_source/libs/fpga_buffer_monitor.h
+++ b/src/algorithms/signal_source/libs/fpga_buffer_monitor.h
@@ -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
  * \{ */
diff --git a/src/core/libs/gnss_sdr_supl_client.cc b/src/core/libs/gnss_sdr_supl_client.cc
index e5af67588..d09b3c099 100644
--- a/src/core/libs/gnss_sdr_supl_client.cc
+++ b/src/core/libs/gnss_sdr_supl_client.cc
@@ -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"));
diff --git a/src/core/libs/uio_fpga.cc b/src/core/libs/uio_fpga.cc
index c8a143a90..9d436d7c3 100644
--- a/src/core/libs/uio_fpga.cc
+++ b/src/core/libs/uio_fpga.cc
@@ -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;
diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc
index 557b53ab2..fb62f9d86 100644
--- a/src/core/receiver/control_thread.cc
+++ b/src/core/receiver/control_thread.cc
@@ -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);
diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc
index 65fe1162a..f074cb1e0 100644
--- a/src/core/receiver/gnss_flowgraph.cc
+++ b/src/core/receiver/gnss_flowgraph.cc
@@ -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++)
         {
diff --git a/src/core/receiver/gnss_flowgraph.h b/src/core/receiver/gnss_flowgraph.h
index 59086a366..aea6c94e0 100644
--- a/src/core/receiver/gnss_flowgraph.h
+++ b/src/core/receiver/gnss_flowgraph.h
@@ -297,6 +297,7 @@ private:
     bool enable_monitor_;
     bool enable_acquisition_monitor_;
     bool enable_tracking_monitor_;
+    bool enable_fpga_offloading_;
 };
 
 
diff --git a/src/core/system_parameters/CMakeLists.txt b/src/core/system_parameters/CMakeLists.txt
index 6486d8aaa..224dbe361 100644
--- a/src/core/system_parameters/CMakeLists.txt
+++ b/src/core/system_parameters/CMakeLists.txt
@@ -27,6 +27,7 @@ set(SYSTEM_PARAMETERS_SOURCES
 )
 
 set(SYSTEM_PARAMETERS_HEADERS
+    gnss_almanac.h
     gnss_ephemeris.h
     gnss_satellite.h
     gnss_signal.h
diff --git a/src/core/system_parameters/agnss_ref_time.h b/src/core/system_parameters/agnss_ref_time.h
index df3859aaa..06bdd79d0 100644
--- a/src/core/system_parameters/agnss_ref_time.h
+++ b/src/core/system_parameters/agnss_ref_time.h
@@ -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);
     }
 };
diff --git a/src/core/system_parameters/beidou_dnav_almanac.h b/src/core/system_parameters/beidou_dnav_almanac.h
index 37d7e33da..03610990f 100644
--- a/src/core/system_parameters/beidou_dnav_almanac.h
+++ b/src/core/system_parameters/beidou_dnav_almanac.h
@@ -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);
     }
 };
 
diff --git a/src/core/system_parameters/galileo_almanac.h b/src/core/system_parameters/galileo_almanac.h
index 5799d2be4..a76a3af66 100644
--- a/src/core/system_parameters/galileo_almanac.h
+++ b/src/core/system_parameters/galileo_almanac.h
@@ -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);
diff --git a/src/core/system_parameters/galileo_almanac_helper.cc b/src/core/system_parameters/galileo_almanac_helper.cc
index f2f2f093e..9b7a40ed1 100644
--- a/src/core/system_parameters/galileo_almanac_helper.cc
+++ b/src/core/system_parameters/galileo_almanac_helper.cc
@@ -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;
diff --git a/src/core/system_parameters/gnss_almanac.h b/src/core/system_parameters/gnss_almanac.h
new file mode 100644
index 000000000..2206f4acc
--- /dev/null
+++ b/src/core/system_parameters/gnss_almanac.h
@@ -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
diff --git a/src/core/system_parameters/gnss_ephemeris.cc b/src/core/system_parameters/gnss_ephemeris.cc
index a8698ed43..101fbf63c 100644
--- a/src/core/system_parameters/gnss_ephemeris.cc
+++ b/src/core/system_parameters/gnss_ephemeris.cc
@@ -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;
         }
diff --git a/src/core/system_parameters/gps_almanac.h b/src/core/system_parameters/gps_almanac.h
index 2a513b588..63511656d 100644
--- a/src/core/system_parameters/gps_almanac.h
+++ b/src/core/system_parameters/gps_almanac.h
@@ -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);
     }
 };
 
diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc
index 17bf694c8..8201dfdd6 100644
--- a/src/tests/test_main.cc
+++ b/src/tests/test_main.cc
@@ -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"
diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_ambiguous_acquisition_test_fpga.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_ambiguous_acquisition_test_fpga.cc
index 821eefadc..8cd656409 100644
--- a/src/tests/unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_ambiguous_acquisition_test_fpga.cc
+++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_ambiguous_acquisition_test_fpga.cc
@@ -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
diff --git a/src/tests/unit-tests/signal-processing-blocks/pvt/serdes_monitor_pvt_test.cc b/src/tests/unit-tests/signal-processing-blocks/pvt/serdes_monitor_pvt_test.cc
index caa1aad58..5cfca59d5 100644
--- a/src/tests/unit-tests/signal-processing-blocks/pvt/serdes_monitor_pvt_test.cc
+++ b/src/tests/unit-tests/signal-processing-blocks/pvt/serdes_monitor_pvt_test.cc
@@ -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);
+}