mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-14 20:20:35 +00:00
Merge branch 'next' into observables_and_display_color
This commit is contained in:
commit
ebb908f2e7
@ -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)
|
||||
|
||||
|
||||
################################################################################
|
||||
|
@ -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
|
||||
|
44
README.md
44
README.md
@ -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).
|
||||
|
||||
|
53
cmake/Modules/Findlibiio.cmake
Normal file
53
cmake/Modules/Findlibiio.cmake
Normal 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)
|
@ -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
|
||||
|
141
conf/gnss-sdr_GLONASS_L2_CA_GPS_L1_CA_ibyte.conf
Normal file
141
conf/gnss-sdr_GLONASS_L2_CA_GPS_L1_CA_ibyte.conf
Normal 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
|
142
conf/gnss-sdr_GLONASS_L2_CA_GPS_L2C_ibyte.conf
Normal file
142
conf/gnss-sdr_GLONASS_L2_CA_GPS_L2C_ibyte.conf
Normal 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
|
73
conf/gnss-sdr_GLONASS_L2_CA_ibyte.conf
Normal file
73
conf/gnss-sdr_GLONASS_L2_CA_ibyte.conf
Normal 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
|
83
conf/gnss-sdr_GLONASS_L2_CA_ibyte_coh_trk.conf
Normal file
83
conf/gnss-sdr_GLONASS_L2_CA_ibyte_coh_trk.conf
Normal 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
|
112
conf/gnss-sdr_GPS_L1_2ch_fmcomms2_realtime.conf
Normal file
112
conf/gnss-sdr_GPS_L1_2ch_fmcomms2_realtime.conf
Normal 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
|
@ -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
|
||||
|
@ -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 */
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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_;
|
||||
}
|
@ -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_ */
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
152
src/algorithms/libs/glonass_l2_signal_processing.cc
Normal file
152
src/algorithms/libs/glonass_l2_signal_processing.cc
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
47
src/algorithms/libs/glonass_l2_signal_processing.h
Normal file
47
src/algorithms/libs/glonass_l2_signal_processing.h
Normal 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
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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) */
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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_;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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++)
|
||||
|
@ -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
|
||||
*-----------------------------------------------------------------------------*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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*/
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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})
|
||||
|
||||
|
764
src/algorithms/signal_source/libs/ad9361_manager.cc
Normal file
764
src/algorithms/signal_source/libs/ad9361_manager.cc
Normal 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;
|
||||
}
|
130
src/algorithms/signal_source/libs/ad9361_manager.h
Normal file
130
src/algorithms/signal_source/libs/ad9361_manager.h
Normal 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
|
@ -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(
|
||||
|
@ -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_;
|
||||
}
|
@ -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
|
@ -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(
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -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_
|
||||
|
@ -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>
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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_
|
@ -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_;
|
||||
}
|
@ -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_
|
@ -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_;
|
||||
}
|
||||
|
@ -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_
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user