Merge branch 'next' into observables_and_display_color

This commit is contained in:
Antonio Ramos 2018-04-03 11:01:59 +02:00
commit ebb908f2e7
201 changed files with 18865 additions and 16681 deletions

View File

@ -41,9 +41,10 @@ endif(NOT CMAKE_PREFIX_PATH)
########################################################################
# Determine optional blocks/libraries to be built (default: not built)
# Enable them here or at the command line by doing 'cmake -DENABLE_XXX=ON ../'
# Enable them at the command line by doing 'cmake -DENABLE_XXX=ON ../'
########################################################################
# Support of optional RF front-ends
option(ENABLE_UHD "Enable the use of UHD (driver for all USRP devices)" ON)
option(ENABLE_OSMOSDR "Enable the use of OsmoSDR and other front-ends (RTL-based dongles, HackRF, bladeRF, etc.) as signal source (experimental)" OFF)
option(ENABLE_FLEXIBAND "Enable the use of the signal source adater for the Teleorbit Flexiband GNURadio driver" OFF)
option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal source (experimental)" OFF)
@ -1196,18 +1197,18 @@ endif(NOT MATIO_FOUND OR MATIO_VERSION_STRING VERSION_LESS ${GNSSSDR_MATIO_MIN_V
################################################################################
# USRP Hardware Driver (UHD) - OPTIONAL
################################################################################
find_package(UHD)
if(NOT UHD_FOUND)
set(ENABLE_UHD OFF)
message(STATUS " The USRP Hardware Driver (UHD) signal source will not be built,")
message(STATUS " so all USRP-based front-ends will not be usable.")
message(STATUS " Please check http://files.ettus.com/manual/")
else(NOT UHD_FOUND)
set(GR_REQUIRED_COMPONENTS UHD)
find_package(Gnuradio)
set(ENABLE_UHD ON)
endif(NOT UHD_FOUND)
if(ENABLE_UHD)
find_package(UHD)
if(NOT UHD_FOUND)
set(ENABLE_UHD OFF)
message(STATUS " The USRP Hardware Driver (UHD) signal source will not be built,")
message(STATUS " so all USRP-based front-ends will not be usable.")
message(STATUS " Please check http://files.ettus.com/manual/")
else(NOT UHD_FOUND)
set(GR_REQUIRED_COMPONENTS UHD)
find_package(Gnuradio)
endif(NOT UHD_FOUND)
endif(ENABLE_UHD)
################################################################################

View File

@ -67,7 +67,7 @@ GitHub](https://github.com/join).
GitHub](https://github.com/gnss-sdr/gnss-sdr/fork). This will copy the
whole gnss-sdr repository to your personal account.
3. Then, go to your favourite working folder in your computer and
3. Then, go to your favorite working folder in your computer and
clone your forked repository by typing (replacing ```YOUR_USERNAME``` by
the actual username of your GitHub account):
@ -128,7 +128,7 @@ $ git pull --rebase upstream next
### How to submit a pull request
Before submitting you code, please be sure to [apply clang-format](http://gnss-sdr.org/coding-style/#use-tools-for-automated-code-formatting).
Before submitting your code, please be sure to [apply clang-format](http://gnss-sdr.org/coding-style/#use-tools-for-automated-code-formatting).
When the contribution is ready, you can [submit a pull
request](https://github.com/gnss-sdr/gnss-sdr/compare/). Head to your

View File

@ -13,6 +13,7 @@ In the L1 band (centered at 1575.42 MHz):
In the L2 band (centered at 1227.60 MHz):
- 🛰 GPS L2C :white_check_mark:
- 🛰 GLONASS L2 C/A :white_check_mark:
In the L5 band (centered at 1176.45 MHz):
- 🛰 GPS L5 :white_check_mark:
@ -52,7 +53,7 @@ Before building GNSS-SDR, you need to install all the required dependencies. The
### Alternative 1: Install dependencies using software packages
If you want to start building and running GNSS-SDR as quick and easy as possible, the best option is to install all the required dependencies as binary packages.
If you want to start building and running GNSS-SDR as quick and easy as possible, the best option is to install all the required dependencies as binary packages.
#### Debian / Ubuntu
@ -84,7 +85,7 @@ $ sudo yum install make automake gcc gcc-c++ kernel-devel cmake git boost-devel
boost-date-time boost-system boost-filesystem boost-thread boost-chrono \
boost-serialization log4cpp-devel gnuradio-devel gr-osmosdr-devel \
blas-devel lapack-devel matio-devel armadillo-devel gflags-devel \
glog-devel openssl-devel python-mako python-six
glog-devel openssl-devel python-mako python-six
~~~~~~
Once you have installed these packages, you can jump directly to [download the source code and build GNSS-SDR](#download-and-build-linux).
@ -303,7 +304,7 @@ $ cmake ../
$ make
~~~~~~
By default, CMake will build the Release version, meaning that the compiler will generate a fast, optimized executable. This is the recommended build type when using a RF front-end and you need to attain real time. If working with a file (and thus without real-time constraints), you may want to obtain more information about the internals of the receiver, as well as more fine-grained logging. This can be done by building the Debug version, by doing:
By default, CMake will build the Release version, meaning that the compiler will generate a fast, optimized executable. This is the recommended build type when using an RF front-end and you need to attain real time. If working with a file (and thus without real-time constraints), you may want to obtain more information about the internals of the receiver, as well as more fine-grained logging. This can be done by building the Debug version, by doing:
~~~~~~
$ cmake -DCMAKE_BUILD_TYPE=Debug ../
@ -696,8 +697,8 @@ Getting started
2. You will need a GPS active antenna, a [USRP](http://www.ettus.com/product) and a suitable USRP daughter board to receive GPS L1 C/A signals. GNSS-SDR require to have at least 2 MHz of bandwidth in 1.57542 GHz. (remember to enable the DC bias with the daughter board jumper).
We use a [DBSRX2](https://www.ettus.com/product/details/DBSRX2) to do the task, but you can try the newer Ettus' daughter boards as well.
3. The easiest way to capture a signal file is to use the GNU Radio Companion GUI. Only two blocks are needed: a USRP signal source connected to complex float file sink. You need to tune the USRP central frequency and decimation factor using USRP signal source properties box. We suggest using a decimation factor of 20 if you use the USRP2. This will give you 100/20 = 5 MSPS which will be enough to receive GPS L1 C/A signals. The front-end gain should also be configured. In our test with the DBSRX2 we obtained good results with ```G=50```.
4. Capture at least 80 seconds of signal in open sky conditions. During the process, be aware of USRP driver buffer underuns messages. If your hard disk is not fast enough to write data at this speed you can capture to a virtual RAM drive. 80 seconds of signal at 5 MSPS occupies less than 3 Gbytes using ```gr_complex<float>```.
5. If you have no access to a RF front-end, you can download a sample raw data file (that contains GPS and Galileo signals) from [here](http://sourceforge.net/projects/gnss-sdr/files/data/).
4. Capture at least 80 seconds of signal in open sky conditions. During the process, be aware of USRP driver buffer underruns messages. If your hard disk is not fast enough to write data at this speed you can capture to a virtual RAM drive. 80 seconds of signal at 5 MSPS occupies less than 3 Gbytes using ```gr_complex<float>```.
5. If you have no access to an RF front-end, you can download a sample raw data file (that contains GPS and Galileo signals) from [here](http://sourceforge.net/projects/gnss-sdr/files/data/).
3. You are ready to configure the receiver to use your captured file among other parameters:
1. The default configuration file resides at [/usr/local/share/gnss-sdr/conf/default.conf](./conf/gnss-sdr.conf).
2. You need to review/modify at least the following settings:
@ -717,7 +718,7 @@ For more information, check out our [quick start guide](http://gnss-sdr.org/quic
Using GNSS-SDR
==============
With GNSS-SDR, you can define you own receiver, work with captured raw data or from a RF front-end, dump into files intermediate signals, or tune every single algorithm used in the signal processing. All the configuration is done in a single file. Those configuration files reside at the [gnss-sdr/conf/](./conf/) folder (or at /usr/local/share/gnss-sdr/conf if you installed the program). By default, the executable ```gnss-sdr``` will read the configuration available at ```gnss-sdr/conf/gnss-sdr.conf``` (or at (usr/local/share/gnss-sdr/conf/default.conf if you installed the program). You can edit that file to fit your needs, or even better, define a new ```my_receiver.conf``` file with your own configuration. This new receiver can be generated by invoking gnss-sdr with the ```--config_file``` flag pointing to your configuration file:
With GNSS-SDR, you can define your own receiver, work with captured raw data or from an RF front-end, dump into files intermediate signals, or tune every single algorithm used in the signal processing. All the configuration is done in a single file. Those configuration files reside at the [gnss-sdr/conf/](./conf/) folder (or at /usr/local/share/gnss-sdr/conf if you installed the program). By default, the executable ```gnss-sdr``` will read the configuration available at ```gnss-sdr/conf/gnss-sdr.conf``` (or at (usr/local/share/gnss-sdr/conf/default.conf if you installed the program). You can edit that file to fit your needs, or even better, define a new ```my_receiver.conf``` file with your own configuration. This new receiver can be generated by invoking gnss-sdr with the ```--config_file``` flag pointing to your configuration file:
~~~~~~
$ gnss-sdr --config_file=/path/to/my_receiver.conf
@ -769,7 +770,7 @@ Since the configuration is just a set of property names and values without any m
### GNSS block factory
Hence, the application defines a simple accessor class to fetch the configuration pairs of values and passes them to a factory class called [GNSSBlockFactory](./src/core/receiver/gnss_block_factory.h). This factory decides, according to the configuration, which class needs to be instantiated and which parameters should be passed to the constructor. Hence, the factory encapsulates the complexity of blocks' instantiation. With that approach, adding a new block that requires new parameters will be as simple as adding the block class and modifying the factory to be able to instantiate it. This loose coupling between the blocks' implementations and the syntax of the configuration enables extending the application capacities in a high degree. It also allows to produce fully customized receivers, for instance a testbed for acquisition algorithms, and to place observers at any point of the receiver chain.
Hence, the application defines a simple accessor class to fetch the configuration pairs of values and passes them to a factory class called [GNSSBlockFactory](./src/core/receiver/gnss_block_factory.h). This factory decides, according to the configuration, which class needs to be instantiated and which parameters should be passed to the constructor. Hence, the factory encapsulates the complexity of blocks' instantiation. With that approach, adding a new block that requires new parameters will be as simple as adding the block class and modifying the factory to be able to instantiate it. This loose coupling between the blocks' implementations and the syntax of the configuration enables extending the application capacities in a high degree. It also allows producing fully customized receivers, for instance a testbed for acquisition algorithms, and to place observers at any point of the receiver chain.
More information can be found at the [Control Plane page](http://gnss-sdr.org/docs/control-plane/).
@ -783,9 +784,9 @@ GNU Radio's class ```gr::basic_block``` is the abstract base class for all signa
A signal processing flow is constructed by creating a tree of hierarchical blocks, which at any level may also contain terminal nodes that actually implement signal processing functions.
Class ```gr::top_block``` is the top-level hierarchical block representing a flowgraph. It defines GNU Radio runtime functions used during the execution of the program: run(), start(), stop(), wait(), etc. A a subclass called [GNSSBlockInterface](./src/core/interfaces/gnss_block_interface.h) is the common interface for all the GNSS-SDR modules. It defines pure virtual methods, that are required to be implemented by a derived class.
Class ```gr::top_block``` is the top-level hierarchical block representing a flowgraph. It defines GNU Radio runtime functions used during the execution of the program: run(), start(), stop(), wait(), etc. A subclass called [GNSSBlockInterface](./src/core/interfaces/gnss_block_interface.h) is the common interface for all the GNSS-SDR modules. It defines pure virtual methods, that are required to be implemented by a derived class.
Subclassing GNSSBlockInterface, we defined interfaces for the GNSS receiver blocks depicted in the figure above. This hierarchy provides the definition of different algorithms and different implementations, which will be instantiated according to the configuration. This strategy allows multiple implementations sharing a common interface, achieving the objective of decoupling interfaces from implementations: it defines a family of algorithms, encapsulates each one, and makes them interchangeable. Hence, we let the algorithm vary independently from the program that uses it.
Subclassing GNSSBlockInterface, we defined interfaces for the GNSS receiver blocks depicted in the figure above. This hierarchy provides the definition of different algorithms and different implementations, which will be instantiated according to the configuration. This strategy allows multiple implementations sharing a common interface, achieving the objective of decoupling interfaces from implementations: it defines a family of algorithms, encapsulates each one, and makes them interchangeable. Hence, we let the algorithm vary independently of the program that uses it.
Internally, GNSS-SDR makes use of the complex data types defined by [VOLK](http://libvolk.org/ "Vector-Optimized Library of Kernels home"). They are fundamental for handling sample streams in which samples are complex numbers with real and imaginary components of 8, 16 or 32 bits, common formats delivered by GNSS (and generic SDR) radio frequency front-ends. The following list shows the data type names that GNSS-SDR exposes through the configuration file:
@ -805,7 +806,7 @@ More information about the available processing blocks and their configuration p
The input of a software receiver are the raw bits that come out from the front-end's analog-to-digital converter (ADC). Those bits can be read from a file stored in the hard disk or directly in real-time from a hardware device through USB or Ethernet buses.
The Signal Source module is in charge of implementing the hardware driver, that is, the portion of the code that communicates with the RF front-end and receives the samples coming from the ADC. This communication is usually performed through USB or Ethernet buses. Since real-time processing requires a highly optimized implementation of the whole receiver, this module also allows to read samples from a file stored in a hard disk, and thus processing without time constraints. Relevant parameters of those samples are the intermediate frequency (or baseband I&Q components), the sampling rate and number of bits per sample, that must be specified by the user in the configuration file.
The Signal Source module is in charge of implementing the hardware driver, that is, the portion of the code that communicates with the RF front-end and receives the samples coming from the ADC. This communication is usually performed through USB or Ethernet buses. Since real-time processing requires a highly optimized implementation of the whole receiver, this module also allows reading samples from a file stored in a hard disk, and thus processing without time constraints. Relevant parameters of those samples are the intermediate frequency (or baseband I&Q components), the sampling rate and number of bits per sample, that must be specified by the user in the configuration file.
This module also performs bit-depth adaptation, since most of the existing RF front-ends provide samples quantized with 2 or 3 bits, while operations inside the processor are performed on 32- or 64-bit words, depending on its architecture. Although there are implementations of the most intensive computational processes (mainly correlation) that take advantage of specific data types and architectures for the sake of efficiency, the approach is processor-specific and hardly portable. We suggest to keep signal samples in standard data types and letting the compiler select the best library version (implemented using SIMD or any other processor-specific technology) of the required routines for a given processor.
@ -821,7 +822,7 @@ SignalSource.item_type=gr_complex
SignalSource.sampling_frequency=4000000 ; Sampling frequency in samples per second (Sps)
~~~~~~
Type ```gr_complex``` refers to a GNU Radio typedef equivalent to ```std::complex<float>```. In order to save some storage space, you might wanted to store your signal in a more efficient format such as an I/Q interleaved ```short`` integer sample stream. In that case, change the corresponding line to:
Type ```gr_complex``` refers to a GNU Radio typedef equivalent to ```std::complex<float>```. In order to save some storage space, you might want to store your signal in a more efficient format such as an I/Q interleaved ```short`` integer sample stream. In that case, change the corresponding line to:
~~~~~~
SignalSource.item_type=ishort
@ -845,7 +846,7 @@ Sometimes, samples are stored in files with a format which is not in the list of
Within a byte the samples may be packed in big endian ```big_endian_bytes=true``` (if the most significant byte value is stored at the memory location with the lowest address, the next byte value in significance is stored at the following memory location, and so on) or little endian ```big_endian_bytes=false``` (if the least significant byte value is at the lowest address, and the other bytes follow in increasing order of significance). If the order is big endian then the most significant two bits will form the first sample output, otherwise the least significant two bits will be used.
Additionally the samples may be either real ```sample_type=real```, or complex. If the sample type is complex, then the samples are either stored in the order: real, imag, real, imag, ... ```sample_type=iq``` or in the order: imag, real, imag, real, ... ```sample_type=qi```.
Additionally, the samples may be either real ```sample_type=real```, or complex. If the sample type is complex, then the samples are either stored in the order: real, imag, real, imag, ... ```sample_type=iq``` or in the order: imag, real, imag, real, ... ```sample_type=qi```.
Finally, if the data is stored as shorts ```item_type=short```, then it may be stored in either big endian ```big_endian_items=true``` or little endian ```big_endian_items=false```. If the shorts are big endian then the 2nd byte in each short is output first.
@ -1007,7 +1008,7 @@ If your signal source is providing baseband signal samples of type ```gr_complex
SignalConditioner.implementation=Pass_Through
~~~~~~
If you need to adapt some aspect of you signal, you can enable the Signal Conditioner and configure three internal blocks: a data type adpater, an input signal and a resampler.
If you need to adapt some aspect of your signal, you can enable the Signal Conditioner and configure three internal blocks: a data type adapter, an input signal and a resampler.
~~~~~~
;#[Signal_Conditioner] enables this block. Then you have to configure [DataTypeAdapter], [InputFilter] and [Resampler] blocks
@ -1030,7 +1031,7 @@ More documentation at the [Data Type Adapter Blocks page](http://gnss-sdr.org/do
#### Input filter
This block filters the input data. It can be combined with frequency translation for IF signals. The computation of the filter taps is based on parameters of GNU Radio's function [pm_remez](http://gnuradio.org/doc/doxygen/pm__remez_8h.html), that calculates the optimal (in the Chebyshev/minimax sense) FIR filter impulse response given a set of band edges, the desired reponse on those bands, and the weight given to the error in those bands.
This block filters the input data. It can be combined with frequency translation for IF signals. The computation of the filter taps is based on parameters of GNU Radio's function [pm_remez](http://gnuradio.org/doc/doxygen/pm__remez_8h.html), that calculates the optimal (in the Chebyshev/minimax sense) FIR filter impulse response given a set of band edges, the desired response on those bands, and the weight given to the error in those bands.
The block can be configured like this:
@ -1085,7 +1086,7 @@ More documentation at the [Input Filter Blocks page](http://gnss-sdr.org/docs/sp
#### Resampler
This block resamples the input data stream. The ```Direct_Resampler``` block implements a nearest neigbourhood interpolation:
This block resamples the input data stream. The ```Direct_Resampler``` block implements a nearest neighbourhood interpolation:
~~~~~~
;######### RESAMPLER CONFIG ############
@ -1103,7 +1104,7 @@ More documentation at the [Resampler Blocks page](http://gnss-sdr.org/docs/sp-bl
### Channel
A channel encapsulates all signal processing devoted to a single satellite. Thus, it is a large composite object which encapsulates the acquisition, tracking and navigation data decoding modules. As a composite object, it can be treated as a single entity, meaning that it can be easily replicated. Since the number of channels is selectable by the user in the configuration file, this approach helps improving the scalability and maintainability of the receiver.
A channel encapsulates all signal processing devoted to a single satellite. Thus, it is a large composite object which encapsulates the acquisition, tracking and navigation data decoding modules. As a composite object, it can be treated as a single entity, meaning that it can be easily replicated. Since the number of channels is selectable by the user in the configuration file, this approach helps to improve the scalability and maintainability of the receiver.
Each channel must be assigned to a GNSS signal, according to the following identifiers:
@ -1113,6 +1114,7 @@ Each channel must be assigned to a GNSS signal, according to the following ident
| Galileo E1b/c | 1B |
| Glonass L1 C/A | 1G |
| GPS L2 L2C(M) | 2S |
| Glonass L2 C/A | 2G |
| GPS L5 | L5 |
| Galileo E5a | 5X |
@ -1144,7 +1146,7 @@ Channel6.signal=1B ;
Channel7.signal=1B ;
~~~~~~
This module is also in charge of managing the interplay between acquisition and tracking. Acquisition can be initialized in several ways, depending on the prior information available (called cold start when the receiver has no information about its position nor the satellites almanac; warm start when a rough location and the approximate time of day are available, and the receiver has a recently recorded almanac broadcast; or hot start when the receiver was tracking a satellite and the signal line of sight broke for a short period of time, but the ephemeris and almanac data is still valid, or this information is provided by other means), and an acquisition process can finish deciding that the satellite is not present, that longer integration is needed in order to confirm the presence of the satellite, or declaring the satellite present. In the latter case, acquisition process should stop and trigger the tracking module with coarse estimations of the synchronization parameters. The mathematical abstraction used to design this logic is known as finite state machine (FSM), that is a behavior model composed of a finite number of states, transitions between those states, and actions. For the implementation, we use the [Boost.Statechart library](http://www.boost.org/libs/statechart/doc/tutorial.html), which provides desirable features such as support for asynchronous state machines, multi-threading, type-safety, error handling and compile-time validation.
This module is also in charge of managing the interplay between acquisition and tracking. Acquisition can be initialized in several ways, depending on the prior information available (called cold start when the receiver has no information about its position nor the satellites' almanac; warm start when a rough location and the approximate time of day are available, and the receiver has a recently recorded almanac broadcast; or hot start when the receiver was tracking a satellite and the signal line of sight broke for a short period of time, but the ephemeris and almanac data is still valid, or this information is provided by other means), and an acquisition process can finish deciding that the satellite is not present, that longer integration is needed in order to confirm the presence of the satellite, or declaring the satellite present. In the latter case, acquisition process should stop and trigger the tracking module with coarse estimations of the synchronization parameters. The mathematical abstraction used to design this logic is known as finite state machine (FSM), that is a behavior model composed of a finite number of states, transitions between those states, and actions.
The abstract class [ChannelInterface](./src/core/interfaces/channel_interface.h) represents an interface to a channel GNSS block. Check [Channel](./src/algorithms/channel/adapters/channel.h) for an actual implementation.
@ -1254,7 +1256,7 @@ More documentation at the [Tracking Blocks page](http://gnss-sdr.org/docs/sp-blo
#### Decoding of the navigation message
Most of GNSS signal links are modulated by a navigation message containing the time the message was transmitted, orbital parameters of satellites (also known as ephemeris) and an almanac (information about the general system health, rough orbits of all satellites in the network as well as data related to error correction). Navigation data bits are structured in words, pages, subframes, frames and superframes. Sometimes, bits corresponding to a single parameter are spread over different words, and values extracted from different frames are required for proper decoding. Some words are for synchronization purposes, others for error control an others contain actual information. There are also error control mechanisms, from parity checks to forward error correction (FEC) encoding and interleaving, depending on the system. All this decoding complexity is managed by a finite state machine implemented with the [Boost.Statechart library](http://www.boost.org/libs/statechart/doc/tutorial.html).
Most of GNSS signal links are modulated by a navigation message containing the time the message was transmitted, orbital parameters of satellites (also known as ephemeris) and an almanac (information about the general system health, rough orbits of all satellites in the network as well as data related to error correction). Navigation data bits are structured in words, pages, subframes, frames and superframes. Sometimes, bits corresponding to a single parameter are spread over different words, and values extracted from different frames are required for proper decoding. Some words are for synchronization purposes, others for error control and others contain actual information. There are also error control mechanisms, from parity checks to forward error correction (FEC) encoding and interleaving, depending on the system. All this decoding complexity is managed by a finite state machine.
The common interface is [TelemetryDecoderInterface](./src/core/interfaces/telemetry_decoder_interface.h). Check [GpsL1CaTelemetryDecoder](./src/algorithms/telemetry_decoder/adapters/gps_l1_ca_telemetry_decoder.h) for an example of the GPS L1 NAV message decoding adapter, and [gps_l1_ca_telemetry_decoder_cc](./src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.h) for an actual implementation of a signal processing block. Configuration example:
@ -1341,7 +1343,7 @@ PVT.rtcm_MT1077_rate_ms=1000
PVT.rinex_version=2
~~~~~~
* **RTCM SC-104** provides standards that define the data structure for differential GNSS correction information for a variety of differential correction applications. Developed by the Radio Technical Commission for Maritime Services ([RTCM](http://www.rtcm.org/overview.php#Standards "Radio Technical Commission for Maritime Services")), they have become an industry standard for communication of correction information. GNSS-SDR implements RTCM version 3.2, defined in the document *RTCM 10403.2, Differential GNSS (Global Navigation Satellite Systems) Services - Version 3* (February 1, 2013), which can be [purchased online](https://ssl29.pair.com/dmarkle/puborder.php?show=3 "RTCM Online Publication Order Form"). By default, the generated RTCM binary messages are dumped into a text file in hexadecimal format. However, GNSS-SDR is equipped with a TCP/IP server, acting as an NTRIP source that can feed an NTRIP server. NTRIP (Networked Transport of RTCM via Internet Protocol) is an open standard protocol that can be freely download from [BKG](http://igs.bkg.bund.de/root_ftp/NTRIP/documentation/NtripDocumentation.pdf "Networked Transport of RTCM via Internet Protocol (Ntrip) Version 1.0"), and it is designed for disseminating differential correction data (*e.g.* in the RTCM-104 format) or other kinds of GNSS streaming data to stationary or mobile users over the Internet. The TCP/IP server can be enabled by setting ```PVT.flag_rtcm_server=true``` in the configuration file, and will be active during the execution of the software receiver. By default, the server will operate on port 2101 (which is the recommended port for RTCM services according to the Internet Assigned Numbers Authority, [IANA](http://www.iana.org/assignments/service-names-port-numbers "Service Name and Transport Protocol Port Number Registry")), and will identify the Reference Station with ID=1234. This behaviour can be changed in the configuration file:
* **RTCM SC-104** provides standards that define the data structure for differential GNSS correction information for a variety of differential correction applications. Developed by the Radio Technical Commission for Maritime Services ([RTCM](http://www.rtcm.org/overview.php#Standards "Radio Technical Commission for Maritime Services")), they have become an industry standard for communication of correction information. GNSS-SDR implements RTCM version 3.2, defined in the document *RTCM 10403.2, Differential GNSS (Global Navigation Satellite Systems) Services - Version 3* (February 1, 2013), which can be [purchased online](https://ssl29.pair.com/dmarkle/puborder.php?show=3 "RTCM Online Publication Order Form"). By default, the generated RTCM binary messages are dumped into a text file in hexadecimal format. However, GNSS-SDR is equipped with a TCP/IP server, acting as an NTRIP source that can feed an NTRIP server. NTRIP (Networked Transport of RTCM via Internet Protocol) is an open standard protocol that can be freely downloaded from [BKG](http://igs.bkg.bund.de/root_ftp/NTRIP/documentation/NtripDocumentation.pdf "Networked Transport of RTCM via Internet Protocol (Ntrip) Version 1.0"), and it is designed for disseminating differential correction data (*e.g.* in the RTCM-104 format) or other kinds of GNSS streaming data to stationary or mobile users over the Internet. The TCP/IP server can be enabled by setting ```PVT.flag_rtcm_server=true``` in the configuration file, and will be active during the execution of the software receiver. By default, the server will operate on port 2101 (which is the recommended port for RTCM services according to the Internet Assigned Numbers Authority, [IANA](http://www.iana.org/assignments/service-names-port-numbers "Service Name and Transport Protocol Port Number Registry")), and will identify the Reference Station with ID=1234. This behaviour can be changed in the configuration file:
~~~~~~
PVT.flag_rtcm_server=true
PVT.rtcm_tcp_port=2102
@ -1398,9 +1400,9 @@ There is a list of papers related to GNSS-SDR in our [publications page](http://
Ok, now what?
=============
In order to start using GNSS-SDR, you may want to populate ```gnss-sdr/data``` folder (or anywhere else on your system) with raw data files. By "raw data" we mean the output of a Radio Frequency front-end's Analog-to-Digital converter. GNSS-SDR needs signal samples already in baseband or in passband, at a suitable intemediate frequency (on the order of MHz). Prepare your configuration file, and then you are ready for running ```gnss-sdr --config_file=your_configuration.conf```, and seeing how the file is processed.
In order to start using GNSS-SDR, you may want to populate ```gnss-sdr/data``` folder (or anywhere else on your system) with raw data files. By "raw data" we mean the output of a Radio Frequency front-end's Analog-to-Digital converter. GNSS-SDR needs signal samples already in baseband or in passband, at a suitable intermediate frequency (on the order of MHz). Prepare your configuration file, and then you are ready for running ```gnss-sdr --config_file=your_configuration.conf```, and seeing how the file is processed.
Another interesting option is working in real-time with a RF front-end. We provide drivers for UHD-compatible hardware such as the [USRP family](http://www.ettus.com/product), for OsmoSDR and other front-ends (HackRF, bladeRF, LimeSDR), for the GN3S v2 USB dongle and for some DVB-T USB dongles. Start with a low number of channels and then increase it in order to test how many channels your processor can handle in real-time.
Another interesting option is working in real-time with an RF front-end. We provide drivers for UHD-compatible hardware such as the [USRP family](http://www.ettus.com/product), for OsmoSDR and other front-ends (HackRF, bladeRF, LimeSDR), for the GN3S v2 USB dongle and for some DVB-T USB dongles. Start with a low number of channels and then increase it in order to test how many channels your processor can handle in real-time.
You can find more information at the [GNSS-SDR Documentation page](http://gnss-sdr.org/docs/) or directly asking to the [GNSS-SDR Developers mailing list](http://lists.sourceforge.net/lists/listinfo/gnss-sdr-developers).

View File

@ -0,0 +1,53 @@
INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(PC_LIBIIO libiio)
FIND_PATH(
LIBIIO_INCLUDE_DIRS
NAMES gnuradio/iio/api.h
HINTS $ENV{LIBIIO_DIR}/include
${PC_LIBIIO_INCLUDEDIR}
PATHS ${CMAKE_INSTALL_PREFIX}/include
/usr/local/include
/usr/include
/opt/local/include
)
FIND_LIBRARY(
LIBIIO_LIBRARIES
NAMES libiio.so iio
HINTS $ENV{LIBIIO_DIR}/lib
${PC_LIBIIO_LIBDIR}
PATHS ${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
/usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
/usr/lib/x86_64-linux-gnu
/usr/lib/gcc/alpha-linux-gnu
/usr/lib/gcc/aarch64-linux-gnu
/usr/lib/gcc/arm-linux-gnueabi
/usr/lib/gcc/arm-linux-gnueabihf
/usr/lib/gcc/hppa-linux-gnu
/usr/lib/gcc/i686-gnu
/usr/lib/gcc/i686-linux-gnu
/usr/lib/gcc/x86_64-kfreebsd-gnu
/usr/lib/gcc/i686-kfreebsd-gnu
/usr/lib/gcc/m68k-linux-gnu
/usr/lib/gcc/mips-linux-gnu
/usr/lib/gcc/mips64el-linux-gnuabi64
/usr/lib/gcc/mipsel-linux-gnu
/usr/lib/gcc/powerpc-linux-gnu
/usr/lib/gcc/powerpc-linux-gnuspe
/usr/lib/gcc/powerpc64-linux-gnu
/usr/lib/gcc/powerpc64le-linux-gnu
/usr/lib/gcc/s390x-linux-gnu
/usr/lib/gcc/sparc64-linux-gnu
/usr/lib/gcc/x86_64-linux-gnux32
/usr/lib/gcc/sh4-linux-gnu
/Library/Frameworks/iio.framework/
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBIIO DEFAULT_MSG LIBIIO_LIBRARIES LIBIIO_INCLUDE_DIRS)
MARK_AS_ADVANCED(LIBIIO_LIBRARIES LIBIIO_INCLUDE_DIRS)

View File

@ -5,7 +5,7 @@ GNSS-SDR.internal_fs_sps=6625000
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/archive/NT1065_GLONASS_L1_20160924_fs6625e6_if0e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource.filename=/media/dmiralles/Seagate Backup Plus Drive/GNSS Data/NT1065_GLONASS_L1_20160923_fs6625e6_if0e3_schar.bin ; <- PUT YOUR FILE HERE ; <- PUT YOUR FILE HERE
SignalSource.item_type=ibyte
SignalSource.sampling_frequency=6625000
SignalSource.samples=0
@ -25,11 +25,11 @@ Channel.signal=1G
Channels.in_acquisition=1
Channels_1G.count=5
;Channel0.satellite=24 ; k=
;Channel1.satellite=1 ; k=1
;Channel2.satellite=2 ; k=-4
;Channel3.satellite=20 ; k=-5
;Channel4.satellite=21 ; k=4
Channel0.satellite=24 ; k=
Channel1.satellite=1 ; k=1
Channel2.satellite=2 ; k=-4
Channel3.satellite=20 ; k=-5
Channel4.satellite=21 ; k=4
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1G.implementation=GLONASS_L1_CA_PCPS_Acquisition

View File

@ -0,0 +1,141 @@
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=6625000
Receiver.sources_count=2
;######### SIGNAL_SOURCE CONFIG ############
SignalSource0.implementation=File_Signal_Source
SignalSource0.filename=/media/dmiralles/Seagate Backup Plus Drive/GNSS Data/NT1065_L1_20160923_fs6625e6_if60e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource0.item_type=ibyte
SignalSource0.sampling_frequency=6625000
SignalSource0.samples=0
SignalSource0.dump=false;
SignalSource0.dump_filename=/archive/signal_glonass.bin
SignalSource1.implementation=File_Signal_Source
SignalSource1.filename=/media/dmiralles/Seagate Backup Plus Drive/GNSS Data/NT1065_GLONASS_L2_20160923_fs6625e6_if0e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource1.item_type=ibyte
SignalSource1.sampling_frequency=6625000
SignalSource1.samples=0
SignalSource1.dump=false;
SignalSource1.dump_filename=/archive/signal_glonass.bin
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner0.implementation=Signal_Conditioner
DataTypeAdapter0.implementation=Ibyte_To_Complex
InputFilter0.implementation=Freq_Xlating_Fir_Filter
InputFilter0.item_type=gr_complex
InputFilter0.output_item_type=gr_complex
InputFilter0.taps_item_type=float
InputFilter0.number_of_taps=5
InputFilter0.number_of_bands=2
InputFilter0.band1_begin=0.0
InputFilter0.band1_end=0.70
InputFilter0.band2_begin=0.80
InputFilter0.band2_end=1.0
InputFilter0.ampl1_begin=1.0
InputFilter0.ampl1_end=1.0
InputFilter0.ampl2_begin=0.0
InputFilter0.ampl2_end=0.0
InputFilter0.band1_error=1.0
InputFilter0.band2_error=1.0
InputFilter0.filter_type=bandpass
InputFilter0.grid_density=16
InputFilter0.sampling_frequency=6625000
InputFilter0.IF=60000
Resampler0.implementation=Direct_Resampler
Resampler0.sample_freq_in=6625000
Resampler0.sample_freq_out=6625000
Resampler0.item_type=gr_complex
SignalConditioner1.implementation=Signal_Conditioner
DataTypeAdapter1.implementation=Ibyte_To_Complex
InputFilter1.implementation=Pass_Through
InputFilter1.item_type=gr_complex
Resampler1.implementation=Pass_Through
Resampler1.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels.in_acquisition=1
Channels_2G.count=5
Channels_1C.count=5
;# Defining GLONASS satellites
Channel0.RF_channel_ID=0
Channel1.RF_channel_ID=0
Channel2.RF_channel_ID=0
Channel3.RF_channel_ID=0
Channel4.RF_channel_ID=0
Channel5.RF_channel_ID=1
Channel6.RF_channel_ID=1
Channel7.RF_channel_ID=1
Channel8.RF_channel_ID=1
Channel9.RF_channel_ID=1
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.threshold=0.0
Acquisition_1C.pfa=0.00001
Acquisition_1C.if=0
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=250
Acquisition_1C.dump=false;
Acquisition_1C.dump_filename=/archive/gps_acquisition.dat
;Acquisition_1C.coherent_integration_time_ms=10
Acquisition_2G.implementation=GLONASS_L2_CA_PCPS_Acquisition
Acquisition_2G.item_type=gr_complex
Acquisition_2G.threshold=0.0
Acquisition_2G.pfa=0.00001
Acquisition_2G.if=0
Acquisition_2G.doppler_max=10000
Acquisition_2G.doppler_step=250
Acquisition_2G.dump=false;
Acquisition_2G.dump_filename=/archive/glo_acquisition.dat
;Acquisition_2G.coherent_integration_time_ms=10
;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.if=0
Tracking_1C.early_late_space_chips=0.5
Tracking_1C.pll_bw_hz=20.0;
Tracking_1C.dll_bw_hz=2.0;
Tracking_1C.dump=false;
Tracking_1C.dump_filename=/archive/gps_tracking_ch_
Tracking_2G.implementation=GLONASS_L2_CA_DLL_PLL_Tracking
Tracking_2G.item_type=gr_complex
Tracking_2G.if=0
Tracking_2G.early_late_space_chips=0.5
Tracking_2G.pll_bw_hz=25.0;
Tracking_2G.dll_bw_hz=2.0;
Tracking_2G.dump=false;
Tracking_2G.dump_filename=/archive/glo_tracking_ch_
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_2G.implementation=GLONASS_L2_CA_Telemetry_Decoder
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false;
Observables.dump_filename=/archive/gnss_observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.trop_model=Saastamoinen
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.rtcm_tcp_port=2101
PVT.rtcm_MT1019_rate_ms=5000
PVT.rtcm_MT1045_rate_ms=5000
PVT.rtcm_MT1097_rate_ms=1000
PVT.rtcm_MT1077_rate_ms=1000
PVT.rinex_version=2

View File

@ -0,0 +1,142 @@
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=6625000
Receiver.sources_count=2
;######### SIGNAL_SOURCE CONFIG ############
SignalSource0.implementation=File_Signal_Source
SignalSource0.filename=/archive/NT1065_L2_20160923_fs6625e6_if60e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource0.item_type=ibyte
SignalSource0.sampling_frequency=6625000
SignalSource0.samples=0
SignalSource0.dump=false;
SignalSource0.dump_filename=/archive/signal_glonass.bin
SignalSource1.implementation=File_Signal_Source
SignalSource1.filename=/archive/NT1065_GLONASS_L2_20160923_fs6625e6_if0e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource1.item_type=ibyte
SignalSource1.sampling_frequency=6625000
SignalSource1.samples=0
SignalSource1.dump=false;
SignalSource1.dump_filename=/archive/signal_glonass.bin
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner0.implementation=Signal_Conditioner
DataTypeAdapter0.implementation=Ibyte_To_Complex
InputFilter0.implementation=Freq_Xlating_Fir_Filter
InputFilter0.item_type=gr_complex
InputFilter0.output_item_type=gr_complex
InputFilter0.taps_item_type=float
InputFilter0.number_of_taps=5
InputFilter0.number_of_bands=2
InputFilter0.band1_begin=0.0
InputFilter0.band1_end=0.70
InputFilter0.band2_begin=0.80
InputFilter0.band2_end=1.0
InputFilter0.ampl1_begin=1.0
InputFilter0.ampl1_end=1.0
InputFilter0.ampl2_begin=0.0
InputFilter0.ampl2_end=0.0
InputFilter0.band1_error=1.0
InputFilter0.band2_error=1.0
InputFilter0.filter_type=bandpass
InputFilter0.grid_density=16
InputFilter0.sampling_frequency=6625000
InputFilter0.IF=60000
Resampler0.implementation=Pass_Through
Resampler0.item_type=gr_complex
SignalConditioner1.implementation=Signal_Conditioner
DataTypeAdapter1.implementation=Ibyte_To_Complex
InputFilter1.implementation=Pass_Through
InputFilter1.item_type=gr_complex
Resampler1.implementation=Pass_Through
Resampler1.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channels.in_acquisition=5
Channels_2S.count=5
Channels_2G.count=5
;# Defining GLONASS satellites
Channel0.RF_channel_ID=0
Channel0.signal=2S
Channel1.RF_channel_ID=0
Channel1.signal=2S
Channel2.RF_channel_ID=0
Channel2.signal=2S
Channel3.RF_channel_ID=0
Channel3.signal=2S
Channel4.RF_channel_ID=0
Channel4.signal=2S
Channel5.RF_channel_ID=1
Channel6.RF_channel_ID=1
Channel7.RF_channel_ID=1
Channel8.RF_channel_ID=1
Channel9.RF_channel_ID=1
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_2S.implementation=GPS_L2_M_PCPS_Acquisition
Acquisition_2S.item_type=gr_complex
Acquisition_2S.threshold=0.0
Acquisition_2S.pfa=0.00001
Acquisition_2S.if=0
Acquisition_2S.doppler_max=10000
Acquisition_2S.doppler_step=60
Acquisition_2S.max_dwells=1
Acquisition_2G.implementation=GLONASS_L2_CA_PCPS_Acquisition
Acquisition_2G.item_type=gr_complex
Acquisition_2G.threshold=0.0
Acquisition_2G.pfa=0.00001
Acquisition_2G.if=0
Acquisition_2G.doppler_max=10000
Acquisition_2G.doppler_step=250
Acquisition_2G.dump=false;
Acquisition_2G.dump_filename=/archive/glo_acquisition.dat
;######### TRACKING GLOBAL CONFIG ############
Tracking_2S.implementation=GPS_L2_M_DLL_PLL_Tracking
Tracking_2S.item_type=gr_complex
Tracking_2S.if=0
Tracking_2S.early_late_space_chips=0.5
Tracking_2S.pll_bw_hz=2.0;
Tracking_2S.dll_bw_hz=0.250;
Tracking_2S.order=2;
Tracking_2S.dump=false;
Tracking_2S.dump_filename=/archive/gps_tracking_ch_
Tracking_2G.implementation=GLONASS_L2_CA_DLL_PLL_Tracking
Tracking_2G.item_type=gr_complex
Tracking_2G.if=0
Tracking_2G.early_late_space_chips=0.5
Tracking_2G.pll_bw_hz=25.0;
Tracking_2G.dll_bw_hz=3.0;
Tracking_2G.dump=false;
Tracking_2G.dump_filename=/archive/glo_tracking_ch_
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_2S.implementation=GPS_L2C_Telemetry_Decoder
TelemetryDecoder_2G.implementation=GLONASS_L2_CA_Telemetry_Decoder
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false;
Observables.dump_filename=/archive/gnss_observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.trop_model=Saastamoinen
PVT.flag_rtcm_server=true
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.rtcm_tcp_port=2101
PVT.rtcm_MT1019_rate_ms=5000
PVT.rtcm_MT1045_rate_ms=5000
PVT.rtcm_MT1097_rate_ms=1000
PVT.rtcm_MT1077_rate_ms=1000
PVT.rinex_version=3

View File

@ -0,0 +1,73 @@
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=6625000
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/media/dmiralles/Seagate Backup Plus Drive/GNSS Data/NT1065_GLONASS_L2_20160831_fs6625e6_60e3_schar_1m.bin ; <- PUT YOUR FILE HERE
SignalSource.item_type=ibyte
SignalSource.sampling_frequency=6625000
SignalSource.samples=0
SignalSource.dump=false;
SignalSource.dump_filename=/archive/signal_glonass.bin
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Signal_Conditioner
DataTypeAdapter.implementation=Ibyte_To_Complex
InputFilter.implementation=Pass_Through
InputFilter.item_type=gr_complex
Resampler.implementation=Pass_Through
Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channel.signal=2G
Channels.in_acquisition=1
Channels_2G.count=5
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_2G.implementation=GLONASS_L2_CA_PCPS_Acquisition
Acquisition_2G.item_type=gr_complex
Acquisition_2G.threshold=0.0
Acquisition_2G.pfa=0.0001
Acquisition_2G.if=0
Acquisition_2G.doppler_max=10000
Acquisition_2G.doppler_step=250
Acquisition_2G.dump=true;
Acquisition_2G.dump_filename=/archive/glo_acquisition.dat
;Acquisition_2G.coherent_integration_time_ms=1
;Acquisition_2G.max_dwells = 5
;######### TRACKING GLOBAL CONFIG ############
Tracking_2G.implementation=GLONASS_L2_CA_DLL_PLL_Tracking
Tracking_2G.item_type=gr_complex
Tracking_2G.if=0
Tracking_2G.early_late_space_chips=0.5
Tracking_2G.pll_bw_hz=20.0;
Tracking_2G.dll_bw_hz=2.0;
Tracking_2G.dump=true;
Tracking_2G.dump_filename=/archive/glo_tracking_ch_
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_2G.implementation=GLONASS_L2_CA_Telemetry_Decoder
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=true;
Observables.dump_filename=/archive/glo_observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.trop_model=Saastamoinen
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.rtcm_tcp_port=2101
PVT.rtcm_MT1019_rate_ms=5000
PVT.rtcm_MT1045_rate_ms=5000
PVT.rtcm_MT1097_rate_ms=1000
PVT.rtcm_MT1077_rate_ms=1000
PVT.rinex_version=2

View File

@ -0,0 +1,83 @@
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=6625000
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/archive/NT1065_GLONASS_L1_20160923_fs6625e6_if0e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource.item_type=ibyte
SignalSource.sampling_frequency=6625000
SignalSource.samples=0
SignalSource.dump=false;
SignalSource.dump_filename=/archive/signal_glonass.bin
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner.implementation=Signal_Conditioner
DataTypeAdapter.implementation=Ibyte_To_Complex
InputFilter.implementation=Pass_Through
InputFilter.item_type=gr_complex
Resampler.implementation=Pass_Through
Resampler.item_type=gr_complex
;######### CHANNELS GLOBAL CONFIG ############
Channel.signal=1G
Channels.in_acquisition=2
Channels_1G.count=8
;Channel0.satellite=24 ; k=2
;Channel1.satellite=1 ; k=1
;Channel2.satellite=2 ; k=-4
;Channel3.satellite=20 ; k=-5
;Channel4.satellite=21 ; k=4
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1G.implementation=GLONASS_L1_CA_PCPS_Acquisition
Acquisition_1G.item_type=gr_complex
Acquisition_1G.threshold=0.0
Acquisition_1G.pfa=0.0001
Acquisition_1G.if=0
Acquisition_1G.doppler_max=10000
Acquisition_1G.doppler_step=250
Acquisition_1G.dump=false;
Acquisition_1G.dump_filename=/archive/glo_acquisition.dat
;Acquisition_1G.coherent_integration_time_ms=1
;Acquisition_1G.max_dwells = 5
;######### TRACKING GLOBAL CONFIG ############
Tracking_1G.implementation=GLONASS_L1_CA_DLL_PLL_C_Aid_Tracking
Tracking_1G.item_type=gr_complex
Tracking_1G.if=0
Tracking_1G.early_late_space_chips=0.5
Tracking_1G.pll_bw_hz=40.0;
Tracking_1G.dll_bw_hz=3.0;
Tracking_1G.pll_bw_narrow_hz = 25.0;
Tracking_1G.dll_bw_narrow_hz = 2.0;
Tracking_1G.extend_correlation_ms = 1;
Tracking_1G.dump=false;
Tracking_1G.dump_filename=/archive/glo_tracking_ch_
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1G.implementation=GLONASS_L1_CA_Telemetry_Decoder
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=/archive/glo_observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.trop_model=Saastamoinen
PVT.flag_rtcm_server=true
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.rtcm_tcp_port=2101
PVT.rtcm_MT1019_rate_ms=5000
PVT.rtcm_MT1045_rate_ms=5000
PVT.rtcm_MT1097_rate_ms=1000
PVT.rtcm_MT1077_rate_ms=1000
PVT.rinex_version=2

View File

@ -0,0 +1,112 @@
; You can define your own receiver and invoke it by doing
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf
;
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [Sps].
GNSS-SDR.internal_fs_sps=7000000
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=Fmcomms2_Signal_Source
SignalSource.item_type=gr_complex
SignalSource.device_address=192.168.0.4
SignalSource.sampling_frequency=7000000
SignalSource.freq=1575420000
SignalSource.bandwidth=4000000
SignalSource.RF_channels=2
SignalSource.rx1_enable=true
SignalSource.rx2_enable=true
SignalSource.gain_mode_rx1=slow_attack
SignalSource.gain_mode_rx2=slow_attack
SignalSource.rf_port_select=A_BALANCED
SignalSource.gain_rx1=64
SignalSource.gain_rx2=64
SignalSource.samples=0
SignalSource.repeat=false
SignalSource.dump=false
SignalSource.dump_filename=../data/signal_source.dat
SignalSource.enable_throttle_control=false
SignalSource.enable_dds_lo=false
SignalSource.freq_rf_tx_hz=1260000000
SignalSource.freq_dds_tx_hz=1000
SignalSource.scale_dds_dbfs=0.0
SignalSource.phase_dds_deg=0.0
SignalSource.tx_attenuation_db=0.0
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner0.implementation=Pass_Through
SignalConditioner1.implementation=Pass_Through
;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=8
Channels.in_acquisition=1
;# CHANNEL CONNECTION
Channel0.RF_channel_ID=0
Channel0.signal=1C
Channel1.RF_channel_ID=0
Channel1.signal=1C
Channel2.RF_channel_ID=0
Channel2.signal=1C
Channel3.RF_channel_ID=0
Channel3.signal=1C
Channel4.RF_channel_ID=1
Channel4.signal=1C
Channel5.RF_channel_ID=1
Channel5.signal=1C
Channel6.RF_channel_ID=1
Channel6.signal=1C
Channel7.RF_channel_ID=1
Channel7.signal=1C
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.threshold=20
Acquisition_1C.use_CFAR_algorithm=false
Acquisition_1C.blocking=true
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=250
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat
;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.dump=false
Tracking_1C.dump_filename=./tracking_ch_
Tracking_1C.pll_bw_hz=35.0;
Tracking_1C.dll_bw_hz=2.0;
Tracking_1C.early_late_space_chips=0.5;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
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.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

View File

@ -129,7 +129,7 @@ INLINE_INHERITED_MEMB = NO
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = YES
FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
@ -703,7 +703,7 @@ EXAMPLE_RECURSIVE = NO
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH = @top_srcdir@/docs/doxygen/images/
IMAGE_PATH = @top_srcdir@/docs/doxygen/images/
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@ -791,7 +791,7 @@ REFERENCES_LINK_SOURCE = YES
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
@ -901,7 +901,7 @@ HTML_COLORSTYLE_GAMMA = 80
# page will contain the date and time when the page was generated. Setting
# this to NO can help when comparing the output of multiple runs.
HTML_TIMESTAMP = YES
HTML_TIMESTAMP = NO
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
# files or namespaces will be aligned in HTML using tables. If set to
@ -1164,7 +1164,7 @@ MATHJAX_EXTENSIONS =
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box
# for the HTML output. The underlying search engine uses javascript
@ -1677,7 +1677,7 @@ DOT_FONTSIZE = 10
# different font using DOT_FONTNAME you can set the path where dot
# can find it using this tag.
DOT_FONTPATH =
DOT_FONTPATH =
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and

View File

@ -178,40 +178,44 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
int gal_E5a_count = configuration->property("Channels_5X.count", 0);
int gal_E5b_count = configuration->property("Channels_7X.count", 0);
int glo_1G_count = configuration->property("Channels_1G.count", 0);
int glo_2G_count = configuration->property("Channels_2G.count", 0);
unsigned int type_of_receiver = 0;
// *******************WARNING!!!!!!!***********
// GPS L5 only configurable for single frequency, single system at the moment!!!!!!
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 1;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 2;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 3;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 4;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 5;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 6;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 1;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 2;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 3;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 4;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 5;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 6;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 7;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 7;
//if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 8;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 9;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 10;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 11;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 12;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 9;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 10;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 11;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 12;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 13;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 14;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 15;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 14;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 15;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 16;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 17;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0)) type_of_receiver = 18;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 17;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 18;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 19;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 20;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0)) type_of_receiver = 21;
if ((gps_1C_count != 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count == 0)) type_of_receiver = 21;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count = 0)) type_of_receiver = 22;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 23;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2R_count != 0)) type_of_receiver = 24;
//if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_1G_count != 0)) type_of_receiver = 25;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 26;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 27;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 28;
if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 24;
if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count != 0)) type_of_receiver = 25;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 26;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 27;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_2G_count == 0)) type_of_receiver = 28;
if ((gps_1C_count != 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 29;
if ((gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 30;
if ((gps_1C_count == 0) && (gps_2S_count != 0) && (gps_L5_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count == 0) && (glo_2G_count != 0)) type_of_receiver = 31;
//RTKLIB PVT solver options
// Settings 1
int positioning_mode = -1;
@ -236,9 +240,9 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
int num_bands = 0;
if ((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) num_bands = 1;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && (gps_2S_count > 0)) num_bands = 2;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gps_2S_count > 0) || (glo_2G_count > 0))) num_bands = 2;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0))) num_bands = 2;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && (gps_2S_count > 0) && ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0))) num_bands = 3;
if (((gps_1C_count > 0) || (gal_1B_count > 0) || (glo_1G_count > 0)) && ((gps_2S_count > 0) || (glo_2G_count > 0)) && ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0))) num_bands = 3;
int number_of_frequencies = configuration->property(role + ".num_bands", num_bands); /* (1:L1, 2:L1+L2, 3:L1+L2+L5) */
if ((number_of_frequencies < 1) || (number_of_frequencies > 3))
@ -321,7 +325,7 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
int nsys = 0;
if ((gps_1C_count > 0) || (gps_2S_count > 0) || (gps_L5_count > 0)) nsys += SYS_GPS;
if ((gal_1B_count > 0) || (gal_E5a_count > 0) || (gal_E5b_count > 0)) nsys += SYS_GAL;
if ((glo_1G_count > 0)) nsys += SYS_GLO;
if ((glo_1G_count > 0) || (glo_2G_count > 0)) nsys += SYS_GLO;
int navigation_system = configuration->property(role + ".navigation_system", nsys); /* (SYS_XXX) see src/algorithms/libs/rtklib/rtklib.h */
if ((navigation_system < 1) || (navigation_system > 255)) /* GPS: 1 SBAS: 2 GPS+SBAS: 3 Galileo: 8 Galileo+GPS: 9 GPS+SBAS+Galileo: 11 All: 255 */
{

View File

@ -712,6 +712,9 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
* 26 | GPS L1 C/A + GLONASS L1 C/A
* 27 | Galileo E1B + GLONASS L1 C/A
* 28 | GPS L2C + GLONASS L1 C/A
* 29 | GPS L1 C/A + GLONASS L2 C/A
* 30 | Galileo E1B + GLONASS L2 C/A
* 31 | GPS L2C + GLONASS L2 C/A
*/
// ####################### RINEX FILES #################
@ -913,6 +916,43 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
b_rinex_header_written = true; // do not write header anymore
}
}
if (type_of_rx == 29) // GPS L1 C/A + GLONASS L2 C/A
{
if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) && (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend()))
{
std::string glo_signal("2G");
rp->rinex_obs_header(rp->obsFile, gps_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, glo_signal);
if (d_rinex_version == 3)
rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac);
if (d_rinex_version == 2)
{
rp->rinex_nav_header(rp->navFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model);
rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, glonass_gnav_ephemeris_iter->second);
}
b_rinex_header_written = true; // do not write header anymore
}
}
if (type_of_rx == 30) // Galileo E1B + GLONASS L2 C/A
{
if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) && (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend()))
{
std::string glo_signal("2G");
std::string gal_signal("1B");
rp->rinex_obs_header(rp->obsFile, galileo_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, glo_signal, gal_signal);
rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->galileo_iono, d_ls_pvt->galileo_utc_model, d_ls_pvt->galileo_almanac, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac);
b_rinex_header_written = true; // do not write header anymore
}
}
if (type_of_rx == 31) // GPS L2C + GLONASS L2 C/A
{
if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) && (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.cend()))
{
std::string glo_signal("2G");
rp->rinex_obs_header(rp->obsFile, gps_cnav_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, glo_signal);
rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_cnav_iono, d_ls_pvt->gps_cnav_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac);
b_rinex_header_written = true; // do not write header anymore
}
}
}
if (b_rinex_header_written) // The header is already written, we can now log the navigation message data
{
@ -968,6 +1008,24 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
{
rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_cnav_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map);
}
if (type_of_rx == 29) // GPS L1 C/A + GLONASS L2 C/A
{
if (d_rinex_version == 3)
rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map);
if (d_rinex_version == 2)
{
rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_ephemeris_map);
rp->log_rinex_nav(rp->navGloFile, d_ls_pvt->glonass_gnav_ephemeris_map);
}
}
if (type_of_rx == 30) // Galileo E1B + GLONASS L2 C/A
{
rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->galileo_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map);
}
if (type_of_rx == 31) // GPS L2C + GLONASS L2 C/A
{
rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_cnav_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map);
}
}
galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin();
gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin();
@ -1185,6 +1243,45 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
b_rinex_header_updated = true; // do not write header anymore
}
}
if (type_of_rx == 29) // GPS L1 C/A + GLONASS L2 C/A
{
if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) && (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end()))
{
rp->log_rinex_obs(rp->obsFile, gps_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map);
}
if (!b_rinex_header_updated && (d_ls_pvt->gps_utc_model.d_A0 != 0))
{
rp->update_obs_header(rp->obsFile, d_ls_pvt->gps_utc_model);
rp->update_nav_header(rp->navMixFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac);
b_rinex_header_updated = true; // do not write header anymore
}
}
if (type_of_rx == 30) // Galileo E1B + GLONASS L2 C/A
{
if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) && (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end()))
{
rp->log_rinex_obs(rp->obsFile, galileo_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map);
}
if (!b_rinex_header_updated && (d_ls_pvt->galileo_utc_model.A0_6 != 0))
{
rp->update_obs_header(rp->obsFile, d_ls_pvt->galileo_utc_model);
rp->update_nav_header(rp->navMixFile, d_ls_pvt->galileo_iono, d_ls_pvt->galileo_utc_model, d_ls_pvt->galileo_almanac, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac);
b_rinex_header_updated = true; // do not write header anymore
}
}
if (type_of_rx == 31) // GPS L2C + GLONASS L2 C/A
{
if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) && (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.end()))
{
rp->log_rinex_obs(rp->obsFile, gps_cnav_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map);
}
if (!b_rinex_header_updated && (d_ls_pvt->gps_cnav_utc_model.d_A0 != 0))
{
rp->update_obs_header(rp->obsFile, d_ls_pvt->gps_cnav_utc_model);
rp->update_nav_header(rp->navMixFile, d_ls_pvt->gps_cnav_iono, d_ls_pvt->gps_cnav_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac);
b_rinex_header_updated = true; // do not write header anymore
}
}
}
}
@ -1466,6 +1563,136 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
}
}
}
if (type_of_rx == 29) // GPS L1 C/A + GLONASS L2 C/A
{
if (flag_write_RTCM_1019_output == true)
{
for (gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin(); gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend(); gps_ephemeris_iter++)
{
d_rtcm_printer->Print_Rtcm_MT1019(gps_ephemeris_iter->second);
}
}
if (flag_write_RTCM_1020_output == true)
{
for (std::map<int, Glonass_Gnav_Ephemeris>::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++)
{
d_rtcm_printer->Print_Rtcm_MT1020(glonass_gnav_ephemeris_iter->second, d_ls_pvt->glonass_gnav_utc_model);
}
}
if (flag_write_RTCM_MSM_output == true)
{
//gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.end();
//galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.end();
unsigned int i = 0;
for (gnss_observables_iter = gnss_observables_map.begin(); gnss_observables_iter != gnss_observables_map.end(); gnss_observables_iter++)
{
std::string system(&gnss_observables_iter->second.System, 1);
if (gps_channel == 0)
{
if (system.compare("G") == 0)
{
// This is a channel with valid GPS signal
gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend())
{
gps_channel = i;
}
}
}
if (glo_channel == 0)
{
if (system.compare("R") == 0)
{
glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend())
{
glo_channel = i;
}
}
}
i++;
}
if (flag_write_RTCM_MSM_output == true)
{
if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend())
{
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
}
if (flag_write_RTCM_MSM_output == true)
{
if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend())
{
d_rtcm_printer->Print_Rtcm_MSM(7, gps_ephemeris_iter->second, {}, {}, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
}
}
}
if (type_of_rx == 30) // GLONASS L2 C/A + Galileo E1B
{
if (flag_write_RTCM_1020_output == true)
{
for (std::map<int, Glonass_Gnav_Ephemeris>::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++)
{
d_rtcm_printer->Print_Rtcm_MT1020(glonass_gnav_ephemeris_iter->second, d_ls_pvt->glonass_gnav_utc_model);
}
}
if (flag_write_RTCM_1045_output == true)
{
for (galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin(); galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend(); galileo_ephemeris_iter++)
{
d_rtcm_printer->Print_Rtcm_MT1045(galileo_ephemeris_iter->second);
}
}
if (flag_write_RTCM_MSM_output == true)
{
//gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.end();
//galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.end();
unsigned int i = 0;
for (gnss_observables_iter = gnss_observables_map.cbegin(); gnss_observables_iter != gnss_observables_map.cend(); gnss_observables_iter++)
{
std::string system(&gnss_observables_iter->second.System, 1);
if (gal_channel == 0)
{
if (system.compare("E") == 0)
{
// This is a channel with valid GPS signal
galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend())
{
gal_channel = i;
}
}
}
if (glo_channel == 0)
{
if (system.compare("R") == 0)
{
glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end())
{
glo_channel = i;
}
}
}
i++;
}
if (flag_write_RTCM_MSM_output == true)
{
if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end())
{
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, galileo_ephemeris_iter->second, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
}
if (flag_write_RTCM_MSM_output == true)
{
if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end())
{
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
}
}
}
}
if (!b_rtcm_writing_started) // the first time
@ -1704,8 +1931,124 @@ int rtklib_pvt_cc::work(int noutput_items, gr_vector_const_void_star& input_item
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
}
if (type_of_rx == 29) // GPS L1 C/A + GLONASS L2 C/A
{
if (d_rtcm_MT1019_rate_ms != 0) // allows deactivating messages by setting rate = 0
{
for (gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin(); gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend(); gps_ephemeris_iter++)
{
d_rtcm_printer->Print_Rtcm_MT1019(gps_ephemeris_iter->second);
}
}
if (d_rtcm_MT1020_rate_ms != 0) // allows deactivating messages by setting rate = 0
{
for (std::map<int, Glonass_Gnav_Ephemeris>::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++)
{
d_rtcm_printer->Print_Rtcm_MT1020(glonass_gnav_ephemeris_iter->second, d_ls_pvt->glonass_gnav_utc_model);
}
}
//gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.end();
//galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.end();
unsigned int i = 0;
for (gnss_observables_iter = gnss_observables_map.cbegin(); gnss_observables_iter != gnss_observables_map.cend(); gnss_observables_iter++)
{
std::string system(&gnss_observables_iter->second.System, 1);
if (gps_channel == 0)
{
if (system.compare("G") == 0)
{
// This is a channel with valid GPS signal
gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend())
{
gps_channel = i;
}
}
}
if (glo_channel == 0)
{
if (system.compare("R") == 0)
{
glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend())
{
glo_channel = i;
}
}
}
i++;
}
if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend())
{
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.cend())
{
d_rtcm_printer->Print_Rtcm_MSM(7, gps_ephemeris_iter->second, {}, {}, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
b_rtcm_writing_started = true;
}
if (type_of_rx == 30) // GLONASS L2 C/A + Galileo E1B
{
if (d_rtcm_MT1020_rate_ms != 0) // allows deactivating messages by setting rate = 0
{
for (std::map<int, Glonass_Gnav_Ephemeris>::const_iterator glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.cbegin(); glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend(); glonass_gnav_ephemeris_iter++)
{
d_rtcm_printer->Print_Rtcm_MT1020(glonass_gnav_ephemeris_iter->second, d_ls_pvt->glonass_gnav_utc_model);
}
}
if (d_rtcm_MT1045_rate_ms != 0) // allows deactivating messages by setting rate = 0
{
for (galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin(); galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend(); galileo_ephemeris_iter++)
{
d_rtcm_printer->Print_Rtcm_MT1045(galileo_ephemeris_iter->second);
}
}
unsigned int i = 0;
for (gnss_observables_iter = gnss_observables_map.cbegin(); gnss_observables_iter != gnss_observables_map.cend(); gnss_observables_iter++)
{
std::string system(&gnss_observables_iter->second.System, 1);
if (gal_channel == 0)
{
if (system.compare("E") == 0)
{
// This is a channel with valid GPS signal
galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend())
{
gal_channel = i;
}
}
}
if (glo_channel == 0)
{
if (system.compare("R") == 0)
{
glonass_gnav_ephemeris_iter = d_ls_pvt->glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end())
{
glo_channel = i;
}
}
}
i++;
}
if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end())
{
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, galileo_ephemeris_iter->second, {}, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end())
{
d_rtcm_printer->Print_Rtcm_MSM(7, {}, {}, {}, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map, 0, 0, 0, 0, 0);
}
}
}
}
catch (const boost::exception& ex)
{
std::cout << "RTCM boost exception: " << boost::diagnostic_information(ex) << std::endl;

View File

@ -57,7 +57,7 @@
#include "glonass_gnav_navigation_message.h"
#include "GPS_L1_CA.h"
#include "Galileo_E1.h"
#include "GLONASS_L1_CA.h"
#include "GLONASS_L1_L2_CA.h"
#include "gnss_synchro.h"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <string>

View File

@ -55,7 +55,7 @@
#include "rtklib_conversions.h"
#include "GPS_L1_CA.h"
#include "Galileo_E1.h"
#include "GLONASS_L1_CA.h"
#include "GLONASS_L1_L2_CA.h"
#include <glog/logging.h>

View File

@ -33,6 +33,7 @@ set(ACQ_ADAPTER_SOURCES
galileo_e5a_noncoherent_iq_acquisition_caf.cc
galileo_e5a_pcps_acquisition.cc
glonass_l1_ca_pcps_acquisition.cc
glonass_l2_ca_pcps_acquisition.cc
)
if(ENABLE_FPGA)

View File

@ -34,8 +34,8 @@
#include "glonass_l1_ca_pcps_acquisition.h"
#include "configuration_interface.h"
#include "glonass_l1_signal_processing.h"
#include "GLONASS_L1_CA.h"
#include "gnss_sdr_flags.h"
#include "GLONASS_L1_L2_CA.h"
#include <boost/math/distributions/exponential.hpp>
#include <glog/logging.h>

View File

@ -0,0 +1,312 @@
/*!
* \file glonass_l2_ca_pcps_acquisition.cc
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* Glonass L2 C/A signals
* \author Damian Miralles, 2018, dmiralles2009@gmail.com
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "glonass_l2_ca_pcps_acquisition.h"
#include "configuration_interface.h"
#include "glonass_l2_signal_processing.h"
#include "GLONASS_L1_L2_CA.h"
#include "gnss_sdr_flags.h"
#include <boost/math/distributions/exponential.hpp>
#include <glog/logging.h>
using google::LogMessage;
GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
configuration_ = configuration;
std::string default_item_type = "gr_complex";
std::string default_dump_filename = "./data/acquisition.dat";
DLOG(INFO) << "role " << role;
item_type_ = configuration_->property(role + ".item_type", default_item_type);
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
if_ = configuration_->property(role + ".if", 0);
dump_ = configuration_->property(role + ".dump", false);
blocking_ = configuration_->property(role + ".blocking", true);
doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1);
bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
max_dwells_ = configuration_->property(role + ".max_dwells", 1);
dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
//--- Find number of samples per spreading code -------------------------
code_length_ = round(fs_in_ / (GLONASS_L2_CA_CODE_RATE_HZ / GLONASS_L2_CA_CODE_LENGTH_CHIPS));
vector_length_ = code_length_ * sampled_ms_;
if (bit_transition_flag_)
{
vector_length_ *= 2;
}
code_ = new gr_complex[vector_length_];
if (item_type_.compare("cshort") == 0)
{
item_size_ = sizeof(lv_16sc_t);
}
else
{
item_size_ = sizeof(gr_complex);
}
acquisition_ = pcps_make_acquisition(sampled_ms_, max_dwells_,
doppler_max_, if_, fs_in_, code_length_, code_length_,
bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_, item_size_);
DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")";
stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_);
DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")";
if (item_type_.compare("cbyte") == 0)
{
cbyte_to_float_x2_ = make_complex_byte_to_float_x2();
float_to_complex_ = gr::blocks::float_to_complex::make();
}
channel_ = 0;
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = 0;
}
GlonassL2CaPcpsAcquisition::~GlonassL2CaPcpsAcquisition()
{
delete[] code_;
}
void GlonassL2CaPcpsAcquisition::set_channel(unsigned int channel)
{
channel_ = channel;
acquisition_->set_channel(channel_);
}
void GlonassL2CaPcpsAcquisition::set_threshold(float threshold)
{
float pfa = configuration_->property(role_ + ".pfa", 0.0);
if (pfa == 0.0)
{
threshold_ = threshold;
}
else
{
threshold_ = calculate_threshold(pfa);
}
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_;
acquisition_->set_threshold(threshold_);
}
void GlonassL2CaPcpsAcquisition::set_doppler_max(unsigned int doppler_max)
{
doppler_max_ = doppler_max;
acquisition_->set_doppler_max(doppler_max_);
}
void GlonassL2CaPcpsAcquisition::set_doppler_step(unsigned int doppler_step)
{
doppler_step_ = doppler_step;
acquisition_->set_doppler_step(doppler_step_);
}
void GlonassL2CaPcpsAcquisition::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
{
gnss_synchro_ = gnss_synchro;
acquisition_->set_gnss_synchro(gnss_synchro_);
}
signed int GlonassL2CaPcpsAcquisition::mag()
{
return acquisition_->mag();
}
void GlonassL2CaPcpsAcquisition::init()
{
acquisition_->init();
set_local_code();
}
void GlonassL2CaPcpsAcquisition::set_local_code()
{
std::complex<float>* code = new std::complex<float>[code_length_];
glonass_l2_ca_code_gen_complex_sampled(code, /* gnss_synchro_->PRN,*/ fs_in_, 0);
for (unsigned int i = 0; i < sampled_ms_; i++)
{
memcpy(&(code_[i * code_length_]), code,
sizeof(gr_complex) * code_length_);
}
acquisition_->set_local_code(code_);
delete[] code;
}
void GlonassL2CaPcpsAcquisition::reset()
{
acquisition_->set_active(true);
}
void GlonassL2CaPcpsAcquisition::set_state(int state)
{
acquisition_->set_state(state);
}
float GlonassL2CaPcpsAcquisition::calculate_threshold(float pfa)
{
//Calculate the threshold
unsigned int frequency_bins = 0;
/*
for (int doppler = (int)(-doppler_max_); doppler <= (int)doppler_max_; doppler += doppler_step_)
{
frequency_bins++;
}
*/
frequency_bins = (2 * doppler_max_ + doppler_step_) / doppler_step_;
DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
unsigned int ncells = vector_length_ * frequency_bins;
double exponent = 1 / static_cast<double>(ncells);
double val = pow(1.0 - pfa, exponent);
double lambda = static_cast<double>(vector_length_);
boost::math::exponential_distribution<double> mydist(lambda);
float threshold = static_cast<float>(quantile(mydist, val));
return threshold;
}
void GlonassL2CaPcpsAcquisition::connect(gr::top_block_sptr top_block)
{
if (item_type_.compare("gr_complex") == 0)
{
top_block->connect(stream_to_vector_, 0, acquisition_, 0);
}
else if (item_type_.compare("cshort") == 0)
{
top_block->connect(stream_to_vector_, 0, acquisition_, 0);
}
else if (item_type_.compare("cbyte") == 0)
{
top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
top_block->connect(float_to_complex_, 0, stream_to_vector_, 0);
top_block->connect(stream_to_vector_, 0, acquisition_, 0);
}
else
{
LOG(WARNING) << item_type_ << " unknown acquisition item type";
}
}
void GlonassL2CaPcpsAcquisition::disconnect(gr::top_block_sptr top_block)
{
if (item_type_.compare("gr_complex") == 0)
{
top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
}
else if (item_type_.compare("cshort") == 0)
{
top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
}
else if (item_type_.compare("cbyte") == 0)
{
// Since a byte-based acq implementation is not available,
// we just convert cshorts to gr_complex
top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0);
top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
}
else
{
LOG(WARNING) << item_type_ << " unknown acquisition item type";
}
}
gr::basic_block_sptr GlonassL2CaPcpsAcquisition::get_left_block()
{
if (item_type_.compare("gr_complex") == 0)
{
return stream_to_vector_;
}
else if (item_type_.compare("cshort") == 0)
{
return stream_to_vector_;
}
else if (item_type_.compare("cbyte") == 0)
{
return cbyte_to_float_x2_;
}
else
{
LOG(WARNING) << item_type_ << " unknown acquisition item type";
return nullptr;
}
}
gr::basic_block_sptr GlonassL2CaPcpsAcquisition::get_right_block()
{
return acquisition_;
}

View File

@ -0,0 +1,166 @@
/*!
* \file glonass_l2_ca_pcps_acquisition.h
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* Glonass L2 C/A signals
* \author Damian Miralles, 2018, dmiralles2009@gmail.com
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GLONASS_L2_CA_PCPS_ACQUISITION_H_
#define GNSS_SDR_GLONASS_L2_CA_PCPS_ACQUISITION_H_
#include "acquisition_interface.h"
#include "gnss_synchro.h"
#include "pcps_acquisition.h"
#include "complex_byte_to_float_x2.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <gnuradio/blocks/float_to_complex.h>
#include <string>
class ConfigurationInterface;
/*!
* \brief This class adapts a PCPS acquisition block to an AcquisitionInterface
* for GLONASS L2 C/A signals
*/
class GlonassL2CaPcpsAcquisition : public AcquisitionInterface
{
public:
GlonassL2CaPcpsAcquisition(ConfigurationInterface* configuration,
std::string role, unsigned int in_streams,
unsigned int out_streams);
virtual ~GlonassL2CaPcpsAcquisition();
inline std::string role() override
{
return role_;
}
/*!
* \brief Returns "GLONASS_L2_CA_PCPS_Acquisition"
*/
inline std::string implementation() override
{
return "GLONASS_L2_CA_PCPS_Acquisition";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and
* tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
/*!
* \brief Set acquisition channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set statistics threshold of PCPS algorithm
*/
void set_threshold(float threshold) override;
/*!
* \brief Set maximum Doppler off grid search
*/
void set_doppler_max(unsigned int doppler_max) override;
/*!
* \brief Set Doppler steps for the grid search
*/
void set_doppler_step(unsigned int doppler_step) override;
/*!
* \brief Initializes acquisition algorithm.
*/
void init() override;
/*!
* \brief Sets local code for GLONASS L2/CA PCPS acquisition algorithm.
*/
void set_local_code() override;
/*!
* \brief Returns the maximum peak of grid search
*/
signed int mag() override;
/*!
* \brief Restart acquisition algorithm
*/
void reset() override;
/*!
* \brief If state = 1, it forces the block to start acquiring from the first sample
*/
void set_state(int state);
private:
ConfigurationInterface* configuration_;
pcps_acquisition_sptr acquisition_;
gr::blocks::stream_to_vector::sptr stream_to_vector_;
gr::blocks::float_to_complex::sptr float_to_complex_;
complex_byte_to_float_x2_sptr cbyte_to_float_x2_;
size_t item_size_;
std::string item_type_;
unsigned int vector_length_;
unsigned int code_length_;
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;
unsigned int sampled_ms_;
unsigned int max_dwells_;
long fs_in_;
long if_;
bool dump_;
bool blocking_;
std::string dump_filename_;
std::complex<float>* code_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
float calculate_threshold(float pfa);
};
#endif /* GNSS_SDR_GLONASS_L2_CA_PCPS_ACQUISITION_H_ */

View File

@ -34,8 +34,8 @@
*/
#include "pcps_acquisition.h"
#include "GPS_L1_CA.h" // for GPS_TWO_PI
#include "GLONASS_L1_CA.h" // for GLONASS_TWO_PI
#include "GPS_L1_CA.h" // for GPS_TWO_PI
#include "GLONASS_L1_L2_CA.h" // for GLONASS_TWO_PI"
#include <glog/logging.h>
#include <gnuradio/io_signature.h>
#include <matio.h>
@ -210,6 +210,12 @@ bool pcps_acquisition::is_fdma()
LOG(INFO) << "Trying to acquire SV PRN " << d_gnss_synchro->PRN << " with freq " << d_freq << " in Glonass Channel " << GLONASS_PRN.at(d_gnss_synchro->PRN) << std::endl;
return true;
}
else if (strcmp(d_gnss_synchro->Signal, "2G") == 0)
{
d_freq += DFRQ2_GLO * GLONASS_PRN.at(d_gnss_synchro->PRN);
LOG(INFO) << "Trying to acquire SV PRN " << d_gnss_synchro->PRN << " with freq " << d_freq << " in Glonass Channel " << GLONASS_PRN.at(d_gnss_synchro->PRN) << std::endl;
return true;
}
else
{
return false;

View File

@ -316,7 +316,7 @@ int pcps_quicksync_acquisition_cc::general_work(int noutput_items,
gr_complex* corr_output = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_samples_per_code * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
/*Stores a copy of the folded version of the signal.This is used for
the FFT operations in future steps of excecution*/
the FFT operations in future steps of execution*/
// gr_complex in_folded[d_fft_size];
float fft_normalization_factor = static_cast<float>(d_fft_size) * static_cast<float>(d_fft_size);
@ -468,7 +468,7 @@ int pcps_quicksync_acquisition_cc::general_work(int noutput_items,
if (d_dump)
{
/*Since QuickSYnc performs a folded correlation in frequency by means
of the FFT, it is esential to also keep the values obtained from the
of the FFT, it is essential to also keep the values obtained from the
possible delay to show how it is maximize*/
std::stringstream filename;
std::streamsize n = sizeof(float) * (d_fft_size); // complex file write

View File

@ -16,40 +16,11 @@
# along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
#
#if(ENABLE_CUDA)
# # Append current NVCC flags by something, eg comput capability
# # set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} --gpu-architecture sm_30)
# list(APPEND CUDA_NVCC_FLAGS "-gencode arch=compute_30,code=sm_30; -std=c++11;-O3; -use_fast_math -default-stream per-thread")
# set(CUDA_PROPAGATE_HOST_FLAGS OFF)
# CUDA_INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR})
# set(LIB_TYPE STATIC) #set the lib type
# CUDA_ADD_LIBRARY(CUDA_CORRELATOR_LIB ${LIB_TYPE} cuda_multicorrelator.h cuda_multicorrelator.cu)
# set(OPT_TRACKING_LIBRARIES ${OPT_TRACKING_LIBRARIES} CUDA_CORRELATOR_LIB)
# set(OPT_TRACKING_INCLUDES ${OPT_TRACKING_INCLUDES} ${CUDA_INCLUDE_DIRS} )
#endif(ENABLE_CUDA)
#set(TRACKING_LIB_SOURCES
set(ACQUISITION_LIB_SOURCES
gps_fpga_acquisition_8sc.cc
# cpu_multicorrelator.cc
# cpu_multicorrelator_16sc.cc
# lock_detectors.cc
# tcp_communication.cc
# tcp_packet_data.cc
# tracking_2nd_DLL_filter.cc
# tracking_2nd_PLL_filter.cc
# tracking_discriminators.cc
# tracking_FLL_PLL_filter.cc
# tracking_loop_filter.cc
)
#if(ENABLE_FPGA)
# SET(ACQUISITION_LIB_SOURCES ${ACQUISITION_LIB_SOURCES} fpga_acquisition_8sc.cc)
#endif(ENABLE_FPGA)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/core/system_parameters
@ -59,34 +30,17 @@ include_directories(
${VOLK_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS}
${OPT_TRACKING_INCLUDES}
${VOLK_GNSSSDR_INCLUDE_DIRS}
)
if(ENABLE_GENERIC_ARCH)
add_definitions( -DGENERIC_ARCH=1 )
endif(ENABLE_GENERIC_ARCH)
if (SSE3_AVAILABLE)
add_definitions( -DHAVE_SSE3=1 )
endif(SSE3_AVAILABLE)
#file(GLOB TRACKING_LIB_HEADERS "*.h")
file(GLOB ACQUISITION_LIB_HEADERS "*.h")
#list(SORT TRACKING_LIB_HEADERS)
list(SORT ACQUISITION_LIB_HEADERS)
#add_library(tracking_lib ${TRACKING_LIB_SOURCES} ${TRACKING_LIB_HEADERS})
add_library(acquisition_lib ${ACQUISITION_LIB_SOURCES} ${ACQUISITION_LIB_HEADERS})
#source_group(Headers FILES ${TRACKING_LIB_HEADERS})
source_group(Headers FILES ${ACQUISITION_LIB_HEADERS})
#target_link_libraries(tracking_lib ${OPT_TRACKING_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES})
target_link_libraries(acquisition_lib ${OPT_ACQUISITION_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES})
target_link_libraries(acquisition_lib ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES})
if(VOLK_GNSSSDR_FOUND)
# add_dependencies(tracking_lib glog-${glog_RELEASE})
add_dependencies(acquisition_lib glog-${glog_RELEASE})
else(VOLK_GNSSSDR_FOUND)
# add_dependencies(tracking_lib glog-${glog_RELEASE} volk_gnsssdr_module)
add_dependencies(acquisition_lib glog-${glog_RELEASE} volk_gnsssdr_module)
endif()

View File

@ -35,34 +35,32 @@
#include "gps_fpga_acquisition_8sc.h"
#include "gps_sdr_signal_processing.h"
#include "GPS_L1_CA.h"
#include <cmath>
#include <volk/volk.h>
// allocate memory dynamically
#include <new>
// libraries used by DMA test code and GIPO test code
#include <stdio.h>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <cerrno>
// libraries used by DMA test code
#include <sys/stat.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include <cstdint>
#include <cassert>
// libraries used by GPIO test code
#include <stdlib.h>
#include <signal.h>
#include <cstdlib>
#include <csignal>
#include <sys/mman.h>
// logging
#include <glog/logging.h>
#include <volk/volk.h>
#include "GPS_L1_CA.h"
#define PAGE_SIZE 0x10000
#define MAX_PHASE_STEP_RAD 0.999999999534339 // 1 - pow(2,-31);
@ -110,7 +108,7 @@ gps_fpga_acquisition_8sc::gps_fpga_acquisition_8sc(std::string device_name,
// allocate memory to compute all the PRNs
// and compute all the possible codes
std::complex<float>* code = new std::complex<float>[nsamples_total]; // buffer for the local code
std::complex<float>* code_total = new gr_complex[vector_length]; // buffer for the local code repeate every number of ms
std::complex<float>* code_total = new gr_complex[vector_length]; // buffer for the local code repeat every number of ms
gr_complex* d_fft_codes_padded = static_cast<gr_complex*>(volk_gnsssdr_malloc(vector_length * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
@ -252,8 +250,8 @@ void gps_fpga_acquisition_8sc::set_phase_step(unsigned int doppler_index)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
phase_step_rad_int_temp = phase_step_rad_real * 4; // * 2^2
phase_step_rad_int = (int32_t)(phase_step_rad_int_temp * (536870912)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
phase_step_rad_int_temp = phase_step_rad_real * 4; // * 2^2
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_int_temp * (536870912)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
d_map_base[3] = phase_step_rad_int;
}

View File

@ -92,7 +92,7 @@ private:
int d_fd; // driver descriptor
volatile unsigned *d_map_base; // driver memory map
lv_16sc_t *d_all_fft_codes; // memory that contains all the code ffts
unsigned int d_vector_length; // number of samples incluing padding and number of ms
unsigned int d_vector_length; // number of samples including padding and number of ms
unsigned int d_nsamples; // number of samples not including padding
unsigned int d_select_queue; // queue selection
std::string d_device_name; // HW device name

View File

@ -1,6 +1,6 @@
/*!
* \file notch_filter_lite.h
* \brief Adapts a ligth version of a multistate notch filter
* \brief Adapts a light version of a multistate notch filter
* \author Antonio Ramos, 2017. antonio.ramosdet(at)gmail.com
*
* Detailed description of the file here if needed.

View File

@ -1,6 +1,6 @@
/*!
* \file notch_lite_cc.h
* \brief Implements a notch filter ligth algorithm
* \brief Implements a notch filter light algorithm
* \author Antonio Ramos (antonio.ramosdet(at)gmail.com)
*
* -------------------------------------------------------------------------
@ -43,7 +43,7 @@ typedef boost::shared_ptr<NotchLite> notch_lite_sptr;
notch_lite_sptr make_notch_filter_lite(float p_c_factor, float pfa, int length_, int n_segments_est, int n_segments_reset, int n_segments_coeff);
/*!
* \brief This class implements a real-time software-defined multi state notch filter ligth version
* \brief This class implements a real-time software-defined multi state notch filter light version
*/
class NotchLite : public gr::block

View File

@ -27,6 +27,7 @@ set(GNSS_SPLIBS_SOURCES
gnss_signal_processing.cc
gps_sdr_signal_processing.cc
glonass_l1_signal_processing.cc
glonass_l2_signal_processing.cc
pass_through.cc
galileo_e5_signal_processing.cc
complex_byte_to_float_x2.cc

View File

@ -0,0 +1,152 @@
/*!
* \file glonass_l2_signal_processing.cc
* \brief This class implements various functions for GLONASS L2 CA signals
* \author Damian Miralles, 2018, dmiralles2009(at)gmail.com
*
* Detailed description of the file here if needed.
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "glonass_l2_signal_processing.h"
auto auxCeil = [](float x) { return static_cast<int>(static_cast<long>((x) + 1)); };
void glonass_l2_ca_code_gen_complex(std::complex<float>* _dest, /* signed int _prn,*/ unsigned int _chip_shift)
{
const unsigned int _code_length = 511;
bool G1[_code_length];
bool G1_register[9];
bool feedback1;
bool aux;
unsigned int delay;
unsigned int lcv, lcv2;
for (lcv = 0; lcv < 9; lcv++)
{
G1_register[lcv] = 1;
}
/* Generate G1 Register */
for (lcv = 0; lcv < _code_length; lcv++)
{
G1[lcv] = G1_register[2];
feedback1 = G1_register[4] ^ G1_register[0];
for (lcv2 = 0; lcv2 < 8; lcv2++)
{
G1_register[lcv2] = G1_register[lcv2 + 1];
}
G1_register[8] = feedback1;
}
/* Generate PRN from G1 Register */
for (lcv = 0; lcv < _code_length; lcv++)
{
aux = G1[lcv];
if (aux == true)
{
_dest[lcv] = std::complex<float>(1, 0);
}
else
{
_dest[lcv] = std::complex<float>(-1, 0);
}
}
/* Set the delay */
delay = _code_length;
delay += _chip_shift;
delay %= _code_length;
/* Generate PRN from G1 and G2 Registers */
for (lcv = 0; lcv < _code_length; lcv++)
{
aux = G1[(lcv + _chip_shift) % _code_length];
if (aux == true)
{
_dest[lcv] = std::complex<float>(1, 0);
}
else
{
_dest[lcv] = std::complex<float>(-1, 0);
}
delay++;
delay %= _code_length;
}
}
/*
* Generates complex GLONASS L2 C/A code for the desired SV ID and sampled to specific sampling frequency
*/
void glonass_l2_ca_code_gen_complex_sampled(std::complex<float>* _dest, /* unsigned int _prn,*/ signed int _fs, unsigned int _chip_shift)
{
// This function is based on the GNU software GPS for MATLAB in the Kay Borre book
std::complex<float> _code[511];
signed int _samplesPerCode, _codeValueIndex;
float _ts;
float _tc;
float aux;
const signed int _codeFreqBasis = 511000; //Hz
const signed int _codeLength = 511;
//--- Find number of samples per spreading code ----------------------------
_samplesPerCode = static_cast<signed int>(static_cast<double>(_fs) / static_cast<double>(_codeFreqBasis / _codeLength));
//--- Find time constants --------------------------------------------------
_ts = 1.0 / static_cast<float>(_fs); // Sampling period in sec
_tc = 1.0 / static_cast<float>(_codeFreqBasis); // C/A chip period in sec
glonass_l2_ca_code_gen_complex(_code, _chip_shift); //generate C/A code 1 sample per chip
for (signed int i = 0; i < _samplesPerCode; i++)
{
//=== Digitizing =======================================================
//--- Make index array to read C/A code values -------------------------
// The length of the index array depends on the sampling frequency -
// number of samples per millisecond (because one C/A code period is one
// millisecond).
// _codeValueIndex = ceil((_ts * ((float)i + 1)) / _tc) - 1;
aux = (_ts * (i + 1)) / _tc;
_codeValueIndex = auxCeil(aux) - 1;
//--- Make the digitized version of the C/A code -----------------------
// The "upsampled" code is made by selecting values form the CA code
// chip array (caCode) for the time instances of each sample.
if (i == _samplesPerCode - 1)
{
//--- Correct the last index (due to number rounding issues) -----------
_dest[i] = _code[_codeLength - 1];
}
else
{
_dest[i] = _code[_codeValueIndex]; //repeat the chip -> upsample
}
}
}

View File

@ -0,0 +1,47 @@
/*!
* \file glonass_l2_signal_processing.h
* \brief This class implements various functions for GLONASS L2 CA signals
* \author Damian Miralles, 2018, dmiralles2009(at)gmail.com
*
* Detailed description of the file here if needed.
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GLONASS_L2_SIGNAL_PROCESSING_H_
#define GNSS_SDR_GLONASS_L2_SIGNAL_PROCESSING_H_
#include <complex>
//!Generates complex GLONASS L2 C/A code for the desired SV ID and code shift, and sampled to specific sampling frequency
void glonass_l2_ca_code_gen_complex(std::complex<float>* _dest, /*signed int _prn,*/ unsigned int _chip_shift);
//! Generates N complex GLONASS L2 C/A codes for the desired SV ID and code shift
void glonass_l2_ca_code_gen_complex_sampled(std::complex<float>* _dest, /* unsigned int _prn,*/ signed int _fs, unsigned int _chip_shift, unsigned int _ncodes);
//! Generates complex GLONASS L2 C/A code for the desired SV ID and code shift
void glonass_l2_ca_code_gen_complex_sampled(std::complex<float>* _dest, /* unsigned int _prn,*/ signed int _fs, unsigned int _chip_shift);
#endif /* GNSS_SDR_GLONASS_L2_SIGNAL_PROCESSING_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -663,7 +663,7 @@ int satpos_sbas(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
*svh = -1;
return 0;
}
/* satellite postion and clock by broadcast ephemeris */
/* satellite position and clock by broadcast ephemeris */
if (!ephpos(time, teph, sat, nav, sbs->lcorr.iode, rs, dts, var, svh)) return 0;
/* sbas satellite correction (long term and fast) */
@ -734,7 +734,7 @@ int satpos_ssr(gtime_t time, gtime_t teph, int sat, const nav_t *nav,
*svh = -1;
return 0;
}
/* satellite postion and clock by broadcast ephemeris */
/* satellite position and clock by broadcast ephemeris */
if (!ephpos(time, teph, sat, nav, ssr->iode, rs, dts, var, svh)) return 0;
/* satellite clock for gps, galileo and qzss */

View File

@ -859,7 +859,7 @@ int pntpos(const obsd_t *obs, int n, const nav_t *nav,
opt_.ionoopt = IONOOPT_BRDC;
opt_.tropopt = TROPOPT_SAAS;
}
/* satellite positons, velocities and clocks */
/* satellite positions, velocities and clocks */
satposs(sol->time, obs, n, nav, opt_.sateph, rs, dts, var, svh);
/* estimate receiver position with pseudorange */

View File

@ -425,7 +425,7 @@ int fix_amb_ROUND(rtk_t *rtk, int *sat1, int *sat2, const int *NW, int n)
sat2[m] = sat2[i];
NC[m++] = BC;
}
/* select fixed ambiguities by dependancy check */
/* select fixed ambiguities by dependency check */
m = sel_amb(sat1, sat2, NC, var, m);
/* fixed solution */

View File

@ -79,7 +79,7 @@
const double MIN_ARC_GAP = 300.0; /* min arc gap (s) */
const double CONST_AMB = 0.001; /* constraint to fixed ambiguity */
const double THRES_RES = 0.3; /* threashold of residuals test (m) */
const double THRES_RES = 0.3; /* threshold of residuals test (m) */
const double LOG_PI = 1.14472988584940017; /* log(pi) */
const double SQRT2 = 1.41421356237309510; /* sqrt(2) */

View File

@ -843,7 +843,7 @@ void satantoff(gtime_t time, const double *rs, int sat, const nav_t *nav,
* args : gtime_t time I time (gpst)
* int sat I satellite number
* nav_t *nav I navigation data
* int opt I sat postion option
* int opt I sat position option
* (0: center of mass, 1: antenna phase center)
* double *rs O sat position and velocity (ecef)
* {x,y,z,vx,vy,vz} (m|m/s)

View File

@ -315,7 +315,7 @@ int input_rtcm3(rtcm_t *rtcm, unsigned char data)
/* input rtcm 2 message from file ----------------------------------------------
* fetch next rtcm 2 message and input a messsage from file
* fetch next rtcm 2 message and input a message from file
* args : rtcm_t *rtcm IO rtcm control struct
* FILE *fp I file pointer
* return : status (-2: end of file, -1...10: same as above)
@ -337,7 +337,7 @@ int input_rtcm2f(rtcm_t *rtcm, FILE *fp)
/* input rtcm 3 message from file ----------------------------------------------
* fetch next rtcm 3 message and input a messsage from file
* fetch next rtcm 3 message and input a message from file
* args : rtcm_t *rtcm IO rtcm control struct
* FILE *fp I file pointer
* return : status (-2: end of file, -1...10: same as above)

View File

@ -1056,7 +1056,7 @@ int decode_type1021(rtcm_t *rtcm __attribute__((unused)))
}
/* decode type 1022: moledenski-badekas transfromation -----------------------*/
/* decode type 1022: moledenski-badekas transformation -----------------------*/
int decode_type1022(rtcm_t *rtcm __attribute__((unused)))
{
trace(2, "rtcm3 1022: not supported message\n");
@ -2699,7 +2699,7 @@ void save_msm_obs(rtcm_t *rtcm, int sys, msm_h_t *h, const double *r,
/* signal to rinex obs type */
code[i] = obs2code(sig[i], freq + i);
/* freqency index for beidou */
/* frequency index for beidou */
if (sys == SYS_BDS)
{
if (freq[i] == 5)

View File

@ -1818,7 +1818,7 @@ unsigned int tickget(void)
/* sleep ms --------------------------------------------------------------------
* sleep ms
* args : int ms I miliseconds to sleep (<0:no sleep)
* args : int ms I milliseconds to sleep (<0:no sleep)
* return : none
*-----------------------------------------------------------------------------*/
void sleepms(int ms)
@ -1883,7 +1883,7 @@ double dms2deg(const double *dms)
}
/* transform ecef to geodetic postion ------------------------------------------
/* transform ecef to geodetic position ------------------------------------------
* transform ecef position to geodetic position
* args : double *r I ecef position {x,y,z} (m)
* double *pos O geodetic position {lat,lon,h} (rad,m)
@ -1925,8 +1925,8 @@ void pos2ecef(const double *pos, double *r)
}
/* ecef to local coordinate transfromation matrix ------------------------------
* compute ecef to local coordinate transfromation matrix
/* ecef to local coordinate transformation matrix ------------------------------
* compute ecef to local coordinate transformation matrix
* args : double *pos I geodetic position {lat,lon} (rad)
* double *E O ecef to local coord transformation matrix (3x3)
* return : none
@ -2222,7 +2222,7 @@ void eci2ecef(gtime_t tutc, const double *erpv, double *U, double *gmst)
matmul("NN", 3, 3, 3, 1.0, R1, R2, 0.0, R);
matmul("NN", 3, 3, 3, 1.0, R, R3, 0.0, N); /* N=Rx(-eps)*Rz(-dspi)*Rx(eps) */
/* greenwich aparent sidereal time (rad) */
/* greenwich apparent sidereal time (rad) */
gmst_ = utc2gmst(tutc_, erpv[2]);
gast = gmst_ + dpsi * cos(eps);
gast += (0.00264 * sin(f[4]) + 0.000063 * sin(2.0 * f[4])) * AS2R;
@ -4165,7 +4165,7 @@ void sunmoonpos(gtime_t tutc, const double *erpv, double *rsun,
/* eci to ecef transformation matrix */
eci2ecef(tutc, erpv, U, &gmst_);
/* sun and moon postion in ecef */
/* sun and moon position in ecef */
if (rsun) matmul("NN", 3, 1, 3, 1.0, U, rs, 0.0, rsun);
if (rmoon) matmul("NN", 3, 1, 3, 1.0, U, rm, 0.0, rmoon);
if (gmst) *gmst = gmst_;

View File

@ -599,7 +599,7 @@ void udpos(rtk_t *rtk, double tt)
for (i = 0; i < 3; i++) initx_rtk(rtk, rtk->sol.rr[i], VAR_POS, i);
return;
}
/* check variance of estimated postion */
/* check variance of estimated position */
for (i = 0; i < 3; i++)
{
var += rtk->P[i + i * rtk->nx];
@ -2223,7 +2223,7 @@ void rtkfree(rtk_t *rtk)
* .vs [r] O data valid single (r=0:rover,1:base)
* .resp [f] O freq(f+1) pseudorange residual (m)
* .resc [f] O freq(f+1) carrier-phase residual (m)
* .vsat [f] O freq(f+1) data vaild (0:invalid,1:valid)
* .vsat [f] O freq(f+1) data valid (0:invalid,1:valid)
* .fix [f] O freq(f+1) ambiguity flag
* (0:nodata,1:float,2:fix,3:hold)
* .slip [f] O freq(f+1) slip flag
@ -2262,7 +2262,7 @@ int rtkpos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
traceobs(4, obs, n);
/*trace(5,"nav=\n"); tracenav(5,nav);*/
/* set base staion position */
/* set base station position */
if (opt->refpos <= POSOPT_RINEX && opt->mode != PMODE_SINGLE &&
opt->mode != PMODE_MOVEB)
{

View File

@ -210,7 +210,7 @@ void updatesvr(rtksvr_t *svr, int ret, obs_t *obs, nav_t *nav, int sat,
svr->nmsg[index][2]++;
}
else if (ret == 5)
{ /* antenna postion parameters */
{ /* antenna position parameters */
if (svr->rtk.opt.refpos == 4 && index == 1)
{
for (i = 0; i < 3; i++)

View File

@ -616,10 +616,10 @@ int cmpmsgs(const void *p1, const void *p2)
* (gtime_t te I end time )
* sbs_t *sbs IO sbas messages
* return : number of sbas messages
* notes : sbas message are appended and sorted. before calling the funciton,
* notes : sbas message are appended and sorted. before calling the function,
* sbs->n, sbs->nmax and sbs->msgs must be set properly. (initially
* sbs->n=sbs->nmax=0, sbs->msgs=NULL)
* only the following file extentions after wild card expanded are valid
* only the following file extensions after wild card expanded are valid
* to read. others are skipped
* .sbs, .SBS, .ems, .EMS
*-----------------------------------------------------------------------------*/

View File

@ -150,7 +150,7 @@ void covtosol(const double *P, sol_t *sol)
}
/* decode nmea gprmc: recommended minumum data for gps -----------------------*/
/* decode nmea gprmc: recommended minimum data for gps -----------------------*/
int decode_nmearmc(char **val, int n, sol_t *sol)
{
double tod = 0.0, lat = 0.0, lon = 0.0, vel = 0.0, dir = 0.0, date = 0.0, ang = 0.0, ep[6];
@ -219,7 +219,7 @@ int decode_nmearmc(char **val, int n, sol_t *sol)
sol->stat = mode == 'D' ? SOLQ_DGPS : SOLQ_SINGLE;
sol->ns = 0;
sol->type = 0; /* postion type = xyz */
sol->type = 0; /* position type = xyz */
trace(5, "decode_nmearmc: %s rr=%.3f %.3f %.3f stat=%d ns=%d vel=%.2f dir=%.0f ang=%.0f mew=%c mode=%c\n",
time_str(sol->time, 0), sol->rr[0], sol->rr[1], sol->rr[2], sol->stat, sol->ns,
@ -310,7 +310,7 @@ int decode_nmeagga(char **val, int n, sol_t *sol)
sol->stat = 0 <= solq && solq <= 8 ? solq_nmea[solq] : SOLQ_NONE;
sol->ns = nrcv;
sol->type = 0; /* postion type = xyz */
sol->type = 0; /* position type = xyz */
trace(5, "decode_nmeagga: %s rr=%.3f %.3f %.3f stat=%d ns=%d hdop=%.1f ua=%c um=%c\n",
time_str(sol->time, 0), sol->rr[0], sol->rr[1], sol->rr[2], sol->stat, sol->ns,
@ -453,7 +453,7 @@ int decode_solxyz(char *buff, const solopt_t *opt, sol_t *sol)
if (i < n) sol->age = (float)val[i++];
if (i < n) sol->ratio = (float)val[i];
sol->type = 0; /* postion type = xyz */
sol->type = 0; /* position type = xyz */
if (MAXSOLQ < sol->stat) sol->stat = SOLQ_NONE;
return 1;
@ -512,7 +512,7 @@ int decode_solllh(char *buff, const solopt_t *opt, sol_t *sol)
if (i < n) sol->age = (float)val[i++];
if (i < n) sol->ratio = (float)val[i];
sol->type = 0; /* postion type = xyz */
sol->type = 0; /* position type = xyz */
if (MAXSOLQ < sol->stat) sol->stat = SOLQ_NONE;
return 1;
@ -558,7 +558,7 @@ int decode_solenu(char *buff, const solopt_t *opt, sol_t *sol)
if (i < n) sol->age = (float)val[i++];
if (i < n) sol->ratio = (float)val[i];
sol->type = 1; /* postion type = enu */
sol->type = 1; /* position type = enu */
if (MAXSOLQ < sol->stat) sol->stat = SOLQ_NONE;
return 1;
@ -1798,7 +1798,7 @@ int outsols(unsigned char *buff, const sol_t *sol, const double *rb,
/* output solution extended ----------------------------------------------------
* output solution exteneded infomation
* output solution exteneded information
* args : unsigned char *buff IO output buffer
* sol_t *sol I solution
* ssat_t *ssat I satellite status
@ -1892,7 +1892,7 @@ void outsol(FILE *fp, const sol_t *sol, const double *rb,
/* output solution extended ----------------------------------------------------
* output solution exteneded infomation to file
* output solution exteneded information to file
* args : FILE *fp I output file pointer
* sol_t *sol I solution
* ssat_t *ssat I satellite status

View File

@ -1916,7 +1916,7 @@ void strunlock(stream_t *stream) { rtk_unlock(&stream->lock); }
/* read stream -----------------------------------------------------------------
* read data from stream (unblocked)
* args : stream_t *stream I stream
* unsinged char *buff O data buffer
* unsigned char *buff O data buffer
* int n I maximum data length
* return : read data length
* notes : if no data, return immediately with no data
@ -1978,7 +1978,7 @@ int strread(stream_t *stream, unsigned char *buff, int n)
/* write stream ----------------------------------------------------------------
* write data to stream (unblocked)
* args : stream_t *stream I stream
* unsinged char *buff I data buffer
* unsigned char *buff I data buffer
* int n I data length
* return : status (0:error, 1:ok)
* notes : write data to buffer and return immediately

View File

@ -145,7 +145,7 @@ INLINE_INHERITED_MEMB = NO
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = YES
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand

View File

@ -7,8 +7,8 @@ and contact information about the original VOLK library.
The boilerplate of this code was initially generated with
```volk_modtool```, an application provided by VOLK that creates the
skeleton than can then be filled with custom kernels. Some modifications
were added to accomodate the specificities of Global Navigation
skeleton that can then be filled with custom kernels. Some modifications
were added to accommodate the specificities of Global Navigation
Satellite Systems (GNSS) signal processing. Those changes are clearly
indicated in the source code, and do not break compatibility.
@ -39,7 +39,7 @@ This library is automatically built and installed along with GNSS-SDR if
it is not found by CMake on your system at configure time.
However, you can install and use VOLK_GNSSSDR kernels as you use VOLK's,
independently from GNSS-SDR.
independently of GNSS-SDR.
First, make sure that the required dependencies are installed in your
machine:

View File

@ -16,8 +16,8 @@
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef VOLK_VOLK_OPTION_HELPERS_H
#define VOLK_VOLK_OPTION_HELPERS_H
#ifndef VOLK_GNSSSDR_OPTION_HELPERS_H
#define VOLK_GNSSSDR_OPTION_HELPERS_H
#include <climits>
#include <cstring>
@ -71,4 +71,4 @@ private:
};
#endif //VOLK_VOLK_OPTION_HELPERS_H
#endif //VOLK_GNSSSDR_OPTION_HELPERS_H

View File

@ -148,7 +148,7 @@ int main(int argc, char *argv[])
}
catch (std::string &error)
{
std::cerr << "Caught Exception in 'run_volk_gnssdr_tests': " << error << std::endl;
std::cerr << "Caught Exception in 'run_volk_gnsssdr_tests': " << error << std::endl;
}
}
}

View File

@ -32,7 +32,7 @@
#include <string> // for string
#include <vector> // for vector
class volk_test_results_t;
class volk_gnsssdr_test_results_t;
void read_results(std::vector<volk_gnsssdr_test_results_t> *results);

View File

@ -22,24 +22,40 @@ if(DEFINED __INCLUDED_VOLK_ADD_TEST)
endif()
set(__INCLUDED_VOLK_ADD_TEST TRUE)
########################################################################
# Generate a test executable which can be used in ADD_TEST to call
# various subtests.
#
# SOURCES - sources for the test
# TARGET_DEPS - build target dependencies (e.g., libraries)
########################################################################
function(VOLK_GEN_TEST executable_name)
include(CMakeParseArgumentsCopy)
CMAKE_PARSE_ARGUMENTS(VOLK_TEST "" "" "SOURCES;TARGET_DEPS;EXTRA_LIB_DIRS;ENVIRONS;ARGS" ${ARGN})
add_executable(${executable_name} ${VOLK_TEST_SOURCES})
target_link_libraries(${executable_name} ${VOLK_TEST_TARGET_DEPS})
endfunction()
########################################################################
# Add a unit test and setup the environment for it.
# Encloses ADD_TEST, with additional functionality to create a shell
# script that sets the environment to gain access to in-build binaries
# properly. The following variables are used to pass in settings:
# A test executable has to be generated with VOLK_GEN_TEST beforehand.
# The executable name has to be passed as argument.
#
# NAME - the test name
# SOURCES - sources for the test
# TARGET_DEPS - build target dependencies (e.g., libraries)
# EXTRA_LIB_DIRS - other directories for the library path
# ENVIRONS - other environment key/value pairs
# ARGS - arguments for the test
########################################################################
function(VOLK_ADD_TEST test_name)
function(VOLK_ADD_TEST test_name executable_name)
#parse the arguments for component names
include(CMakeParseArgumentsCopy)
CMAKE_PARSE_ARGUMENTS(VOLK_TEST "" "" "SOURCES;TARGET_DEPS;EXTRA_LIB_DIRS;ENVIRONS;ARGS" ${ARGN})
CMAKE_PARSE_ARGUMENTS(VOLK_TEST "" "" "TARGET_DEPS;EXTRA_LIB_DIRS;ENVIRONS;ARGS" ${ARGN})
#set the initial environs to use
set(environs ${VOLK_TEST_ENVIRONS})
@ -65,7 +81,7 @@ function(VOLK_ADD_TEST test_name)
#"add_test" command, via the $<FOO:BAR> operator; make sure the
#test's directory is first, since it ($1) is prepended to PATH.
unset(TARGET_DIR_LIST)
foreach(target ${test_name} ${VOLK_TEST_TARGET_DEPS})
foreach(target ${executable_name} ${VOLK_TEST_TARGET_DEPS})
list(APPEND TARGET_DIR_LIST "\$<TARGET_FILE_DIR:${target}>")
endforeach()
@ -134,18 +150,17 @@ function(VOLK_ADD_TEST test_name)
file(APPEND ${sh_file} "export ${environ}\n")
endforeach(environ)
set(VOLK_TEST_ARGS "${test_name}")
#redo the test args to have a space between each
string(REPLACE ";" " " VOLK_TEST_ARGS "${VOLK_TEST_ARGS}")
#finally: append the test name to execute
file(APPEND ${sh_file} ${test_name} " " ${VOLK_TEST_ARGS} "\n")
file(APPEND ${sh_file} "${CMAKE_CROSSCOMPILING_EMULATOR} ${executable_name} ${VOLK_TEST_ARGS}\n")
#make the shell file executable
execute_process(COMMAND chmod +x ${sh_file})
add_executable(${test_name} ${VOLK_TEST_SOURCES})
target_link_libraries(${test_name} ${VOLK_TEST_TARGET_DEPS})
#add the shell file as the test to execute;
#use the form that allows for $<FOO:BAR> substitutions,
#then combine the script arguments inside the script.
@ -196,10 +211,8 @@ function(VOLK_ADD_TEST test_name)
file(APPEND ${bat_file} ${test_name} " " ${VOLK_TEST_ARGS} "\n")
file(APPEND ${bat_file} "\n")
add_executable(${test_name} ${VOLK_TEST_SOURCES})
target_link_libraries(${test_name} ${VOLK_TEST_TARGET_DEPS})
add_test(${test_name} ${bat_file})
endif(WIN32)
endfunction(VOLK_ADD_TEST)

View File

@ -187,7 +187,7 @@ static inline void volk_gnsssdr_16ic_x2_dot_prod_16ic_u_sse2(lv_16sc_t* out, con
for (number = 0; number < sse_iters; number++)
{
//std::complex<T> memory structure: real part -> reinterpret_cast<cv T*>(a)[2*i]
//imaginery part -> reinterpret_cast<cv T*>(a)[2*i + 1]
//imaginary part -> reinterpret_cast<cv T*>(a)[2*i + 1]
// a[127:0]=[a3.i,a3.r,a2.i,a2.r,a1.i,a1.r,a0.i,a0.r]
a = _mm_loadu_si128((__m128i*)_in_a); //load (2 byte imag, 2 byte real) x 4 into 128 bits reg
__VOLK_GNSSSDR_PREFETCH(_in_a + 8);

View File

@ -94,7 +94,7 @@ static inline void volk_gnsssdr_16ic_x2_multiply_16ic_a_sse2(lv_16sc_t* out, con
for (number = 0; number < sse_iters; number++)
{
//std::complex<T> memory structure: real part -> reinterpret_cast<cv T*>(a)[2*i]
//imaginery part -> reinterpret_cast<cv T*>(a)[2*i + 1]
//imaginary part -> reinterpret_cast<cv T*>(a)[2*i + 1]
// a[127:0]=[a3.i,a3.r,a2.i,a2.r,a1.i,a1.r,a0.i,a0.r]
a = _mm_load_si128((__m128i*)_in_a); //load (2 byte imag, 2 byte real) x 4 into 128 bits reg
b = _mm_load_si128((__m128i*)_in_b);
@ -148,7 +148,7 @@ static inline void volk_gnsssdr_16ic_x2_multiply_16ic_u_sse2(lv_16sc_t* out, con
for (number = 0; number < sse_iters; number++)
{
//std::complex<T> memory structure: real part -> reinterpret_cast<cv T*>(a)[2*i]
//imaginery part -> reinterpret_cast<cv T*>(a)[2*i + 1]
//imaginary part -> reinterpret_cast<cv T*>(a)[2*i + 1]
// a[127:0]=[a3.i,a3.r,a2.i,a2.r,a1.i,a1.r,a0.i,a0.r]
a = _mm_loadu_si128((__m128i*)_in_a); //load (2 byte imag, 2 byte real) x 4 into 128 bits reg
b = _mm_loadu_si128((__m128i*)_in_b);

View File

@ -6,7 +6,7 @@
* </ul>
*
* VOLK_GNSSSDR kernel that esamples N 16 bits integer short complex vectors using zero hold resample algorithm.
* It is optimized to resample a sigle GNSS local code signal replica into N vectors fractional-resampled and fractional-delayed
* It is optimized to resample a single GNSS local code signal replica into N vectors fractional-resampled and fractional-delayed
* (i.e. it creates the Early, Prompt, and Late code replicas)
*
* -------------------------------------------------------------------------
@ -145,7 +145,7 @@ static inline void volk_gnsssdr_16ic_xn_resampler_fast_16ic_xn_a_sse2(lv_16sc_t*
//common to all outputs
_code_phase_out = _mm_mul_ps(_code_phase_step_chips, _4output_index); //compute the code phase point with the phase step
//output vector dependant (different code phase offset)
//output vector dependent (different code phase offset)
for (current_vector = 0; current_vector < num_out_vectors; current_vector++)
{
tmp_rem_code_phase_chips = rem_code_phase_chips[current_vector] - 0.5f; // adjust offset to perform correct rounding (chip transition at 0)
@ -241,7 +241,7 @@ static inline void volk_gnsssdr_16ic_xn_resampler_fast_16ic_xn_u_sse2(lv_16sc_t*
//common to all outputs
_code_phase_out = _mm_mul_ps(_code_phase_step_chips, _4output_index); //compute the code phase point with the phase step
//output vector dependant (different code phase offset)
//output vector dependent (different code phase offset)
for (current_vector = 0; current_vector < num_out_vectors; current_vector++)
{
tmp_rem_code_phase_chips = rem_code_phase_chips[current_vector] - 0.5f; // adjust offset to perform correct rounding (chip transition at 0)
@ -339,7 +339,7 @@ static inline void volk_gnsssdr_16ic_xn_resampler_fast_16ic_xn_neon(lv_16sc_t**
//common to all outputs
_code_phase_out = vmulq_f32(_code_phase_step_chips, _4output_index); //compute the code phase point with the phase step
//output vector dependant (different code phase offset)
//output vector dependent (different code phase offset)
for (current_vector = 0; current_vector < num_out_vectors; current_vector++)
{
tmp_rem_code_phase_chips = rem_code_phase_chips[current_vector] - 0.5f; // adjust offset to perform correct rounding (chip transition at 0)

View File

@ -345,7 +345,7 @@ macro(gen_template tmpl output)
)
endmacro(gen_template)
make_directory(${PROJECT_BINARY_DIR}/include/volk_gnsssdr)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include/volk_gnsssdr)
gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr.tmpl.h ${PROJECT_BINARY_DIR}/include/volk_gnsssdr/volk_gnsssdr.h)
gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr.tmpl.c ${PROJECT_BINARY_DIR}/lib/volk_gnsssdr.c)
@ -604,18 +604,24 @@ if(ENABLE_TESTING)
#include Boost headers
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
make_directory(${CMAKE_CURRENT_BINARY_DIR}/.unittest)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/.unittest)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/testqa.cc PROPERTIES
COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK;BOOST_TEST_MAIN"
)
include(VolkAddTest)
VOLK_ADD_TEST(test_all
VOLK_GEN_TEST("volk_gnsssdr_test_all"
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/testqa.cc
${CMAKE_CURRENT_SOURCE_DIR}/qa_utils.cc
${CMAKE_CURRENT_SOURCE_DIR}/qa_utils.cc
TARGET_DEPS volk_gnsssdr
)
)
foreach(kernel ${h_files})
get_filename_component(kernel ${kernel} NAME)
string(REPLACE ".h" "" kernel ${kernel})
if(NOT ${kernel} MATCHES puppet*)
VOLK_ADD_TEST(${kernel} "volk_gnsssdr_test_all")
endif(NOT ${kernel} MATCHES puppet*)
endforeach()
endif(ENABLE_TESTING)

View File

@ -16,14 +16,10 @@
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*/
#include "volk_gnsssdr/volk_gnsssdr.h" // for volk_gnsssdr_func_desc_t
#include "qa_utils.h"
#include "volk_gnsssdr/volk_gnsssdr.h" // for volk_gnsssdr_func_desc_t
#include "volk_gnsssdr/volk_gnsssdr_malloc.h" // for volk_gnsssdr_free, volk_gnsssdr_malloc
#include <boost/foreach.hpp> // for auto_any_base
#include <boost/lexical_cast.hpp> // for lexical_cast
#include <boost/token_functions.hpp> // for char_separator
#include <boost/token_iterator.hpp> // for token_iterator
#include <boost/tokenizer.hpp> // for tokenizer
#include <volk_gnsssdr/volk_gnsssdr_malloc.h> // for volk_gnsssdr_free, volk_gnsssdr_malloc
#include <cassert> // for assert
#include <chrono> // for system_clock, duration,...
#include <cmath> // for sqrt, fabs, abs
@ -122,6 +118,24 @@ static std::vector<std::string> get_arch_list(volk_gnsssdr_func_desc_t desc)
return archlist;
}
template <typename T>
T volk_lexical_cast(const std::string &str)
{
for (unsigned int c_index = 0; c_index < str.size(); ++c_index)
{
if (str.at(c_index) < '0' || str.at(c_index) > '9')
{
throw "not all numbers!";
}
}
T var;
std::istringstream iss;
iss.str(str);
iss >> var;
// deal with any error bits that may have been set on the stream
return var;
}
volk_gnsssdr_type_t volk_gnsssdr_type_from_string(std::string name)
{
volk_gnsssdr_type_t type;
@ -151,7 +165,7 @@ volk_gnsssdr_type_t volk_gnsssdr_type_from_string(std::string name)
throw std::string("no size spec in type ").append(name);
}
//will throw if malformed
int size = boost::lexical_cast<int>(name.substr(0, last_size_pos + 1));
int size = volk_lexical_cast<int>(name.substr(0, last_size_pos + 1));
assert(((size % 8) == 0) && (size <= 64) && (size != 0));
type.size = size / 8; //in bytes
@ -180,21 +194,42 @@ volk_gnsssdr_type_t volk_gnsssdr_type_from_string(std::string name)
return type;
}
std::vector<std::string> split_signature(const std::string &protokernel_signature)
{
std::vector<std::string> signature_tokens;
std::string token;
for (unsigned int loc = 0; loc < protokernel_signature.size(); ++loc)
{
if (protokernel_signature.at(loc) == '_')
{
if (protokernel_signature.substr(loc + 1, 7).compare("gnsssdr") == 0) // jump the "gnsssdr" part of "volk_gnsssdr"
{
loc += 7;
}
else
{
// this is a break
signature_tokens.push_back(token);
token = "";
}
}
else
{
token.push_back(protokernel_signature.at(loc));
}
}
// Get the last one to the end of the string
signature_tokens.push_back(token);
return signature_tokens;
}
static void get_signatures_from_name(std::vector<volk_gnsssdr_type_t> &inputsig,
std::vector<volk_gnsssdr_type_t> &outputsig,
std::string name)
{
boost::char_separator<char> sep("_");
boost::tokenizer<boost::char_separator<char> > tok(name, sep);
std::vector<std::string> toked;
tok.assign(name);
toked.assign(tok.begin(), tok.end());
std::vector<std::string> toked = split_signature(name);
assert(toked[0] == "volk");
toked.erase(toked.begin());
toked.erase(toked.begin());
//ok. we're assuming a string in the form
//(sig)_(multiplier-opt)_..._(name)_(sig)_(multiplier-opt)_..._(alignment)
enum
{
@ -204,8 +239,9 @@ static void get_signatures_from_name(std::vector<volk_gnsssdr_type_t> &inputsig,
} side = SIDE_INPUT;
std::string fn_name;
volk_gnsssdr_type_t type;
BOOST_FOREACH (std::string token, toked)
for (unsigned int token_index = 0; token_index < toked.size(); ++token_index)
{
std::string token = toked[token_index];
try
{
type = volk_gnsssdr_type_from_string(token);
@ -224,7 +260,7 @@ static void get_signatures_from_name(std::vector<volk_gnsssdr_type_t> &inputsig,
assert(inputsig.size() > 0);
else
assert(outputsig.size() > 0);
int multiplier = boost::lexical_cast<int>(token.substr(1, token.size() - 1)); //will throw if invalid ///////////
int multiplier = volk_lexical_cast<int>(token.substr(1, token.size() - 1)); // will throw if invalid
for (int i = 1; i < multiplier; i++)
{
if (side == SIDE_INPUT)
@ -523,7 +559,7 @@ bool run_volk_gnsssdr_tests(volk_gnsssdr_func_desc_t desc,
{
get_signatures_from_name(inputsig, outputsig, name);
}
catch (boost::bad_lexical_cast &error)
catch (std::exception &error)
{
std::cerr << "Error: unable to get function signature from kernel name" << std::endl;
std::cerr << " - " << name << std::endl;
@ -542,8 +578,9 @@ bool run_volk_gnsssdr_tests(volk_gnsssdr_func_desc_t desc,
}
}
std::vector<void *> inbuffs;
BOOST_FOREACH (volk_gnsssdr_type_t sig, inputsig)
for (unsigned int inputsig_index = 0; inputsig_index < inputsig.size(); ++inputsig_index)
{
volk_gnsssdr_type_t sig = inputsig[inputsig_index];
if (!sig.is_scalar) //we don't make buffers for scalars
inbuffs.push_back(mem_pool.get_new(vlen * sig.size * (sig.is_complex ? 2 : 1)));
}
@ -703,6 +740,9 @@ bool run_volk_gnsssdr_tests(volk_gnsssdr_func_desc_t desc,
else
throw "unsupported 3 arg function >1 scalars";
break;
case 4:
run_cast_test4((volk_gnsssdr_fn_4arg)(manual_func), test_data[i], vlen, iter, arch_list[i]);
break;
default:
throw "no function handler for this signature";
break;

View File

@ -31,7 +31,7 @@
void print_qa_xml(std::vector<volk_gnsssdr_test_results_t> results, unsigned int nfails);
int main()
int main(int argc, char* argv[])
{
bool qa_ret_val = 0;
@ -45,47 +45,78 @@ int main()
volk_gnsssdr_test_params_t test_params(def_tol, def_scalar, def_vlen, def_iter,
def_benchmark_mode, def_kernel_regex);
std::vector<volk_gnsssdr_test_case_t> test_cases = init_test_list(test_params);
std::vector<std::string> qa_failures;
std::vector<volk_gnsssdr_test_results_t> results;
// Test every kernel reporting failures when they occur
for (unsigned int ii = 0; ii < test_cases.size(); ++ii)
if (argc > 1)
{
bool qa_result = false;
volk_gnsssdr_test_case_t test_case = test_cases[ii];
try
const size_t len = std::char_traits<char>::length(argv[1]);
if (len == 0 || len > 2046)
{
qa_result = run_volk_gnsssdr_tests(test_case.desc(), test_case.kernel_ptr(), test_case.name(),
test_case.test_parameters(), &results, test_case.puppet_master_name());
std::cerr << "Test name is too long." << std::endl;
return 0;
}
catch (...)
for (unsigned int ii = 0; ii < test_cases.size(); ++ii)
{
// TODO: what exceptions might we need to catch and how do we handle them?
std::cerr << "Exception found on kernel: " << test_case.name() << std::endl;
qa_result = false;
}
if (qa_result)
{
std::cerr << "Failure on " << test_case.name() << std::endl;
qa_failures.push_back(test_case.name());
if (std::string(argv[1]) == test_cases[ii].name())
{
volk_gnsssdr_test_case_t test_case = test_cases[ii];
if (run_volk_gnsssdr_tests(test_case.desc(), test_case.kernel_ptr(),
test_case.name(),
test_case.test_parameters(), &results,
test_case.puppet_master_name()))
{
return 1;
}
else
{
return 0;
}
}
}
std::cerr << "Did not run a test for kernel: " << std::string(argv[1]) << " !" << std::endl;
return 0;
}
// Generate XML results
print_qa_xml(results, qa_failures.size());
// Summarize QA results
std::cerr << "Kernel QA finished: " << qa_failures.size() << " failures out of "
<< test_cases.size() << " tests." << std::endl;
if (qa_failures.size() > 0)
else
{
std::cerr << "The following kernels failed QA:" << std::endl;
for (unsigned int ii = 0; ii < qa_failures.size(); ++ii)
std::vector<std::string> qa_failures;
// Test every kernel reporting failures when they occur
for (unsigned int ii = 0; ii < test_cases.size(); ++ii)
{
std::cerr << " " << qa_failures[ii] << std::endl;
bool qa_result = false;
volk_gnsssdr_test_case_t test_case = test_cases[ii];
try
{
qa_result = run_volk_gnsssdr_tests(test_case.desc(), test_case.kernel_ptr(), test_case.name(),
test_case.test_parameters(), &results, test_case.puppet_master_name());
}
catch (...)
{
// TODO: what exceptions might we need to catch and how do we handle them?
std::cerr << "Exception found on kernel: " << test_case.name() << std::endl;
qa_result = false;
}
if (qa_result)
{
std::cerr << "Failure on " << test_case.name() << std::endl;
qa_failures.push_back(test_case.name());
}
}
// Generate XML results
print_qa_xml(results, qa_failures.size());
// Summarize QA results
std::cerr << "Kernel QA finished: " << qa_failures.size() << " failures out of "
<< test_cases.size() << " tests." << std::endl;
if (qa_failures.size() > 0)
{
std::cerr << "The following kernels failed QA:" << std::endl;
for (unsigned int ii = 0; ii < qa_failures.size(); ++ii)
{
std::cerr << " " << qa_failures[ii] << std::endl;
}
qa_ret_val = 1;
}
qa_ret_val = 1;
}
return qa_ret_val;
@ -128,7 +159,6 @@ void print_qa_xml(std::vector<volk_gnsssdr_test_results_t> results, unsigned int
qa_file << " </testsuite>" << std::endl;
}
qa_file << "</testsuites>" << std::endl;
qa_file.close();
}

View File

@ -35,7 +35,7 @@ typedef struct volk_gnsssdr_func_desc
const char **impl_names;
const int *impl_deps;
const bool *impl_alignment;
const size_t n_impls;
size_t n_impls;
} volk_gnsssdr_func_desc_t;
//! Prints a list of machines available
@ -68,12 +68,12 @@ VOLK_API size_t volk_gnsssdr_get_alignment(void);
*/
VOLK_API bool volk_gnsssdr_is_aligned(const void *ptr);
// clang-format off
%for kern in kernels:
//! A function pointer to the dispatcher implementation
extern VOLK_API ${kern.pname} ${kern.name};
// clang-format off
//! A function pointer to the fastest aligned implementation
extern VOLK_API ${kern.pname} ${kern.name}_a;
@ -86,9 +86,7 @@ extern VOLK_API void ${kern.name}_manual(${kern.arglist_full}, const char* impl_
//! Get description parameters for this kernel
extern VOLK_API volk_gnsssdr_func_desc_t ${kern.name}_get_func_desc(void);
%endfor
// clang-format off
__VOLK_DECL_END
// clang-format on
#endif /*INCLUDED_VOLK_GNSSSDR_RUNTIME*/

View File

@ -32,9 +32,9 @@ include_directories(
)
if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" )
if(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.15" )
add_definitions( -DGR_GREATER_38=1 )
endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.13" )
endif(${PC_GNURADIO_RUNTIME_VERSION} VERSION_GREATER "3.7.15" )
file(GLOB RESAMPLER_ADAPTER_HEADERS "*.h")

View File

@ -35,7 +35,7 @@
#include "Galileo_E1.h"
#include "GPS_L1_CA.h"
#include "Galileo_E5a.h"
#include "GLONASS_L1_CA.h"
#include "GLONASS_L1_L2_CA.h"
#include <glog/logging.h>
@ -100,7 +100,14 @@ SignalGenerator::SignalGenerator(ConfigurationInterface* configuration,
}
else if (std::find(system.begin(), system.end(), "R") != system.end())
{
vector_length = round((float)fs_in / (GLONASS_L1_CA_CODE_RATE_HZ / GLONASS_L1_CA_CODE_LENGTH_CHIPS));
if (signal1[0].at(0) == '1')
{
vector_length = round((float)fs_in / (GLONASS_L1_CA_CODE_RATE_HZ / GLONASS_L1_CA_CODE_LENGTH_CHIPS));
}
else
{
vector_length = round((float)fs_in / (GLONASS_L2_CA_CODE_RATE_HZ / GLONASS_L2_CA_CODE_LENGTH_CHIPS));
}
}
if (item_type_.compare("gr_complex") == 0)

View File

@ -36,11 +36,12 @@
#include "Galileo_E1.h"
#include "Galileo_E5a.h"
#include "GPS_L1_CA.h"
#include "GLONASS_L1_CA.h"
#include "GLONASS_L1_L2_CA.h"
#include <gnuradio/io_signature.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <fstream>
/*
* Create a new instance of signal_generator_c and return
* a boost shared_ptr. This is effectively the public constructor.

View File

@ -32,7 +32,9 @@
#include "fmcomms2_signal_source.h"
#include "configuration_interface.h"
#include "gnss_sdr_valve.h"
#include "ad9361_manager.h"
#include "GPS_L1_CA.h"
#include "GPS_L2C.h"
#include <glog/logging.h>
#include <iostream>
@ -55,6 +57,7 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration
quadrature_ = configuration->property(role + ".quadrature", true);
rf_dc_ = configuration->property(role + ".rf_dc", true);
bb_dc_ = configuration->property(role + ".bb_dc", true);
RF_channels_ = configuration->property(role + ".RF_channels", 1);
gain_mode_rx1_ = configuration->property(role + ".gain_mode_rx1", std::string("manual"));
gain_mode_rx2_ = configuration->property(role + ".gain_mode_rx2", std::string("manual"));
rf_gain_rx1_ = configuration->property(role + ".gain_rx1", 64.0);
@ -67,6 +70,14 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file);
//AD9361 Local Oscillator generation for dual band operation
enable_dds_lo_ = configuration->property(role + ".enable_dds_lo", false);
freq_rf_tx_hz_ = configuration->property(role + ".freq_rf_tx_hz", GPS_L1_FREQ_HZ - GPS_L2_FREQ_HZ - 1000);
freq_dds_tx_hz_ = configuration->property(role + ".freq_dds_tx_hz", 1000);
scale_dds_dbfs_ = configuration->property(role + ".scale_dds_dbfs", 0.0);
phase_dds_deg_ = configuration->property(role + ".phase_dds_deg", 0.0);
tx_attenuation_db_ = configuration->property(role + ".tx_attenuation_db", 0.0);
item_size_ = sizeof(gr_complex);
std::cout << "device address: " << uri_ << std::endl;
@ -75,15 +86,73 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration
if (item_type_.compare("gr_complex") == 0)
{
fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make(
uri_.c_str(), freq_, sample_rate_,
bandwidth_,
rx1_en_, rx2_en_,
buffer_size_, quadrature_, rf_dc_,
bb_dc_, gain_mode_rx1_.c_str(), rf_gain_rx1_,
gain_mode_rx2_.c_str(), rf_gain_rx2_,
rf_port_select_.c_str(), filter_file_.c_str(),
filter_auto_);
if (RF_channels_ == 1)
{
if (rx1_en_ and rx2_en_)
{
LOG(FATAL) << "Configuration error: both rx1 and rx2 are enabled but RF_channels=1 !";
}
else
{
fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make(
uri_.c_str(), freq_, sample_rate_,
bandwidth_,
rx1_en_, rx2_en_,
buffer_size_, quadrature_, rf_dc_,
bb_dc_, gain_mode_rx1_.c_str(), rf_gain_rx1_,
gain_mode_rx2_.c_str(), rf_gain_rx2_,
rf_port_select_.c_str(), filter_file_.c_str(),
filter_auto_);
//configure LO
if (enable_dds_lo_ == true)
{
std::cout << "Enabling Local Oscillator generator in FMCOMMS2\n";
config_ad9361_lo_remote(uri_,
bandwidth_,
sample_rate_,
freq_rf_tx_hz_,
tx_attenuation_db_,
freq_dds_tx_hz_,
scale_dds_dbfs_);
}
}
}
else if (RF_channels_ == 2)
{
if (!(rx1_en_ and rx2_en_))
{
LOG(FATAL) << "Configuration error: RF_channels=2 but are not enabled both receivers in FMCOMMS2 !";
}
else
{
fmcomms2_source_f32c_ = gr::iio::fmcomms2_source_f32c::make(
uri_.c_str(), freq_, sample_rate_,
bandwidth_,
rx1_en_, rx2_en_,
buffer_size_, quadrature_, rf_dc_,
bb_dc_, gain_mode_rx1_.c_str(), rf_gain_rx1_,
gain_mode_rx2_.c_str(), rf_gain_rx2_,
rf_port_select_.c_str(), filter_file_.c_str(),
filter_auto_);
//configure LO
if (enable_dds_lo_ == true)
{
std::cout << "Enabling Local Oscillator generator in FMCOMMS2\n";
config_ad9361_lo_remote(uri_,
bandwidth_,
sample_rate_,
freq_rf_tx_hz_,
tx_attenuation_db_,
freq_dds_tx_hz_,
scale_dds_dbfs_);
}
}
}
else
{
LOG(FATAL) << "Configuration error: Unsupported number of RF_channels !";
}
}
else
{
@ -108,6 +177,10 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(ConfigurationInterface* configuration
Fmcomms2SignalSource::~Fmcomms2SignalSource()
{
if (enable_dds_lo_ == true)
{
ad9361_disable_lo_remote(uri_);
}
}

View File

@ -88,6 +88,7 @@ private:
bool quadrature_;
bool rf_dc_;
bool bb_dc_;
int RF_channels_;
std::string gain_mode_rx1_;
std::string gain_mode_rx2_;
double rf_gain_rx1_;
@ -96,6 +97,14 @@ private:
std::string filter_file_;
bool filter_auto_;
//DDS configuration for LO generation for external mixer
bool enable_dds_lo_;
unsigned long freq_rf_tx_hz_;
unsigned long freq_dds_tx_hz_;
double scale_dds_dbfs_;
double phase_dds_deg_;
double tx_attenuation_db_;
unsigned int in_stream_;
unsigned int out_stream_;

View File

@ -55,7 +55,7 @@ RtlTcpSignalSource::RtlTcpSignalSource(ConfigurationInterface* configuration,
dump_filename_ = configuration->property(role + ".dump_filename",
default_dump_file);
// rtl_tcp PARAMTERS
// rtl_tcp PARAMETERS
std::string default_address = "127.0.0.1";
short default_port = 1234;
AGC_enabled_ = configuration->property(role + ".AGC_enabled", true);

View File

@ -121,7 +121,7 @@ unpack_2bit_samples::unpack_2bit_samples(bool big_endian_bytes,
bool big_endian_system = systemIsBigEndian();
// Only swap the item bytes if the item size > 1 byte and the system
// endianess is not the same as the item endianness:
// endianness is not the same as the item endianness:
swap_endian_items_ = (item_size_ > 1) &&
(big_endian_system != big_endian_items);

View File

@ -16,16 +16,61 @@
# along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
#
if(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2)
find_package(iio REQUIRED)
if(NOT IIO_FOUND)
message(STATUS "gnuradio-iio not found, its installation is required.")
message(STATUS "Please build and install the following projects:")
message(STATUS " * libiio from https://github.com/analogdevicesinc/libiio")
message(STATUS " * libad9361-iio from https://github.com/analogdevicesinc/libad9361-iio")
message(STATUS " * gnuradio-iio from https://github.com/analogdevicesinc/gr-iio")
message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled")
endif(NOT IIO_FOUND)
set(OPT_LIBRARIES ${OPT_LIBRARIES} ${IIO_LIBRARIES})
set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${IIO_INCLUDE_DIRS})
find_package(libiio REQUIRED)
if(NOT LIBIIO_FOUND)
message(STATUS "gnuradio-iio not found, its installation is required.")
message(STATUS "Please build and install the following projects:")
message(STATUS " * libiio from https://github.com/analogdevicesinc/libiio")
message(STATUS " * libad9361-iio from https://github.com/analogdevicesinc/libad9361-iio")
message(STATUS " * gnuradio-iio from https://github.com/analogdevicesinc/gr-iio")
message(FATAL_ERROR "gnuradio-iio required for building gnss-sdr with this option enabled")
endif(NOT LIBIIO_FOUND)
set(OPT_LIBRARIES ${OPT_LIBRARIES} ${LIBIIO_LIBRARIES})
set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${LIBIIO_INCLUDE_DIRS})
endif(ENABLE_PLUTOSDR OR ENABLE_FMCOMMS2)
if(ENABLE_FMCOMMS2)
###############################################
# FMCOMMS2 based SDR Hardware
###############################################
if(IIO_FOUND)
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ad9361_manager.cc)
endif(IIO_FOUND)
endif(ENABLE_FMCOMMS2)
set (SIGNAL_SOURCE_LIB_SOURCES
rtl_tcp_commands.cc
rtl_tcp_dongle_info.cc)
rtl_tcp_dongle_info.cc
${OPT_SIGNAL_SOURCE_LIB_SOURCES})
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${Boost_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS}
${OPT_DRIVER_INCLUDE_DIRS}
)
file(GLOB SIGNAL_SOURCE_LIB_HEADERS "*.h")
list(SORT SIGNAL_SOURCE_LIB_HEADERS)
list(SORT SIGNAL_SOURCE_LIB_SOURCES)
add_library(signal_source_lib ${SIGNAL_SOURCE_LIB_SOURCES} ${SIGNAL_SOURCE_LIB_HEADERS})
source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS})
source_group(Headers FILES ${SIGNAL_SOURCE_LIB_HEADERS})
add_dependencies(signal_source_lib glog-${glog_RELEASE})
target_link_libraries(signal_source_lib ${OPT_LIBRARIES})

View File

@ -0,0 +1,764 @@
/*!
* \file ad9361_manager.cc
* \brief An Analog Devices AD9361 front-end configuration library wrapper for configure some functions via iiod link.
* \author Javier Arribas, jarribas(at)cttc.es
*
* This file contains information taken from librtlsdr:
* http://git.osmocom.org/rtl-sdr/
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "ad9361_manager.h"
#include <glog/logging.h>
#include <cmath>
#include <iostream>
#include <sstream>
/* check return value of attr_write function */
void errchk(int v, const char *what)
{
if (v < 0)
{
LOG(WARNING) << "Error " << v << " writing to channel " << what << " value may not be supported. ";
}
}
/* write attribute: long long int */
void wr_ch_lli(struct iio_channel *chn, const char *what, long long val)
{
errchk(iio_channel_attr_write_longlong(chn, what, val), what);
}
/* write attribute: string */
void wr_ch_str(struct iio_channel *chn, const char *what, const char *str)
{
errchk(iio_channel_attr_write(chn, what, str), what);
}
/* returns ad9361 phy device */
struct iio_device *get_ad9361_phy(struct iio_context *ctx)
{
struct iio_device *dev = iio_context_find_device(ctx, "ad9361-phy");
return dev;
}
/* finds AD9361 streaming IIO devices */
bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev)
{
switch (d)
{
case TX:
*dev = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc");
return *dev != NULL;
case RX:
*dev = iio_context_find_device(ctx, "cf-ad9361-lpc");
return *dev != NULL;
default:
return false;
}
}
/* finds AD9361 streaming IIO channels */
bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn)
{
std::stringstream name;
name.str("");
name << "voltage";
name << chid;
*chn = iio_device_find_channel(dev, name.str().c_str(), d == TX);
if (!*chn)
{
name.str("");
name << "altvoltage";
name << chid;
*chn = iio_device_find_channel(dev, name.str().c_str(), d == TX);
}
return *chn != NULL;
}
/* finds AD9361 phy IIO configuration channel with id chid */
bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn)
{
std::stringstream name;
switch (d)
{
case RX:
name.str("");
name << "voltage";
name << chid;
*chn = iio_device_find_channel(get_ad9361_phy(ctx), name.str().c_str(), false);
return *chn != NULL;
break;
case TX:
name.str("");
name << "voltage";
name << chid;
*chn = iio_device_find_channel(get_ad9361_phy(ctx), name.str().c_str(), true);
return *chn != NULL;
break;
default:
return false;
}
}
/* finds AD9361 local oscillator IIO configuration channels */
bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn)
{
switch (d)
{
// LO chan is always output, i.e. true
case RX:
*chn = iio_device_find_channel(get_ad9361_phy(ctx), "altvoltage0", true);
return *chn != NULL;
case TX:
*chn = iio_device_find_channel(get_ad9361_phy(ctx), "altvoltage1", true);
return *chn != NULL;
default:
return false;
}
}
/* applies streaming configuration through IIO */
bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid)
{
struct iio_channel *chn = NULL;
// Configure phy and lo channels
//LOG(INFO)<<"* Acquiring AD9361 phy channel"<<chid;
std::cout << "* Acquiring AD9361 phy channel" << chid << std::endl;
if (!get_phy_chan(ctx, type, chid, &chn))
{
return false;
}
wr_ch_str(chn, "rf_port_select", cfg->rfport);
wr_ch_lli(chn, "rf_bandwidth", cfg->bw_hz);
wr_ch_lli(chn, "sampling_frequency", cfg->fs_hz);
// Configure LO channel
//LOG(INFO)<<"* Acquiring AD9361 "<<type == TX ? "TX" : "RX";
std::cout << "* Acquiring AD9361 " << (type == TX ? "TX" : "RX") << std::endl;
if (!get_lo_chan(ctx, type, &chn))
{
return false;
}
wr_ch_lli(chn, "frequency", cfg->lo_hz);
return true;
}
bool config_ad9361_rx_local(unsigned long bandwidth_,
unsigned long sample_rate_,
unsigned long freq_,
std::string rf_port_select_,
std::string gain_mode_rx1_,
std::string gain_mode_rx2_,
double rf_gain_rx1_,
double rf_gain_rx2_)
{
// RX stream config
// Stream configurations
struct stream_cfg rxcfg;
rxcfg.bw_hz = bandwidth_; // 2 MHz rf bandwidth
rxcfg.fs_hz = sample_rate_; // 2.5 MS/s rx sample rate
rxcfg.lo_hz = freq_; // 2.5 GHz rf frequency
rxcfg.rfport = rf_port_select_.c_str(); // port A (select for rf freq.)
std::cout << "AD9361 Acquiring IIO LOCAL context\n";
struct iio_context *ctx;
// Streaming devices
struct iio_device *rx;
struct iio_channel *rx0_i;
struct iio_channel *rx0_q;
ctx = iio_create_default_context();
if (!ctx)
{
std::cout << "No context\n";
throw std::runtime_error("AD9361 IIO No context");
}
if (iio_context_get_devices_count(ctx) <= 0)
{
std::cout << "No devices\n";
throw std::runtime_error("AD9361 IIO No devices");
}
std::cout << "* Acquiring AD9361 streaming devices\n";
if (!get_ad9361_stream_dev(ctx, RX, &rx))
{
std::cout << "No rx dev found\n";
throw std::runtime_error("AD9361 IIO No rx dev found");
};
std::cout << "* Configuring AD9361 for streaming\n";
if (!cfg_ad9361_streaming_ch(ctx, &rxcfg, RX, 0))
{
std::cout << "RX port 0 not found\n";
throw std::runtime_error("AD9361 IIO RX port 0 not found");
}
std::cout << "* Initializing AD9361 IIO streaming channels\n";
if (!get_ad9361_stream_ch(ctx, RX, rx, 0, &rx0_i))
{
std::cout << "RX chan i not found\n";
throw std::runtime_error("RX chan i not found");
}
if (!get_ad9361_stream_ch(ctx, RX, rx, 1, &rx0_q))
{
std::cout << "RX chan q not found\n";
throw std::runtime_error("RX chan q not found");
}
std::cout << "* Enabling IIO streaming channels\n";
iio_channel_enable(rx0_i);
iio_channel_enable(rx0_q);
struct iio_device *ad9361_phy;
ad9361_phy = iio_context_find_device(ctx, "ad9361-phy");
int ret;
ret = iio_device_attr_write(ad9361_phy, "trx_rate_governor", "nominal");
if (ret < 0)
{
std::cout << "Failed to set trx_rate_governor: " << ret << std::endl;
}
ret = iio_device_attr_write(ad9361_phy, "ensm_mode", "fdd");
if (ret < 0)
{
std::cout << "Failed to set ensm_mode: " << ret << std::endl;
}
ret = iio_device_attr_write(ad9361_phy, "calib_mode", "auto");
if (ret < 0)
{
std::cout << "Failed to set calib_mode: " << ret << std::endl;
}
ret = iio_device_attr_write(ad9361_phy, "in_voltage0_gain_control_mode", gain_mode_rx1_.c_str());
if (ret < 0)
{
std::cout << "Failed to set in_voltage0_gain_control_mode: " << ret << std::endl;
}
ret = iio_device_attr_write(ad9361_phy, "in_voltage1_gain_control_mode", gain_mode_rx2_.c_str());
if (ret < 0)
{
std::cout << "Failed to set in_voltage1_gain_control_mode: " << ret << std::endl;
}
ret = iio_device_attr_write_double(ad9361_phy, "in_voltage0_hardwaregain", rf_gain_rx1_);
if (ret < 0)
{
std::cout << "Failed to set in_voltage0_hardwaregain: " << ret << std::endl;
}
ret = iio_device_attr_write_double(ad9361_phy, "in_voltage1_hardwaregain", rf_gain_rx2_);
if (ret < 0)
{
std::cout << "Failed to set in_voltage1_hardwaregain: " << ret << std::endl;
}
std::cout << "End of AD9361 RX configuration.\n";
iio_context_destroy(ctx);
return true;
}
bool config_ad9361_rx_remote(std::string remote_host,
unsigned long bandwidth_,
unsigned long sample_rate_,
unsigned long freq_,
std::string rf_port_select_,
std::string gain_mode_rx1_,
std::string gain_mode_rx2_,
double rf_gain_rx1_,
double rf_gain_rx2_)
{
// RX stream config
// Stream configurations
struct stream_cfg rxcfg;
rxcfg.bw_hz = bandwidth_; // 2 MHz rf bandwidth
rxcfg.fs_hz = sample_rate_; // 2.5 MS/s rx sample rate
rxcfg.lo_hz = freq_; // 2.5 GHz rf frequency
rxcfg.rfport = rf_port_select_.c_str(); // port A (select for rf freq.)
std::cout << "AD9361 Acquiring IIO REMOTE context in host " << remote_host << std::endl;
struct iio_context *ctx;
// Streaming devices
struct iio_device *rx;
struct iio_channel *rx0_i;
struct iio_channel *rx0_q;
ctx = iio_create_network_context(remote_host.c_str());
if (!ctx)
{
std::cout << "No context\n";
throw std::runtime_error("AD9361 IIO No context");
}
if (iio_context_get_devices_count(ctx) <= 0)
{
std::cout << "No devices\n";
throw std::runtime_error("AD9361 IIO No devices");
}
std::cout << "* Acquiring AD9361 streaming devices\n";
if (!get_ad9361_stream_dev(ctx, RX, &rx))
{
std::cout << "No rx dev found\n";
throw std::runtime_error("AD9361 IIO No rx dev found");
};
std::cout << "* Configuring AD9361 for streaming\n";
if (!cfg_ad9361_streaming_ch(ctx, &rxcfg, RX, 0))
{
std::cout << "RX port 0 not found\n";
throw std::runtime_error("AD9361 IIO RX port 0 not found");
}
std::cout << "* Initializing AD9361 IIO streaming channels\n";
if (!get_ad9361_stream_ch(ctx, RX, rx, 0, &rx0_i))
{
std::cout << "RX chan i not found\n";
throw std::runtime_error("RX chan i not found");
}
if (!get_ad9361_stream_ch(ctx, RX, rx, 1, &rx0_q))
{
std::cout << "RX chan q not found\n";
throw std::runtime_error("RX chan q not found");
}
std::cout << "* Enabling IIO streaming channels\n";
iio_channel_enable(rx0_i);
iio_channel_enable(rx0_q);
struct iio_device *ad9361_phy;
ad9361_phy = iio_context_find_device(ctx, "ad9361-phy");
int ret;
ret = iio_device_attr_write(ad9361_phy, "trx_rate_governor", "nominal");
if (ret < 0)
{
std::cout << "Failed to set trx_rate_governor: " << ret << std::endl;
}
ret = iio_device_attr_write(ad9361_phy, "ensm_mode", "fdd");
if (ret < 0)
{
std::cout << "Failed to set ensm_mode: " << ret << std::endl;
}
ret = iio_device_attr_write(ad9361_phy, "calib_mode", "auto");
if (ret < 0)
{
std::cout << "Failed to set calib_mode: " << ret << std::endl;
}
ret = iio_device_attr_write(ad9361_phy, "in_voltage0_gain_control_mode", gain_mode_rx1_.c_str());
if (ret < 0)
{
std::cout << "Failed to set in_voltage0_gain_control_mode: " << ret << std::endl;
}
ret = iio_device_attr_write(ad9361_phy, "in_voltage1_gain_control_mode", gain_mode_rx2_.c_str());
if (ret < 0)
{
std::cout << "Failed to set in_voltage1_gain_control_mode: " << ret << std::endl;
}
ret = iio_device_attr_write_double(ad9361_phy, "in_voltage0_hardwaregain", rf_gain_rx1_);
if (ret < 0)
{
std::cout << "Failed to set in_voltage0_hardwaregain: " << ret << std::endl;
}
ret = iio_device_attr_write_double(ad9361_phy, "in_voltage1_hardwaregain", rf_gain_rx2_);
if (ret < 0)
{
std::cout << "Failed to set in_voltage1_hardwaregain: " << ret << std::endl;
}
std::cout << "End of AD9361 RX configuration.\n";
iio_context_destroy(ctx);
return true;
}
bool config_ad9361_lo_local(unsigned long bandwidth_,
unsigned long sample_rate_,
unsigned long freq_rf_tx_hz_,
double tx_attenuation_db_,
long long freq_dds_tx_hz_,
double scale_dds_dbfs_)
{
// TX stream config
std::cout << "Start of AD9361 TX Local Oscillator DDS configuration\n";
struct stream_cfg txcfg;
txcfg.bw_hz = bandwidth_;
txcfg.fs_hz = sample_rate_;
txcfg.lo_hz = freq_rf_tx_hz_;
txcfg.rfport = "A";
std::cout << "AD9361 Acquiring IIO LOCAL context\n";
struct iio_context *ctx;
ctx = iio_create_default_context();
if (!ctx)
{
std::cout << "No context\n";
throw std::runtime_error("AD9361 IIO No context");
}
//find tx device
struct iio_device *tx;
std::cout << "* Acquiring AD9361 TX streaming devices\n";
if (!get_ad9361_stream_dev(ctx, TX, &tx))
{
std::cout << "No tx dev found\n";
throw std::runtime_error("AD9361 IIO No tx dev found");
};
std::cout << "* Configuring AD9361 for streaming TX\n";
if (!cfg_ad9361_streaming_ch(ctx, &txcfg, TX, 0))
{
std::cout << "TX port 0 not found\n";
throw std::runtime_error("AD9361 IIO TX port 0 not found");
}
//ENABLE DDS on TX1
struct iio_device *ad9361_phy;
ad9361_phy = iio_context_find_device(ctx, "ad9361-phy");
int ret;
//set output amplifier attenuation
ret = iio_device_attr_write_double(ad9361_phy, "out_voltage0_hardwaregain", -tx_attenuation_db_);
if (ret < 0)
{
std::cout << "Failed to set out_voltage0_hardwaregain value " << -tx_attenuation_db_ << " error " << ret << std::endl;
}
struct iio_device *dds;
dds = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc");
struct iio_channel *dds_channel0_I;
dds_channel0_I = iio_device_find_channel(dds, "TX1_I_F1", true);
struct iio_channel *dds_channel0_Q;
dds_channel0_Q = iio_device_find_channel(dds, "TX1_Q_F1", true);
ret = iio_channel_attr_write_bool(dds_channel0_I, "raw", true);
if (ret < 0)
{
std::cout << "Failed to toggle DDS: " << ret << std::endl;
}
//set frequency, scale and phase
ret = iio_channel_attr_write_longlong(dds_channel0_I, "frequency", (long long)freq_dds_tx_hz_);
if (ret < 0)
{
std::cout << "Failed to set TX DDS frequency I: " << ret << std::endl;
}
ret = iio_channel_attr_write_longlong(dds_channel0_Q, "frequency", (long long)freq_dds_tx_hz_);
if (ret < 0)
{
std::cout << "Failed to set TX DDS frequency Q: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_I, "phase", 0.0);
if (ret < 0)
{
std::cout << "Failed to set TX DDS phase I: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_Q, "phase", 270000.0);
if (ret < 0)
{
std::cout << "Failed to set TX DDS phase Q: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_I, "scale", pow(10, scale_dds_dbfs_ / 20.0));
if (ret < 0)
{
std::cout << "Failed to set TX DDS scale I: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_Q, "scale", pow(10, scale_dds_dbfs_ / 20.0));
if (ret < 0)
{
std::cout << "Failed to set TX DDS scale Q: " << ret << std::endl;
}
//disable TX2
ret = iio_device_attr_write_double(ad9361_phy, "out_voltage1_hardwaregain", -89.0);
if (ret < 0)
{
std::cout << "Failed to set out_voltage1_hardwaregain value " << -89.0 << " error " << ret << std::endl;
}
struct iio_channel *dds_channel1_I;
dds_channel1_I = iio_device_find_channel(dds, "TX2_I_F1", true);
struct iio_channel *dds_channel1_Q;
dds_channel1_Q = iio_device_find_channel(dds, "TX2_Q_F1", true);
ret = iio_channel_attr_write_double(dds_channel1_I, "scale", 0);
if (ret < 0)
{
std::cout << "Failed to set TX2 DDS scale I: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel1_Q, "scale", 0);
if (ret < 0)
{
std::cout << "Failed to set TX2 DDS scale Q: " << ret << std::endl;
}
iio_context_destroy(ctx);
return true;
}
bool config_ad9361_lo_remote(std::string remote_host,
unsigned long bandwidth_,
unsigned long sample_rate_,
unsigned long freq_rf_tx_hz_,
double tx_attenuation_db_,
long long freq_dds_tx_hz_,
double scale_dds_dbfs_)
{
// TX stream config
std::cout << "Start of AD9361 TX Local Oscillator DDS configuration\n";
struct stream_cfg txcfg;
txcfg.bw_hz = bandwidth_;
txcfg.fs_hz = sample_rate_;
txcfg.lo_hz = freq_rf_tx_hz_;
txcfg.rfport = "A";
std::cout << "AD9361 Acquiring IIO REMOTE context in host " << remote_host << std::endl;
struct iio_context *ctx;
ctx = iio_create_network_context(remote_host.c_str());
if (!ctx)
{
std::cout << "No context\n";
throw std::runtime_error("AD9361 IIO No context");
}
//find tx device
struct iio_device *tx;
std::cout << "* Acquiring AD9361 TX streaming devices\n";
if (!get_ad9361_stream_dev(ctx, TX, &tx))
{
std::cout << "No tx dev found\n";
throw std::runtime_error("AD9361 IIO No tx dev found");
};
std::cout << "* Configuring AD9361 for streaming TX\n";
if (!cfg_ad9361_streaming_ch(ctx, &txcfg, TX, 0))
{
std::cout << "TX port 0 not found\n";
throw std::runtime_error("AD9361 IIO TX port 0 not found");
}
//ENABLE DDS on TX1
struct iio_device *ad9361_phy;
ad9361_phy = iio_context_find_device(ctx, "ad9361-phy");
int ret;
//set output amplifier attenuation
ret = iio_device_attr_write_double(ad9361_phy, "out_voltage0_hardwaregain", -tx_attenuation_db_);
if (ret < 0)
{
std::cout << "Failed to set out_voltage0_hardwaregain value " << -tx_attenuation_db_ << " error " << ret << std::endl;
}
struct iio_device *dds;
dds = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc");
struct iio_channel *dds_channel0_I;
dds_channel0_I = iio_device_find_channel(dds, "TX1_I_F1", true);
struct iio_channel *dds_channel0_Q;
dds_channel0_Q = iio_device_find_channel(dds, "TX1_Q_F1", true);
ret = iio_channel_attr_write_bool(dds_channel0_I, "raw", true);
if (ret < 0)
{
std::cout << "Failed to toggle DDS: " << ret << std::endl;
}
//set frequency, scale and phase
ret = iio_channel_attr_write_longlong(dds_channel0_I, "frequency", (long long)freq_dds_tx_hz_);
if (ret < 0)
{
std::cout << "Failed to set TX DDS frequency I: " << ret << std::endl;
}
ret = iio_channel_attr_write_longlong(dds_channel0_Q, "frequency", (long long)freq_dds_tx_hz_);
if (ret < 0)
{
std::cout << "Failed to set TX DDS frequency Q: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_I, "phase", 0.0);
if (ret < 0)
{
std::cout << "Failed to set TX DDS phase I: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_Q, "phase", 270000.0);
if (ret < 0)
{
std::cout << "Failed to set TX DDS phase Q: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_I, "scale", pow(10, scale_dds_dbfs_ / 20.0));
if (ret < 0)
{
std::cout << "Failed to set TX DDS scale I: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_Q, "scale", pow(10, scale_dds_dbfs_ / 20.0));
if (ret < 0)
{
std::cout << "Failed to set TX DDS scale Q: " << ret << std::endl;
}
//disable TX2
ret = iio_device_attr_write_double(ad9361_phy, "out_voltage1_hardwaregain", -89.0);
if (ret < 0)
{
std::cout << "Failed to set out_voltage1_hardwaregain value " << -89.0 << " error " << ret << std::endl;
}
struct iio_channel *dds_channel1_I;
dds_channel1_I = iio_device_find_channel(dds, "TX2_I_F1", true);
struct iio_channel *dds_channel1_Q;
dds_channel1_Q = iio_device_find_channel(dds, "TX2_Q_F1", true);
ret = iio_channel_attr_write_double(dds_channel1_I, "scale", 0);
if (ret < 0)
{
std::cout << "Failed to set TX2 DDS scale I: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel1_Q, "scale", 0);
if (ret < 0)
{
std::cout << "Failed to set TX2 DDS scale Q: " << ret << std::endl;
}
iio_context_destroy(ctx);
return true;
}
bool ad9361_disable_lo_remote(std::string remote_host)
{
std::cout << "AD9361 Acquiring IIO REMOTE context in host " << remote_host << std::endl;
struct iio_context *ctx;
ctx = iio_create_network_context(remote_host.c_str());
if (!ctx)
{
std::cout << "No context\n";
throw std::runtime_error("AD9361 IIO No context");
}
struct iio_device *dds;
dds = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc");
struct iio_channel *dds_channel0_I;
dds_channel0_I = iio_device_find_channel(dds, "TX1_I_F1", true);
struct iio_channel *dds_channel0_Q;
dds_channel0_Q = iio_device_find_channel(dds, "TX1_Q_F1", true);
int ret;
ret = iio_channel_attr_write_bool(dds_channel0_I, "raw", false);
if (ret < 0)
{
std::cout << "Failed to toggle DDS: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_I, "scale", 0.0);
if (ret < 0)
{
std::cout << "Failed to set TX DDS scale I: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_Q, "scale", 0.0);
if (ret < 0)
{
std::cout << "Failed to set TX DDS scale Q: " << ret << std::endl;
}
iio_context_destroy(ctx);
return true;
}
bool ad9361_disable_lo_local()
{
std::cout << "AD9361 Acquiring IIO LOCAL context" << std::endl;
struct iio_context *ctx;
ctx = iio_create_default_context();
if (!ctx)
{
std::cout << "No context\n";
throw std::runtime_error("AD9361 IIO No context");
}
struct iio_device *dds;
dds = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc");
struct iio_channel *dds_channel0_I;
dds_channel0_I = iio_device_find_channel(dds, "TX1_I_F1", true);
struct iio_channel *dds_channel0_Q;
dds_channel0_Q = iio_device_find_channel(dds, "TX1_Q_F1", true);
int ret;
ret = iio_channel_attr_write_bool(dds_channel0_I, "raw", false);
if (ret < 0)
{
std::cout << "Failed to toggle DDS: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_I, "scale", 0.0);
if (ret < 0)
{
std::cout << "Failed to set TX DDS scale I: " << ret << std::endl;
}
ret = iio_channel_attr_write_double(dds_channel0_Q, "scale", 0.0);
if (ret < 0)
{
std::cout << "Failed to set TX DDS scale Q: " << ret << std::endl;
}
iio_context_destroy(ctx);
return true;
}

View File

@ -0,0 +1,130 @@
/*!
* \file ad9361_manager.h
* \brief An Analog Devices AD9361 front-end configuration library wrapper for configure some functions via iiod link.
* \author Javier Arribas, jarribas(at)cttc.es
*
* This file contains information taken from librtlsdr:
* http://git.osmocom.org/rtl-sdr/
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_AD9361_MANAGER_H
#define GNSS_SDR_AD9361_MANAGER_H
#include <string>
#ifdef __APPLE__
#include <iio/iio.h>
#else
#include <iio.h>
#endif
/* RX is input, TX is output */
enum iodev
{
RX,
TX
};
/* common RX and TX streaming params */
struct stream_cfg
{
long long bw_hz; // Analog banwidth in Hz
long long fs_hz; // Baseband sample rate in Hz
long long lo_hz; // Local oscillator frequency in Hz
const char *rfport; // Port name
};
/* check return value of attr_write function */
void errchk(int v, const char *what);
/* write attribute: long long int */
void wr_ch_lli(struct iio_channel *chn, const char *what, long long val);
/* write attribute: string */
void wr_ch_str(struct iio_channel *chn, const char *what, const char *str);
/* helper function generating channel names */
char *get_ch_name(const char *type, int id, char *tmpstr);
/* returns ad9361 phy device */
struct iio_device *get_ad9361_phy(struct iio_context *ctx);
/* finds AD9361 streaming IIO devices */
bool get_ad9361_stream_dev(struct iio_context *ctx, enum iodev d, struct iio_device **dev);
/* finds AD9361 streaming IIO channels */
bool get_ad9361_stream_ch(struct iio_context *ctx, enum iodev d, struct iio_device *dev, int chid, struct iio_channel **chn);
/* finds AD9361 phy IIO configuration channel with id chid */
bool get_phy_chan(struct iio_context *ctx, enum iodev d, int chid, struct iio_channel **chn);
/* finds AD9361 local oscillator IIO configuration channels */
bool get_lo_chan(struct iio_context *ctx, enum iodev d, struct iio_channel **chn);
/* applies streaming configuration through IIO */
bool cfg_ad9361_streaming_ch(struct iio_context *ctx, struct stream_cfg *cfg, enum iodev type, int chid);
bool config_ad9361_rx_local(unsigned long bandwidth_,
unsigned long sample_rate_,
unsigned long freq_,
std::string rf_port_select_,
std::string gain_mode_rx1_,
std::string gain_mode_rx2_,
double rf_gain_rx1_,
double rf_gain_rx2_);
bool config_ad9361_rx_remote(std::string remote_host,
unsigned long bandwidth_,
unsigned long sample_rate_,
unsigned long freq_,
std::string rf_port_select_,
std::string gain_mode_rx1_,
std::string gain_mode_rx2_,
double rf_gain_rx1_,
double rf_gain_rx2_);
bool config_ad9361_lo_local(unsigned long bandwidth_,
unsigned long sample_rate_,
unsigned long freq_rf_tx_hz_,
double tx_attenuation_db_,
long long freq_dds_tx_hz_,
double scale_dds_dbfs_);
bool config_ad9361_lo_remote(std::string remote_host,
unsigned long bandwidth_,
unsigned long sample_rate_,
unsigned long freq_rf_tx_hz_,
double tx_attenuation_db_,
long long freq_dds_tx_hz_,
double scale_dds_dbfs_);
bool ad9361_disable_lo_remote(std::string remote_host);
bool ad9361_disable_lo_local();
#endif

View File

@ -24,7 +24,8 @@ set(TELEMETRY_DECODER_ADAPTER_SOURCES
galileo_e1b_telemetry_decoder.cc
sbas_l1_telemetry_decoder.cc
galileo_e5a_telemetry_decoder.cc
glonass_l1_ca_telemetry_decoder.cc
glonass_l1_ca_telemetry_decoder.cc
glonass_l2_ca_telemetry_decoder.cc
)
include_directories(

View File

@ -0,0 +1,103 @@
/*!
* \file glonass_l2_ca_telemetry_decoder.cc
* \brief Implementation of an adapter of a GLONASS L2 C/A NAV data decoder block
* to a TelemetryDecoderInterface
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "glonass_l2_ca_telemetry_decoder.h"
#include "configuration_interface.h"
#include "glonass_gnav_ephemeris.h"
#include "glonass_gnav_almanac.h"
#include "glonass_gnav_utc_model.h"
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
using google::LogMessage;
GlonassL2CaTelemetryDecoder::GlonassL2CaTelemetryDecoder(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams) : role_(role),
in_streams_(in_streams),
out_streams_(out_streams)
{
std::string default_dump_filename = "./navigation.dat";
DLOG(INFO) << "role " << role;
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
// make telemetry decoder object
telemetry_decoder_ = glonass_l2_ca_make_telemetry_decoder_cc(satellite_, dump_);
DLOG(INFO) << "telemetry_decoder(" << telemetry_decoder_->unique_id() << ")";
channel_ = 0;
}
GlonassL2CaTelemetryDecoder::~GlonassL2CaTelemetryDecoder()
{
}
void GlonassL2CaTelemetryDecoder::set_satellite(const Gnss_Satellite& satellite)
{
satellite_ = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
telemetry_decoder_->set_satellite(satellite_);
DLOG(INFO) << "TELEMETRY DECODER: satellite set to " << satellite_;
}
void GlonassL2CaTelemetryDecoder::connect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
// Nothing to connect internally
DLOG(INFO) << "nothing to connect internally";
}
void GlonassL2CaTelemetryDecoder::disconnect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
// Nothing to disconnect
}
gr::basic_block_sptr GlonassL2CaTelemetryDecoder::get_left_block()
{
return telemetry_decoder_;
}
gr::basic_block_sptr GlonassL2CaTelemetryDecoder::get_right_block()
{
return telemetry_decoder_;
}

View File

@ -0,0 +1,90 @@
/*!
* \file glonass_l2_ca_telemetry_decoder.h
* \brief Interface of an adapter of a GLONASS L2 C/A NAV data decoder block
* to a TelemetryDecoderInterface
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GLONASS_L2_CA_TELEMETRY_DECODER_H_
#define GNSS_SDR_GLONASS_L2_CA_TELEMETRY_DECODER_H_
#include "telemetry_decoder_interface.h"
#include "glonass_l2_ca_telemetry_decoder_cc.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a NAV data decoder for GLONASS L2 C/A
*/
class GlonassL2CaTelemetryDecoder : public TelemetryDecoderInterface
{
public:
GlonassL2CaTelemetryDecoder(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~GlonassL2CaTelemetryDecoder();
std::string role() override
{
return role_;
}
//! Returns "GLONASS_L2_CA_Telemetry_Decoder"
std::string implementation() override
{
return "GLONASS_L2_CA_Telemetry_Decoder";
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
void set_satellite(const Gnss_Satellite& satellite) override;
void set_channel(int channel) override { telemetry_decoder_->set_channel(channel); }
void reset() override
{
return;
}
size_t item_size() override
{
return 0;
}
private:
glonass_l2_ca_telemetry_decoder_cc_sptr telemetry_decoder_;
Gnss_Satellite satellite_;
int channel_;
bool dump_;
std::string dump_filename_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
};
#endif

View File

@ -24,6 +24,7 @@ set(TELEMETRY_DECODER_GR_BLOCKS_SOURCES
sbas_l1_telemetry_decoder_cc.cc
galileo_e5a_telemetry_decoder_cc.cc
glonass_l1_ca_telemetry_decoder_cc.cc
glonass_l2_ca_telemetry_decoder_cc.cc
)
include_directories(

View File

@ -320,7 +320,7 @@ int galileo_e1b_telemetry_decoder_cc::general_work(int noutput_items __attribute
d_stat = 1; // enter into frame pre-detection status
}
}
else if (d_stat == 1) // posible preamble lock
else if (d_stat == 1) // possible preamble lock
{
if (abs(corr_value) >= d_symbols_per_preamble)
{

View File

@ -338,7 +338,7 @@ int galileo_e5a_telemetry_decoder_cc::general_work(int noutput_items __attribute
d_stat = 1; // enter into frame pre-detection status
}
}
else if ((d_stat == 1) && new_symbol) // posible preamble lock
else if ((d_stat == 1) && new_symbol) // possible preamble lock
{
if (abs(corr_value) >= GALILEO_FNAV_PREAMBLE_LENGTH_BITS)
{

View File

@ -271,7 +271,7 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the preamble sample stamp
}
}
else if (d_stat == 1) // posible preamble lock
else if (d_stat == 1) // possible preamble lock
{
if (abs(corr_value) >= d_symbols_per_preamble)
{

View File

@ -34,13 +34,13 @@
#define GNSS_SDR_GLONASS_L1_CA_TELEMETRY_DECODER_CC_H
#include "GLONASS_L1_CA.h"
#include "glonass_gnav_navigation_message.h"
#include "glonass_gnav_ephemeris.h"
#include "glonass_gnav_almanac.h"
#include "glonass_gnav_utc_model.h"
#include "gnss_satellite.h"
#include "gnss_synchro.h"
#include "GLONASS_L1_L2_CA.h"
#include <gnuradio/block.h>
#include <fstream>
#include <string>

View File

@ -0,0 +1,449 @@
/*!
* \file glonass_l2_ca_telemetry_decoder_cc.cc
* \brief Implementation of an adapter of a GLONASS L1 C/A NAV data decoder block
* to a TelemetryDecoderInterface
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "glonass_l2_ca_telemetry_decoder_cc.h"
#include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
#define CRC_ERROR_LIMIT 6
using google::LogMessage;
glonass_l2_ca_telemetry_decoder_cc_sptr
glonass_l2_ca_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump)
{
return glonass_l2_ca_telemetry_decoder_cc_sptr(new glonass_l2_ca_telemetry_decoder_cc(satellite, dump));
}
glonass_l2_ca_telemetry_decoder_cc::glonass_l2_ca_telemetry_decoder_cc(
const Gnss_Satellite &satellite,
bool dump) : gr::block("glonass_l2_ca_telemetry_decoder_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{
// Telemetry Bit transition synchronization port out
this->message_port_register_out(pmt::mp("preamble_timestamp_s"));
// Ephemeris data port out
this->message_port_register_out(pmt::mp("telemetry"));
// initialize internal vars
d_dump = dump;
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
LOG(INFO) << "Initializing GLONASS L2 CA TELEMETRY DECODING";
// Define the number of sampes per symbol. Notice that GLONASS has 2 rates,
//one for the navigation data and the other for the preamble information
d_samples_per_symbol = (GLONASS_L2_CA_CODE_RATE_HZ / GLONASS_L2_CA_CODE_LENGTH_CHIPS) / GLONASS_L2_CA_SYMBOL_RATE_BPS;
// Set the preamble information
unsigned short int preambles_bits[GLONASS_GNAV_PREAMBLE_LENGTH_BITS] = GLONASS_GNAV_PREAMBLE;
// Since preamble rate is different than navigation data rate we use a constant
d_symbols_per_preamble = GLONASS_GNAV_PREAMBLE_LENGTH_SYMBOLS;
memcpy(static_cast<unsigned short int *>(this->d_preambles_bits), static_cast<unsigned short int *>(preambles_bits), GLONASS_GNAV_PREAMBLE_LENGTH_BITS * sizeof(unsigned short int));
// preamble bits to sampled symbols
d_preambles_symbols = static_cast<signed int *>(malloc(sizeof(signed int) * d_symbols_per_preamble));
int n = 0;
for (int i = 0; i < GLONASS_GNAV_PREAMBLE_LENGTH_BITS; i++)
{
for (unsigned int j = 0; j < GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_PREAMBLE_BIT; j++)
{
if (d_preambles_bits[i] == 1)
{
d_preambles_symbols[n] = 1;
}
else
{
d_preambles_symbols[n] = -1;
}
n++;
}
}
d_sample_counter = 0;
d_stat = 0;
d_preamble_index = 0;
d_flag_frame_sync = false;
d_flag_parity = false;
d_TOW_at_current_symbol = 0;
Flag_valid_word = false;
delta_t = 0;
d_CRC_error_counter = 0;
d_flag_preamble = false;
d_channel = 0;
flag_TOW_set = false;
d_preamble_time_samples = 0;
}
glonass_l2_ca_telemetry_decoder_cc::~glonass_l2_ca_telemetry_decoder_cc()
{
delete d_preambles_symbols;
if (d_dump_file.is_open() == true)
{
try
{
d_dump_file.close();
}
catch (const std::exception &ex)
{
LOG(WARNING) << "Exception in destructor closing the dump file " << ex.what();
}
}
}
void glonass_l2_ca_telemetry_decoder_cc::decode_string(double *frame_symbols, int frame_length)
{
double chip_acc = 0.0;
int chip_acc_counter = 0;
// 1. Transform from symbols to bits
std::string bi_binary_code;
std::string relative_code;
std::string data_bits;
// Group samples into bi-binary code
for (int i = 0; i < (frame_length); i++)
{
chip_acc += frame_symbols[i];
chip_acc_counter += 1;
if (chip_acc_counter == (GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_BIT))
{
if (chip_acc > 0)
{
bi_binary_code.push_back('1');
chip_acc_counter = 0;
chip_acc = 0;
}
else
{
bi_binary_code.push_back('0');
chip_acc_counter = 0;
chip_acc = 0;
}
}
}
// Convert from bi-binary code to relative code
for (int i = 0; i < (GLONASS_GNAV_STRING_BITS); i++)
{
if (bi_binary_code[2 * i] == '1' && bi_binary_code[2 * i + 1] == '0')
{
relative_code.push_back('1');
}
else
{
relative_code.push_back('0');
}
}
// Convert from relative code to data bits
data_bits.push_back('0');
for (int i = 1; i < (GLONASS_GNAV_STRING_BITS); i++)
{
data_bits.push_back(((relative_code[i - 1] - '0') ^ (relative_code[i] - '0')) + '0');
}
// 2. Call the GLONASS GNAV string decoder
d_nav.string_decoder(data_bits);
// 3. Check operation executed correctly
if (d_nav.flag_CRC_test == true)
{
LOG(INFO) << "GLONASS GNAV CRC correct on channel " << d_channel << " from satellite " << d_satellite;
}
else
{
LOG(INFO) << "GLONASS GNAV CRC error on channel " << d_channel << " from satellite " << d_satellite;
}
// 4. Push the new navigation data to the queues
if (d_nav.have_new_ephemeris() == true)
{
// get object for this SV (mandatory)
d_nav.gnav_ephemeris.i_satellite_freq_channel = d_satellite.get_rf_link();
std::shared_ptr<Glonass_Gnav_Ephemeris> tmp_obj = std::make_shared<Glonass_Gnav_Ephemeris>(d_nav.get_ephemeris());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
LOG(INFO) << "GLONASS GNAV Ephemeris have been received on channel" << d_channel << " from satellite " << d_satellite;
}
if (d_nav.have_new_utc_model() == true)
{
// get object for this SV (mandatory)
std::shared_ptr<Glonass_Gnav_Utc_Model> tmp_obj = std::make_shared<Glonass_Gnav_Utc_Model>(d_nav.get_utc_model());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
LOG(INFO) << "GLONASS GNAV UTC Model have been received on channel" << d_channel << " from satellite " << d_satellite;
}
if (d_nav.have_new_almanac() == true)
{
unsigned int slot_nbr = d_nav.i_alm_satellite_slot_number;
std::shared_ptr<Glonass_Gnav_Almanac> tmp_obj = std::make_shared<Glonass_Gnav_Almanac>(d_nav.get_almanac(slot_nbr));
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
LOG(INFO) << "GLONASS GNAV Almanac have been received on channel" << d_channel << " in slot number " << slot_nbr;
}
// 5. Update satellite information on system
if (d_nav.flag_update_slot_number == true)
{
LOG(INFO) << "GLONASS GNAV Slot Number Identified on channel " << d_channel;
d_satellite.update_PRN(d_nav.gnav_ephemeris.d_n);
d_satellite.what_block(d_satellite.get_system(), d_nav.gnav_ephemeris.d_n);
d_nav.flag_update_slot_number = false;
}
}
int glonass_l2_ca_telemetry_decoder_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
int corr_value = 0;
int preamble_diff = 0;
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer
const Gnss_Synchro **in = reinterpret_cast<const Gnss_Synchro **>(&input_items[0]); // Get the input buffer pointer
Gnss_Synchro current_symbol; //structure to save the synchronization information and send the output object to the next block
//1. Copy the current tracking output
current_symbol = in[0][0];
d_symbol_history.push_back(current_symbol); //add new symbol to the symbol queue
d_sample_counter++; //count for the processed samples
consume_each(1);
d_flag_preamble = false;
unsigned int required_symbols = GLONASS_GNAV_STRING_SYMBOLS;
if (d_symbol_history.size() > required_symbols)
{
//******* preamble correlation ********
for (int i = 0; i < d_symbols_per_preamble; i++)
{
if (d_symbol_history.at(i).Prompt_I < 0) // symbols clipping
{
corr_value -= d_preambles_symbols[i];
}
else
{
corr_value += d_preambles_symbols[i];
}
}
}
//******* frame sync ******************
if (d_stat == 0) //no preamble information
{
if (abs(corr_value) >= d_symbols_per_preamble)
{
// Record the preamble sample stamp
d_preamble_index = d_sample_counter;
LOG(INFO) << "Preamble detection for GLONASS L2 C/A SAT " << this->d_satellite;
// Enter into frame pre-detection status
d_stat = 1;
d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the preamble sample stamp
}
}
else if (d_stat == 1) // possible preamble lock
{
if (abs(corr_value) >= d_symbols_per_preamble)
{
//check preamble separation
preamble_diff = d_sample_counter - d_preamble_index;
// Record the PRN start sample index associated to the preamble
d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter;
if (abs(preamble_diff - GLONASS_GNAV_PREAMBLE_PERIOD_SYMBOLS) == 0)
{
//try to decode frame
LOG(INFO) << "Starting string decoder for GLONASS L2 C/A SAT " << this->d_satellite;
d_preamble_index = d_sample_counter; //record the preamble sample stamp
d_stat = 2;
// send asynchronous message to tracking to inform of frame sync and extend correlation time
pmt::pmt_t value = pmt::from_double(static_cast<double>(d_preamble_time_samples) / static_cast<double>(d_symbol_history.at(0).fs) - 0.001);
this->message_port_pub(pmt::mp("preamble_timestamp_s"), value);
}
else
{
if (preamble_diff > GLONASS_GNAV_PREAMBLE_PERIOD_SYMBOLS)
{
d_stat = 0; // start again
}
DLOG(INFO) << "Failed string decoder for GLONASS L2 C/A SAT " << this->d_satellite;
}
}
}
else if (d_stat == 2)
{
// FIXME: The preamble index marks the first symbol of the string count. Here I just wait for another full string to be received before processing
if (d_sample_counter == d_preamble_index + GLONASS_GNAV_STRING_SYMBOLS)
{
// NEW GLONASS string received
// 0. fetch the symbols into an array
int string_length = GLONASS_GNAV_STRING_SYMBOLS - d_symbols_per_preamble;
double string_symbols[GLONASS_GNAV_DATA_SYMBOLS] = {0};
//******* SYMBOL TO BIT *******
for (int i = 0; i < string_length; i++)
{
if (corr_value > 0)
{
string_symbols[i] = d_symbol_history.at(i + d_symbols_per_preamble).Prompt_I; // because last symbol of the preamble is just received now!
}
else
{
string_symbols[i] = -d_symbol_history.at(i + d_symbols_per_preamble).Prompt_I; // because last symbol of the preamble is just received now!
}
}
//call the decoder
decode_string(string_symbols, string_length);
if (d_nav.flag_CRC_test == true)
{
d_CRC_error_counter = 0;
d_flag_preamble = true; //valid preamble indicator (initialized to false every work())
d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P)
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< d_symbol_history.at(0).Tracking_sample_counter << " [samples]";
}
}
else
{
d_CRC_error_counter++;
d_preamble_index = d_sample_counter; //record the preamble sample stamp
if (d_CRC_error_counter > CRC_ERROR_LIMIT)
{
LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite;
d_flag_frame_sync = false;
d_stat = 0;
}
}
}
}
// UPDATE GNSS SYNCHRO DATA
//2. Add the telemetry decoder information
if (this->d_flag_preamble == true and d_nav.flag_TOW_new == true)
//update TOW at the preamble instant
{
d_TOW_at_current_symbol = floor((d_nav.gnav_ephemeris.d_TOW - GLONASS_GNAV_PREAMBLE_DURATION_S) * 1000) / 1000;
d_nav.flag_TOW_new = false;
}
else //if there is not a new preamble, we define the TOW of the current symbol
{
d_TOW_at_current_symbol = d_TOW_at_current_symbol + GLONASS_L2_CA_CODE_PERIOD;
}
//if (d_flag_frame_sync == true and d_nav.flag_TOW_set==true and d_nav.flag_CRC_test == true)
// if(d_nav.flag_GGTO_1 == true and d_nav.flag_GGTO_2 == true and d_nav.flag_GGTO_3 == true and d_nav.flag_GGTO_4 == true) //all GGTO parameters arrived
// {
// delta_t = d_nav.A_0G_10 + d_nav.A_1G_10 * (d_TOW_at_current_symbol - d_nav.t_0G_10 + 604800.0 * (fmod((d_nav.WN_0 - d_nav.WN_0G_10), 64)));
// }
if (d_flag_frame_sync == true and d_nav.flag_TOW_set == true)
{
current_symbol.Flag_valid_word = true;
}
else
{
current_symbol.Flag_valid_word = false;
}
current_symbol.PRN = this->d_satellite.get_PRN();
current_symbol.TOW_at_current_symbol_s = d_TOW_at_current_symbol;
current_symbol.TOW_at_current_symbol_s -= delta_t; // Galileo to GPS TOW
if (d_dump == true)
{
// MULTIPLEXED FILE RECORDING - Record results to file
try
{
double tmp_double;
unsigned long int tmp_ulong_int;
tmp_double = d_TOW_at_current_symbol;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_ulong_int = current_symbol.Tracking_sample_counter;
d_dump_file.write(reinterpret_cast<char *>(&tmp_ulong_int), sizeof(unsigned long int));
tmp_double = 0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "Exception writing observables dump file " << e.what();
}
}
// remove used symbols from history
if (d_symbol_history.size() > required_symbols)
{
d_symbol_history.pop_front();
}
//3. Make the output (copy the object contents to the GNURadio reserved memory)
*out[0] = current_symbol;
return 1;
}
void glonass_l2_ca_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite)
{
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite;
DLOG(INFO) << "Navigation Satellite set to " << d_satellite;
}
void glonass_l2_ca_telemetry_decoder_cc::set_channel(int channel)
{
d_channel = channel;
LOG(INFO) << "Navigation channel set to " << channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
d_dump_filename = "telemetry";
d_dump_filename.append(boost::lexical_cast<std::string>(d_channel));
d_dump_filename.append(".dat");
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
LOG(INFO) << "Telemetry decoder dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str();
}
catch (const std::ifstream::failure &e)
{
LOG(WARNING) << "channel " << d_channel << ": exception opening Glonass TLM dump file. " << e.what();
}
}
}
}

View File

@ -0,0 +1,117 @@
/*!
* \file glonass_l2_ca_telemetry_decoder_cc.h
* \brief Implementation of an adapter of a GLONASS L2 C/A NAV data decoder block
* to a TelemetryDecoderInterface
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GLONASS_L2_CA_TELEMETRY_DECODER_CC_H
#define GNSS_SDR_GLONASS_L2_CA_TELEMETRY_DECODER_CC_H
#include "GLONASS_L1_L2_CA.h"
#include "glonass_gnav_navigation_message.h"
#include "glonass_gnav_ephemeris.h"
#include "glonass_gnav_almanac.h"
#include "glonass_gnav_utc_model.h"
#include "gnss_satellite.h"
#include "gnss_synchro.h"
#include <gnuradio/block.h>
#include <fstream>
#include <string>
class glonass_l2_ca_telemetry_decoder_cc;
typedef boost::shared_ptr<glonass_l2_ca_telemetry_decoder_cc> glonass_l2_ca_telemetry_decoder_cc_sptr;
glonass_l2_ca_telemetry_decoder_cc_sptr glonass_l2_ca_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
/*!
* \brief This class implements a block that decodes the GNAV data defined in GLONASS ICD v5.1
* \see <a href="http://russianspacesystems.ru/wp-content/uploads/2016/08/ICD_GLONASS_eng_v5.1.pdf">GLONASS ICD</a>
*
*/
class glonass_l2_ca_telemetry_decoder_cc : public gr::block
{
public:
~glonass_l2_ca_telemetry_decoder_cc(); //!< Class destructor
void set_satellite(const Gnss_Satellite &satellite); //!< Set satellite PRN
void set_channel(int channel); //!< Set receiver's channel
/*!
* \brief This is where all signal processing takes place
*/
int general_work(int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
private:
friend glonass_l2_ca_telemetry_decoder_cc_sptr
glonass_l2_ca_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
glonass_l2_ca_telemetry_decoder_cc(const Gnss_Satellite &satellite, bool dump);
void decode_string(double *symbols, int frame_length);
//!< Help with coherent tracking
double d_preamble_time_samples;
//!< Preamble decoding
unsigned short int d_preambles_bits[GLONASS_GNAV_PREAMBLE_LENGTH_BITS];
int *d_preambles_symbols;
unsigned int d_samples_per_symbol;
int d_symbols_per_preamble;
//!< Storage for incoming data
std::deque<Gnss_Synchro> d_symbol_history;
//!< Variables for internal functionality
long unsigned int d_sample_counter; //!< Sample counter as an index (1,2,3,..etc) indicating number of samples processed
long unsigned int d_preamble_index; //!< Index of sample number where preamble was found
unsigned int d_stat; //!< Status of decoder
bool d_flag_frame_sync; //!< Indicate when a frame sync is achieved
bool d_flag_parity; //!< Flag indicating when parity check was achieved (crc check)
bool d_flag_preamble; //!< Flag indicating when preamble was found
int d_CRC_error_counter; //!< Number of failed CRC operations
bool flag_TOW_set; //!< Indicates when time of week is set
double delta_t; //!< GPS-GLONASS time offset
//!< Navigation Message variable
Glonass_Gnav_Navigation_Message d_nav;
//!< Values to populate gnss synchronization structure
double d_TOW_at_current_symbol;
bool Flag_valid_word;
//!< Satellite Information and logging capacity
Gnss_Satellite d_satellite;
int d_channel;
bool d_dump;
std::string d_dump_filename;
std::ofstream d_dump_file;
};
#endif

View File

@ -25,7 +25,7 @@ if(ENABLE_FPGA)
SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_c_aid_tracking_fpga.cc)
endif(ENABLE_FPGA)
set(TRACKING_ADAPTER_SOURCES
set(TRACKING_ADAPTER_SOURCES
galileo_e1_dll_pll_veml_tracking.cc
galileo_e1_tcp_connector_tracking.cc
gps_l1_ca_dll_pll_tracking.cc
@ -36,9 +36,11 @@ set(TRACKING_ADAPTER_SOURCES
glonass_l1_ca_dll_pll_tracking.cc
glonass_l1_ca_dll_pll_c_aid_tracking.cc
gps_l5i_dll_pll_tracking.cc
glonass_l2_ca_dll_pll_tracking.cc
glonass_l2_ca_dll_pll_c_aid_tracking.cc
${OPT_TRACKING_ADAPTERS}
)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/core/system_parameters

View File

@ -51,7 +51,6 @@ GalileoE1DllPllVemlTracking::GalileoE1DllPllVemlTracking(
DLOG(INFO) << "role " << role;
//################# CONFIGURATION PARAMETERS ########################
std::string default_item_type = "gr_complex";
unified_ = configuration->property(role + ".unified", false);
std::string item_type = configuration->property(role + ".item_type", default_item_type);
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
@ -89,45 +88,24 @@ GalileoE1DllPllVemlTracking::GalileoE1DllPllVemlTracking(
//################# MAKE TRACKING GNURadio object ###################
if (item_type.compare("gr_complex") == 0)
{
if (unified_)
{
char sig_[3] = "1B";
item_size_ = sizeof(gr_complex);
tracking_unified_ = dll_pll_veml_make_tracking(
fs_in,
vector_length,
dump,
dump_filename,
pll_bw_hz,
dll_bw_hz,
pll_bw_narrow_hz,
dll_bw_narrow_hz,
early_late_space_chips,
very_early_late_space_chips,
early_late_space_narrow_chips,
very_early_late_space_narrow_chips,
extend_correlation_symbols,
track_pilot, 'E', sig_);
}
else
{
tracking_ = galileo_e1_dll_pll_veml_make_tracking_cc(
0,
fs_in,
vector_length,
dump,
dump_filename,
pll_bw_hz,
dll_bw_hz,
pll_bw_narrow_hz,
dll_bw_narrow_hz,
early_late_space_chips,
very_early_late_space_chips,
early_late_space_narrow_chips,
very_early_late_space_narrow_chips,
extend_correlation_symbols,
track_pilot);
}
item_size_ = sizeof(gr_complex);
char sig_[3] = "1B";
tracking_ = dll_pll_veml_make_tracking(
fs_in,
vector_length,
dump,
dump_filename,
pll_bw_hz,
dll_bw_hz,
pll_bw_narrow_hz,
dll_bw_narrow_hz,
early_late_space_chips,
very_early_late_space_chips,
early_late_space_narrow_chips,
very_early_late_space_narrow_chips,
extend_correlation_symbols,
track_pilot, 'E', sig_);
}
else
{
@ -147,10 +125,7 @@ GalileoE1DllPllVemlTracking::~GalileoE1DllPllVemlTracking()
void GalileoE1DllPllVemlTracking::start_tracking()
{
if (unified_)
tracking_unified_->start_tracking();
else
tracking_->start_tracking();
tracking_->start_tracking();
}
@ -160,19 +135,13 @@ void GalileoE1DllPllVemlTracking::start_tracking()
void GalileoE1DllPllVemlTracking::set_channel(unsigned int channel)
{
channel_ = channel;
if (unified_)
tracking_unified_->set_channel(channel);
else
tracking_->set_channel(channel);
tracking_->set_channel(channel);
}
void GalileoE1DllPllVemlTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
if (unified_)
tracking_unified_->set_gnss_synchro(p_gnss_synchro);
else
tracking_->set_gnss_synchro(p_gnss_synchro);
tracking_->set_gnss_synchro(p_gnss_synchro);
}
@ -196,17 +165,11 @@ void GalileoE1DllPllVemlTracking::disconnect(gr::top_block_sptr top_block)
gr::basic_block_sptr GalileoE1DllPllVemlTracking::get_left_block()
{
if (unified_)
return tracking_unified_;
else
return tracking_;
return tracking_;
}
gr::basic_block_sptr GalileoE1DllPllVemlTracking::get_right_block()
{
if (unified_)
return tracking_unified_;
else
return tracking_;
return tracking_;
}

View File

@ -38,7 +38,6 @@
#define GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_H_
#include "tracking_interface.h"
#include "galileo_e1_dll_pll_veml_tracking_cc.h"
#include "dll_pll_veml_tracking.h"
#include <string>
@ -95,14 +94,12 @@ public:
void start_tracking() override;
private:
galileo_e1_dll_pll_veml_tracking_cc_sptr tracking_;
dll_pll_veml_tracking_sptr tracking_unified_;
dll_pll_veml_tracking_sptr tracking_;
size_t item_size_;
unsigned int channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
bool unified_;
};
#endif // GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_H_

View File

@ -39,8 +39,8 @@
#include "glonass_l1_ca_dll_pll_c_aid_tracking.h"
#include "configuration_interface.h"
#include "GLONASS_L1_CA.h"
#include "gnss_sdr_flags.h"
#include "GLONASS_L1_L2_CA.h"
#include <glog/logging.h>

View File

@ -38,8 +38,8 @@
#include "glonass_l1_ca_dll_pll_tracking.h"
#include "configuration_interface.h"
#include "GLONASS_L1_CA.h"
#include "gnss_sdr_flags.h"
#include "GLONASS_L1_L2_CA.h"
#include <glog/logging.h>

View File

@ -0,0 +1,241 @@
/*!
* \file glonass_l2_ca_dll_pll_c_aid_tracking.cc
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for Glonass L2 C/A to a TrackingInterface
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkha user, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "glonass_l2_ca_dll_pll_c_aid_tracking.h"
#include "configuration_interface.h"
#include "GLONASS_L1_L2_CA.h"
#include "gnss_sdr_flags.h"
#include <glog/logging.h>
using google::LogMessage;
GlonassL2CaDllPllCAidTracking::GlonassL2CaDllPllCAidTracking(
ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
DLOG(INFO) << "role " << role;
//################# CONFIGURATION PARAMETERS ########################
int fs_in;
int vector_length;
int f_if;
bool dump;
std::string dump_filename;
std::string default_item_type = "gr_complex";
float pll_bw_hz;
float pll_bw_narrow_hz;
float dll_bw_hz;
float dll_bw_narrow_hz;
float early_late_space_chips;
item_type_ = configuration->property(role + ".item_type", default_item_type);
//vector_length = configuration->property(role + ".vector_length", 2048);
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
f_if = configuration->property(role + ".if", 0);
dump = configuration->property(role + ".dump", false);
pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0);
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 20.0);
dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 2.0);
int extend_correlation_ms;
extend_correlation_ms = configuration->property(role + ".extend_correlation_ms", 1);
early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5);
std::string default_dump_filename = "./track_ch";
dump_filename = configuration->property(role + ".dump_filename",
default_dump_filename); //unused!
vector_length = std::round(fs_in / (GLONASS_L2_CA_CODE_RATE_HZ / GLONASS_L2_CA_CODE_LENGTH_CHIPS));
//################# MAKE TRACKING GNURadio object ###################
if (item_type_.compare("gr_complex") == 0)
{
item_size_ = sizeof(gr_complex);
tracking_cc = glonass_l2_ca_dll_pll_c_aid_make_tracking_cc(
f_if,
fs_in,
vector_length,
dump,
dump_filename,
pll_bw_hz,
dll_bw_hz,
pll_bw_narrow_hz,
dll_bw_narrow_hz,
extend_correlation_ms,
early_late_space_chips);
DLOG(INFO) << "tracking(" << tracking_cc->unique_id() << ")";
}
else if (item_type_.compare("cshort") == 0)
{
item_size_ = sizeof(lv_16sc_t);
tracking_sc = glonass_l2_ca_dll_pll_c_aid_make_tracking_sc(
f_if,
fs_in,
vector_length,
dump,
dump_filename,
pll_bw_hz,
dll_bw_hz,
pll_bw_narrow_hz,
dll_bw_narrow_hz,
extend_correlation_ms,
early_late_space_chips);
DLOG(INFO) << "tracking(" << tracking_sc->unique_id() << ")";
}
else
{
item_size_ = sizeof(gr_complex);
LOG(WARNING) << item_type_ << " unknown tracking item type.";
}
channel_ = 0;
}
GlonassL2CaDllPllCAidTracking::~GlonassL2CaDllPllCAidTracking()
{
}
void GlonassL2CaDllPllCAidTracking::start_tracking()
{
if (item_type_.compare("gr_complex") == 0)
{
tracking_cc->start_tracking();
}
else if (item_type_.compare("cshort") == 0)
{
tracking_sc->start_tracking();
}
else
{
LOG(WARNING) << item_type_ << " unknown tracking item type";
}
}
/*
* Set tracking channel unique ID
*/
void GlonassL2CaDllPllCAidTracking::set_channel(unsigned int channel)
{
channel_ = channel;
if (item_type_.compare("gr_complex") == 0)
{
tracking_cc->set_channel(channel);
}
else if (item_type_.compare("cshort") == 0)
{
tracking_sc->set_channel(channel);
}
else
{
LOG(WARNING) << item_type_ << " unknown tracking item type";
}
}
void GlonassL2CaDllPllCAidTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
if (item_type_.compare("gr_complex") == 0)
{
tracking_cc->set_gnss_synchro(p_gnss_synchro);
}
else if (item_type_.compare("cshort") == 0)
{
tracking_sc->set_gnss_synchro(p_gnss_synchro);
}
else
{
LOG(WARNING) << item_type_ << " unknown tracking item type";
}
}
void GlonassL2CaDllPllCAidTracking::connect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
//nothing to connect, now the tracking uses gr_sync_decimator
}
void GlonassL2CaDllPllCAidTracking::disconnect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
//nothing to disconnect, now the tracking uses gr_sync_decimator
}
gr::basic_block_sptr GlonassL2CaDllPllCAidTracking::get_left_block()
{
if (item_type_.compare("gr_complex") == 0)
{
return tracking_cc;
}
else if (item_type_.compare("cshort") == 0)
{
return tracking_sc;
}
else
{
LOG(WARNING) << item_type_ << " unknown tracking item type";
return nullptr;
}
}
gr::basic_block_sptr GlonassL2CaDllPllCAidTracking::get_right_block()
{
if (item_type_.compare("gr_complex") == 0)
{
return tracking_cc;
}
else if (item_type_.compare("cshort") == 0)
{
return tracking_sc;
}
else
{
LOG(WARNING) << item_type_ << " unknown tracking item type";
return nullptr;
}
}

View File

@ -0,0 +1,106 @@
/*!
* \file glonass_l2_ca_dll_pll_c_aid_tracking.h
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for Glonass L2 C/A to a TrackingInterface
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkha user, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GLONASS_L2_CA_DLL_PLL_C_AID_TRACKING_H_
#define GNSS_SDR_GLONASS_L2_CA_DLL_PLL_C_AID_TRACKING_H_
#include "tracking_interface.h"
#include "glonass_l2_ca_dll_pll_c_aid_tracking_cc.h"
#include "glonass_l2_ca_dll_pll_c_aid_tracking_sc.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a code DLL + carrier PLL tracking loop
*/
class GlonassL2CaDllPllCAidTracking : public TrackingInterface
{
public:
GlonassL2CaDllPllCAidTracking(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~GlonassL2CaDllPllCAidTracking();
inline std::string role() override
{
return role_;
}
//! Returns "GLONASS_L2_CA_DLL_PLL_C_Aid_Tracking"
inline std::string implementation() override
{
return "GLONASS_L2_CA_DLL_PLL_C_Aid_Tracking";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set tracking channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
void start_tracking() override;
private:
glonass_l2_ca_dll_pll_c_aid_tracking_cc_sptr tracking_cc;
glonass_l2_ca_dll_pll_c_aid_tracking_sc_sptr tracking_sc;
size_t item_size_;
std::string item_type_;
unsigned int channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
};
#endif // GNSS_SDR_GLONASS_L2_CA_DLL_PLL_C_AID_TRACKING_H_

View File

@ -0,0 +1,154 @@
/*!
* \file glonass_l2_ca_dll_pll_tracking.cc
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for Glonass L2 C/A to a TrackingInterface
* \author Damian Miralles, 2018, dmiralles2009(at)gmail.com *
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkha user, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "glonass_l2_ca_dll_pll_tracking.h"
#include "configuration_interface.h"
#include "GLONASS_L1_L2_CA.h"
#include "gnss_sdr_flags.h"
#include <glog/logging.h>
using google::LogMessage;
GlonassL2CaDllPllTracking::GlonassL2CaDllPllTracking(
ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
DLOG(INFO) << "role " << role;
//################# CONFIGURATION PARAMETERS ########################
int fs_in;
int vector_length;
int f_if;
bool dump;
std::string dump_filename;
std::string item_type;
std::string default_item_type = "gr_complex";
float pll_bw_hz;
float dll_bw_hz;
float early_late_space_chips;
item_type = configuration->property(role + ".item_type", default_item_type);
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
f_if = configuration->property(role + ".if", 0);
dump = configuration->property(role + ".dump", false);
pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0);
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5);
std::string default_dump_filename = "./track_ch";
dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); //unused!
vector_length = std::round(fs_in / (GLONASS_L2_CA_CODE_RATE_HZ / GLONASS_L2_CA_CODE_LENGTH_CHIPS));
//################# MAKE TRACKING GNURadio object ###################
if (item_type.compare("gr_complex") == 0)
{
item_size_ = sizeof(gr_complex);
tracking_ = glonass_l2_ca_dll_pll_make_tracking_cc(
f_if,
fs_in,
vector_length,
dump,
dump_filename,
pll_bw_hz,
dll_bw_hz,
early_late_space_chips);
}
else
{
item_size_ = sizeof(gr_complex);
LOG(WARNING) << item_type << " unknown tracking item type.";
}
channel_ = 0;
DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")";
}
GlonassL2CaDllPllTracking::~GlonassL2CaDllPllTracking()
{
}
void GlonassL2CaDllPllTracking::start_tracking()
{
tracking_->start_tracking();
}
/*
* Set tracking channel unique ID
*/
void GlonassL2CaDllPllTracking::set_channel(unsigned int channel)
{
channel_ = channel;
tracking_->set_channel(channel);
}
void GlonassL2CaDllPllTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
tracking_->set_gnss_synchro(p_gnss_synchro);
}
void GlonassL2CaDllPllTracking::connect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
//nothing to connect, now the tracking uses gr_sync_decimator
}
void GlonassL2CaDllPllTracking::disconnect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
//nothing to disconnect, now the tracking uses gr_sync_decimator
}
gr::basic_block_sptr GlonassL2CaDllPllTracking::get_left_block()
{
return tracking_;
}
gr::basic_block_sptr GlonassL2CaDllPllTracking::get_right_block()
{
return tracking_;
}

View File

@ -0,0 +1,103 @@
/*!
* \file glonass_l2_ca_dll_pll_tracking.h
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for Glonass L2 C/A to a TrackingInterface
* \author Damian Miralles, 2018, dmiralles2009(at)gmail.com
*
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkha user, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GLONASS_L2_CA_DLL_PLL_TRACKING_H_
#define GNSS_SDR_GLONASS_L2_CA_DLL_PLL_TRACKING_H_
#include "tracking_interface.h"
#include "glonass_l2_ca_dll_pll_tracking_cc.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a code DLL + carrier PLL tracking loop
*/
class GlonassL2CaDllPllTracking : public TrackingInterface
{
public:
GlonassL2CaDllPllTracking(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~GlonassL2CaDllPllTracking();
inline std::string role() override
{
return role_;
}
//! Returns "GLONASS_L1_CA_DLL_PLL_Tracking"
inline std::string implementation() override
{
return "GLONASS_L2_CA_DLL_PLL_Tracking";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set tracking channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
void start_tracking() override;
private:
glonass_l2_ca_dll_pll_tracking_cc_sptr tracking_;
size_t item_size_;
unsigned int channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
};
#endif // GNSS_SDR_GLONASS_L2_CA_DLL_PLL_TRACKING_H_

View File

@ -56,7 +56,6 @@ GpsL1CaDllPllTracking::GpsL1CaDllPllTracking(
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
bool dump = configuration->property(role + ".dump", false);
unified_ = configuration->property(role + ".unified", false);
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 20.0);
@ -132,10 +131,7 @@ GpsL1CaDllPllTracking::~GpsL1CaDllPllTracking()
void GpsL1CaDllPllTracking::start_tracking()
{
if (unified_)
tracking_unified_->start_tracking();
else
tracking_->start_tracking();
tracking_->start_tracking();
}
@ -145,19 +141,13 @@ void GpsL1CaDllPllTracking::start_tracking()
void GpsL1CaDllPllTracking::set_channel(unsigned int channel)
{
channel_ = channel;
if (unified_)
tracking_unified_->set_channel(channel);
else
tracking_->set_channel(channel);
tracking_->set_channel(channel);
}
void GpsL1CaDllPllTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
if (unified_)
tracking_unified_->set_gnss_synchro(p_gnss_synchro);
else
tracking_->set_gnss_synchro(p_gnss_synchro);
tracking_->set_gnss_synchro(p_gnss_synchro);
}
@ -181,17 +171,11 @@ void GpsL1CaDllPllTracking::disconnect(gr::top_block_sptr top_block)
gr::basic_block_sptr GpsL1CaDllPllTracking::get_left_block()
{
if (unified_)
return tracking_unified_;
else
return tracking_;
return tracking_;
}
gr::basic_block_sptr GpsL1CaDllPllTracking::get_right_block()
{
if (unified_)
return tracking_unified_;
else
return tracking_;
return tracking_;
}

View File

@ -39,7 +39,6 @@
#define GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_H_
#include "tracking_interface.h"
#include "gps_l1_ca_dll_pll_tracking_cc.h"
#include "dll_pll_veml_tracking.h"
#include <string>
@ -93,14 +92,12 @@ public:
void start_tracking() override;
private:
gps_l1_ca_dll_pll_tracking_cc_sptr tracking_;
dll_pll_veml_tracking_sptr tracking_unified_;
dll_pll_veml_tracking_sptr tracking_;
size_t item_size_;
unsigned int channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
bool unified_;
};
#endif // GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_H_

View File

@ -19,7 +19,7 @@
if(ENABLE_CUDA)
set(OPT_TRACKING_BLOCKS ${OPT_TRACKING_BLOCKS} gps_l1_ca_dll_pll_tracking_gpu_cc.cc)
set(OPT_TRACKING_INCLUDES ${OPT_TRACKING_INCLUDES} ${CUDA_INCLUDE_DIRS})
set(OPT_TRACKING_LIBRARIES ${OPT_TRACKING_LIBRARIES} ${CUDA_LIBRARIES})
set(OPT_TRACKING_LIBRARIES ${OPT_TRACKING_LIBRARIES} ${CUDA_LIBRARIES})
endif(ENABLE_CUDA)
if(ENABLE_FPGA)
@ -27,9 +27,7 @@ if(ENABLE_FPGA)
endif(ENABLE_FPGA)
set(TRACKING_GR_BLOCKS_SOURCES
galileo_e1_dll_pll_veml_tracking_cc.cc
galileo_e1_tcp_connector_tracking_cc.cc
gps_l1_ca_dll_pll_tracking_cc.cc
gps_l1_ca_tcp_connector_tracking_cc.cc
galileo_e5a_dll_pll_tracking_cc.cc
gps_l2_m_dll_pll_tracking_cc.cc
@ -39,8 +37,11 @@ set(TRACKING_GR_BLOCKS_SOURCES
glonass_l1_ca_dll_pll_tracking_cc.cc
glonass_l1_ca_dll_pll_c_aid_tracking_cc.cc
glonass_l1_ca_dll_pll_c_aid_tracking_sc.cc
glonass_l2_ca_dll_pll_tracking_cc.cc
glonass_l2_ca_dll_pll_c_aid_tracking_cc.cc
glonass_l2_ca_dll_pll_c_aid_tracking_sc.cc
dll_pll_veml_tracking.cc
${OPT_TRACKING_BLOCKS}
${OPT_TRACKING_BLOCKS}
)
include_directories(

View File

@ -1,8 +1,7 @@
/*!
* \file dll_pll_veml_tracking.cc
* \brief Implementation of a code DLL + carrier PLL VEML (Very Early
* Minus Late) tracking block for Galileo E1 signals
* \author Luis Esteve, 2012. luis(at)epsilon-formacion.com
* \brief Implementation of a code DLL + carrier PLL tracking block.
* \author Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com
*
* Code DLL + carrier PLL according to the algorithms described in:
* [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
@ -11,7 +10,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -39,8 +38,6 @@
#include "lock_detectors.h"
#include "control_message_factory.h"
#include "MATH_CONSTANTS.h"
#include "gnss_sdr_flags.h"
#include "Galileo_E1.h"
#include "galileo_e1_signal_processing.h"
#include "Galileo_E5a.h"
@ -51,17 +48,16 @@
#include "gps_l2c_signal.h"
#include "GPS_L5.h"
#include "gps_l5_signal.h"
#include "gnss_sdr_flags.h"
#include <boost/lexical_cast.hpp>
#include <glog/logging.h>
#include <gnuradio/io_signature.h>
#include <matio.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h>
#include <glog/logging.h>
#include <matio.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
using google::LogMessage;
@ -116,8 +112,9 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
float pll_bw_narrow_hz, float dll_bw_narrow_hz,
float early_late_space_chips, float very_early_late_space_chips,
float early_late_space_narrow_chips, float very_early_late_space_narrow_chips,
int extend_correlation_symbols, bool track_pilot, char system, char signal[3]) : gr::block("dll_pll_veml_tracking", gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
int extend_correlation_symbols, bool track_pilot, char system,
char signal[3]) : gr::block("dll_pll_veml_tracking", gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{
// Telemetry bit synchronization message port input
this->message_port_register_in(pmt::mp("preamble_timestamp_s"));
@ -149,7 +146,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
d_correlation_length_ms = 1;
d_code_samples_per_chip = 1;
d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS);
//GPS L1 C/A does not have pilot component nor secondary code
// GPS L1 C/A does not have pilot component nor secondary code
d_secondary = false;
d_track_pilot = false;
interchange_iq = false;
@ -163,7 +160,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
d_symbols_per_bit = GPS_L2_SAMPLES_PER_SYMBOL;
d_correlation_length_ms = 20;
d_code_samples_per_chip = 1;
//GPS L2 does not have pilot component nor secondary code
// GPS L2 does not have pilot component nor secondary code
d_secondary = false;
d_track_pilot = false;
interchange_iq = false;
@ -177,7 +174,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
d_correlation_length_ms = 1;
d_code_samples_per_chip = 1;
d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
//GPS L5 does not have pilot secondary code
// GPS L5 does not have pilot secondary code
d_secondary = true;
if (d_track_pilot)
{
@ -195,7 +192,15 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
else
{
LOG(WARNING) << "Invalid Signal argument when instantiating tracking blocks";
std::cout << "Invalid Signal argument when instantiating tracking blocks" << std::endl;
std::cerr << "Invalid Signal argument when instantiating tracking blocks" << std::endl;
d_correlation_length_ms = 1;
d_secondary = false;
interchange_iq = false;
d_signal_carrier_freq = 0.0;
d_code_period = 0.0;
d_code_length_chips = 0;
d_code_samples_per_chip = 0;
d_symbols_per_bit = 0;
}
}
else if (system == 'E')
@ -249,12 +254,28 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
{
LOG(WARNING) << "Invalid Signal argument when instantiating tracking blocks";
std::cout << "Invalid Signal argument when instantiating tracking blocks" << std::endl;
d_correlation_length_ms = 1;
d_secondary = false;
interchange_iq = false;
d_signal_carrier_freq = 0.0;
d_code_period = 0.0;
d_code_length_chips = 0;
d_code_samples_per_chip = 0;
d_symbols_per_bit = 0;
}
}
else
{
LOG(WARNING) << "Invalid System argument when instantiating tracking blocks";
std::cout << "Invalid System argument when instantiating tracking blocks" << std::endl;
std::cerr << "Invalid System argument when instantiating tracking blocks" << std::endl;
d_correlation_length_ms = 1;
d_secondary = false;
interchange_iq = false;
d_signal_carrier_freq = 0.0;
d_code_period = 0.0;
d_code_length_chips = 0;
d_code_samples_per_chip = 0;
d_symbols_per_bit = 0;
}
T_chip_seconds = 0.0;
T_prn_seconds = 0.0;
@ -349,6 +370,11 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
d_data_code = static_cast<float *>(volk_gnsssdr_malloc(2 * d_code_length_chips * sizeof(float), volk_gnsssdr_get_alignment()));
}
else
{
d_Prompt_Data = nullptr;
d_data_code = nullptr;
}
//--- Initializations ---//
// Initial code frequency basis of NCO
@ -402,12 +428,11 @@ void dll_pll_veml_tracking::start_tracking()
d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz;
d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples;
long int acq_trk_diff_samples = static_cast<long int>(d_sample_counter) - static_cast<long int>(d_acq_sample_stamp); //-d_vector_length;
long int acq_trk_diff_samples = static_cast<long int>(d_sample_counter) - static_cast<long int>(d_acq_sample_stamp);
double acq_trk_diff_seconds = static_cast<double>(acq_trk_diff_samples) / d_fs_in;
DLOG(INFO) << "Number of samples between Acquisition and Tracking = " << acq_trk_diff_samples;
DLOG(INFO) << "Number of seconds between Acquisition and Tracking = " << acq_trk_diff_seconds;
// Doppler effect
// Fd=(C/(C+Vr))*F
// Doppler effect Fd = (C / (C + Vr)) * F
double radial_velocity = (d_signal_carrier_freq + d_acq_carrier_doppler_hz) / d_signal_carrier_freq;
// new chip and prn sequence periods based on acq Doppler
d_code_freq_chips = radial_velocity * d_code_chip_rate;
@ -416,13 +441,13 @@ void dll_pll_veml_tracking::start_tracking()
double T_prn_mod_seconds = T_chip_mod_seconds * static_cast<double>(d_code_length_chips);
double T_prn_mod_samples = T_prn_mod_seconds * d_fs_in;
d_current_prn_length_samples = round(T_prn_mod_samples);
d_current_prn_length_samples = std::round(T_prn_mod_samples);
double T_prn_true_seconds = static_cast<double>(d_code_length_chips) / d_code_chip_rate;
double T_prn_true_samples = T_prn_true_seconds * d_fs_in;
double T_prn_diff_seconds = T_prn_true_seconds - T_prn_mod_seconds;
double N_prn_diff = acq_trk_diff_seconds / T_prn_true_seconds;
double corrected_acq_phase_samples = fmod(d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * d_fs_in, T_prn_true_samples);
double corrected_acq_phase_samples = std::fmod(d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * d_fs_in, T_prn_true_samples);
if (corrected_acq_phase_samples < 0.0)
{
corrected_acq_phase_samples += T_prn_mod_samples;
@ -477,7 +502,7 @@ void dll_pll_veml_tracking::start_tracking()
}
else if (systemName.compare("Galileo") == 0 and signal_type.compare("5X") == 0)
{
gr_complex aux_code[d_code_length_chips];
gr_complex *aux_code = static_cast<gr_complex *>(volk_gnsssdr_malloc(sizeof(gr_complex) * d_code_length_chips, volk_gnsssdr_get_alignment()));
galileo_e5_a_code_gen_complex_primary(aux_code, d_acquisition_gnss_synchro->PRN, const_cast<char *>(signal_type.c_str()));
if (d_track_pilot)
{
@ -497,6 +522,7 @@ void dll_pll_veml_tracking::start_tracking()
d_tracking_code[i] = aux_code[i].real();
}
}
volk_gnsssdr_free(aux_code);
}
multicorrelator_cpu.set_local_code_and_taps(d_code_samples_per_chip * d_code_length_chips, d_tracking_code, d_local_code_shift_chips);
@ -594,7 +620,7 @@ dll_pll_veml_tracking::~dll_pll_veml_tracking()
bool dll_pll_veml_tracking::acquire_secondary()
{
//******* preamble correlation ********
// ******* preamble correlation ********
int corr_value = 0;
for (unsigned int i = 0; i < d_secondary_code_length; i++)
{
@ -756,13 +782,14 @@ void dll_pll_veml_tracking::clear_tracking_vars()
d_last_prompt = gr_complex(0.0, 0.0);
}
void dll_pll_veml_tracking::update_tracking_vars()
{
T_chip_seconds = 1.0 / d_code_freq_chips;
T_prn_seconds = T_chip_seconds * static_cast<double>(d_code_length_chips);
double code_error_filt_secs = T_prn_seconds * d_code_error_filt_chips * T_chip_seconds; //[seconds]
// ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT #######################
// ################## CARRIER AND CODE NCO BUFFER ALIGNMENT #######################
// keep alignment parameters for the next input buffer
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
T_prn_samples = T_prn_seconds * d_fs_in;
@ -786,6 +813,7 @@ void dll_pll_veml_tracking::update_tracking_vars()
d_rem_code_phase_chips = d_code_freq_chips * d_rem_code_phase_samples / d_fs_in;
}
void dll_pll_veml_tracking::save_correlation_results()
{
if (d_secondary)
@ -890,12 +918,15 @@ void dll_pll_veml_tracking::log_data(bool integrating)
{
//TODO: Improve this solution!
// It compensates the amplitude difference while integrating
float scale_factor = static_cast<float>(d_extend_correlation_symbols) / static_cast<float>(d_extend_correlation_symbols_count);
tmp_VE *= scale_factor;
tmp_E *= scale_factor;
tmp_P *= scale_factor;
tmp_L *= scale_factor;
tmp_VL *= scale_factor;
if (d_extend_correlation_symbols_count > 0)
{
float scale_factor = static_cast<float>(d_extend_correlation_symbols) / static_cast<float>(d_extend_correlation_symbols_count);
tmp_VE *= scale_factor;
tmp_E *= scale_factor;
tmp_P *= scale_factor;
tmp_L *= scale_factor;
tmp_VL *= scale_factor;
}
}
try
@ -951,305 +982,6 @@ void dll_pll_veml_tracking::log_data(bool integrating)
}
int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
gr::thread::scoped_lock l(d_setlock);
const gr_complex *in = reinterpret_cast<const gr_complex *>(input_items[0]);
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]);
Gnss_Synchro current_synchro_data = Gnss_Synchro();
switch (d_state)
{
case 0: // Standby - Pass Through. Full throttle
{
d_sample_counter += ninput_items[0];
consume_each(ninput_items[0]);
return 0;
break;
}
case 1: // Pull-in
{
// Signal alignment (skip samples until the incoming signal is aligned with local replica)
// Fill the acquisition data
int acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp;
double acq_trk_shif_correction_samples = static_cast<double>(d_current_prn_length_samples) - std::fmod(static_cast<double>(acq_to_trk_delay_samples), static_cast<double>(d_current_prn_length_samples));
int samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples);
if (samples_offset < 0)
{
samples_offset = 0;
}
d_acc_carrier_phase_rad -= d_carrier_phase_step_rad * static_cast<double>(samples_offset);
d_state = 2;
d_sample_counter += samples_offset; // count for the processed samples
consume_each(samples_offset); // shift input to perform alignment with local replica
return 0;
}
case 2: // Wide tracking and symbol synchronization
{
do_correlation_step(in);
// Save single correlation step variables
if (d_veml)
{
d_VE_accu = *d_Very_Early;
d_VL_accu = *d_Very_Late;
}
d_E_accu = *d_Early;
d_P_accu = *d_Prompt;
d_L_accu = *d_Late;
// Check lock status
if (!cn0_and_tracking_lock_status())
{
clear_tracking_vars();
d_state = 0; // loss-of-lock detected
}
else
{
bool next_state = false;
// Perform DLL/PLL tracking loop computations. Costas Loop enabled
run_dll_pll();
update_tracking_vars();
// enable write dump file this cycle (valid DLL/PLL cycle)
log_data(false);
if (d_secondary)
{
// ####### SECONDARY CODE LOCK #####
d_Prompt_buffer_deque.push_back(*d_Prompt);
if (d_Prompt_buffer_deque.size() == d_secondary_code_length)
{
next_state = acquire_secondary();
if (next_state)
{
std::cout << "Secondary code locked for CH " << d_channel
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
}
d_Prompt_buffer_deque.pop_front();
}
}
else if (d_symbols_per_bit > 1) //Signal does not have secondary code. Search a bit transition by sign change
{
if (d_synchonizing)
{
if (d_Prompt->real() * d_last_prompt.real() > 0.0)
{
d_current_symbol++;
}
else if (d_current_symbol > d_symbols_per_bit)
{
d_synchonizing = false;
d_current_symbol = 1;
}
else
{
d_current_symbol = 1;
d_last_prompt = *d_Prompt;
}
}
else if (d_last_prompt.real() != 0.0)
{
d_current_symbol++;
if (d_current_symbol == d_symbols_per_bit) next_state = true;
}
else
{
d_last_prompt = *d_Prompt;
d_synchonizing = true;
d_current_symbol = 1;
}
}
else
{
next_state = true;
}
if (next_state)
{ // reset extended correlator
d_VE_accu = gr_complex(0.0, 0.0);
d_E_accu = gr_complex(0.0, 0.0);
d_P_accu = gr_complex(0.0, 0.0);
d_L_accu = gr_complex(0.0, 0.0);
d_VL_accu = gr_complex(0.0, 0.0);
d_last_prompt = gr_complex(0.0, 0.0);
d_Prompt_buffer_deque.clear();
d_current_symbol = 0;
d_synchonizing = false;
if (d_enable_extended_integration)
{
// UPDATE INTEGRATION TIME
d_extend_correlation_symbols_count = 0;
float new_correlation_time = static_cast<float>(d_extend_correlation_symbols) * static_cast<float>(d_code_period);
d_carrier_loop_filter.set_pdi(new_correlation_time);
d_code_loop_filter.set_pdi(new_correlation_time);
d_state = 3; // next state is the extended correlator integrator
LOG(INFO) << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH "
<< d_channel
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN);
std::cout << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH "
<< d_channel
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
// Set narrow taps delay values [chips]
d_code_loop_filter.set_DLL_BW(d_dll_bw_narrow_hz);
d_carrier_loop_filter.set_PLL_BW(d_pll_bw_narrow_hz);
if (d_veml)
{
d_local_code_shift_chips[0] = -d_very_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[1] = -d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[3] = d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[4] = d_very_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
}
else
{
d_local_code_shift_chips[0] = -d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[2] = d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
}
}
else
{
d_state = 4;
}
}
}
break;
}
case 3: // coherent integration (correlation time extension)
{
// Fill the acquisition data
current_synchro_data = *d_acquisition_gnss_synchro;
// perform a correlation step
do_correlation_step(in);
update_tracking_vars();
save_correlation_results();
// ########### Output the tracking results to Telemetry block ##########
if (interchange_iq)
{
if (d_track_pilot)
{
//Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
}
}
else
{
if (d_track_pilot)
{
//Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
}
}
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
current_synchro_data.Flag_valid_symbol_output = true;
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
d_extend_correlation_symbols_count++;
if (d_extend_correlation_symbols_count == (d_extend_correlation_symbols - 1))
{
d_extend_correlation_symbols_count = 0;
d_state = 4;
}
log_data(true);
break;
}
case 4: // narrow tracking
{
// Fill the acquisition data
current_synchro_data = *d_acquisition_gnss_synchro;
// perform a correlation step
do_correlation_step(in);
save_correlation_results();
// check lock status
if (!cn0_and_tracking_lock_status())
{
clear_tracking_vars();
d_state = 0; // loss-of-lock detected
}
else
{
run_dll_pll();
update_tracking_vars();
// ########### Output the tracking results to Telemetry block ##########
if (interchange_iq)
{
if (d_track_pilot)
{
//Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
}
}
else
{
if (d_track_pilot)
{
//Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
}
}
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
current_synchro_data.Flag_valid_symbol_output = true;
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
// enable write dump file this cycle (valid DLL/PLL cycle)
log_data(false);
// reset extended correlator
d_VE_accu = gr_complex(0.0, 0.0);
d_E_accu = gr_complex(0.0, 0.0);
d_P_accu = gr_complex(0.0, 0.0);
d_L_accu = gr_complex(0.0, 0.0);
d_VL_accu = gr_complex(0.0, 0.0);
if (d_enable_extended_integration)
{
d_state = 3; //new coherent integration (correlation time extension) cycle
}
}
}
}
consume_each(d_current_prn_length_samples);
d_sample_counter += d_current_prn_length_samples;
if (current_synchro_data.Flag_valid_symbol_output)
{
current_synchro_data.fs = static_cast<long int>(d_fs_in);
current_synchro_data.Tracking_sample_counter = d_sample_counter;
*out[0] = current_synchro_data;
return 1;
}
return 0;
}
int dll_pll_veml_tracking::save_matfile()
{
// READ DUMP FILE
@ -1505,3 +1237,301 @@ void dll_pll_veml_tracking::set_gnss_synchro(Gnss_Synchro *p_gnss_synchro)
gr::thread::scoped_lock l(d_setlock);
d_acquisition_gnss_synchro = p_gnss_synchro;
}
int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
gr::thread::scoped_lock l(d_setlock);
const gr_complex *in = reinterpret_cast<const gr_complex *>(input_items[0]);
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]);
Gnss_Synchro current_synchro_data = Gnss_Synchro();
switch (d_state)
{
case 0: // Standby - Consume samples at full throttle, do nothing
{
d_sample_counter += ninput_items[0];
consume_each(ninput_items[0]);
return 0;
break;
}
case 1: // Pull-in
{
// Signal alignment (skip samples until the incoming signal is aligned with local replica)
unsigned long int acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp;
double acq_trk_shif_correction_samples = static_cast<double>(d_current_prn_length_samples) - std::fmod(static_cast<double>(acq_to_trk_delay_samples), static_cast<double>(d_current_prn_length_samples));
int samples_offset = std::round(d_acq_code_phase_samples + acq_trk_shif_correction_samples);
if (samples_offset < 0)
{
samples_offset = 0;
}
d_acc_carrier_phase_rad -= d_carrier_phase_step_rad * d_acq_code_phase_samples;
d_state = 2;
d_sample_counter += samples_offset; // count for the processed samples
consume_each(samples_offset); // shift input to perform alignment with local replica
return 0;
}
case 2: // Wide tracking and symbol synchronization
{
do_correlation_step(in);
// Save single correlation step variables
if (d_veml)
{
d_VE_accu = *d_Very_Early;
d_VL_accu = *d_Very_Late;
}
d_E_accu = *d_Early;
d_P_accu = *d_Prompt;
d_L_accu = *d_Late;
// Check lock status
if (!cn0_and_tracking_lock_status())
{
clear_tracking_vars();
d_state = 0; // loss-of-lock detected
}
else
{
bool next_state = false;
// Perform DLL/PLL tracking loop computations. Costas Loop enabled
run_dll_pll();
update_tracking_vars();
// enable write dump file this cycle (valid DLL/PLL cycle)
log_data(false);
if (d_secondary)
{
// ####### SECONDARY CODE LOCK #####
d_Prompt_buffer_deque.push_back(*d_Prompt);
if (d_Prompt_buffer_deque.size() == d_secondary_code_length)
{
next_state = acquire_secondary();
if (next_state)
{
std::cout << "Secondary code locked for CH " << d_channel
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
}
d_Prompt_buffer_deque.pop_front();
}
}
else if (d_symbols_per_bit > 1) //Signal does not have secondary code. Search a bit transition by sign change
{
if (d_synchonizing)
{
if (d_Prompt->real() * d_last_prompt.real() > 0.0)
{
d_current_symbol++;
}
else if (d_current_symbol > d_symbols_per_bit)
{
d_synchonizing = false;
d_current_symbol = 1;
}
else
{
d_current_symbol = 1;
d_last_prompt = *d_Prompt;
}
}
else if (d_last_prompt.real() != 0.0)
{
d_current_symbol++;
if (d_current_symbol == d_symbols_per_bit) next_state = true;
}
else
{
d_last_prompt = *d_Prompt;
d_synchonizing = true;
d_current_symbol = 1;
}
}
else
{
next_state = true;
}
if (next_state)
{ // reset extended correlator
d_VE_accu = gr_complex(0.0, 0.0);
d_E_accu = gr_complex(0.0, 0.0);
d_P_accu = gr_complex(0.0, 0.0);
d_L_accu = gr_complex(0.0, 0.0);
d_VL_accu = gr_complex(0.0, 0.0);
d_last_prompt = gr_complex(0.0, 0.0);
d_Prompt_buffer_deque.clear();
d_current_symbol = 0;
d_synchonizing = false;
if (d_enable_extended_integration)
{
// UPDATE INTEGRATION TIME
d_extend_correlation_symbols_count = 0;
float new_correlation_time = static_cast<float>(d_extend_correlation_symbols) * static_cast<float>(d_code_period);
d_carrier_loop_filter.set_pdi(new_correlation_time);
d_code_loop_filter.set_pdi(new_correlation_time);
d_state = 3; // next state is the extended correlator integrator
LOG(INFO) << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH "
<< d_channel
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN);
std::cout << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH "
<< d_channel
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
// Set narrow taps delay values [chips]
d_code_loop_filter.set_DLL_BW(d_dll_bw_narrow_hz);
d_carrier_loop_filter.set_PLL_BW(d_pll_bw_narrow_hz);
if (d_veml)
{
d_local_code_shift_chips[0] = -d_very_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[1] = -d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[3] = d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[4] = d_very_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
}
else
{
d_local_code_shift_chips[0] = -d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[2] = d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
}
}
else
{
d_state = 4;
}
}
}
break;
}
case 3: // coherent integration (correlation time extension)
{
// Fill the acquisition data
current_synchro_data = *d_acquisition_gnss_synchro;
// perform a correlation step
do_correlation_step(in);
update_tracking_vars();
save_correlation_results();
// ########### Output the tracking results to Telemetry block ##########
if (interchange_iq)
{
if (d_track_pilot)
{
// Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
}
}
else
{
if (d_track_pilot)
{
// Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
}
}
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
current_synchro_data.Flag_valid_symbol_output = true;
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
d_extend_correlation_symbols_count++;
if (d_extend_correlation_symbols_count == (d_extend_correlation_symbols - 1))
{
d_extend_correlation_symbols_count = 0;
d_state = 4;
}
log_data(true);
break;
}
case 4: // narrow tracking
{
// Fill the acquisition data
current_synchro_data = *d_acquisition_gnss_synchro;
// perform a correlation step
do_correlation_step(in);
save_correlation_results();
// check lock status
if (!cn0_and_tracking_lock_status())
{
clear_tracking_vars();
d_state = 0; // loss-of-lock detected
}
else
{
run_dll_pll();
update_tracking_vars();
// ########### Output the tracking results to Telemetry block ##########
if (interchange_iq)
{
if (d_track_pilot)
{
// Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
}
}
else
{
if (d_track_pilot)
{
// Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
}
}
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
current_synchro_data.Flag_valid_symbol_output = true;
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
// enable write dump file this cycle (valid DLL/PLL cycle)
log_data(false);
// reset extended correlator
d_VE_accu = gr_complex(0.0, 0.0);
d_E_accu = gr_complex(0.0, 0.0);
d_P_accu = gr_complex(0.0, 0.0);
d_L_accu = gr_complex(0.0, 0.0);
d_VL_accu = gr_complex(0.0, 0.0);
if (d_enable_extended_integration)
{
d_state = 3; // new coherent integration (correlation time extension) cycle
}
}
}
}
consume_each(d_current_prn_length_samples);
d_sample_counter += d_current_prn_length_samples;
if (current_synchro_data.Flag_valid_symbol_output)
{
current_synchro_data.fs = static_cast<long int>(d_fs_in);
current_synchro_data.Tracking_sample_counter = d_sample_counter;
*out[0] = current_synchro_data;
return 1;
}
return 0;
}

View File

@ -1,8 +1,7 @@
/*!
* \file dll_pll_veml_tracking.h
* \brief Implementation of a code DLL + carrier PLL VEML (Very Early
* Minus Late) tracking block for Galileo E1 signals
* \author Luis Esteve, 2012. luis(at)epsilon-formacion.com
* \brief Implementation of a code DLL + carrier PLL tracking block.
* \author Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com
*
* -------------------------------------------------------------------------
*
@ -36,9 +35,9 @@
#include "tracking_2nd_DLL_filter.h"
#include "tracking_2nd_PLL_filter.h"
#include "cpu_multicorrelator_real_codes.h"
#include <gnuradio/block.h>
#include <fstream>
#include <string>
#include <gnuradio/block.h>
class dll_pll_veml_tracking;
@ -56,8 +55,7 @@ dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(double fs_in, unsigned int
char system, char signal[3]);
/*!
* \brief This class implements a code DLL + carrier PLL VEML (Very Early
* Minus Late) tracking block for Galileo E1 signals
* \brief This class implements a code DLL + carrier PLL tracking block.
*/
class dll_pll_veml_tracking : public gr::block
{
@ -68,12 +66,6 @@ public:
void set_gnss_synchro(Gnss_Synchro *p_gnss_synchro);
void start_tracking();
/*!
* \brief Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency Approach,
* Birkhauser, 2007
*/
int general_work(int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
@ -215,9 +207,9 @@ private:
double T_prn_seconds;
double T_prn_samples;
double K_blk_samples;
//PRN period in samples
// PRN period in samples
int d_current_prn_length_samples;
//processing samples counters
// processing samples counters
unsigned long int d_sample_counter;
unsigned long int d_acq_sample_stamp;
@ -235,4 +227,4 @@ private:
std::ofstream d_dump_file;
};
#endif //GNSS_SDR_DLL_PLL_VEML_TRACKING_H
#endif // GNSS_SDR_DLL_PLL_VEML_TRACKING_H

View File

@ -1,244 +0,0 @@
/*!
* \file galileo_e1_dll_pll_veml_tracking_cc.h
* \brief Implementation of a code DLL + carrier PLL VEML (Very Early
* Minus Late) tracking block for Galileo E1 signals
* \author Luis Esteve, 2012. luis(at)epsilon-formacion.com
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_CC_H
#define GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_CC_H
#include "gnss_synchro.h"
#include "tracking_2nd_DLL_filter.h"
#include "tracking_2nd_PLL_filter.h"
#include "cpu_multicorrelator_real_codes.h"
#include <gnuradio/block.h>
#include <fstream>
#include <string>
#include <map>
class galileo_e1_dll_pll_veml_tracking_cc;
typedef boost::shared_ptr<galileo_e1_dll_pll_veml_tracking_cc> galileo_e1_dll_pll_veml_tracking_cc_sptr;
galileo_e1_dll_pll_veml_tracking_cc_sptr
galileo_e1_dll_pll_veml_make_tracking_cc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
float early_late_space_chips,
float very_early_late_space_chips,
float early_late_space_narrow_chips,
float very_early_late_space_narrow_chips,
int extend_correlation_symbols,
bool track_pilot);
/*!
* \brief This class implements a code DLL + carrier PLL VEML (Very Early
* Minus Late) tracking block for Galileo E1 signals
*/
class galileo_e1_dll_pll_veml_tracking_cc : public gr::block
{
public:
~galileo_e1_dll_pll_veml_tracking_cc();
void set_channel(unsigned int channel);
void set_gnss_synchro(Gnss_Synchro *p_gnss_synchro);
void start_tracking();
/*!
* \brief Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency Approach,
* Birkhauser, 2007
*/
int general_work(int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
void forecast(int noutput_items, gr_vector_int &ninput_items_required);
private:
friend galileo_e1_dll_pll_veml_tracking_cc_sptr
galileo_e1_dll_pll_veml_make_tracking_cc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
float early_late_space_chips,
float very_early_late_space_chips,
float early_late_space_narrow_chips,
float very_early_late_space_narrow_chips,
int extend_correlation_symbols,
bool track_pilot);
galileo_e1_dll_pll_veml_tracking_cc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
float early_late_space_chips,
float very_early_late_space_chips,
float early_late_space_narrow_chips,
float very_early_late_space_narrow_chips,
int extend_correlation_symbols,
bool track_pilot);
bool cn0_and_tracking_lock_status();
void do_correlation_step(const gr_complex *input_samples);
void run_dll_pll(bool disable_costas_loop);
void update_local_code();
void update_local_carrier();
bool acquire_secondary();
void clear_tracking_vars();
void log_data();
// tracking configuration vars
unsigned int d_vector_length;
bool d_dump;
Gnss_Synchro *d_acquisition_gnss_synchro;
unsigned int d_channel;
long d_if_freq;
long d_fs_in;
//tracking state machine
int d_state;
//Integration period in samples
int d_correlation_length_samples;
int d_n_correlator_taps;
double d_early_late_spc_chips;
double d_very_early_late_spc_chips;
double d_early_late_spc_narrow_chips;
double d_very_early_late_spc_narrow_chips;
float *d_tracking_code;
float *d_data_code;
float *d_local_code_shift_chips;
gr_complex *d_correlator_outs;
cpu_multicorrelator_real_codes multicorrelator_cpu;
//todo: currently the multicorrelator does not support adding extra correlator
//with different local code, thus we need extra multicorrelator instance.
//Implement this functionality inside multicorrelator class
//as an enhancement to increase the performance
float *d_local_code_data_shift_chips;
cpu_multicorrelator_real_codes correlator_data_cpu; //for data channel
gr_complex *d_Very_Early;
gr_complex *d_Early;
gr_complex *d_Prompt;
gr_complex *d_Late;
gr_complex *d_Very_Late;
int d_extend_correlation_symbols;
int d_extend_correlation_symbols_count;
bool d_enable_extended_integration;
int d_current_symbol;
gr_complex d_VE_accu;
gr_complex d_E_accu;
gr_complex d_P_accu;
gr_complex d_L_accu;
gr_complex d_VL_accu;
bool d_track_pilot;
gr_complex *d_Prompt_Data;
double d_code_phase_step_chips;
double d_carrier_phase_step_rad;
// remaining code phase and carrier phase between tracking loops
double d_rem_code_phase_samples;
double d_rem_carr_phase_rad;
// PLL and DLL filter library
Tracking_2nd_DLL_filter d_code_loop_filter;
Tracking_2nd_PLL_filter d_carrier_loop_filter;
// acquisition
double d_acq_code_phase_samples;
double d_acq_carrier_doppler_hz;
// tracking parameters
float d_dll_bw_hz;
float d_pll_bw_hz;
float d_dll_bw_narrow_hz;
float d_pll_bw_narrow_hz;
// tracking vars
double d_carr_error_hz;
double d_carr_error_filt_hz;
double d_code_error_chips;
double d_code_error_filt_chips;
double d_K_blk_samples;
double d_code_freq_chips;
double d_carrier_doppler_hz;
double d_acc_carrier_phase_rad;
double d_rem_code_phase_chips;
double d_code_phase_samples;
//PRN period in samples
int d_current_prn_length_samples;
//processing samples counters
unsigned long int d_sample_counter;
unsigned long int d_acq_sample_stamp;
// CN0 estimation and lock detector
int d_cn0_estimation_counter;
std::deque<gr_complex> d_Prompt_buffer_deque;
gr_complex *d_Prompt_buffer;
double d_carrier_lock_test;
double d_CN0_SNV_dB_Hz;
double d_carrier_lock_threshold;
int d_carrier_lock_fail_counter;
// file dump
std::string d_dump_filename;
std::ofstream d_dump_file;
std::map<std::string, std::string> systemName;
std::string sys;
int save_matfile();
};
#endif //GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_CC_H

View File

@ -355,13 +355,13 @@ int Galileo_E1_Tcp_Connector_Tracking_cc::general_work(int noutput_items __attri
code_error_filt_secs = (Galileo_E1_CODE_PERIOD * code_error_filt_chips) / Galileo_E1_CODE_CHIP_RATE_HZ; //[seconds]
d_acc_code_phase_secs = d_acc_code_phase_secs + code_error_filt_secs;
// ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT #######################
// ################## CARRIER AND CODE NCO BUFFER ALIGNMENT #######################
// keep alignment parameters for the next input buffer
double T_chip_seconds;
double T_prn_seconds;
double T_prn_samples;
double K_blk_samples;
// Compute the next buffer lenght based in the new period of the PRN sequence and the code phase error estimation
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
T_chip_seconds = 1 / static_cast<double>(d_code_freq_chips);
T_prn_seconds = T_chip_seconds * Galileo_E1_B_CODE_LENGTH_CHIPS;
T_prn_samples = T_prn_seconds * static_cast<double>(d_fs_in);
@ -443,21 +443,18 @@ int Galileo_E1_Tcp_Connector_Tracking_cc::general_work(int noutput_items __attri
// MULTIPLEXED FILE RECORDING - Record results to file
float prompt_I;
float prompt_Q;
float tmp_VE, tmp_E, tmp_P, tmp_L, tmp_VL;
float tmp_E, tmp_P, tmp_L;
float tmp_VE = 0.0;
float tmp_VL = 0.0;
float tmp_float;
tmp_float = 0;
double tmp_double;
prompt_I = (*d_Prompt).real();
prompt_Q = (*d_Prompt).imag();
tmp_VE = std::abs<float>(*d_Very_Early);
tmp_E = std::abs<float>(*d_Early);
tmp_P = std::abs<float>(*d_Prompt);
tmp_L = std::abs<float>(*d_Late);
tmp_VL = std::abs<float>(*d_Very_Late);
prompt_I = d_correlator_outs[1].real();
prompt_Q = d_correlator_outs[1].imag();
tmp_E = std::abs<float>(d_correlator_outs[0]);
tmp_P = std::abs<float>(d_correlator_outs[1]);
tmp_L = std::abs<float>(d_correlator_outs[2]);
try
{
// EPR
// Dump correlators output
d_dump_file.write(reinterpret_cast<char *>(&tmp_VE), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_E), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_P), sizeof(float));
@ -469,30 +466,33 @@ int Galileo_E1_Tcp_Connector_Tracking_cc::general_work(int noutput_items __attri
// PRN start sample stamp
d_dump_file.write(reinterpret_cast<char *>(&d_sample_counter), sizeof(unsigned long int));
// accumulated carrier phase
d_dump_file.write(reinterpret_cast<char *>(&d_acc_carrier_phase_rad), sizeof(float));
tmp_float = d_acc_carrier_phase_rad;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// carrier and code frequency
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_doppler_hz), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&d_code_freq_chips), sizeof(float));
//PLL commands
tmp_float = d_carrier_doppler_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&carr_error_filt_hz), sizeof(float));
//DLL commands
tmp_float = d_code_freq_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// PLL commands
tmp_float = 0.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = carr_error_filt_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// DLL commands
tmp_float = 0.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = code_error_filt_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&code_error_filt_chips), sizeof(float));
// CN0 and carrier lock test
d_dump_file.write(reinterpret_cast<char *>(&d_CN0_SNV_dB_Hz), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_lock_test), sizeof(float));
// AUX vars (for debug purposes)
tmp_float = d_rem_code_phase_samples;
tmp_float = d_CN0_SNV_dB_Hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_double = static_cast<double>(d_sample_counter + d_current_prn_length_samples);
tmp_float = d_carrier_lock_test;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// AUX vars (for debug purposes)
tmp_float = 0.0;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
double tmp_double = static_cast<double>(d_sample_counter + d_correlation_length_samples);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
// PRN
unsigned int prn_ = d_acquisition_gnss_synchro->PRN;
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(unsigned int));

View File

@ -38,9 +38,9 @@
#include "glonass_l1_ca_dll_pll_c_aid_tracking_cc.h"
#include "glonass_l1_signal_processing.h"
#include "GLONASS_L1_L2_CA.h"
#include "tracking_discriminators.h"
#include "lock_detectors.h"
#include "GLONASS_L1_CA.h"
#include "gnss_sdr_flags.h"
#include "control_message_factory.h"
#include <boost/lexical_cast.hpp>
@ -56,6 +56,8 @@
#include <sstream>
#define CN0_ESTIMATION_SAMPLES 10
using google::LogMessage;
glonass_l1_ca_dll_pll_c_aid_tracking_cc_sptr
@ -605,7 +607,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_cc::general_work(int noutput_items __at
d_code_phase_step_chips,
d_correlation_length_samples);
// ####### coherent intergration extension
// ####### coherent integration extension
// keep the last symbols
d_E_history.push_back(d_correlator_outs[0]); // save early output
d_P_history.push_back(d_correlator_outs[1]); // save prompt output
@ -720,7 +722,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_cc::general_work(int noutput_items __at
d_code_error_filt_chips_Ti = d_code_error_filt_chips_s * CURRENT_INTEGRATION_TIME_S;
code_error_filt_secs_Ti = d_code_error_filt_chips_Ti / d_code_freq_chips; // [s/Ti]
// ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT #######################
// ################## CARRIER AND CODE NCO BUFFER ALIGNMENT #######################
// keep alignment parameters for the next input buffer
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
double T_chip_seconds = 1.0 / d_code_freq_chips;
@ -750,7 +752,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_cc::general_work(int noutput_items __at
d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast<double>(d_fs_in));
// ####### CN0 ESTIMATION AND LOCK DETECTORS #######################################
if (d_cn0_estimation_counter < FLAGS_cn0_samples)
if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES)
{
// fill buffer with prompt correlator output values
d_Prompt_buffer[d_cn0_estimation_counter] = d_correlator_outs[1]; // prompt
@ -760,9 +762,9 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_cc::general_work(int noutput_items __at
{
d_cn0_estimation_counter = 0;
// Code lock indicator
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, FLAGS_cn0_samples, d_fs_in, GLONASS_L1_CA_CODE_LENGTH_CHIPS);
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, GLONASS_L1_CA_CODE_LENGTH_CHIPS);
// Carrier lock indicator
d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, FLAGS_cn0_samples);
d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES);
// Loss of lock detection
if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < FLAGS_cn0_min)
{
@ -829,7 +831,9 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_cc::general_work(int noutput_items __at
float prompt_I;
float prompt_Q;
float tmp_E, tmp_P, tmp_L;
double tmp_double;
float tmp_VE = 0.0;
float tmp_VL = 0.0;
float tmp_float;
prompt_I = d_correlator_outs[1].real();
prompt_Q = d_correlator_outs[1].imag();
tmp_E = std::abs<float>(d_correlator_outs[0]);
@ -837,42 +841,45 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_cc::general_work(int noutput_items __at
tmp_L = std::abs<float>(d_correlator_outs[2]);
try
{
// EPR
// Dump correlators output
d_dump_file.write(reinterpret_cast<char *>(&tmp_VE), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_E), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_P), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_L), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_VL), sizeof(float));
// PROMPT I and Q (to analyze navigation symbols)
d_dump_file.write(reinterpret_cast<char *>(&prompt_I), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&prompt_Q), sizeof(float));
// PRN start sample stamp
//tmp_float=(float)d_sample_counter;
d_dump_file.write(reinterpret_cast<char *>(&d_sample_counter), sizeof(unsigned long int));
// accumulated carrier phase
d_dump_file.write(reinterpret_cast<char *>(&d_acc_carrier_phase_cycles), sizeof(double));
tmp_float = d_acc_carrier_phase_cycles * GLONASS_TWO_PI;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// carrier and code frequency
double if_freq_carrier = d_carrier_doppler_hz + d_if_freq + (DFRQ1_GLO * static_cast<double>(GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)));
d_dump_file.write(reinterpret_cast<char *>(&if_freq_carrier), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_code_freq_chips), sizeof(double));
//PLL commands
d_dump_file.write(reinterpret_cast<char *>(&d_carr_phase_error_secs_Ti), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_doppler_hz), sizeof(double));
//DLL commands
d_dump_file.write(reinterpret_cast<char *>(&d_code_error_chips_Ti), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_code_error_filt_chips_Ti), sizeof(double));
tmp_float = d_carrier_doppler_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_freq_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// PLL commands
tmp_float = 1.0 / (d_carr_phase_error_secs_Ti * CURRENT_INTEGRATION_TIME_S);
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = 1.0 / (d_code_error_filt_chips_Ti * CURRENT_INTEGRATION_TIME_S);
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// DLL commands
tmp_float = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_error_filt_chips_Ti;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// CN0 and carrier lock test
d_dump_file.write(reinterpret_cast<char *>(&d_CN0_SNV_dB_Hz), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_lock_test), sizeof(double));
tmp_float = d_CN0_SNV_dB_Hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_carrier_lock_test;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// AUX vars (for debug purposes)
tmp_double = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
tmp_float = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
double tmp_double = static_cast<double>(d_sample_counter + d_correlation_length_samples);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_double = static_cast<double>(d_sample_counter + d_correlation_length_samples);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
// PRN
unsigned int prn_ = d_acquisition_gnss_synchro->PRN;
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(unsigned int));

View File

@ -39,9 +39,9 @@
#include "glonass_l1_ca_dll_pll_c_aid_tracking_sc.h"
#include "gnss_synchro.h"
#include "glonass_l1_signal_processing.h"
#include "GLONASS_L1_L2_CA.h"
#include "tracking_discriminators.h"
#include "lock_detectors.h"
#include "GLONASS_L1_CA.h"
#include "gnss_sdr_flags.h"
#include "control_message_factory.h"
#include <boost/bind.hpp>
@ -57,6 +57,7 @@
#include <sstream>
#define CN0_ESTIMATION_SAMPLES 10
using google::LogMessage;
glonass_l1_ca_dll_pll_c_aid_tracking_sc_sptr
@ -599,7 +600,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_sc::general_work(int noutput_items __at
d_code_phase_step_chips,
d_correlation_length_samples);
// ####### coherent intergration extension
// ####### coherent integration extension
// keep the last symbols
d_E_history.push_back(d_correlator_outs_16sc[0]); // save early output
d_P_history.push_back(d_correlator_outs_16sc[1]); // save prompt output
@ -712,7 +713,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_sc::general_work(int noutput_items __at
d_code_error_filt_chips_Ti = d_code_error_filt_chips_s * CURRENT_INTEGRATION_TIME_S;
code_error_filt_secs_Ti = d_code_error_filt_chips_Ti / d_code_freq_chips; // [s/Ti]
// ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT #######################
// ################## CARRIER AND CODE NCO BUFFER ALIGNMENT #######################
// keep alignment parameters for the next input buffer
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
double T_chip_seconds = 1.0 / d_code_freq_chips;
@ -742,7 +743,7 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_sc::general_work(int noutput_items __at
d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast<double>(d_fs_in));
// ####### CN0 ESTIMATION AND LOCK DETECTORS #######################################
if (d_cn0_estimation_counter < FLAGS_cn0_samples)
if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES)
{
// fill buffer with prompt correlator output values
d_Prompt_buffer[d_cn0_estimation_counter] = lv_cmake(static_cast<float>(d_correlator_outs_16sc[1].real()), static_cast<float>(d_correlator_outs_16sc[1].imag())); // prompt
@ -752,9 +753,9 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_sc::general_work(int noutput_items __at
{
d_cn0_estimation_counter = 0;
// Code lock indicator
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, FLAGS_cn0_samples, d_fs_in, GLONASS_L1_CA_CODE_LENGTH_CHIPS);
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, GLONASS_L1_CA_CODE_LENGTH_CHIPS);
// Carrier lock indicator
d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, FLAGS_cn0_samples);
d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES);
// Loss of lock detection
if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < FLAGS_cn0_min)
{
@ -821,49 +822,55 @@ int glonass_l1_ca_dll_pll_c_aid_tracking_sc::general_work(int noutput_items __at
float prompt_I;
float prompt_Q;
float tmp_E, tmp_P, tmp_L;
double tmp_double;
float tmp_VE = 0.0;
float tmp_VL = 0.0;
float tmp_float;
prompt_I = d_correlator_outs_16sc[1].real();
prompt_Q = d_correlator_outs_16sc[1].imag();
tmp_E = std::abs<float>(std::complex<float>(d_correlator_outs_16sc[0].real(), d_correlator_outs_16sc[0].imag()));
tmp_P = std::abs<float>(std::complex<float>(d_correlator_outs_16sc[1].real(), d_correlator_outs_16sc[1].imag()));
tmp_L = std::abs<float>(std::complex<float>(d_correlator_outs_16sc[2].real(), d_correlator_outs_16sc[2].imag()));
tmp_E = std::abs<float>(gr_complex(d_correlator_outs_16sc[0].real(), d_correlator_outs_16sc[0].imag()));
tmp_P = std::abs<float>(gr_complex(d_correlator_outs_16sc[1].real(), d_correlator_outs_16sc[1].imag()));
tmp_L = std::abs<float>(gr_complex(d_correlator_outs_16sc[2].real(), d_correlator_outs_16sc[2].imag()));
try
{
// EPR
// Dump correlators output
d_dump_file.write(reinterpret_cast<char *>(&tmp_VE), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_E), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_P), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_L), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_VL), sizeof(float));
// PROMPT I and Q (to analyze navigation symbols)
d_dump_file.write(reinterpret_cast<char *>(&prompt_I), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&prompt_Q), sizeof(float));
// PRN start sample stamp
//tmp_float=(float)d_sample_counter;
d_dump_file.write(reinterpret_cast<char *>(&d_sample_counter), sizeof(unsigned long int));
// accumulated carrier phase
d_dump_file.write(reinterpret_cast<char *>(&d_acc_carrier_phase_cycles), sizeof(double));
tmp_float = d_acc_carrier_phase_cycles * GLONASS_TWO_PI;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// carrier and code frequency
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_doppler_hz), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_code_freq_chips), sizeof(double));
//PLL commands
d_dump_file.write(reinterpret_cast<char *>(&d_carr_phase_error_secs_Ti), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_doppler_hz), sizeof(double));
//DLL commands
d_dump_file.write(reinterpret_cast<char *>(&d_code_error_chips_Ti), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_code_error_filt_chips_Ti), sizeof(double));
tmp_float = d_carrier_doppler_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_freq_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// PLL commands
tmp_float = 1.0 / (d_carr_phase_error_secs_Ti * CURRENT_INTEGRATION_TIME_S);
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = 1.0 / (d_code_error_filt_chips_Ti * CURRENT_INTEGRATION_TIME_S);
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// DLL commands
tmp_float = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_error_filt_chips_Ti;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// CN0 and carrier lock test
d_dump_file.write(reinterpret_cast<char *>(&d_CN0_SNV_dB_Hz), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_lock_test), sizeof(double));
tmp_float = d_CN0_SNV_dB_Hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_carrier_lock_test;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// AUX vars (for debug purposes)
tmp_double = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
tmp_float = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
double tmp_double = static_cast<double>(d_sample_counter + d_correlation_length_samples);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_double = static_cast<double>(d_sample_counter + d_correlation_length_samples);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
// PRN
unsigned int prn_ = d_acquisition_gnss_synchro->PRN;
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(unsigned int));

View File

@ -38,9 +38,9 @@
#include "glonass_l1_ca_dll_pll_tracking_cc.h"
#include "glonass_l1_signal_processing.h"
#include "GLONASS_L1_L2_CA.h"
#include "tracking_discriminators.h"
#include "lock_detectors.h"
#include "GLONASS_L1_CA.h"
#include "gnss_sdr_flags.h"
#include "control_message_factory.h"
#include <boost/lexical_cast.hpp>
@ -54,6 +54,7 @@
#include <sstream>
#define CN0_ESTIMATION_SAMPLES 10
using google::LogMessage;
glonass_l1_ca_dll_pll_tracking_cc_sptr
@ -584,7 +585,7 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work(int noutput_items __attribut
double code_error_filt_secs = (T_prn_seconds * code_error_filt_chips * T_chip_seconds); //[seconds]
//double code_error_filt_secs = (GPS_L1_CA_CODE_PERIOD * code_error_filt_chips) / GLONASS_L1_CA_CODE_RATE_HZ; // [seconds]
// ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT #######################
// ################## CARRIER AND CODE NCO BUFFER ALIGNMENT #######################
// keep alignment parameters for the next input buffer
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
//double T_chip_seconds = 1.0 / static_cast<double>(d_code_freq_chips);
@ -611,7 +612,7 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work(int noutput_items __attribut
d_rem_code_phase_chips = d_code_freq_chips * (d_rem_code_phase_samples / static_cast<double>(d_fs_in));
// ####### CN0 ESTIMATION AND LOCK DETECTORS ######
if (d_cn0_estimation_counter < FLAGS_cn0_samples)
if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES)
{
// fill buffer with prompt correlator output values
d_Prompt_buffer[d_cn0_estimation_counter] = d_correlator_outs[1]; //prompt
@ -621,9 +622,9 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work(int noutput_items __attribut
{
d_cn0_estimation_counter = 0;
// Code lock indicator
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, FLAGS_cn0_samples, d_fs_in, GLONASS_L1_CA_CODE_LENGTH_CHIPS);
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, GLONASS_L1_CA_CODE_LENGTH_CHIPS);
// Carrier lock indicator
d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, FLAGS_cn0_samples);
d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES);
// Loss of lock detection
if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < FLAGS_cn0_min)
{
@ -674,8 +675,9 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work(int noutput_items __attribut
float prompt_I;
float prompt_Q;
float tmp_E, tmp_P, tmp_L;
double tmp_double;
unsigned long int tmp_long;
float tmp_float;
float tmp_VE = 0.0;
float tmp_VL = 0.0;
prompt_I = d_correlator_outs[1].real();
prompt_Q = d_correlator_outs[1].imag();
tmp_E = std::abs<float>(d_correlator_outs[0]);
@ -683,41 +685,45 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work(int noutput_items __attribut
tmp_L = std::abs<float>(d_correlator_outs[2]);
try
{
// EPR
// Dump correlators output
d_dump_file.write(reinterpret_cast<char *>(&tmp_VE), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_E), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_P), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_L), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_VL), sizeof(float));
// PROMPT I and Q (to analyze navigation symbols)
d_dump_file.write(reinterpret_cast<char *>(&prompt_I), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&prompt_Q), sizeof(float));
// PRN start sample stamp
tmp_long = d_sample_counter + d_current_prn_length_samples;
d_dump_file.write(reinterpret_cast<char *>(&tmp_long), sizeof(unsigned long int));
d_dump_file.write(reinterpret_cast<char *>(&d_sample_counter), sizeof(unsigned long int));
// accumulated carrier phase
d_dump_file.write(reinterpret_cast<char *>(&d_acc_carrier_phase_rad), sizeof(double));
tmp_float = d_acc_carrier_phase_rad;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// carrier and code frequency
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_frequency_hz), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_code_freq_chips), sizeof(double));
tmp_float = d_carrier_doppler_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_freq_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// PLL commands
d_dump_file.write(reinterpret_cast<char *>(&carr_error_hz), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&carr_error_filt_hz), sizeof(double));
tmp_float = carr_error_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = carr_error_filt_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// DLL commands
d_dump_file.write(reinterpret_cast<char *>(&code_error_chips), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&code_error_filt_chips), sizeof(double));
tmp_float = code_error_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = code_error_filt_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// CN0 and carrier lock test
d_dump_file.write(reinterpret_cast<char *>(&d_CN0_SNV_dB_Hz), sizeof(double));
d_dump_file.write(reinterpret_cast<char *>(&d_carrier_lock_test), sizeof(double));
tmp_float = d_CN0_SNV_dB_Hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_carrier_lock_test;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// AUX vars (for debug purposes)
tmp_double = d_rem_code_phase_samples;
tmp_float = d_rem_code_phase_samples;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
double tmp_double = static_cast<double>(d_sample_counter + d_current_prn_length_samples);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_double = static_cast<double>(d_sample_counter);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
// PRN
unsigned int prn_ = d_acquisition_gnss_synchro->PRN;
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(unsigned int));

View File

@ -0,0 +1,926 @@
/*!
* \file glonass_l2_ca_dll_pll_c_aid_tracking_cc.h
* \brief Implementation of a code DLL + carrier PLL tracking block
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkha user, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "glonass_l2_ca_dll_pll_c_aid_tracking_cc.h"
#include "glonass_l2_signal_processing.h"
#include "tracking_discriminators.h"
#include "lock_detectors.h"
#include "GLONASS_L1_L2_CA.h"
#include "gnss_sdr_flags.h"
#include "control_message_factory.h"
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
#include <gnuradio/io_signature.h>
#include <matio.h>
#include <pmt/pmt.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <glog/logging.h>
#include <cmath>
#include <iostream>
#include <memory>
#include <sstream>
#define CN0_ESTIMATION_SAMPLES 10
using google::LogMessage;
glonass_l2_ca_dll_pll_c_aid_tracking_cc_sptr
glonass_l2_ca_dll_pll_c_aid_make_tracking_cc(
long if_freq,
long fs_in,
unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips)
{
return glonass_l2_ca_dll_pll_c_aid_tracking_cc_sptr(new glonass_l2_ca_dll_pll_c_aid_tracking_cc(if_freq,
fs_in, vector_length, dump, dump_filename, pll_bw_hz, dll_bw_hz, pll_bw_narrow_hz, dll_bw_narrow_hz, extend_correlation_ms, early_late_space_chips));
}
void glonass_l2_ca_dll_pll_c_aid_tracking_cc::forecast(int noutput_items,
gr_vector_int &ninput_items_required)
{
if (noutput_items != 0)
{
ninput_items_required[0] = static_cast<int>(d_vector_length) * 2; //set the required available samples in each call
}
}
void glonass_l2_ca_dll_pll_c_aid_tracking_cc::msg_handler_preamble_index(pmt::pmt_t msg)
{
//pmt::print(msg);
DLOG(INFO) << "Extended correlation enabled for Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN);
if (d_enable_extended_integration == false) //avoid re-setting preamble indicator
{
d_preamble_timestamp_s = pmt::to_double(msg);
d_enable_extended_integration = true;
d_preamble_synchronized = false;
}
}
glonass_l2_ca_dll_pll_c_aid_tracking_cc::glonass_l2_ca_dll_pll_c_aid_tracking_cc(
long if_freq,
long fs_in,
unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips) : gr::block("glonass_l2_ca_dll_pll_c_aid_tracking_cc", gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{
// Telemetry bit synchronization message port input
this->message_port_register_in(pmt::mp("preamble_timestamp_s"));
this->set_msg_handler(pmt::mp("preamble_timestamp_s"),
boost::bind(&glonass_l2_ca_dll_pll_c_aid_tracking_cc::msg_handler_preamble_index, this, _1));
this->message_port_register_out(pmt::mp("events"));
// initialize internal vars
d_dump = dump;
d_if_freq = if_freq;
d_fs_in = fs_in;
d_vector_length = vector_length;
d_dump_filename = dump_filename;
d_correlation_length_samples = static_cast<int>(d_vector_length);
// Initialize tracking ==========================================
d_pll_bw_hz = pll_bw_hz;
d_dll_bw_hz = dll_bw_hz;
d_pll_bw_narrow_hz = pll_bw_narrow_hz;
d_dll_bw_narrow_hz = dll_bw_narrow_hz;
d_extend_correlation_ms = extend_correlation_ms;
d_code_loop_filter.set_DLL_BW(d_dll_bw_hz);
d_carrier_loop_filter.set_params(10.0, d_pll_bw_hz, 2);
// --- DLL variables --------------------------------------------------------
d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips)
// Initialization of local code replica
// Get space for a vector with the C/A code replica sampled 1x/chip
d_ca_code = static_cast<gr_complex *>(volk_gnsssdr_malloc(static_cast<int>(GLONASS_L2_CA_CODE_LENGTH_CHIPS) * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
// correlator outputs (scalar)
d_n_correlator_taps = 3; // Early, Prompt, and Late
d_correlator_outs = static_cast<gr_complex *>(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
for (int n = 0; n < d_n_correlator_taps; n++)
{
d_correlator_outs[n] = gr_complex(0, 0);
}
d_local_code_shift_chips = static_cast<float *>(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(float), volk_gnsssdr_get_alignment()));
// Set TAPs delay values [chips]
d_local_code_shift_chips[0] = -d_early_late_spc_chips;
d_local_code_shift_chips[1] = 0.0;
d_local_code_shift_chips[2] = d_early_late_spc_chips;
multicorrelator_cpu.init(2 * d_correlation_length_samples, d_n_correlator_taps);
//--- Perform initializations ------------------------------
// define initial code frequency basis of NCO
d_code_freq_chips = GLONASS_L2_CA_CODE_RATE_HZ;
// define residual code phase (in chips)
d_rem_code_phase_samples = 0.0;
// define residual carrier phase
d_rem_carrier_phase_rad = 0.0;
// sample synchronization
d_sample_counter = 0; //(from trk to tlm)
d_acq_sample_stamp = 0;
d_enable_tracking = false;
d_pull_in = false;
// CN0 estimation and lock detector buffers
d_cn0_estimation_counter = 0;
d_Prompt_buffer = new gr_complex[FLAGS_cn0_samples];
d_carrier_lock_test = 1;
d_CN0_SNV_dB_Hz = 0;
d_carrier_lock_fail_counter = 0;
d_carrier_lock_threshold = FLAGS_carrier_lock_th;
systemName["R"] = std::string("Glonass");
set_relative_rate(1.0 / static_cast<double>(d_vector_length));
d_acquisition_gnss_synchro = 0;
d_channel = 0;
d_acq_code_phase_samples = 0.0;
d_acq_carrier_doppler_hz = 0.0;
d_carrier_doppler_hz = 0.0;
d_code_error_filt_chips_Ti = 0.0;
d_acc_carrier_phase_cycles = 0.0;
d_code_phase_samples = 0.0;
d_pll_to_dll_assist_secs_Ti = 0.0;
d_rem_code_phase_chips = 0.0;
d_code_phase_step_chips = 0.0;
d_carrier_phase_step_rad = 0.0;
d_enable_extended_integration = false;
d_preamble_synchronized = false;
d_rem_code_phase_integer_samples = 0;
d_code_error_chips_Ti = 0.0;
d_code_error_filt_chips_s = 0.0;
d_carr_phase_error_secs_Ti = 0.0;
d_preamble_timestamp_s = 0.0;
d_carrier_frequency_hz = 0.0;
d_carrier_doppler_old_hz = 0.0;
d_glonass_freq_ch = 0;
//set_min_output_buffer((long int)300);
}
void glonass_l2_ca_dll_pll_c_aid_tracking_cc::start_tracking()
{
/*
* correct the code phase according to the delay between acq and trk
*/
d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples;
d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz;
d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples;
long int acq_trk_diff_samples;
double acq_trk_diff_seconds;
acq_trk_diff_samples = static_cast<long int>(d_sample_counter) - static_cast<long int>(d_acq_sample_stamp); //-d_vector_length;
DLOG(INFO) << "Number of samples between Acquisition and Tracking =" << acq_trk_diff_samples;
acq_trk_diff_seconds = static_cast<double>(acq_trk_diff_samples) / static_cast<double>(d_fs_in);
// Doppler effect
// Fd=(C/(C+Vr))*F
d_glonass_freq_ch = GLONASS_L2_CA_FREQ_HZ + (DFRQ2_GLO * static_cast<double>(GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)));
double radial_velocity = (d_glonass_freq_ch + d_acq_carrier_doppler_hz) / d_glonass_freq_ch;
// new chip and prn sequence periods based on acq Doppler
double T_chip_mod_seconds;
double T_prn_mod_seconds;
double T_prn_mod_samples;
d_code_freq_chips = radial_velocity * GLONASS_L2_CA_CODE_RATE_HZ;
d_code_phase_step_chips = static_cast<double>(d_code_freq_chips) / static_cast<double>(d_fs_in);
T_chip_mod_seconds = 1.0 / d_code_freq_chips;
T_prn_mod_seconds = T_chip_mod_seconds * GLONASS_L2_CA_CODE_LENGTH_CHIPS;
T_prn_mod_samples = T_prn_mod_seconds * static_cast<double>(d_fs_in);
d_correlation_length_samples = round(T_prn_mod_samples);
double T_prn_true_seconds = GLONASS_L2_CA_CODE_LENGTH_CHIPS / GLONASS_L2_CA_CODE_RATE_HZ;
double T_prn_true_samples = T_prn_true_seconds * static_cast<double>(d_fs_in);
double T_prn_diff_seconds = T_prn_true_seconds - T_prn_mod_seconds;
double N_prn_diff = acq_trk_diff_seconds / T_prn_true_seconds;
double corrected_acq_phase_samples, delay_correction_samples;
corrected_acq_phase_samples = fmod((d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * static_cast<double>(d_fs_in)), T_prn_true_samples);
if (corrected_acq_phase_samples < 0)
{
corrected_acq_phase_samples = T_prn_mod_samples + corrected_acq_phase_samples;
}
delay_correction_samples = d_acq_code_phase_samples - corrected_acq_phase_samples;
d_acq_code_phase_samples = corrected_acq_phase_samples;
// d_carrier_doppler_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ2_GLO * GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN));
// d_carrier_doppler_hz = d_acq_carrier_doppler_hz;
// d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_doppler_hz / static_cast<double>(d_fs_in);
d_carrier_frequency_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ2_GLO * static_cast<double>(GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)));
d_carrier_doppler_hz = d_acq_carrier_doppler_hz;
d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_frequency_hz / static_cast<double>(d_fs_in);
// DLL/PLL filter initialization
d_carrier_loop_filter.initialize(d_carrier_frequency_hz); // The carrier loop filter implements the Doppler accumulator
d_code_loop_filter.initialize(); // initialize the code filter
// generate local reference ALWAYS starting at chip 1 (1 sample per chip)
glonass_l2_ca_code_gen_complex(d_ca_code, 0);
multicorrelator_cpu.set_local_code_and_taps(static_cast<int>(GLONASS_L2_CA_CODE_LENGTH_CHIPS), d_ca_code, d_local_code_shift_chips);
for (int n = 0; n < d_n_correlator_taps; n++)
{
d_correlator_outs[n] = gr_complex(0, 0);
}
d_carrier_lock_fail_counter = 0;
d_rem_code_phase_samples = 0.0;
d_rem_carrier_phase_rad = 0.0;
d_rem_code_phase_chips = 0.0;
d_acc_carrier_phase_cycles = 0.0;
d_pll_to_dll_assist_secs_Ti = 0.0;
d_code_phase_samples = d_acq_code_phase_samples;
std::string sys_ = &d_acquisition_gnss_synchro->System;
sys = sys_.substr(0, 1);
// DEBUG OUTPUT
std::cout << "Tracking start on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl;
LOG(INFO) << "Starting tracking of satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " on channel " << d_channel;
// enable tracking
d_pull_in = true;
d_enable_tracking = true;
d_enable_extended_integration = false;
d_preamble_synchronized = false;
LOG(INFO) << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz
<< " Code Phase correction [samples]=" << delay_correction_samples
<< " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples;
}
glonass_l2_ca_dll_pll_c_aid_tracking_cc::~glonass_l2_ca_dll_pll_c_aid_tracking_cc()
{
if (d_dump_file.is_open())
{
try
{
d_dump_file.close();
}
catch (const std::exception &ex)
{
LOG(WARNING) << "Exception in destructor " << ex.what();
}
}
if (d_dump)
{
if (d_channel == 0)
{
std::cout << "Writing .mat files ...";
}
glonass_l2_ca_dll_pll_c_aid_tracking_cc::save_matfile();
if (d_channel == 0)
{
std::cout << " done." << std::endl;
}
}
try
{
volk_gnsssdr_free(d_local_code_shift_chips);
volk_gnsssdr_free(d_correlator_outs);
volk_gnsssdr_free(d_ca_code);
delete[] d_Prompt_buffer;
multicorrelator_cpu.free();
}
catch (const std::exception &ex)
{
LOG(WARNING) << "Exception in destructor " << ex.what();
}
}
int glonass_l2_ca_dll_pll_c_aid_tracking_cc::save_matfile()
{
// READ DUMP FILE
std::ifstream::pos_type size;
int number_of_double_vars = 11;
int number_of_float_vars = 5;
int epoch_size_bytes = sizeof(unsigned long int) + sizeof(double) * number_of_double_vars +
sizeof(float) * number_of_float_vars + sizeof(unsigned int);
std::ifstream dump_file;
dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
dump_file.open(d_dump_filename.c_str(), std::ios::binary | std::ios::ate);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Problem opening dump file:" << e.what() << std::endl;
return 1;
}
// count number of epochs and rewind
long int num_epoch = 0;
if (dump_file.is_open())
{
size = dump_file.tellg();
num_epoch = static_cast<long int>(size) / static_cast<long int>(epoch_size_bytes);
dump_file.seekg(0, std::ios::beg);
}
else
{
return 1;
}
float *abs_E = new float[num_epoch];
float *abs_P = new float[num_epoch];
float *abs_L = new float[num_epoch];
float *Prompt_I = new float[num_epoch];
float *Prompt_Q = new float[num_epoch];
unsigned long int *PRN_start_sample_count = new unsigned long int[num_epoch];
double *acc_carrier_phase_rad = new double[num_epoch];
double *carrier_doppler_hz = new double[num_epoch];
double *code_freq_chips = new double[num_epoch];
double *carr_error_hz = new double[num_epoch];
double *carr_error_filt_hz = new double[num_epoch];
double *code_error_chips = new double[num_epoch];
double *code_error_filt_chips = new double[num_epoch];
double *CN0_SNV_dB_Hz = new double[num_epoch];
double *carrier_lock_test = new double[num_epoch];
double *aux1 = new double[num_epoch];
double *aux2 = new double[num_epoch];
unsigned int *PRN = new unsigned int[num_epoch];
try
{
if (dump_file.is_open())
{
for (long int i = 0; i < num_epoch; i++)
{
dump_file.read(reinterpret_cast<char *>(&abs_E[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&abs_P[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&abs_L[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&Prompt_I[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&Prompt_Q[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&PRN_start_sample_count[i]), sizeof(unsigned long int));
dump_file.read(reinterpret_cast<char *>(&acc_carrier_phase_rad[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&carrier_doppler_hz[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&code_freq_chips[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&carr_error_hz[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&carr_error_filt_hz[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&code_error_chips[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&code_error_filt_chips[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&CN0_SNV_dB_Hz[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&carrier_lock_test[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&aux1[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&aux2[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&PRN[i]), sizeof(unsigned int));
}
}
dump_file.close();
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Problem reading dump file:" << e.what() << std::endl;
delete[] abs_E;
delete[] abs_P;
delete[] abs_L;
delete[] Prompt_I;
delete[] Prompt_Q;
delete[] PRN_start_sample_count;
delete[] acc_carrier_phase_rad;
delete[] carrier_doppler_hz;
delete[] code_freq_chips;
delete[] carr_error_hz;
delete[] carr_error_filt_hz;
delete[] code_error_chips;
delete[] code_error_filt_chips;
delete[] CN0_SNV_dB_Hz;
delete[] carrier_lock_test;
delete[] aux1;
delete[] aux2;
delete[] PRN;
return 1;
}
// WRITE MAT FILE
mat_t *matfp;
matvar_t *matvar;
std::string filename = d_dump_filename;
filename.erase(filename.length() - 4, 4);
filename.append(".mat");
matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT73);
if (reinterpret_cast<long *>(matfp) != NULL)
{
size_t dims[2] = {1, static_cast<size_t>(num_epoch)};
matvar = Mat_VarCreate("abs_E", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_E, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("abs_P", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_P, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("abs_L", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_L, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("Prompt_I", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, Prompt_I, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("Prompt_Q", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, Prompt_Q, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("PRN_start_sample_count", MAT_C_UINT64, MAT_T_UINT64, 2, dims, PRN_start_sample_count, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("acc_carrier_phase_rad", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, acc_carrier_phase_rad, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("carrier_doppler_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carrier_doppler_hz, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("code_freq_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_freq_chips, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("carr_error_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carr_error_hz, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("carr_error_filt_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carr_error_filt_hz, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("code_error_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_error_chips, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("code_error_filt_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_error_filt_chips, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("CN0_SNV_dB_Hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, CN0_SNV_dB_Hz, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("carrier_lock_test", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carrier_lock_test, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("aux1", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, aux1, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("aux2", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, aux2, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("PRN", MAT_C_UINT32, MAT_T_UINT32, 2, dims, PRN, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
}
Mat_Close(matfp);
delete[] abs_E;
delete[] abs_P;
delete[] abs_L;
delete[] Prompt_I;
delete[] Prompt_Q;
delete[] PRN_start_sample_count;
delete[] acc_carrier_phase_rad;
delete[] carrier_doppler_hz;
delete[] code_freq_chips;
delete[] carr_error_hz;
delete[] carr_error_filt_hz;
delete[] code_error_chips;
delete[] code_error_filt_chips;
delete[] CN0_SNV_dB_Hz;
delete[] carrier_lock_test;
delete[] aux1;
delete[] aux2;
delete[] PRN;
return 0;
}
int glonass_l2_ca_dll_pll_c_aid_tracking_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
// Block input data and block output stream pointers
const gr_complex *in = reinterpret_cast<const gr_complex *>(input_items[0]); // PRN start block alignment
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]);
// GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder
Gnss_Synchro current_synchro_data = Gnss_Synchro();
// process vars
double code_error_filt_secs_Ti = 0.0;
double CURRENT_INTEGRATION_TIME_S = 0.0;
double CORRECTED_INTEGRATION_TIME_S = 0.0;
if (d_enable_tracking == true)
{
// Fill the acquisition data
current_synchro_data = *d_acquisition_gnss_synchro;
// Receiver signal alignment
if (d_pull_in == true)
{
int samples_offset;
double acq_trk_shif_correction_samples;
int acq_to_trk_delay_samples;
acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp;
acq_trk_shif_correction_samples = d_correlation_length_samples - fmod(static_cast<double>(acq_to_trk_delay_samples), static_cast<double>(d_correlation_length_samples));
samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples);
current_synchro_data.Tracking_sample_counter = d_sample_counter + samples_offset;
d_sample_counter += samples_offset; // count for the processed samples
d_pull_in = false;
d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * samples_offset / GLONASS_TWO_PI;
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_cycles * GLONASS_TWO_PI;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.fs = d_fs_in;
*out[0] = current_synchro_data;
consume_each(samples_offset); // shift input to perform alignment with local replica
return 1;
}
// ################# CARRIER WIPEOFF AND CORRELATORS ##############################
// perform carrier wipe-off and compute Early, Prompt and Late correlation
multicorrelator_cpu.set_input_output_vectors(d_correlator_outs, in);
multicorrelator_cpu.Carrier_wipeoff_multicorrelator_resampler(d_rem_carrier_phase_rad,
d_carrier_phase_step_rad,
d_rem_code_phase_chips,
d_code_phase_step_chips,
d_correlation_length_samples);
// ####### coherent integration extension
// keep the last symbols
d_E_history.push_back(d_correlator_outs[0]); // save early output
d_P_history.push_back(d_correlator_outs[1]); // save prompt output
d_L_history.push_back(d_correlator_outs[2]); // save late output
if (static_cast<int>(d_P_history.size()) > d_extend_correlation_ms)
{
d_E_history.pop_front();
d_P_history.pop_front();
d_L_history.pop_front();
}
bool enable_dll_pll;
if (d_enable_extended_integration == true)
{
long int symbol_diff = round(1000.0 * ((static_cast<double>(d_sample_counter) + d_rem_code_phase_samples) / static_cast<double>(d_fs_in) - d_preamble_timestamp_s));
if (symbol_diff > 0 and symbol_diff % d_extend_correlation_ms == 0)
{
// compute coherent integration and enable tracking loop
// perform coherent integration using correlator output history
// std::cout<<"##### RESET COHERENT INTEGRATION ####"<<std::endl;
d_correlator_outs[0] = gr_complex(0.0, 0.0);
d_correlator_outs[1] = gr_complex(0.0, 0.0);
d_correlator_outs[2] = gr_complex(0.0, 0.0);
for (int n = 0; n < d_extend_correlation_ms; n++)
{
d_correlator_outs[0] += d_E_history.at(n);
d_correlator_outs[1] += d_P_history.at(n);
d_correlator_outs[2] += d_L_history.at(n);
}
if (d_preamble_synchronized == false)
{
d_code_loop_filter.set_DLL_BW(d_dll_bw_narrow_hz);
d_carrier_loop_filter.set_params(10.0, d_pll_bw_narrow_hz, 2);
d_preamble_synchronized = true;
std::cout << "Enabled " << d_extend_correlation_ms << " [ms] extended correlator for CH " << d_channel << " : Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN)
<< " pll_bw = " << d_pll_bw_hz << " [Hz], pll_narrow_bw = " << d_pll_bw_narrow_hz << " [Hz]" << std::endl
<< " dll_bw = " << d_dll_bw_hz << " [Hz], dll_narrow_bw = " << d_dll_bw_narrow_hz << " [Hz]" << std::endl;
}
// UPDATE INTEGRATION TIME
CURRENT_INTEGRATION_TIME_S = static_cast<double>(d_extend_correlation_ms) * GLONASS_L2_CA_CODE_PERIOD;
d_code_loop_filter.set_pdi(CURRENT_INTEGRATION_TIME_S);
enable_dll_pll = true;
}
else
{
if (d_preamble_synchronized == true)
{
// continue extended coherent correlation
// Compute the next buffer length based on the period of the PRN sequence and the code phase error estimation
double T_chip_seconds = 1.0 / d_code_freq_chips;
double T_prn_seconds = T_chip_seconds * GLONASS_L2_CA_CODE_LENGTH_CHIPS;
double T_prn_samples = T_prn_seconds * static_cast<double>(d_fs_in);
int K_prn_samples = round(T_prn_samples);
double K_T_prn_error_samples = K_prn_samples - T_prn_samples;
d_rem_code_phase_samples = d_rem_code_phase_samples - K_T_prn_error_samples;
d_rem_code_phase_integer_samples = round(d_rem_code_phase_samples); // round to a discrete number of samples
d_correlation_length_samples = K_prn_samples + d_rem_code_phase_integer_samples;
d_rem_code_phase_samples = d_rem_code_phase_samples - d_rem_code_phase_integer_samples;
// code phase step (Code resampler phase increment per sample) [chips/sample]
d_code_phase_step_chips = d_code_freq_chips / static_cast<double>(d_fs_in);
// remnant code phase [chips]
d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast<double>(d_fs_in));
d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + d_carrier_phase_step_rad * static_cast<double>(d_correlation_length_samples), GLONASS_TWO_PI);
// UPDATE ACCUMULATED CARRIER PHASE
CORRECTED_INTEGRATION_TIME_S = (static_cast<double>(d_correlation_length_samples) / static_cast<double>(d_fs_in));
d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * d_correlation_length_samples / GLONASS_TWO_PI;
// disable tracking loop and inform telemetry decoder
enable_dll_pll = false;
}
else
{
// perform basic (1ms) correlation
// UPDATE INTEGRATION TIME
CURRENT_INTEGRATION_TIME_S = static_cast<double>(d_correlation_length_samples) / static_cast<double>(d_fs_in);
d_code_loop_filter.set_pdi(CURRENT_INTEGRATION_TIME_S);
enable_dll_pll = true;
}
}
}
else
{
// UPDATE INTEGRATION TIME
CURRENT_INTEGRATION_TIME_S = static_cast<double>(d_correlation_length_samples) / static_cast<double>(d_fs_in);
enable_dll_pll = true;
}
if (enable_dll_pll == true)
{
// ################## PLL ##########################################################
// Update PLL discriminator [rads/Ti -> Secs/Ti]
d_carr_phase_error_secs_Ti = pll_cloop_two_quadrant_atan(d_correlator_outs[1]) / GLONASS_TWO_PI; // prompt output
d_carrier_doppler_old_hz = d_carrier_doppler_hz;
// Carrier discriminator filter
// NOTICE: The carrier loop filter includes the Carrier Doppler accumulator, as described in Kaplan
// Input [s/Ti] -> output [Hz]
d_carrier_doppler_hz = d_carrier_loop_filter.get_carrier_error(0.0, d_carr_phase_error_secs_Ti, CURRENT_INTEGRATION_TIME_S);
// PLL to DLL assistance [Secs/Ti]
d_pll_to_dll_assist_secs_Ti = (d_carrier_doppler_hz * CURRENT_INTEGRATION_TIME_S) / d_glonass_freq_ch;
// code Doppler frequency update
d_code_freq_chips = GLONASS_L2_CA_CODE_RATE_HZ + (((d_carrier_doppler_hz - d_carrier_doppler_old_hz) * GLONASS_L2_CA_CODE_RATE_HZ) / d_glonass_freq_ch);
// ################## DLL ##########################################################
// DLL discriminator
d_code_error_chips_Ti = dll_nc_e_minus_l_normalized(d_correlator_outs[0], d_correlator_outs[2]); // [chips/Ti] //early and late
// Code discriminator filter
d_code_error_filt_chips_s = d_code_loop_filter.get_code_nco(d_code_error_chips_Ti); // input [chips/Ti] -> output [chips/second]
d_code_error_filt_chips_Ti = d_code_error_filt_chips_s * CURRENT_INTEGRATION_TIME_S;
code_error_filt_secs_Ti = d_code_error_filt_chips_Ti / d_code_freq_chips; // [s/Ti]
// ################## CARRIER AND CODE NCO BUFFER ALIGNMENT #######################
// keep alignment parameters for the next input buffer
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
double T_chip_seconds = 1.0 / d_code_freq_chips;
double T_prn_seconds = T_chip_seconds * GLONASS_L2_CA_CODE_LENGTH_CHIPS;
double T_prn_samples = T_prn_seconds * static_cast<double>(d_fs_in);
double K_prn_samples = round(T_prn_samples);
double K_T_prn_error_samples = K_prn_samples - T_prn_samples;
d_rem_code_phase_samples = d_rem_code_phase_samples - K_T_prn_error_samples + code_error_filt_secs_Ti * static_cast<double>(d_fs_in); //(code_error_filt_secs_Ti + d_pll_to_dll_assist_secs_Ti) * static_cast<double>(d_fs_in);
d_rem_code_phase_integer_samples = round(d_rem_code_phase_samples); // round to a discrete number of samples
d_correlation_length_samples = K_prn_samples + d_rem_code_phase_integer_samples;
d_rem_code_phase_samples = d_rem_code_phase_samples - d_rem_code_phase_integer_samples;
//################### PLL COMMANDS #################################################
//carrier phase step (NCO phase increment per sample) [rads/sample]
d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_doppler_hz / static_cast<double>(d_fs_in);
d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * d_correlation_length_samples / GLONASS_TWO_PI;
// UPDATE ACCUMULATED CARRIER PHASE
CORRECTED_INTEGRATION_TIME_S = (static_cast<double>(d_correlation_length_samples) / static_cast<double>(d_fs_in));
//remnant carrier phase [rad]
d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + GLONASS_TWO_PI * d_carrier_doppler_hz * CORRECTED_INTEGRATION_TIME_S, GLONASS_TWO_PI);
//################### DLL COMMANDS #################################################
//code phase step (Code resampler phase increment per sample) [chips/sample]
d_code_phase_step_chips = d_code_freq_chips / static_cast<double>(d_fs_in);
//remnant code phase [chips]
d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast<double>(d_fs_in));
// ####### CN0 ESTIMATION AND LOCK DETECTORS #######################################
if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES)
{
// fill buffer with prompt correlator output values
d_Prompt_buffer[d_cn0_estimation_counter] = d_correlator_outs[1]; // prompt
d_cn0_estimation_counter++;
}
else
{
d_cn0_estimation_counter = 0;
// Code lock indicator
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, GLONASS_L2_CA_CODE_LENGTH_CHIPS);
// Carrier lock indicator
d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES);
// Loss of lock detection
if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < FLAGS_cn0_min)
{
d_carrier_lock_fail_counter++;
}
else
{
if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--;
}
if (d_carrier_lock_fail_counter > FLAGS_max_lock_fail)
{
std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl;
LOG(INFO) << "Loss of lock in channel " << d_channel << "!";
this->message_port_pub(pmt::mp("events"), pmt::from_long(3)); //3 -> loss of lock
d_carrier_lock_fail_counter = 0;
d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine
}
}
// ########### Output the tracking data to navigation and PVT ##########
current_synchro_data.Prompt_I = static_cast<double>((d_correlator_outs[1]).real());
current_synchro_data.Prompt_Q = static_cast<double>((d_correlator_outs[1]).imag());
current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples;
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = GLONASS_TWO_PI * d_acc_carrier_phase_cycles;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
current_synchro_data.Flag_valid_symbol_output = true;
if (d_preamble_synchronized == true)
{
current_synchro_data.correlation_length_ms = d_extend_correlation_ms;
}
else
{
current_synchro_data.correlation_length_ms = 1;
}
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((d_correlator_outs[1]).real());
current_synchro_data.Prompt_Q = static_cast<double>((d_correlator_outs[1]).imag());
current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples;
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = GLONASS_TWO_PI * d_acc_carrier_phase_cycles;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; // todo: project the carrier doppler
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
}
}
else
{
for (int n = 0; n < d_n_correlator_taps; n++)
{
d_correlator_outs[n] = gr_complex(0, 0);
}
current_synchro_data.System = {'R'};
current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples;
}
//assign the GNURadio block output data
current_synchro_data.fs = d_fs_in;
*out[0] = current_synchro_data;
if (d_dump)
{
// MULTIPLEXED FILE RECORDING - Record results to file
float prompt_I;
float prompt_Q;
float tmp_E, tmp_P, tmp_L;
float tmp_VE = 0.0;
float tmp_VL = 0.0;
float tmp_float;
prompt_I = d_correlator_outs[1].real();
prompt_Q = d_correlator_outs[1].imag();
tmp_E = std::abs<float>(d_correlator_outs[0]);
tmp_P = std::abs<float>(d_correlator_outs[1]);
tmp_L = std::abs<float>(d_correlator_outs[2]);
try
{
// Dump correlators output
d_dump_file.write(reinterpret_cast<char *>(&tmp_VE), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_E), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_P), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_L), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_VL), sizeof(float));
// PROMPT I and Q (to analyze navigation symbols)
d_dump_file.write(reinterpret_cast<char *>(&prompt_I), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&prompt_Q), sizeof(float));
// PRN start sample stamp
d_dump_file.write(reinterpret_cast<char *>(&d_sample_counter), sizeof(unsigned long int));
// accumulated carrier phase
tmp_float = d_acc_carrier_phase_cycles * GLONASS_TWO_PI;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// carrier and code frequency
tmp_float = d_carrier_doppler_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_freq_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// PLL commands
tmp_float = 1.0 / (d_carr_phase_error_secs_Ti * CURRENT_INTEGRATION_TIME_S);
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = 1.0 / (d_code_error_filt_chips_Ti * CURRENT_INTEGRATION_TIME_S);
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// DLL commands
tmp_float = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_error_filt_chips_Ti;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// CN0 and carrier lock test
tmp_float = d_CN0_SNV_dB_Hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_carrier_lock_test;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// AUX vars (for debug purposes)
tmp_float = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
double tmp_double = static_cast<double>(d_sample_counter + d_correlation_length_samples);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
// PRN
unsigned int prn_ = d_acquisition_gnss_synchro->PRN;
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(unsigned int));
}
catch (const std::ifstream::failure *e)
{
LOG(WARNING) << "Exception writing trk dump file " << e->what();
}
}
consume_each(d_correlation_length_samples); // this is necessary in gr::block derivates
d_sample_counter += d_correlation_length_samples; //count for the processed samples
return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false
}
void glonass_l2_ca_dll_pll_c_aid_tracking_cc::set_channel(unsigned int channel)
{
d_channel = channel;
LOG(INFO) << "Tracking Channel set to " << d_channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
d_dump_filename.append(boost::lexical_cast<std::string>(d_channel));
d_dump_filename.append(".dat");
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
LOG(INFO) << "Tracking dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str() << std::endl;
}
catch (const std::ifstream::failure *e)
{
LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e->what() << std::endl;
}
}
}
}
void glonass_l2_ca_dll_pll_c_aid_tracking_cc::set_gnss_synchro(Gnss_Synchro *p_gnss_synchro)
{
d_acquisition_gnss_synchro = p_gnss_synchro;
}

View File

@ -0,0 +1,203 @@
/*!
* \file glonass_l2_ca_dll_pll_c_aid_tracking_cc.h
* \brief Implementation of a code DLL + carrier PLL tracking block
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkha user, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GLONASS_L2_CA_DLL_PLL_C_AID_TRACKING_CC_H
#define GNSS_SDR_GLONASS_L2_CA_DLL_PLL_C_AID_TRACKING_CC_H
#include "gnss_synchro.h"
#include "tracking_2nd_DLL_filter.h"
#include "tracking_FLL_PLL_filter.h"
//#include "tracking_loop_filter.h"
#include "cpu_multicorrelator.h"
#include <gnuradio/block.h>
#include <pmt/pmt.h>
#include <fstream>
#include <map>
#include <deque>
#include <string>
class glonass_l2_ca_dll_pll_c_aid_tracking_cc;
typedef boost::shared_ptr<glonass_l2_ca_dll_pll_c_aid_tracking_cc>
glonass_l2_ca_dll_pll_c_aid_tracking_cc_sptr;
glonass_l2_ca_dll_pll_c_aid_tracking_cc_sptr
glonass_l2_ca_dll_pll_c_aid_make_tracking_cc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips);
/*!
* \brief This class implements a DLL + PLL tracking loop block
*/
class glonass_l2_ca_dll_pll_c_aid_tracking_cc : public gr::block
{
public:
~glonass_l2_ca_dll_pll_c_aid_tracking_cc();
void set_channel(unsigned int channel);
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro);
void start_tracking();
int general_work(int noutput_items, gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items, gr_vector_void_star& output_items);
void forecast(int noutput_items, gr_vector_int& ninput_items_required);
private:
friend glonass_l2_ca_dll_pll_c_aid_tracking_cc_sptr
glonass_l2_ca_dll_pll_c_aid_make_tracking_cc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips);
glonass_l2_ca_dll_pll_c_aid_tracking_cc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips);
// tracking configuration vars
unsigned int d_vector_length;
bool d_dump;
Gnss_Synchro* d_acquisition_gnss_synchro;
unsigned int d_channel;
long d_if_freq;
long d_fs_in;
double d_glonass_freq_ch;
double d_early_late_spc_chips;
int d_n_correlator_taps;
gr_complex* d_ca_code;
float* d_local_code_shift_chips;
gr_complex* d_correlator_outs;
cpu_multicorrelator multicorrelator_cpu;
// remaining code phase and carrier phase between tracking loops
double d_rem_code_phase_samples;
double d_rem_code_phase_chips;
double d_rem_carrier_phase_rad;
int d_rem_code_phase_integer_samples;
// PLL and DLL filter library
//Tracking_2nd_DLL_filter d_code_loop_filter;
Tracking_2nd_DLL_filter d_code_loop_filter;
Tracking_FLL_PLL_filter d_carrier_loop_filter;
// acquisition
double d_acq_code_phase_samples;
double d_acq_carrier_doppler_hz;
// tracking vars
float d_dll_bw_hz;
float d_pll_bw_hz;
float d_dll_bw_narrow_hz;
float d_pll_bw_narrow_hz;
double d_code_freq_chips;
double d_code_phase_step_chips;
double d_carrier_doppler_hz;
double d_carrier_frequency_hz;
double d_carrier_doppler_old_hz;
double d_carrier_phase_step_rad;
double d_acc_carrier_phase_cycles;
double d_code_phase_samples;
double d_pll_to_dll_assist_secs_Ti;
double d_code_error_chips_Ti;
double d_code_error_filt_chips_s;
double d_code_error_filt_chips_Ti;
double d_carr_phase_error_secs_Ti;
// symbol history to detect bit transition
std::deque<gr_complex> d_E_history;
std::deque<gr_complex> d_P_history;
std::deque<gr_complex> d_L_history;
double d_preamble_timestamp_s;
int d_extend_correlation_ms;
bool d_enable_extended_integration;
bool d_preamble_synchronized;
void msg_handler_preamble_index(pmt::pmt_t msg);
//Integration period in samples
int d_correlation_length_samples;
//processing samples counters
unsigned long int d_sample_counter;
unsigned long int d_acq_sample_stamp;
// CN0 estimation and lock detector
int d_cn0_estimation_counter;
gr_complex* d_Prompt_buffer;
double d_carrier_lock_test;
double d_CN0_SNV_dB_Hz;
double d_carrier_lock_threshold;
int d_carrier_lock_fail_counter;
// control vars
bool d_enable_tracking;
bool d_pull_in;
// file dump
std::string d_dump_filename;
std::ofstream d_dump_file;
std::map<std::string, std::string> systemName;
std::string sys;
int save_matfile();
};
#endif //GNSS_SDR_GLONASS_L1_CA_DLL_PLL_C_AID_TRACKING_CC_H

View File

@ -0,0 +1,918 @@
/*!
* \file glonass_l2_ca_dll_pll_c_aid_tracking_sc.cc
* \brief Implementation of a code DLL + carrier PLL tracking block
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkha user, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "glonass_l2_ca_dll_pll_c_aid_tracking_sc.h"
#include "gnss_synchro.h"
#include "glonass_l2_signal_processing.h"
#include "tracking_discriminators.h"
#include "lock_detectors.h"
#include "GLONASS_L1_L2_CA.h"
#include "gnss_sdr_flags.h"
#include "control_message_factory.h"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h>
#include <matio.h>
#include <pmt/pmt.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <glog/logging.h>
#include <cmath>
#include <iostream>
#include <memory>
#include <sstream>
#define CN0_ESTIMATION_SAMPLES 10
using google::LogMessage;
glonass_l2_ca_dll_pll_c_aid_tracking_sc_sptr
glonass_l2_ca_dll_pll_c_aid_make_tracking_sc(
long if_freq,
long fs_in,
unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips)
{
return glonass_l2_ca_dll_pll_c_aid_tracking_sc_sptr(new glonass_l2_ca_dll_pll_c_aid_tracking_sc(if_freq,
fs_in, vector_length, dump, dump_filename, pll_bw_hz, dll_bw_hz, pll_bw_narrow_hz, dll_bw_narrow_hz, extend_correlation_ms, early_late_space_chips));
}
void glonass_l2_ca_dll_pll_c_aid_tracking_sc::forecast(int noutput_items,
gr_vector_int &ninput_items_required)
{
if (noutput_items != 0)
{
ninput_items_required[0] = static_cast<int>(d_vector_length) * 2; //set the required available samples in each call
}
}
void glonass_l2_ca_dll_pll_c_aid_tracking_sc::msg_handler_preamble_index(pmt::pmt_t msg)
{
//pmt::print(msg);
DLOG(INFO) << "Extended correlation enabled for Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN);
if (d_enable_extended_integration == false) //avoid re-setting preamble indicator
{
d_preamble_timestamp_s = pmt::to_double(msg);
d_enable_extended_integration = true;
d_preamble_synchronized = false;
}
}
glonass_l2_ca_dll_pll_c_aid_tracking_sc::glonass_l2_ca_dll_pll_c_aid_tracking_sc(
long if_freq,
long fs_in,
unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips) : gr::block("glonass_l1_ca_dll_pll_c_aid_tracking_sc", gr::io_signature::make(1, 1, sizeof(lv_16sc_t)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{
// Telemetry bit synchronization message port input
this->message_port_register_in(pmt::mp("preamble_timestamp_s"));
this->set_msg_handler(pmt::mp("preamble_timestamp_s"),
boost::bind(&glonass_l2_ca_dll_pll_c_aid_tracking_sc::msg_handler_preamble_index, this, _1));
this->message_port_register_out(pmt::mp("events"));
// initialize internal vars
d_dump = dump;
d_if_freq = if_freq;
d_fs_in = fs_in;
d_vector_length = vector_length;
d_dump_filename = dump_filename;
d_correlation_length_samples = static_cast<int>(d_vector_length);
// Initialize tracking ==========================================
d_pll_bw_hz = pll_bw_hz;
d_dll_bw_hz = dll_bw_hz;
d_pll_bw_narrow_hz = pll_bw_narrow_hz;
d_dll_bw_narrow_hz = dll_bw_narrow_hz;
d_code_loop_filter.set_DLL_BW(d_dll_bw_hz);
d_carrier_loop_filter.set_params(10.0, d_pll_bw_hz, 2);
d_extend_correlation_ms = extend_correlation_ms;
// --- DLL variables --------------------------------------------------------
d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips)
// Initialization of local code replica
// Get space for a vector with the C/A code replica sampled 1x/chip
d_ca_code = static_cast<gr_complex *>(volk_gnsssdr_malloc(static_cast<int>(GLONASS_L2_CA_CODE_LENGTH_CHIPS) * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_ca_code_16sc = static_cast<lv_16sc_t *>(volk_gnsssdr_malloc(static_cast<int>(GLONASS_L2_CA_CODE_LENGTH_CHIPS) * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment()));
// correlator outputs (scalar)
d_n_correlator_taps = 3; // Early, Prompt, and Late
d_correlator_outs_16sc = static_cast<lv_16sc_t *>(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment()));
for (int n = 0; n < d_n_correlator_taps; n++)
{
d_correlator_outs_16sc[n] = lv_cmake(0, 0);
}
d_local_code_shift_chips = static_cast<float *>(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(float), volk_gnsssdr_get_alignment()));
// Set TAPs delay values [chips]
d_local_code_shift_chips[0] = -d_early_late_spc_chips;
d_local_code_shift_chips[1] = 0.0;
d_local_code_shift_chips[2] = d_early_late_spc_chips;
multicorrelator_cpu_16sc.init(2 * d_correlation_length_samples, d_n_correlator_taps);
//--- Perform initializations ------------------------------
// define initial code frequency basis of NCO
d_code_freq_chips = GLONASS_L2_CA_CODE_RATE_HZ;
// define residual code phase (in chips)
d_rem_code_phase_samples = 0.0;
// define residual carrier phase
d_rem_carrier_phase_rad = 0.0;
// sample synchronization
d_sample_counter = 0; //(from trk to tlm)
d_acq_sample_stamp = 0;
d_enable_tracking = false;
d_pull_in = false;
// CN0 estimation and lock detector buffers
d_cn0_estimation_counter = 0;
d_Prompt_buffer = new gr_complex[FLAGS_cn0_samples];
d_carrier_lock_test = 1;
d_CN0_SNV_dB_Hz = 0;
d_carrier_lock_fail_counter = 0;
d_carrier_lock_threshold = FLAGS_carrier_lock_th;
systemName["R"] = std::string("Glonass");
set_relative_rate(1.0 / static_cast<double>(d_vector_length));
d_acquisition_gnss_synchro = 0;
d_channel = 0;
d_acq_code_phase_samples = 0.0;
d_acq_carrier_doppler_hz = 0.0;
d_carrier_doppler_hz = 0.0;
d_acc_carrier_phase_cycles = 0.0;
d_code_phase_samples = 0.0;
d_enable_extended_integration = false;
d_preamble_synchronized = false;
d_rem_code_phase_integer_samples = 0;
d_code_error_chips_Ti = 0.0;
d_pll_to_dll_assist_secs_Ti = 0.0;
d_rem_code_phase_chips = 0.0;
d_code_phase_step_chips = 0.0;
d_carrier_phase_step_rad = 0.0;
d_code_error_filt_chips_s = 0.0;
d_code_error_filt_chips_Ti = 0.0;
d_preamble_timestamp_s = 0.0;
d_carr_phase_error_secs_Ti = 0.0;
d_carrier_frequency_hz = 0.0;
d_carrier_doppler_old_hz = 0.0;
d_glonass_freq_ch = 0;
//set_min_output_buffer((long int)300);
}
void glonass_l2_ca_dll_pll_c_aid_tracking_sc::start_tracking()
{
/*
* correct the code phase according to the delay between acq and trk
*/
d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples;
d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz;
d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples;
long int acq_trk_diff_samples;
double acq_trk_diff_seconds;
acq_trk_diff_samples = static_cast<long int>(d_sample_counter) - static_cast<long int>(d_acq_sample_stamp); //-d_vector_length;
DLOG(INFO) << "Number of samples between Acquisition and Tracking =" << acq_trk_diff_samples;
acq_trk_diff_seconds = static_cast<double>(acq_trk_diff_samples) / static_cast<double>(d_fs_in);
// Doppler effect
// Fd=(C/(C+Vr))*F
d_glonass_freq_ch = GLONASS_L2_CA_FREQ_HZ + (GLONASS_L2_CA_FREQ_HZ * GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN));
double radial_velocity = (d_glonass_freq_ch + d_acq_carrier_doppler_hz) / d_glonass_freq_ch;
// new chip and prn sequence periods based on acq Doppler
double T_chip_mod_seconds;
double T_prn_mod_seconds;
double T_prn_mod_samples;
d_code_freq_chips = radial_velocity * GLONASS_L2_CA_CODE_RATE_HZ;
d_code_phase_step_chips = static_cast<double>(d_code_freq_chips) / static_cast<double>(d_fs_in);
T_chip_mod_seconds = 1.0 / d_code_freq_chips;
T_prn_mod_seconds = T_chip_mod_seconds * GLONASS_L2_CA_CODE_LENGTH_CHIPS;
T_prn_mod_samples = T_prn_mod_seconds * static_cast<double>(d_fs_in);
d_correlation_length_samples = round(T_prn_mod_samples);
double T_prn_true_seconds = GLONASS_L2_CA_CODE_LENGTH_CHIPS / GLONASS_L2_CA_CODE_RATE_HZ;
double T_prn_true_samples = T_prn_true_seconds * static_cast<double>(d_fs_in);
double T_prn_diff_seconds = T_prn_true_seconds - T_prn_mod_seconds;
double N_prn_diff = acq_trk_diff_seconds / T_prn_true_seconds;
double corrected_acq_phase_samples, delay_correction_samples;
corrected_acq_phase_samples = fmod((d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * static_cast<double>(d_fs_in)), T_prn_true_samples);
if (corrected_acq_phase_samples < 0)
{
corrected_acq_phase_samples = T_prn_mod_samples + corrected_acq_phase_samples;
}
delay_correction_samples = d_acq_code_phase_samples - corrected_acq_phase_samples;
d_acq_code_phase_samples = corrected_acq_phase_samples;
d_carrier_frequency_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ2_GLO * static_cast<double>(GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)));
;
d_carrier_doppler_hz = d_acq_carrier_doppler_hz;
d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_frequency_hz / static_cast<double>(d_fs_in);
// DLL/PLL filter initialization
d_carrier_loop_filter.initialize(d_carrier_frequency_hz); // The carrier loop filter implements the Doppler accumulator
d_code_loop_filter.initialize(); // initialize the code filter
// generate local reference ALWAYS starting at chip 1 (1 sample per chip)
glonass_l2_ca_code_gen_complex(d_ca_code, 0);
volk_gnsssdr_32fc_convert_16ic(d_ca_code_16sc, d_ca_code, static_cast<int>(GLONASS_L2_CA_CODE_LENGTH_CHIPS));
multicorrelator_cpu_16sc.set_local_code_and_taps(static_cast<int>(GLONASS_L2_CA_CODE_LENGTH_CHIPS), d_ca_code_16sc, d_local_code_shift_chips);
for (int n = 0; n < d_n_correlator_taps; n++)
{
d_correlator_outs_16sc[n] = lv_16sc_t(0, 0);
}
d_carrier_lock_fail_counter = 0;
d_rem_code_phase_samples = 0.0;
d_rem_carrier_phase_rad = 0.0;
d_rem_code_phase_chips = 0.0;
d_acc_carrier_phase_cycles = 0.0;
d_pll_to_dll_assist_secs_Ti = 0.0;
d_code_phase_samples = d_acq_code_phase_samples;
std::string sys_ = &d_acquisition_gnss_synchro->System;
sys = sys_.substr(0, 1);
// DEBUG OUTPUT
std::cout << "Tracking start on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl;
LOG(INFO) << "Starting tracking of satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " on channel " << d_channel;
// enable tracking
d_pull_in = true;
d_enable_tracking = true;
d_enable_extended_integration = true;
d_preamble_synchronized = true;
LOG(INFO) << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz
<< " Code Phase correction [samples]=" << delay_correction_samples
<< " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples;
}
int glonass_l2_ca_dll_pll_c_aid_tracking_sc::save_matfile()
{
// READ DUMP FILE
std::ifstream::pos_type size;
int number_of_double_vars = 11;
int number_of_float_vars = 5;
int epoch_size_bytes = sizeof(unsigned long int) + sizeof(double) * number_of_double_vars +
sizeof(float) * number_of_float_vars + sizeof(unsigned int);
std::ifstream dump_file;
dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
dump_file.open(d_dump_filename.c_str(), std::ios::binary | std::ios::ate);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Problem opening dump file:" << e.what() << std::endl;
return 1;
}
// count number of epochs and rewind
long int num_epoch = 0;
if (dump_file.is_open())
{
size = dump_file.tellg();
num_epoch = static_cast<long int>(size) / static_cast<long int>(epoch_size_bytes);
dump_file.seekg(0, std::ios::beg);
}
else
{
return 1;
}
float *abs_E = new float[num_epoch];
float *abs_P = new float[num_epoch];
float *abs_L = new float[num_epoch];
float *Prompt_I = new float[num_epoch];
float *Prompt_Q = new float[num_epoch];
unsigned long int *PRN_start_sample_count = new unsigned long int[num_epoch];
double *acc_carrier_phase_rad = new double[num_epoch];
double *carrier_doppler_hz = new double[num_epoch];
double *code_freq_chips = new double[num_epoch];
double *carr_error_hz = new double[num_epoch];
double *carr_error_filt_hz = new double[num_epoch];
double *code_error_chips = new double[num_epoch];
double *code_error_filt_chips = new double[num_epoch];
double *CN0_SNV_dB_Hz = new double[num_epoch];
double *carrier_lock_test = new double[num_epoch];
double *aux1 = new double[num_epoch];
double *aux2 = new double[num_epoch];
unsigned int *PRN = new unsigned int[num_epoch];
try
{
if (dump_file.is_open())
{
for (long int i = 0; i < num_epoch; i++)
{
dump_file.read(reinterpret_cast<char *>(&abs_E[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&abs_P[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&abs_L[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&Prompt_I[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&Prompt_Q[i]), sizeof(float));
dump_file.read(reinterpret_cast<char *>(&PRN_start_sample_count[i]), sizeof(unsigned long int));
dump_file.read(reinterpret_cast<char *>(&acc_carrier_phase_rad[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&carrier_doppler_hz[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&code_freq_chips[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&carr_error_hz[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&carr_error_filt_hz[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&code_error_chips[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&code_error_filt_chips[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&CN0_SNV_dB_Hz[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&carrier_lock_test[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&aux1[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&aux2[i]), sizeof(double));
dump_file.read(reinterpret_cast<char *>(&PRN[i]), sizeof(unsigned int));
}
}
dump_file.close();
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Problem reading dump file:" << e.what() << std::endl;
delete[] abs_E;
delete[] abs_P;
delete[] abs_L;
delete[] Prompt_I;
delete[] Prompt_Q;
delete[] PRN_start_sample_count;
delete[] acc_carrier_phase_rad;
delete[] carrier_doppler_hz;
delete[] code_freq_chips;
delete[] carr_error_hz;
delete[] carr_error_filt_hz;
delete[] code_error_chips;
delete[] code_error_filt_chips;
delete[] CN0_SNV_dB_Hz;
delete[] carrier_lock_test;
delete[] aux1;
delete[] aux2;
delete[] PRN;
return 1;
}
// WRITE MAT FILE
mat_t *matfp;
matvar_t *matvar;
std::string filename = d_dump_filename;
filename.erase(filename.length() - 4, 4);
filename.append(".mat");
matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT73);
if (reinterpret_cast<long *>(matfp) != NULL)
{
size_t dims[2] = {1, static_cast<size_t>(num_epoch)};
matvar = Mat_VarCreate("abs_E", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_E, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("abs_P", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_P, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("abs_L", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, abs_L, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("Prompt_I", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, Prompt_I, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("Prompt_Q", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, Prompt_Q, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("PRN_start_sample_count", MAT_C_UINT64, MAT_T_UINT64, 2, dims, PRN_start_sample_count, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("acc_carrier_phase_rad", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, acc_carrier_phase_rad, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("carrier_doppler_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carrier_doppler_hz, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("code_freq_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_freq_chips, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("carr_error_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carr_error_hz, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("carr_error_filt_hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carr_error_filt_hz, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("code_error_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_error_chips, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("code_error_filt_chips", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, code_error_filt_chips, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("CN0_SNV_dB_Hz", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, CN0_SNV_dB_Hz, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("carrier_lock_test", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, carrier_lock_test, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("aux1", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, aux1, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("aux2", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, aux2, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("PRN", MAT_C_UINT32, MAT_T_UINT32, 2, dims, PRN, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
}
Mat_Close(matfp);
delete[] abs_E;
delete[] abs_P;
delete[] abs_L;
delete[] Prompt_I;
delete[] Prompt_Q;
delete[] PRN_start_sample_count;
delete[] acc_carrier_phase_rad;
delete[] carrier_doppler_hz;
delete[] code_freq_chips;
delete[] carr_error_hz;
delete[] carr_error_filt_hz;
delete[] code_error_chips;
delete[] code_error_filt_chips;
delete[] CN0_SNV_dB_Hz;
delete[] carrier_lock_test;
delete[] aux1;
delete[] aux2;
delete[] PRN;
return 0;
}
glonass_l2_ca_dll_pll_c_aid_tracking_sc::~glonass_l2_ca_dll_pll_c_aid_tracking_sc()
{
if (d_dump_file.is_open())
{
try
{
d_dump_file.close();
}
catch (const std::exception &ex)
{
LOG(WARNING) << "Exception in destructor " << ex.what();
}
}
if (d_dump)
{
if (d_channel == 0)
{
std::cout << "Writing .mat files ...";
}
glonass_l2_ca_dll_pll_c_aid_tracking_sc::save_matfile();
if (d_channel == 0)
{
std::cout << " done." << std::endl;
}
}
volk_gnsssdr_free(d_local_code_shift_chips);
volk_gnsssdr_free(d_ca_code);
volk_gnsssdr_free(d_ca_code_16sc);
volk_gnsssdr_free(d_correlator_outs_16sc);
delete[] d_Prompt_buffer;
multicorrelator_cpu_16sc.free();
}
int glonass_l2_ca_dll_pll_c_aid_tracking_sc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
// Block input data and block output stream pointers
const lv_16sc_t *in = reinterpret_cast<const lv_16sc_t *>(input_items[0]); // PRN start block alignment
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]);
// GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder
Gnss_Synchro current_synchro_data = Gnss_Synchro();
// process vars
double code_error_filt_secs_Ti = 0.0;
double CURRENT_INTEGRATION_TIME_S = 0.0;
double CORRECTED_INTEGRATION_TIME_S = 0.0;
if (d_enable_tracking == true)
{
// Fill the acquisition data
current_synchro_data = *d_acquisition_gnss_synchro;
// Receiver signal alignment
if (d_pull_in == true)
{
int samples_offset;
double acq_trk_shif_correction_samples;
int acq_to_trk_delay_samples;
acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp;
acq_trk_shif_correction_samples = d_correlation_length_samples - fmod(static_cast<double>(acq_to_trk_delay_samples), static_cast<double>(d_correlation_length_samples));
samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples);
current_synchro_data.Tracking_sample_counter = d_sample_counter + samples_offset;
d_sample_counter += samples_offset; // count for the processed samples
d_pull_in = false;
d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * samples_offset / GLONASS_TWO_PI;
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_cycles * GLONASS_TWO_PI;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.fs = d_fs_in;
*out[0] = current_synchro_data;
consume_each(samples_offset); // shift input to perform alignment with local replica
return 1;
}
// ################# CARRIER WIPEOFF AND CORRELATORS ##############################
// perform carrier wipe-off and compute Early, Prompt and Late correlation
multicorrelator_cpu_16sc.set_input_output_vectors(d_correlator_outs_16sc, in);
multicorrelator_cpu_16sc.Carrier_wipeoff_multicorrelator_resampler(d_rem_carrier_phase_rad,
d_carrier_phase_step_rad,
d_rem_code_phase_chips,
d_code_phase_step_chips,
d_correlation_length_samples);
// ####### coherent integration extension
// keep the last symbols
d_E_history.push_back(d_correlator_outs_16sc[0]); // save early output
d_P_history.push_back(d_correlator_outs_16sc[1]); // save prompt output
d_L_history.push_back(d_correlator_outs_16sc[2]); // save late output
if (static_cast<int>(d_P_history.size()) > d_extend_correlation_ms)
{
d_E_history.pop_front();
d_P_history.pop_front();
d_L_history.pop_front();
}
bool enable_dll_pll;
if (d_enable_extended_integration == true)
{
long int symbol_diff = round(1000.0 * ((static_cast<double>(d_sample_counter) + d_rem_code_phase_samples) / static_cast<double>(d_fs_in) - d_preamble_timestamp_s));
if (symbol_diff > 0 and symbol_diff % d_extend_correlation_ms == 0)
{
// compute coherent integration and enable tracking loop
// perform coherent integration using correlator output history
// std::cout<<"##### RESET COHERENT INTEGRATION ####"<<std::endl;
d_correlator_outs_16sc[0] = lv_cmake(0, 0);
d_correlator_outs_16sc[1] = lv_cmake(0, 0);
d_correlator_outs_16sc[2] = lv_cmake(0, 0);
for (int n = 0; n < d_extend_correlation_ms; n++)
{
d_correlator_outs_16sc[0] += d_E_history.at(n);
d_correlator_outs_16sc[1] += d_P_history.at(n);
d_correlator_outs_16sc[2] += d_L_history.at(n);
}
if (d_preamble_synchronized == false)
{
d_code_loop_filter.set_DLL_BW(d_dll_bw_narrow_hz);
d_carrier_loop_filter.set_params(10.0, d_pll_bw_narrow_hz, 2);
d_preamble_synchronized = true;
std::cout << "Enabled " << d_extend_correlation_ms << " [ms] extended correlator for CH " << d_channel << " : Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN)
<< " pll_bw = " << d_pll_bw_hz << " [Hz], pll_narrow_bw = " << d_pll_bw_narrow_hz << " [Hz]" << std::endl
<< " dll_bw = " << d_dll_bw_hz << " [Hz], dll_narrow_bw = " << d_dll_bw_narrow_hz << " [Hz]" << std::endl;
}
// UPDATE INTEGRATION TIME
CURRENT_INTEGRATION_TIME_S = static_cast<double>(d_extend_correlation_ms) * GLONASS_L2_CA_CODE_PERIOD;
enable_dll_pll = true;
}
else
{
if (d_preamble_synchronized == true)
{
// continue extended coherent correlation
// Compute the next buffer length based on the period of the PRN sequence and the code phase error estimation
double T_chip_seconds = 1.0 / d_code_freq_chips;
double T_prn_seconds = T_chip_seconds * GLONASS_L2_CA_CODE_LENGTH_CHIPS;
double T_prn_samples = T_prn_seconds * static_cast<double>(d_fs_in);
int K_prn_samples = round(T_prn_samples);
double K_T_prn_error_samples = K_prn_samples - T_prn_samples;
d_rem_code_phase_samples = d_rem_code_phase_samples - K_T_prn_error_samples;
d_rem_code_phase_integer_samples = round(d_rem_code_phase_samples); // round to a discrete number of samples
d_correlation_length_samples = K_prn_samples + d_rem_code_phase_integer_samples;
d_rem_code_phase_samples = d_rem_code_phase_samples - d_rem_code_phase_integer_samples;
// code phase step (Code resampler phase increment per sample) [chips/sample]
d_code_phase_step_chips = d_code_freq_chips / static_cast<double>(d_fs_in);
// remnant code phase [chips]
d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast<double>(d_fs_in));
d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + d_carrier_phase_step_rad * static_cast<double>(d_correlation_length_samples), GLONASS_TWO_PI);
// UPDATE ACCUMULATED CARRIER PHASE
CORRECTED_INTEGRATION_TIME_S = (static_cast<double>(d_correlation_length_samples) / static_cast<double>(d_fs_in));
d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * d_correlation_length_samples / GLONASS_TWO_PI;
// disable tracking loop and inform telemetry decoder
enable_dll_pll = false;
}
else
{
// perform basic (1ms) correlation
// UPDATE INTEGRATION TIME
CURRENT_INTEGRATION_TIME_S = static_cast<double>(d_correlation_length_samples) / static_cast<double>(d_fs_in);
enable_dll_pll = true;
}
}
}
else
{
// UPDATE INTEGRATION TIME
CURRENT_INTEGRATION_TIME_S = static_cast<double>(d_correlation_length_samples) / static_cast<double>(d_fs_in);
enable_dll_pll = true;
}
if (enable_dll_pll == true)
{
// ################## PLL ##########################################################
// Update PLL discriminator [rads/Ti -> Secs/Ti]
d_carr_phase_error_secs_Ti = pll_cloop_two_quadrant_atan(std::complex<float>(d_correlator_outs_16sc[1].real(), d_correlator_outs_16sc[1].imag())) / GLONASS_TWO_PI; //prompt output
d_carrier_doppler_old_hz = d_carrier_doppler_hz;
// Carrier discriminator filter
// NOTICE: The carrier loop filter includes the Carrier Doppler accumulator, as described in Kaplan
// Input [s/Ti] -> output [Hz]
d_carrier_doppler_hz = d_carrier_loop_filter.get_carrier_error(0.0, d_carr_phase_error_secs_Ti, CURRENT_INTEGRATION_TIME_S);
// PLL to DLL assistance [Secs/Ti]
d_pll_to_dll_assist_secs_Ti = (d_carrier_doppler_hz * CURRENT_INTEGRATION_TIME_S) / d_glonass_freq_ch;
// code Doppler frequency update
d_code_freq_chips = GLONASS_L2_CA_CODE_RATE_HZ + (((d_carrier_doppler_hz - d_carrier_doppler_old_hz) * GLONASS_L2_CA_CODE_RATE_HZ) / d_glonass_freq_ch);
// ################## DLL ##########################################################
// DLL discriminator
d_code_error_chips_Ti = dll_nc_e_minus_l_normalized(std::complex<float>(d_correlator_outs_16sc[0].real(), d_correlator_outs_16sc[0].imag()), std::complex<float>(d_correlator_outs_16sc[2].real(), d_correlator_outs_16sc[2].imag())); // [chips/Ti] //early and late
// Code discriminator filter
d_code_error_filt_chips_s = d_code_loop_filter.get_code_nco(d_code_error_chips_Ti); // input [chips/Ti] -> output [chips/second]
d_code_error_filt_chips_Ti = d_code_error_filt_chips_s * CURRENT_INTEGRATION_TIME_S;
code_error_filt_secs_Ti = d_code_error_filt_chips_Ti / d_code_freq_chips; // [s/Ti]
// ################## CARRIER AND CODE NCO BUFFER ALIGNMENT #######################
// keep alignment parameters for the next input buffer
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
double T_chip_seconds = 1.0 / d_code_freq_chips;
double T_prn_seconds = T_chip_seconds * GLONASS_L2_CA_CODE_LENGTH_CHIPS;
double T_prn_samples = T_prn_seconds * static_cast<double>(d_fs_in);
double K_prn_samples = round(T_prn_samples);
double K_T_prn_error_samples = K_prn_samples - T_prn_samples;
d_rem_code_phase_samples = d_rem_code_phase_samples - K_T_prn_error_samples + code_error_filt_secs_Ti * static_cast<double>(d_fs_in); //(code_error_filt_secs_Ti + d_pll_to_dll_assist_secs_Ti) * static_cast<double>(d_fs_in);
d_rem_code_phase_integer_samples = round(d_rem_code_phase_samples); // round to a discrete number of samples
d_correlation_length_samples = K_prn_samples + d_rem_code_phase_integer_samples;
d_rem_code_phase_samples = d_rem_code_phase_samples - d_rem_code_phase_integer_samples;
//################### PLL COMMANDS #################################################
//carrier phase step (NCO phase increment per sample) [rads/sample]
d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_doppler_hz / static_cast<double>(d_fs_in);
d_acc_carrier_phase_cycles -= d_carrier_phase_step_rad * d_correlation_length_samples / GLONASS_TWO_PI;
// UPDATE ACCUMULATED CARRIER PHASE
CORRECTED_INTEGRATION_TIME_S = (static_cast<double>(d_correlation_length_samples) / static_cast<double>(d_fs_in));
//remnant carrier phase [rad]
d_rem_carrier_phase_rad = fmod(d_rem_carrier_phase_rad + GLONASS_TWO_PI * d_carrier_doppler_hz * CORRECTED_INTEGRATION_TIME_S, GLONASS_TWO_PI);
//################### DLL COMMANDS #################################################
//code phase step (Code resampler phase increment per sample) [chips/sample]
d_code_phase_step_chips = d_code_freq_chips / static_cast<double>(d_fs_in);
//remnant code phase [chips]
d_rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / static_cast<double>(d_fs_in));
// ####### CN0 ESTIMATION AND LOCK DETECTORS #######################################
if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES)
{
// fill buffer with prompt correlator output values
d_Prompt_buffer[d_cn0_estimation_counter] = lv_cmake(static_cast<float>(d_correlator_outs_16sc[1].real()), static_cast<float>(d_correlator_outs_16sc[1].imag())); // prompt
d_cn0_estimation_counter++;
}
else
{
d_cn0_estimation_counter = 0;
// Code lock indicator
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, GLONASS_L2_CA_CODE_LENGTH_CHIPS);
// Carrier lock indicator
d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES);
// Loss of lock detection
if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < FLAGS_cn0_min)
{
d_carrier_lock_fail_counter++;
}
else
{
if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--;
}
if (d_carrier_lock_fail_counter > FLAGS_max_lock_fail)
{
std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl;
LOG(INFO) << "Loss of lock in channel " << d_channel << "!";
this->message_port_pub(pmt::mp("events"), pmt::from_long(3)); //3 -> loss of lock
d_carrier_lock_fail_counter = 0;
d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine
}
}
// ########### Output the tracking data to navigation and PVT ##########
current_synchro_data.Prompt_I = static_cast<double>((d_correlator_outs_16sc[1]).real());
current_synchro_data.Prompt_Q = static_cast<double>((d_correlator_outs_16sc[1]).imag());
// Tracking_timestamp_secs is aligned with the CURRENT PRN start sample (Hybridization OK!)
current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples;
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = GLONASS_TWO_PI * d_acc_carrier_phase_cycles;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
current_synchro_data.Flag_valid_symbol_output = true;
if (d_preamble_synchronized == true)
{
current_synchro_data.correlation_length_ms = d_extend_correlation_ms;
}
else
{
current_synchro_data.correlation_length_ms = 1;
}
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((d_correlator_outs_16sc[1]).real());
current_synchro_data.Prompt_Q = static_cast<double>((d_correlator_outs_16sc[1]).imag());
current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples;
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = GLONASS_TWO_PI * d_acc_carrier_phase_cycles;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; // todo: project the carrier doppler
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
}
}
else
{
for (int n = 0; n < d_n_correlator_taps; n++)
{
d_correlator_outs_16sc[n] = lv_cmake(0, 0);
}
current_synchro_data.System = {'R'};
current_synchro_data.Tracking_sample_counter = d_sample_counter + d_correlation_length_samples;
}
current_synchro_data.fs = d_fs_in;
*out[0] = current_synchro_data;
if (d_dump)
{
// MULTIPLEXED FILE RECORDING - Record results to file
float prompt_I;
float prompt_Q;
float tmp_E, tmp_P, tmp_L;
float tmp_VE = 0.0;
float tmp_VL = 0.0;
float tmp_float;
prompt_I = d_correlator_outs_16sc[1].real();
prompt_Q = d_correlator_outs_16sc[1].imag();
tmp_E = std::abs<float>(gr_complex(d_correlator_outs_16sc[0].real(), d_correlator_outs_16sc[0].imag()));
tmp_P = std::abs<float>(gr_complex(d_correlator_outs_16sc[1].real(), d_correlator_outs_16sc[1].imag()));
tmp_L = std::abs<float>(gr_complex(d_correlator_outs_16sc[2].real(), d_correlator_outs_16sc[2].imag()));
try
{
// Dump correlators output
d_dump_file.write(reinterpret_cast<char *>(&tmp_VE), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_E), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_P), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_L), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&tmp_VL), sizeof(float));
// PROMPT I and Q (to analyze navigation symbols)
d_dump_file.write(reinterpret_cast<char *>(&prompt_I), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&prompt_Q), sizeof(float));
// PRN start sample stamp
d_dump_file.write(reinterpret_cast<char *>(&d_sample_counter), sizeof(unsigned long int));
// accumulated carrier phase
tmp_float = d_acc_carrier_phase_cycles * GLONASS_TWO_PI;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// carrier and code frequency
tmp_float = d_carrier_doppler_hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_freq_chips;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// PLL commands
tmp_float = 1.0 / (d_carr_phase_error_secs_Ti * CURRENT_INTEGRATION_TIME_S);
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = 1.0 / (d_code_error_filt_chips_Ti * CURRENT_INTEGRATION_TIME_S);
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// DLL commands
tmp_float = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_code_error_filt_chips_Ti;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// CN0 and carrier lock test
tmp_float = d_CN0_SNV_dB_Hz;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
tmp_float = d_carrier_lock_test;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
// AUX vars (for debug purposes)
tmp_float = d_code_error_chips_Ti * CURRENT_INTEGRATION_TIME_S;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
double tmp_double = static_cast<double>(d_sample_counter + d_correlation_length_samples);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
// PRN
unsigned int prn_ = d_acquisition_gnss_synchro->PRN;
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(unsigned int));
}
catch (const std::ifstream::failure *e)
{
LOG(WARNING) << "Exception writing trk dump file " << e->what();
}
}
consume_each(d_correlation_length_samples); // this is necessary in gr::block derivates
d_sample_counter += d_correlation_length_samples; //count for the processed samples
return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false
}
void glonass_l2_ca_dll_pll_c_aid_tracking_sc::set_channel(unsigned int channel)
{
d_channel = channel;
LOG(INFO) << "Tracking Channel set to " << d_channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
if (d_dump_file.is_open() == false)
{
try
{
d_dump_filename.append(boost::lexical_cast<std::string>(d_channel));
d_dump_filename.append(".dat");
d_dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
LOG(INFO) << "Tracking dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str() << std::endl;
}
catch (const std::ifstream::failure *e)
{
LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e->what() << std::endl;
}
}
}
}
void glonass_l2_ca_dll_pll_c_aid_tracking_sc::set_gnss_synchro(Gnss_Synchro *p_gnss_synchro)
{
d_acquisition_gnss_synchro = p_gnss_synchro;
}

View File

@ -0,0 +1,206 @@
/*!
* \file glonass_l2_ca_dll_pll_c_aid_tracking_sc.h
* \brief Implementation of a code DLL + carrier PLL tracking block
* \author Damian Miralles, 2018. dmiralles2009(at)gmail.com
*
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkha user, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GLONASS_L2_CA_DLL_PLL_C_AID_TRACKING_SC_H
#define GNSS_SDR_GLONASS_L2_CA_DLL_PLL_C_AID_TRACKING_SC_H
#include "glonass_l2_signal_processing.h"
#include "gnss_synchro.h"
#include "tracking_2nd_DLL_filter.h"
#include "tracking_FLL_PLL_filter.h"
#include "cpu_multicorrelator_16sc.h"
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <gnuradio/block.h>
#include <volk/volk.h>
#include <fstream>
#include <map>
#include <string>
class glonass_l2_ca_dll_pll_c_aid_tracking_sc;
typedef boost::shared_ptr<glonass_l2_ca_dll_pll_c_aid_tracking_sc>
glonass_l2_ca_dll_pll_c_aid_tracking_sc_sptr;
glonass_l2_ca_dll_pll_c_aid_tracking_sc_sptr
glonass_l2_ca_dll_pll_c_aid_make_tracking_sc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips);
/*!
* \brief This class implements a DLL + PLL tracking loop block
*/
class glonass_l2_ca_dll_pll_c_aid_tracking_sc : public gr::block
{
public:
~glonass_l2_ca_dll_pll_c_aid_tracking_sc();
void set_channel(unsigned int channel);
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro);
void start_tracking();
int general_work(int noutput_items, gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items, gr_vector_void_star& output_items);
void forecast(int noutput_items, gr_vector_int& ninput_items_required);
private:
friend glonass_l2_ca_dll_pll_c_aid_tracking_sc_sptr
glonass_l2_ca_dll_pll_c_aid_make_tracking_sc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips);
glonass_l2_ca_dll_pll_c_aid_tracking_sc(long if_freq,
long fs_in, unsigned int vector_length,
bool dump,
std::string dump_filename,
float pll_bw_hz,
float dll_bw_hz,
float pll_bw_narrow_hz,
float dll_bw_narrow_hz,
int extend_correlation_ms,
float early_late_space_chips);
// tracking configuration vars
unsigned int d_vector_length;
bool d_dump;
Gnss_Synchro* d_acquisition_gnss_synchro;
unsigned int d_channel;
long d_if_freq;
long d_fs_in;
long d_glonass_freq_ch;
double d_early_late_spc_chips;
int d_n_correlator_taps;
gr_complex* d_ca_code;
lv_16sc_t* d_ca_code_16sc;
float* d_local_code_shift_chips;
//gr_complex* d_correlator_outs;
lv_16sc_t* d_correlator_outs_16sc;
//cpu_multicorrelator multicorrelator_cpu;
cpu_multicorrelator_16sc multicorrelator_cpu_16sc;
// remaining code phase and carrier phase between tracking loops
double d_rem_code_phase_samples;
double d_rem_code_phase_chips;
double d_rem_carrier_phase_rad;
int d_rem_code_phase_integer_samples;
// PLL and DLL filter library
Tracking_2nd_DLL_filter d_code_loop_filter;
Tracking_FLL_PLL_filter d_carrier_loop_filter;
// acquisition
double d_acq_code_phase_samples;
double d_acq_carrier_doppler_hz;
// tracking vars
float d_dll_bw_hz;
float d_pll_bw_hz;
float d_dll_bw_narrow_hz;
float d_pll_bw_narrow_hz;
double d_code_freq_chips;
double d_code_phase_step_chips;
double d_carrier_doppler_hz;
double d_carrier_frequency_hz;
double d_carrier_doppler_old_hz;
double d_carrier_phase_step_rad;
double d_acc_carrier_phase_cycles;
double d_code_phase_samples;
double d_pll_to_dll_assist_secs_Ti;
double d_carr_phase_error_secs_Ti;
double d_code_error_chips_Ti;
double d_preamble_timestamp_s;
int d_extend_correlation_ms;
bool d_enable_extended_integration;
bool d_preamble_synchronized;
double d_code_error_filt_chips_s;
double d_code_error_filt_chips_Ti;
void msg_handler_preamble_index(pmt::pmt_t msg);
// symbol history to detect bit transition
std::deque<lv_16sc_t> d_E_history;
std::deque<lv_16sc_t> d_P_history;
std::deque<lv_16sc_t> d_L_history;
//Integration period in samples
int d_correlation_length_samples;
//processing samples counters
unsigned long int d_sample_counter;
unsigned long int d_acq_sample_stamp;
// CN0 estimation and lock detector
int d_cn0_estimation_counter;
gr_complex* d_Prompt_buffer;
double d_carrier_lock_test;
double d_CN0_SNV_dB_Hz;
double d_carrier_lock_threshold;
int d_carrier_lock_fail_counter;
// control vars
bool d_enable_tracking;
bool d_pull_in;
// file dump
std::string d_dump_filename;
std::ofstream d_dump_file;
std::map<std::string, std::string> systemName;
std::string sys;
int save_matfile();
};
#endif //GNSS_SDR_GLONASS_L2_CA_DLL_PLL_C_AID_TRACKING_SC_H

Some files were not shown because too many files have changed in this diff Show More